Merge "Add extra views (tabs) for files in a foreign repository"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 8 Apr 2014 02:34:33 +0000 (02:34 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 8 Apr 2014 02:34:33 +0000 (02:34 +0000)
1560 files changed:
.jshintignore
RELEASE-NOTES-1.23
docs/kss/Makefile [new file with mode: 0644]
docs/kss/README.txt [new file with mode: 0644]
docs/kss/package.json [new file with mode: 0644]
docs/kss/scripts/nodecheck.sh [new file with mode: 0755]
docs/kss/styleguide-template/index.html [new file with mode: 0644]
docs/kss/styleguide-template/public/kss.less [new file with mode: 0644]
docs/kss/styleguide-template/public/less.js [new file with mode: 0644]
includes/AutoLoader.php
includes/Block.php
includes/DefaultSettings.php
includes/EditPage.php
includes/GlobalFunctions.php
includes/HttpFunctions.php
includes/Linker.php
includes/MagicWord.php
includes/OutputPage.php
includes/Preferences.php
includes/PrefixSearch.php
includes/Skin.php
includes/Title.php
includes/UserArrayFromResult.php
includes/WikiPage.php
includes/Xml.php
includes/actions/FormAction.php
includes/actions/WatchAction.php
includes/api/ApiBase.php
includes/api/ApiFeedRecentChanges.php
includes/api/ApiHelp.php
includes/api/ApiMove.php
includes/api/ApiOpenSearch.php
includes/api/ApiQuery.php
includes/api/ApiQueryDeletedrevs.php
includes/api/ApiQueryPrefixSearch.php [new file with mode: 0644]
includes/api/ApiQueryRandom.php
includes/api/ApiQueryRecentChanges.php
includes/composer/ComposerHookHandler.php
includes/content/AbstractContent.php
includes/content/Content.php
includes/content/WikitextContent.php
includes/db/DatabaseMssql.php
includes/db/DatabaseOracle.php
includes/db/LBFactory.php
includes/deferred/SqlDataUpdate.php
includes/diff/DifferenceEngine.php
includes/filebackend/filejournal/FileJournal.php
includes/filerepo/file/LocalFile.php
includes/htmlform/HTMLCheckField.php
includes/htmlform/HTMLMultiSelectField.php
includes/htmlform/HTMLSelectAndOtherField.php
includes/htmlform/HTMLSelectOrOtherField.php
includes/installer/MysqlInstaller.php
includes/installer/PostgresInstaller.php
includes/installer/WebInstallerPage.php
includes/installer/i18n/en.json
includes/installer/i18n/qqq.json
includes/jobqueue/JobQueue.php
includes/jobqueue/JobQueueDB.php
includes/jobqueue/JobQueueRedis.php
includes/jobqueue/jobs/AssembleUploadChunksJob.php
includes/jobqueue/jobs/PublishStashedFileJob.php
includes/logging/LogFormatter.php
includes/logging/LogPage.php
includes/media/Bitmap_ClientOnly.php
includes/media/Exif.php
includes/media/GIF.php
includes/objectcache/MemcachedBagOStuff.php
includes/objectcache/MemcachedClient.php
includes/parser/CacheTime.php
includes/parser/CoreParserFunctions.php
includes/parser/Parser.php
includes/parser/Preprocessor_Hash.php
includes/parser/StripState.php
includes/poolcounter/PoolCounterRedis.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/revisiondelete/RevisionDeleteUser.php
includes/revisiondelete/RevisionDeleter.php
includes/search/SearchEngine.php
includes/site/SiteSQLStore.php
includes/specialpage/FormSpecialPage.php
includes/specialpage/SpecialPage.php
includes/specials/SpecialAllpages.php
includes/specials/SpecialBlock.php
includes/specials/SpecialImport.php
includes/specials/SpecialPrefixindex.php
includes/specials/SpecialRunJobs.php
includes/specials/SpecialSearch.php
includes/specials/SpecialUserrights.php
includes/specials/SpecialVersion.php
includes/utils/UIDGenerator.php
languages/Language.php
languages/i18n/ace.json
languages/i18n/af.json
languages/i18n/aln.json
languages/i18n/am.json
languages/i18n/an.json
languages/i18n/ar.json
languages/i18n/arz.json
languages/i18n/as.json
languages/i18n/ast.json
languages/i18n/avk.json
languages/i18n/az.json
languages/i18n/azb.json
languages/i18n/ba.json
languages/i18n/bar.json
languages/i18n/bcc.json
languages/i18n/bcl.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bg.json
languages/i18n/bjn.json
languages/i18n/bn.json
languages/i18n/bpy.json
languages/i18n/br.json
languages/i18n/bs.json
languages/i18n/ca.json
languages/i18n/cdo.json
languages/i18n/ce.json
languages/i18n/ckb.json
languages/i18n/co.json
languages/i18n/crh-cyrl.json
languages/i18n/crh-latn.json
languages/i18n/cs.json
languages/i18n/csb.json
languages/i18n/cy.json
languages/i18n/da.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/dsb.json
languages/i18n/egl.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/eo.json
languages/i18n/es.json
languages/i18n/et.json
languages/i18n/eu.json
languages/i18n/ext.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fo.json
languages/i18n/fr.json
languages/i18n/frp.json
languages/i18n/frr.json
languages/i18n/fur.json
languages/i18n/fy.json
languages/i18n/ga.json
languages/i18n/gan-hans.json
languages/i18n/gan-hant.json
languages/i18n/gd.json
languages/i18n/gl.json
languages/i18n/gsw.json
languages/i18n/gu.json
languages/i18n/hak.json
languages/i18n/haw.json
languages/i18n/he.json
languages/i18n/hi.json
languages/i18n/hif-latn.json
languages/i18n/hr.json
languages/i18n/hsb.json
languages/i18n/hu.json
languages/i18n/hy.json
languages/i18n/ia.json
languages/i18n/id.json
languages/i18n/ilo.json
languages/i18n/io.json
languages/i18n/is.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/jv.json
languages/i18n/ka.json
languages/i18n/kaa.json
languages/i18n/kab.json
languages/i18n/kk-arab.json
languages/i18n/kk-cyrl.json
languages/i18n/kk-latn.json
languages/i18n/ko.json
languages/i18n/krc.json
languages/i18n/ksh.json
languages/i18n/la.json
languages/i18n/lb.json
languages/i18n/lez.json
languages/i18n/lg.json
languages/i18n/li.json
languages/i18n/loz.json
languages/i18n/lt.json
languages/i18n/lv.json
languages/i18n/lzh.json
languages/i18n/mai.json
languages/i18n/mdf.json
languages/i18n/mg.json
languages/i18n/min.json
languages/i18n/mk.json
languages/i18n/ml.json
languages/i18n/mn.json
languages/i18n/ms.json
languages/i18n/mt.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/nds.json
languages/i18n/ne.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/oc.json
languages/i18n/or.json
languages/i18n/pl.json
languages/i18n/pms.json
languages/i18n/pnb.json
languages/i18n/prg.json
languages/i18n/ps.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/qu.json
languages/i18n/rm.json
languages/i18n/ro.json
languages/i18n/roa-tara.json
languages/i18n/ru.json
languages/i18n/rue.json
languages/i18n/sa.json
languages/i18n/sah.json
languages/i18n/scn.json
languages/i18n/sco.json
languages/i18n/sdc.json
languages/i18n/sh.json
languages/i18n/si.json
languages/i18n/sk.json
languages/i18n/sl.json
languages/i18n/sli.json
languages/i18n/so.json
languages/i18n/sq.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/stq.json
languages/i18n/sv.json
languages/i18n/sw.json
languages/i18n/szl.json
languages/i18n/ta.json
languages/i18n/te.json
languages/i18n/tg-cyrl.json
languages/i18n/tg-latn.json
languages/i18n/th.json
languages/i18n/tk.json
languages/i18n/tl.json
languages/i18n/tr.json
languages/i18n/tt-cyrl.json
languages/i18n/tt-latn.json
languages/i18n/ug-arab.json
languages/i18n/uk.json
languages/i18n/vec.json
languages/i18n/vi.json
languages/i18n/vo.json
languages/i18n/vro.json
languages/i18n/wa.json
languages/i18n/war.json
languages/i18n/yi.json
languages/i18n/yo.json
languages/i18n/yue.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesEn.php
maintenance/benchmarks/bench_delete_truncate.php
maintenance/jsduck/config.json
maintenance/language/messages.inc
maintenance/resources/update-oojs.sh [new file with mode: 0755]
maintenance/runJobs.php
resources/Makefile [deleted file]
resources/README.txt [deleted file]
resources/Resources.php
resources/jquery.chosen/LICENSE [deleted file]
resources/jquery.chosen/chosen-sprite.png [deleted file]
resources/jquery.chosen/chosen-sprite@2x.png [deleted file]
resources/jquery.chosen/chosen.css [deleted file]
resources/jquery.chosen/chosen.jquery.js [deleted file]
resources/jquery.effects/jquery.effects.blind.js [deleted file]
resources/jquery.effects/jquery.effects.bounce.js [deleted file]
resources/jquery.effects/jquery.effects.clip.js [deleted file]
resources/jquery.effects/jquery.effects.core.js [deleted file]
resources/jquery.effects/jquery.effects.drop.js [deleted file]
resources/jquery.effects/jquery.effects.explode.js [deleted file]
resources/jquery.effects/jquery.effects.fade.js [deleted file]
resources/jquery.effects/jquery.effects.fold.js [deleted file]
resources/jquery.effects/jquery.effects.highlight.js [deleted file]
resources/jquery.effects/jquery.effects.pulsate.js [deleted file]
resources/jquery.effects/jquery.effects.scale.js [deleted file]
resources/jquery.effects/jquery.effects.shake.js [deleted file]
resources/jquery.effects/jquery.effects.slide.js [deleted file]
resources/jquery.effects/jquery.effects.transfer.js [deleted file]
resources/jquery.tipsy/images/tipsy.png [deleted file]
resources/jquery.tipsy/jquery.tipsy.css [deleted file]
resources/jquery.tipsy/jquery.tipsy.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-af.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-ar.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-az.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-bg.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-bs.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-ca.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-cs.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-da.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-de.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-el.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-eo.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-es.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-et.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-eu.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-fa.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-fi.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-fo.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-fr.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-gl.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-he.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-hi.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-hr.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-hu.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-hy.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-id.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-is.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-it.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-ja.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-ka.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-kk.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-km.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-ko.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-lb.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-lt.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-lv.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-mk.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-ml.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-ms.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-nl.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-no.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-pl.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-pt.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-rm.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-ro.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-ru.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-sk.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-sl.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-sq.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-sr.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-sv.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-ta.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-th.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-tr.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-uk.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-vi.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js [deleted file]
resources/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js [deleted file]
resources/jquery.ui/jquery.ui.accordion.js [deleted file]
resources/jquery.ui/jquery.ui.autocomplete.js [deleted file]
resources/jquery.ui/jquery.ui.button.js [deleted file]
resources/jquery.ui/jquery.ui.core.js [deleted file]
resources/jquery.ui/jquery.ui.datepicker.js [deleted file]
resources/jquery.ui/jquery.ui.dialog.js [deleted file]
resources/jquery.ui/jquery.ui.draggable.js [deleted file]
resources/jquery.ui/jquery.ui.droppable.js [deleted file]
resources/jquery.ui/jquery.ui.mouse.js [deleted file]
resources/jquery.ui/jquery.ui.position.js [deleted file]
resources/jquery.ui/jquery.ui.progressbar.js [deleted file]
resources/jquery.ui/jquery.ui.resizable.js [deleted file]
resources/jquery.ui/jquery.ui.selectable.js [deleted file]
resources/jquery.ui/jquery.ui.slider.js [deleted file]
resources/jquery.ui/jquery.ui.sortable.js [deleted file]
resources/jquery.ui/jquery.ui.tabs.js [deleted file]
resources/jquery.ui/jquery.ui.widget.js [deleted file]
resources/jquery.ui/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png [deleted file]
resources/jquery.ui/themes/default/images/ui-bg_flat_75_ffffff_40x100.png [deleted file]
resources/jquery.ui/themes/default/images/ui-bg_glass_55_fbf9ee_1x400.png [deleted file]
resources/jquery.ui/themes/default/images/ui-bg_glass_65_ffffff_1x400.png [deleted file]
resources/jquery.ui/themes/default/images/ui-bg_glass_75_dadada_1x400.png [deleted file]
resources/jquery.ui/themes/default/images/ui-bg_glass_75_e6e6e6_1x400.png [deleted file]
resources/jquery.ui/themes/default/images/ui-bg_glass_95_fef1ec_1x400.png [deleted file]
resources/jquery.ui/themes/default/images/ui-bg_highlight-soft_75_cccccc_1x100.png [deleted file]
resources/jquery.ui/themes/default/images/ui-icons_222222_256x240.png [deleted file]
resources/jquery.ui/themes/default/images/ui-icons_2e83ff_256x240.png [deleted file]
resources/jquery.ui/themes/default/images/ui-icons_454545_256x240.png [deleted file]
resources/jquery.ui/themes/default/images/ui-icons_888888_256x240.png [deleted file]
resources/jquery.ui/themes/default/images/ui-icons_cd0a0a_256x240.png [deleted file]
resources/jquery.ui/themes/default/jquery.ui.accordion.css [deleted file]
resources/jquery.ui/themes/default/jquery.ui.autocomplete.css [deleted file]
resources/jquery.ui/themes/default/jquery.ui.button.css [deleted file]
resources/jquery.ui/themes/default/jquery.ui.core.css [deleted file]
resources/jquery.ui/themes/default/jquery.ui.datepicker.css [deleted file]
resources/jquery.ui/themes/default/jquery.ui.dialog.css [deleted file]
resources/jquery.ui/themes/default/jquery.ui.progressbar.css [deleted file]
resources/jquery.ui/themes/default/jquery.ui.resizable.css [deleted file]
resources/jquery.ui/themes/default/jquery.ui.selectable.css [deleted file]
resources/jquery.ui/themes/default/jquery.ui.slider.css [deleted file]
resources/jquery.ui/themes/default/jquery.ui.tabs.css [deleted file]
resources/jquery.ui/themes/default/jquery.ui.theme.css [deleted file]
resources/jquery.ui/themes/vector/images/close.png [deleted file]
resources/jquery.ui/themes/vector/images/titlebar-fade.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-anim_basic_16x16.gif [deleted file]
resources/jquery.ui/themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-bg_flat_70_000000_40x100.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-icons_2694e8_256x240.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-icons_2e83ff_256x240.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-icons_3d80b3_256x240.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-icons_666666_256x240.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-icons_72a7cf_256x240.png [deleted file]
resources/jquery.ui/themes/vector/images/ui-icons_ffffff_256x240.png [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.accordion.css [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.autocomplete.css [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.button.css [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.core.css [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.datepicker.css [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.dialog.css [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.progressbar.css [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.resizable.css [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.selectable.css [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.slider.css [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.tabs.css [deleted file]
resources/jquery.ui/themes/vector/jquery.ui.theme.css [deleted file]
resources/jquery/images/jquery.arrowSteps.divider-ltr.png [deleted file]
resources/jquery/images/jquery.arrowSteps.divider-rtl.png [deleted file]
resources/jquery/images/jquery.arrowSteps.head-ltr.png [deleted file]
resources/jquery/images/jquery.arrowSteps.head-rtl.png [deleted file]
resources/jquery/images/jquery.arrowSteps.tail-ltr.png [deleted file]
resources/jquery/images/jquery.arrowSteps.tail-rtl.png [deleted file]
resources/jquery/images/marker.png [deleted file]
resources/jquery/images/mask.png [deleted file]
resources/jquery/images/sort_both.gif [deleted file]
resources/jquery/images/sort_down.gif [deleted file]
resources/jquery/images/sort_none.gif [deleted file]
resources/jquery/images/sort_up.gif [deleted file]
resources/jquery/images/spinner-large.gif [deleted file]
resources/jquery/images/spinner.gif [deleted file]
resources/jquery/images/wheel.png [deleted file]
resources/jquery/jquery.appear.js [deleted file]
resources/jquery/jquery.arrowSteps.css [deleted file]
resources/jquery/jquery.arrowSteps.js [deleted file]
resources/jquery/jquery.async.js [deleted file]
resources/jquery/jquery.autoEllipsis.js [deleted file]
resources/jquery/jquery.ba-throttle-debounce.js [deleted file]
resources/jquery/jquery.badge.css [deleted file]
resources/jquery/jquery.badge.js [deleted file]
resources/jquery/jquery.byteLength.js [deleted file]
resources/jquery/jquery.byteLimit.js [deleted file]
resources/jquery/jquery.checkboxShiftClick.js [deleted file]
resources/jquery/jquery.client.js [deleted file]
resources/jquery/jquery.color.js [deleted file]
resources/jquery/jquery.colorUtil.js [deleted file]
resources/jquery/jquery.cookie.js [deleted file]
resources/jquery/jquery.cycle.all.js [deleted file]
resources/jquery/jquery.delayedBind.js [deleted file]
resources/jquery/jquery.expandableField.js [deleted file]
resources/jquery/jquery.farbtastic.css [deleted file]
resources/jquery/jquery.farbtastic.js [deleted file]
resources/jquery/jquery.footHovzer.css [deleted file]
resources/jquery/jquery.footHovzer.js [deleted file]
resources/jquery/jquery.form.js [deleted file]
resources/jquery/jquery.fullscreen.js [deleted file]
resources/jquery/jquery.getAttrs.js [deleted file]
resources/jquery/jquery.hidpi.js [deleted file]
resources/jquery/jquery.highlightText.js [deleted file]
resources/jquery/jquery.hoverIntent.js [deleted file]
resources/jquery/jquery.jStorage.js [deleted file]
resources/jquery/jquery.js [deleted file]
resources/jquery/jquery.json.js [deleted file]
resources/jquery/jquery.localize.js [deleted file]
resources/jquery/jquery.makeCollapsible.css [deleted file]
resources/jquery/jquery.makeCollapsible.js [deleted file]
resources/jquery/jquery.mockjax.js [deleted file]
resources/jquery/jquery.mw-jump.js [deleted file]
resources/jquery/jquery.mwExtension.js [deleted file]
resources/jquery/jquery.placeholder.js [deleted file]
resources/jquery/jquery.qunit.completenessTest.js [deleted file]
resources/jquery/jquery.qunit.css [deleted file]
resources/jquery/jquery.qunit.js [deleted file]
resources/jquery/jquery.spinner.css [deleted file]
resources/jquery/jquery.spinner.js [deleted file]
resources/jquery/jquery.suggestions.css [deleted file]
resources/jquery/jquery.suggestions.js [deleted file]
resources/jquery/jquery.tabIndex.js [deleted file]
resources/jquery/jquery.tablesorter.css [deleted file]
resources/jquery/jquery.tablesorter.js [deleted file]
resources/jquery/jquery.textSelection.js [deleted file]
resources/jquery/jquery.validate.js [deleted file]
resources/jquery/jquery.xmldom.js [deleted file]
resources/lib/jquery.chosen/LICENSE [new file with mode: 0644]
resources/lib/jquery.chosen/chosen-sprite.png [new file with mode: 0644]
resources/lib/jquery.chosen/chosen-sprite@2x.png [new file with mode: 0644]
resources/lib/jquery.chosen/chosen.css [new file with mode: 0644]
resources/lib/jquery.chosen/chosen.jquery.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.blind.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.bounce.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.clip.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.core.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.drop.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.explode.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.fade.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.fold.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.highlight.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.pulsate.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.scale.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.shake.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.slide.js [new file with mode: 0644]
resources/lib/jquery.effects/jquery.effects.transfer.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-af.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-az.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bg.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bs.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ca.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cs.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-da.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-el.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eo.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-es.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-et.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eu.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fa.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fi.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fo.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-gl.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-he.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hi.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hr.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hu.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hy.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-id.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-is.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-it.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ja.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ka.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-kk.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-km.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ko.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lb.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lt.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lv.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-mk.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ml.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ms.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-no.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pl.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-rm.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ro.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ru.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sk.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sl.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sq.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sv.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ta.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-th.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tr.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-uk.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-vi.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.accordion.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.autocomplete.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.button.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.core.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.datepicker.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.dialog.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.draggable.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.droppable.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.mouse.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.position.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.progressbar.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.resizable.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.selectable.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.slider.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.sortable.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.tabs.js [new file with mode: 0644]
resources/lib/jquery.ui/jquery.ui.widget.js [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-bg_flat_75_ffffff_40x100.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-bg_glass_55_fbf9ee_1x400.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-bg_glass_65_ffffff_1x400.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-bg_glass_75_dadada_1x400.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-bg_glass_75_e6e6e6_1x400.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-bg_glass_95_fef1ec_1x400.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-bg_highlight-soft_75_cccccc_1x100.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-icons_222222_256x240.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-icons_2e83ff_256x240.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-icons_454545_256x240.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-icons_888888_256x240.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/images/ui-icons_cd0a0a_256x240.png [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.accordion.css [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.autocomplete.css [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.button.css [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.core.css [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.datepicker.css [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.dialog.css [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.progressbar.css [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.resizable.css [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.selectable.css [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.slider.css [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.tabs.css [new file with mode: 0644]
resources/lib/jquery.ui/themes/default/jquery.ui.theme.css [new file with mode: 0644]
resources/lib/jquery/jquery.appear.js [new file with mode: 0644]
resources/lib/jquery/jquery.async.js [new file with mode: 0644]
resources/lib/jquery/jquery.ba-throttle-debounce.js [new file with mode: 0644]
resources/lib/jquery/jquery.cookie.js [new file with mode: 0644]
resources/lib/jquery/jquery.cycle.all.js [new file with mode: 0644]
resources/lib/jquery/jquery.form.js [new file with mode: 0644]
resources/lib/jquery/jquery.fullscreen.js [new file with mode: 0644]
resources/lib/jquery/jquery.hoverIntent.js [new file with mode: 0644]
resources/lib/jquery/jquery.jStorage.js [new file with mode: 0644]
resources/lib/jquery/jquery.js [new file with mode: 0644]
resources/lib/jquery/jquery.json.js [new file with mode: 0644]
resources/lib/jquery/jquery.mockjax.js [new file with mode: 0644]
resources/lib/jquery/jquery.qunit.css [new file with mode: 0644]
resources/lib/jquery/jquery.qunit.js [new file with mode: 0644]
resources/lib/jquery/jquery.validate.js [new file with mode: 0644]
resources/lib/jquery/jquery.xmldom.js [new file with mode: 0644]
resources/lib/moment/LICENSE [new file with mode: 0644]
resources/lib/moment/lang/ar-ma.js [new file with mode: 0644]
resources/lib/moment/lang/ar.js [new file with mode: 0644]
resources/lib/moment/lang/bg.js [new file with mode: 0644]
resources/lib/moment/lang/br.js [new file with mode: 0644]
resources/lib/moment/lang/bs.js [new file with mode: 0644]
resources/lib/moment/lang/ca.js [new file with mode: 0644]
resources/lib/moment/lang/cs.js [new file with mode: 0644]
resources/lib/moment/lang/cv.js [new file with mode: 0644]
resources/lib/moment/lang/cy.js [new file with mode: 0644]
resources/lib/moment/lang/da.js [new file with mode: 0644]
resources/lib/moment/lang/de.js [new file with mode: 0644]
resources/lib/moment/lang/el.js [new file with mode: 0644]
resources/lib/moment/lang/en-au.js [new file with mode: 0644]
resources/lib/moment/lang/en-ca.js [new file with mode: 0644]
resources/lib/moment/lang/en-gb.js [new file with mode: 0644]
resources/lib/moment/lang/eo.js [new file with mode: 0644]
resources/lib/moment/lang/es.js [new file with mode: 0644]
resources/lib/moment/lang/et.js [new file with mode: 0644]
resources/lib/moment/lang/eu.js [new file with mode: 0644]
resources/lib/moment/lang/fa.js [new file with mode: 0644]
resources/lib/moment/lang/fi.js [new file with mode: 0644]
resources/lib/moment/lang/fo.js [new file with mode: 0644]
resources/lib/moment/lang/fr-ca.js [new file with mode: 0644]
resources/lib/moment/lang/fr.js [new file with mode: 0644]
resources/lib/moment/lang/gl.js [new file with mode: 0644]
resources/lib/moment/lang/he.js [new file with mode: 0644]
resources/lib/moment/lang/hi.js [new file with mode: 0644]
resources/lib/moment/lang/hr.js [new file with mode: 0644]
resources/lib/moment/lang/hu.js [new file with mode: 0644]
resources/lib/moment/lang/hy-am.js [new file with mode: 0644]
resources/lib/moment/lang/id.js [new file with mode: 0644]
resources/lib/moment/lang/is.js [new file with mode: 0644]
resources/lib/moment/lang/it.js [new file with mode: 0644]
resources/lib/moment/lang/ja.js [new file with mode: 0644]
resources/lib/moment/lang/ka.js [new file with mode: 0644]
resources/lib/moment/lang/ko.js [new file with mode: 0644]
resources/lib/moment/lang/lb.js [new file with mode: 0644]
resources/lib/moment/lang/lt.js [new file with mode: 0644]
resources/lib/moment/lang/lv.js [new file with mode: 0644]
resources/lib/moment/lang/mk.js [new file with mode: 0644]
resources/lib/moment/lang/ml.js [new file with mode: 0644]
resources/lib/moment/lang/mr.js [new file with mode: 0644]
resources/lib/moment/lang/ms-my.js [new file with mode: 0644]
resources/lib/moment/lang/nb.js [new file with mode: 0644]
resources/lib/moment/lang/ne.js [new file with mode: 0644]
resources/lib/moment/lang/nl.js [new file with mode: 0644]
resources/lib/moment/lang/nn.js [new file with mode: 0644]
resources/lib/moment/lang/pl.js [new file with mode: 0644]
resources/lib/moment/lang/pt-br.js [new file with mode: 0644]
resources/lib/moment/lang/pt.js [new file with mode: 0644]
resources/lib/moment/lang/ro.js [new file with mode: 0644]
resources/lib/moment/lang/rs.js [new file with mode: 0644]
resources/lib/moment/lang/ru.js [new file with mode: 0644]
resources/lib/moment/lang/sk.js [new file with mode: 0644]
resources/lib/moment/lang/sl.js [new file with mode: 0644]
resources/lib/moment/lang/sq.js [new file with mode: 0644]
resources/lib/moment/lang/sv.js [new file with mode: 0644]
resources/lib/moment/lang/ta.js [new file with mode: 0644]
resources/lib/moment/lang/th.js [new file with mode: 0644]
resources/lib/moment/lang/tl-ph.js [new file with mode: 0644]
resources/lib/moment/lang/tr.js [new file with mode: 0644]
resources/lib/moment/lang/tzm-la.js [new file with mode: 0644]
resources/lib/moment/lang/tzm.js [new file with mode: 0644]
resources/lib/moment/lang/uk.js [new file with mode: 0644]
resources/lib/moment/lang/uz.js [new file with mode: 0644]
resources/lib/moment/lang/vn.js [new file with mode: 0644]
resources/lib/moment/lang/zh-cn.js [new file with mode: 0644]
resources/lib/moment/lang/zh-tw.js [new file with mode: 0644]
resources/lib/moment/moment.js [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ace.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/af.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/am.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ar.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/arc.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ast.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/az.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ba.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/bcl.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/be-tarask.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/be.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/bg.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/bn.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/br.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/bs.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ca.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ce.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ckb.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/co.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/cs.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/cu.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/cy.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/da.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/de.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/diq.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/dsb.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/el.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/eml.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/en.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/eo.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/es.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/et.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/eu.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/fa.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/fi.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/fo.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/fr.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/frr.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/fur.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/gl.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/gu.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/he.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/hi.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/hr.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/hsb.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/hu.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/hy.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ia.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/id.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ie.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ilo.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/is.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/it.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ja.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/jv.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ka.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/kk-cyrl.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/km.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/kn.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ko.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/krc.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/kw.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ky.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/lb.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/lmo.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/lt.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/lv.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/mg.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/min.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/mk.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ml.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/mr.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ms.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/nap.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/nb.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/nds-nl.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/nds.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ne.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/nl.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/nn.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/om.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/or.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/pa.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/pfl.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/pl.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/pms.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ps.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/pt-br.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/pt.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/qqq.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/qu.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ro.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/roa-tara.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ru.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/sah.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/scn.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/sco.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/sh.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/si.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/sk.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/sl.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/sq.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/sr-ec.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/sv.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/sw.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ta.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/te.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/th.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/tl.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/tr.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/tt-cyrl.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ug-arab.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/uk.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/uz.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/vec.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/vi.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/vo.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/wuu.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/yi.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/yo.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/zh-hans.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/zh-hant.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/zh-hk.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/zh-tw.json [new file with mode: 0644]
resources/lib/oojs-ui/images/fade-down.png [new file with mode: 0644]
resources/lib/oojs-ui/images/fade-up.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/accept.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/accept.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/add-item.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/add-item.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/advanced.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/advanced.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/alert.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/alert.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/arched-arrow-ltr.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/arched-arrow-ltr.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/arched-arrow-rtl.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/arched-arrow-rtl.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/check.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/check.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/clear.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/clear.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/close.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/close.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/code.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/code.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/collapse.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/collapse.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/comment.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/comment.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/expand.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/expand.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/help.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/help.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/history.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/history.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/link.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/link.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/menu.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/menu.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/move-ltr.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/move-ltr.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/move-rtl.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/move-rtl.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/picture.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/picture.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/remove-item.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/remove-item.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/remove.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/remove.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/search.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/search.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/settings.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/settings.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/tag.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/tag.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/window.png [new file with mode: 0644]
resources/lib/oojs-ui/images/icons/window.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/indicators/down.png [new file with mode: 0644]
resources/lib/oojs-ui/images/indicators/down.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/indicators/required.png [new file with mode: 0644]
resources/lib/oojs-ui/images/indicators/required.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/indicators/up.png [new file with mode: 0644]
resources/lib/oojs-ui/images/indicators/up.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/tail.svg [new file with mode: 0644]
resources/lib/oojs-ui/images/textures/pending.gif [new file with mode: 0644]
resources/lib/oojs-ui/images/textures/transparency.png [new file with mode: 0644]
resources/lib/oojs-ui/images/toolbar-shadow.png [new file with mode: 0644]
resources/lib/oojs-ui/oojs-ui-agora.css [new file with mode: 0644]
resources/lib/oojs-ui/oojs-ui-apex.css [new file with mode: 0644]
resources/lib/oojs-ui/oojs-ui.js [new file with mode: 0644]
resources/lib/oojs-ui/oojs-ui.svg.css [new file with mode: 0644]
resources/lib/oojs-ui/update-oojs-ui.sh [new file with mode: 0755]
resources/lib/oojs/oojs.js [new file with mode: 0644]
resources/lib/sinonjs/sinon-1.9.0.js [new file with mode: 0644]
resources/lib/sinonjs/sinon-ie-1.9.0.js [new file with mode: 0644]
resources/mediawiki.action/images/green-checkmark.png [deleted file]
resources/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css [deleted file]
resources/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js [deleted file]
resources/mediawiki.action/mediawiki.action.edit.editWarning.js [deleted file]
resources/mediawiki.action/mediawiki.action.edit.js [deleted file]
resources/mediawiki.action/mediawiki.action.edit.preview.js [deleted file]
resources/mediawiki.action/mediawiki.action.edit.styles.css [deleted file]
resources/mediawiki.action/mediawiki.action.history.diff.css [deleted file]
resources/mediawiki.action/mediawiki.action.history.js [deleted file]
resources/mediawiki.action/mediawiki.action.view.dblClickEdit.js [deleted file]
resources/mediawiki.action/mediawiki.action.view.metadata.js [deleted file]
resources/mediawiki.action/mediawiki.action.view.postEdit.css [deleted file]
resources/mediawiki.action/mediawiki.action.view.postEdit.js [deleted file]
resources/mediawiki.action/mediawiki.action.view.redirectToFragment.js [deleted file]
resources/mediawiki.action/mediawiki.action.view.rightClickEdit.js [deleted file]
resources/mediawiki.api/mediawiki.api.category.js [deleted file]
resources/mediawiki.api/mediawiki.api.edit.js [deleted file]
resources/mediawiki.api/mediawiki.api.js [deleted file]
resources/mediawiki.api/mediawiki.api.login.js [deleted file]
resources/mediawiki.api/mediawiki.api.parse.js [deleted file]
resources/mediawiki.api/mediawiki.api.watch.js [deleted file]
resources/mediawiki.language/languages/bs.js [deleted file]
resources/mediawiki.language/languages/dsb.js [deleted file]
resources/mediawiki.language/languages/fi.js [deleted file]
resources/mediawiki.language/languages/ga.js [deleted file]
resources/mediawiki.language/languages/he.js [deleted file]
resources/mediawiki.language/languages/hsb.js [deleted file]
resources/mediawiki.language/languages/hu.js [deleted file]
resources/mediawiki.language/languages/hy.js [deleted file]
resources/mediawiki.language/languages/la.js [deleted file]
resources/mediawiki.language/languages/os.js [deleted file]
resources/mediawiki.language/languages/ru.js [deleted file]
resources/mediawiki.language/languages/sl.js [deleted file]
resources/mediawiki.language/languages/uk.js [deleted file]
resources/mediawiki.language/mediawiki.cldr.js [deleted file]
resources/mediawiki.language/mediawiki.language.init.js [deleted file]
resources/mediawiki.language/mediawiki.language.js [deleted file]
resources/mediawiki.language/mediawiki.language.months.js [deleted file]
resources/mediawiki.language/mediawiki.language.numbers.js [deleted file]
resources/mediawiki.less/mediawiki.mixins.animation.less [deleted file]
resources/mediawiki.less/mediawiki.mixins.less [deleted file]
resources/mediawiki.less/mediawiki.mixins.rotation.less [deleted file]
resources/mediawiki.libs/CLDRPluralRuleParser.js [deleted file]
resources/mediawiki.libs/mediawiki.libs.jpegmeta.js [deleted file]
resources/mediawiki.page/mediawiki.page.gallery.js [deleted file]
resources/mediawiki.page/mediawiki.page.image.pagination.js [deleted file]
resources/mediawiki.page/mediawiki.page.patrol.ajax.js [deleted file]
resources/mediawiki.page/mediawiki.page.ready.js [deleted file]
resources/mediawiki.page/mediawiki.page.startup.js [deleted file]
resources/mediawiki.page/mediawiki.page.watch.ajax.js [deleted file]
resources/mediawiki.special/images/glyph-people-large.png [deleted file]
resources/mediawiki.special/images/icon-contributors.png [deleted file]
resources/mediawiki.special/images/icon-edits.png [deleted file]
resources/mediawiki.special/images/icon-lock.png [deleted file]
resources/mediawiki.special/images/icon-pages.png [deleted file]
resources/mediawiki.special/mediawiki.special.block.css [deleted file]
resources/mediawiki.special/mediawiki.special.block.js [deleted file]
resources/mediawiki.special/mediawiki.special.changeemail.css [deleted file]
resources/mediawiki.special/mediawiki.special.changeemail.js [deleted file]
resources/mediawiki.special/mediawiki.special.changeslist.css [deleted file]
resources/mediawiki.special/mediawiki.special.changeslist.enhanced.css [deleted file]
resources/mediawiki.special/mediawiki.special.changeslist.legend.css [deleted file]
resources/mediawiki.special/mediawiki.special.changeslist.legend.js [deleted file]
resources/mediawiki.special/mediawiki.special.css [deleted file]
resources/mediawiki.special/mediawiki.special.javaScriptTest.js [deleted file]
resources/mediawiki.special/mediawiki.special.js [deleted file]
resources/mediawiki.special/mediawiki.special.movePage.js [deleted file]
resources/mediawiki.special/mediawiki.special.pagesWithProp.css [deleted file]
resources/mediawiki.special/mediawiki.special.preferences.css [deleted file]
resources/mediawiki.special/mediawiki.special.preferences.js [deleted file]
resources/mediawiki.special/mediawiki.special.recentchanges.js [deleted file]
resources/mediawiki.special/mediawiki.special.search.css [deleted file]
resources/mediawiki.special/mediawiki.special.search.js [deleted file]
resources/mediawiki.special/mediawiki.special.undelete.js [deleted file]
resources/mediawiki.special/mediawiki.special.upload.js [deleted file]
resources/mediawiki.special/mediawiki.special.userlogin.common.css [deleted file]
resources/mediawiki.special/mediawiki.special.userlogin.common.js [deleted file]
resources/mediawiki.special/mediawiki.special.userlogin.login.css [deleted file]
resources/mediawiki.special/mediawiki.special.userlogin.signup.css [deleted file]
resources/mediawiki.special/mediawiki.special.userlogin.signup.js [deleted file]
resources/mediawiki.special/mediawiki.special.version.css [deleted file]
resources/mediawiki.ui/components/default/buttons.less [deleted file]
resources/mediawiki.ui/components/default/forms.less [deleted file]
resources/mediawiki.ui/components/utilities.less [deleted file]
resources/mediawiki.ui/components/vector/buttons.less [deleted file]
resources/mediawiki.ui/components/vector/containers.less [deleted file]
resources/mediawiki.ui/components/vector/forms.less [deleted file]
resources/mediawiki.ui/default.less [deleted file]
resources/mediawiki.ui/mixins/effects.less [deleted file]
resources/mediawiki.ui/mixins/forms.less [deleted file]
resources/mediawiki.ui/mixins/type.less [deleted file]
resources/mediawiki.ui/mixins/utilities.less [deleted file]
resources/mediawiki.ui/settings/colors.less [deleted file]
resources/mediawiki.ui/settings/typography.less [deleted file]
resources/mediawiki.ui/styleguide.md [deleted file]
resources/mediawiki.ui/vector.less [deleted file]
resources/mediawiki/images/arrow-collapsed-ltr.png [deleted file]
resources/mediawiki/images/arrow-collapsed-ltr.svg [deleted file]
resources/mediawiki/images/arrow-collapsed-rtl.png [deleted file]
resources/mediawiki/images/arrow-collapsed-rtl.svg [deleted file]
resources/mediawiki/images/arrow-expanded.png [deleted file]
resources/mediawiki/images/arrow-expanded.svg [deleted file]
resources/mediawiki/mediawiki.Title.js [deleted file]
resources/mediawiki/mediawiki.Uri.js [deleted file]
resources/mediawiki/mediawiki.debug.init.js [deleted file]
resources/mediawiki/mediawiki.debug.js [deleted file]
resources/mediawiki/mediawiki.debug.less [deleted file]
resources/mediawiki/mediawiki.debug.profile.css [deleted file]
resources/mediawiki/mediawiki.debug.profile.js [deleted file]
resources/mediawiki/mediawiki.feedback.css [deleted file]
resources/mediawiki/mediawiki.feedback.js [deleted file]
resources/mediawiki/mediawiki.feedback.spinner.gif [deleted file]
resources/mediawiki/mediawiki.hidpi.js [deleted file]
resources/mediawiki/mediawiki.hlist.css [deleted file]
resources/mediawiki/mediawiki.hlist.js [deleted file]
resources/mediawiki/mediawiki.htmlform.js [deleted file]
resources/mediawiki/mediawiki.icon.less [deleted file]
resources/mediawiki/mediawiki.inspect.js [deleted file]
resources/mediawiki/mediawiki.jqueryMsg.js [deleted file]
resources/mediawiki/mediawiki.jqueryMsg.peg [deleted file]
resources/mediawiki/mediawiki.js [deleted file]
resources/mediawiki/mediawiki.log.js [deleted file]
resources/mediawiki/mediawiki.notification.css [deleted file]
resources/mediawiki/mediawiki.notification.hideForPrint.css [deleted file]
resources/mediawiki/mediawiki.notification.js [deleted file]
resources/mediawiki/mediawiki.notify.js [deleted file]
resources/mediawiki/mediawiki.searchSuggest.css [deleted file]
resources/mediawiki/mediawiki.searchSuggest.js [deleted file]
resources/mediawiki/mediawiki.toc.js [deleted file]
resources/mediawiki/mediawiki.user.js [deleted file]
resources/mediawiki/mediawiki.util.js [deleted file]
resources/moment/LICENSE [deleted file]
resources/moment/lang/ar-ma.js [deleted file]
resources/moment/lang/ar.js [deleted file]
resources/moment/lang/bg.js [deleted file]
resources/moment/lang/br.js [deleted file]
resources/moment/lang/bs.js [deleted file]
resources/moment/lang/ca.js [deleted file]
resources/moment/lang/cs.js [deleted file]
resources/moment/lang/cv.js [deleted file]
resources/moment/lang/cy.js [deleted file]
resources/moment/lang/da.js [deleted file]
resources/moment/lang/de.js [deleted file]
resources/moment/lang/el.js [deleted file]
resources/moment/lang/en-au.js [deleted file]
resources/moment/lang/en-ca.js [deleted file]
resources/moment/lang/en-gb.js [deleted file]
resources/moment/lang/eo.js [deleted file]
resources/moment/lang/es.js [deleted file]
resources/moment/lang/et.js [deleted file]
resources/moment/lang/eu.js [deleted file]
resources/moment/lang/fa.js [deleted file]
resources/moment/lang/fi.js [deleted file]
resources/moment/lang/fo.js [deleted file]
resources/moment/lang/fr-ca.js [deleted file]
resources/moment/lang/fr.js [deleted file]
resources/moment/lang/gl.js [deleted file]
resources/moment/lang/he.js [deleted file]
resources/moment/lang/hi.js [deleted file]
resources/moment/lang/hr.js [deleted file]
resources/moment/lang/hu.js [deleted file]
resources/moment/lang/hy-am.js [deleted file]
resources/moment/lang/id.js [deleted file]
resources/moment/lang/is.js [deleted file]
resources/moment/lang/it.js [deleted file]
resources/moment/lang/ja.js [deleted file]
resources/moment/lang/ka.js [deleted file]
resources/moment/lang/ko.js [deleted file]
resources/moment/lang/lb.js [deleted file]
resources/moment/lang/lt.js [deleted file]
resources/moment/lang/lv.js [deleted file]
resources/moment/lang/mk.js [deleted file]
resources/moment/lang/ml.js [deleted file]
resources/moment/lang/mr.js [deleted file]
resources/moment/lang/ms-my.js [deleted file]
resources/moment/lang/nb.js [deleted file]
resources/moment/lang/ne.js [deleted file]
resources/moment/lang/nl.js [deleted file]
resources/moment/lang/nn.js [deleted file]
resources/moment/lang/pl.js [deleted file]
resources/moment/lang/pt-br.js [deleted file]
resources/moment/lang/pt.js [deleted file]
resources/moment/lang/ro.js [deleted file]
resources/moment/lang/rs.js [deleted file]
resources/moment/lang/ru.js [deleted file]
resources/moment/lang/sk.js [deleted file]
resources/moment/lang/sl.js [deleted file]
resources/moment/lang/sq.js [deleted file]
resources/moment/lang/sv.js [deleted file]
resources/moment/lang/ta.js [deleted file]
resources/moment/lang/th.js [deleted file]
resources/moment/lang/tl-ph.js [deleted file]
resources/moment/lang/tr.js [deleted file]
resources/moment/lang/tzm-la.js [deleted file]
resources/moment/lang/tzm.js [deleted file]
resources/moment/lang/uk.js [deleted file]
resources/moment/lang/uz.js [deleted file]
resources/moment/lang/vn.js [deleted file]
resources/moment/lang/zh-cn.js [deleted file]
resources/moment/lang/zh-tw.js [deleted file]
resources/moment/moment.js [deleted file]
resources/oojs-ui/i18n/ace.json [deleted file]
resources/oojs-ui/i18n/af.json [deleted file]
resources/oojs-ui/i18n/am.json [deleted file]
resources/oojs-ui/i18n/ar.json [deleted file]
resources/oojs-ui/i18n/arc.json [deleted file]
resources/oojs-ui/i18n/ast.json [deleted file]
resources/oojs-ui/i18n/az.json [deleted file]
resources/oojs-ui/i18n/ba.json [deleted file]
resources/oojs-ui/i18n/bcl.json [deleted file]
resources/oojs-ui/i18n/be-tarask.json [deleted file]
resources/oojs-ui/i18n/be.json [deleted file]
resources/oojs-ui/i18n/bg.json [deleted file]
resources/oojs-ui/i18n/bn.json [deleted file]
resources/oojs-ui/i18n/br.json [deleted file]
resources/oojs-ui/i18n/bs.json [deleted file]
resources/oojs-ui/i18n/ca.json [deleted file]
resources/oojs-ui/i18n/ce.json [deleted file]
resources/oojs-ui/i18n/ckb.json [deleted file]
resources/oojs-ui/i18n/co.json [deleted file]
resources/oojs-ui/i18n/cs.json [deleted file]
resources/oojs-ui/i18n/cu.json [deleted file]
resources/oojs-ui/i18n/cy.json [deleted file]
resources/oojs-ui/i18n/da.json [deleted file]
resources/oojs-ui/i18n/de.json [deleted file]
resources/oojs-ui/i18n/diq.json [deleted file]
resources/oojs-ui/i18n/dsb.json [deleted file]
resources/oojs-ui/i18n/el.json [deleted file]
resources/oojs-ui/i18n/eml.json [deleted file]
resources/oojs-ui/i18n/en.json [deleted file]
resources/oojs-ui/i18n/eo.json [deleted file]
resources/oojs-ui/i18n/es.json [deleted file]
resources/oojs-ui/i18n/et.json [deleted file]
resources/oojs-ui/i18n/eu.json [deleted file]
resources/oojs-ui/i18n/fa.json [deleted file]
resources/oojs-ui/i18n/fi.json [deleted file]
resources/oojs-ui/i18n/fo.json [deleted file]
resources/oojs-ui/i18n/fr.json [deleted file]
resources/oojs-ui/i18n/frr.json [deleted file]
resources/oojs-ui/i18n/fur.json [deleted file]
resources/oojs-ui/i18n/gl.json [deleted file]
resources/oojs-ui/i18n/gu.json [deleted file]
resources/oojs-ui/i18n/he.json [deleted file]
resources/oojs-ui/i18n/hi.json [deleted file]
resources/oojs-ui/i18n/hr.json [deleted file]
resources/oojs-ui/i18n/hsb.json [deleted file]
resources/oojs-ui/i18n/hu.json [deleted file]
resources/oojs-ui/i18n/hy.json [deleted file]
resources/oojs-ui/i18n/ia.json [deleted file]
resources/oojs-ui/i18n/id.json [deleted file]
resources/oojs-ui/i18n/ie.json [deleted file]
resources/oojs-ui/i18n/ilo.json [deleted file]
resources/oojs-ui/i18n/is.json [deleted file]
resources/oojs-ui/i18n/it.json [deleted file]
resources/oojs-ui/i18n/ja.json [deleted file]
resources/oojs-ui/i18n/jv.json [deleted file]
resources/oojs-ui/i18n/ka.json [deleted file]
resources/oojs-ui/i18n/kk-cyrl.json [deleted file]
resources/oojs-ui/i18n/km.json [deleted file]
resources/oojs-ui/i18n/kn.json [deleted file]
resources/oojs-ui/i18n/ko.json [deleted file]
resources/oojs-ui/i18n/krc.json [deleted file]
resources/oojs-ui/i18n/kw.json [deleted file]
resources/oojs-ui/i18n/ky.json [deleted file]
resources/oojs-ui/i18n/lb.json [deleted file]
resources/oojs-ui/i18n/lmo.json [deleted file]
resources/oojs-ui/i18n/lt.json [deleted file]
resources/oojs-ui/i18n/lv.json [deleted file]
resources/oojs-ui/i18n/mg.json [deleted file]
resources/oojs-ui/i18n/min.json [deleted file]
resources/oojs-ui/i18n/mk.json [deleted file]
resources/oojs-ui/i18n/ml.json [deleted file]
resources/oojs-ui/i18n/mr.json [deleted file]
resources/oojs-ui/i18n/ms.json [deleted file]
resources/oojs-ui/i18n/nap.json [deleted file]
resources/oojs-ui/i18n/nb.json [deleted file]
resources/oojs-ui/i18n/nds-nl.json [deleted file]
resources/oojs-ui/i18n/nds.json [deleted file]
resources/oojs-ui/i18n/ne.json [deleted file]
resources/oojs-ui/i18n/nl.json [deleted file]
resources/oojs-ui/i18n/nn.json [deleted file]
resources/oojs-ui/i18n/om.json [deleted file]
resources/oojs-ui/i18n/or.json [deleted file]
resources/oojs-ui/i18n/pa.json [deleted file]
resources/oojs-ui/i18n/pfl.json [deleted file]
resources/oojs-ui/i18n/pl.json [deleted file]
resources/oojs-ui/i18n/pms.json [deleted file]
resources/oojs-ui/i18n/ps.json [deleted file]
resources/oojs-ui/i18n/pt-br.json [deleted file]
resources/oojs-ui/i18n/pt.json [deleted file]
resources/oojs-ui/i18n/qqq.json [deleted file]
resources/oojs-ui/i18n/qu.json [deleted file]
resources/oojs-ui/i18n/ro.json [deleted file]
resources/oojs-ui/i18n/roa-tara.json [deleted file]
resources/oojs-ui/i18n/ru.json [deleted file]
resources/oojs-ui/i18n/sah.json [deleted file]
resources/oojs-ui/i18n/scn.json [deleted file]
resources/oojs-ui/i18n/sco.json [deleted file]
resources/oojs-ui/i18n/sh.json [deleted file]
resources/oojs-ui/i18n/si.json [deleted file]
resources/oojs-ui/i18n/sk.json [deleted file]
resources/oojs-ui/i18n/sl.json [deleted file]
resources/oojs-ui/i18n/sq.json [deleted file]
resources/oojs-ui/i18n/sr-ec.json [deleted file]
resources/oojs-ui/i18n/sv.json [deleted file]
resources/oojs-ui/i18n/sw.json [deleted file]
resources/oojs-ui/i18n/ta.json [deleted file]
resources/oojs-ui/i18n/te.json [deleted file]
resources/oojs-ui/i18n/th.json [deleted file]
resources/oojs-ui/i18n/tl.json [deleted file]
resources/oojs-ui/i18n/tr.json [deleted file]
resources/oojs-ui/i18n/tt-cyrl.json [deleted file]
resources/oojs-ui/i18n/ug-arab.json [deleted file]
resources/oojs-ui/i18n/uk.json [deleted file]
resources/oojs-ui/i18n/uz.json [deleted file]
resources/oojs-ui/i18n/vec.json [deleted file]
resources/oojs-ui/i18n/vi.json [deleted file]
resources/oojs-ui/i18n/vo.json [deleted file]
resources/oojs-ui/i18n/wuu.json [deleted file]
resources/oojs-ui/i18n/yi.json [deleted file]
resources/oojs-ui/i18n/yo.json [deleted file]
resources/oojs-ui/i18n/zh-hans.json [deleted file]
resources/oojs-ui/i18n/zh-hant.json [deleted file]
resources/oojs-ui/i18n/zh-hk.json [deleted file]
resources/oojs-ui/i18n/zh-tw.json [deleted file]
resources/oojs-ui/images/fade-down.png [deleted file]
resources/oojs-ui/images/fade-up.png [deleted file]
resources/oojs-ui/images/icons/accept.png [deleted file]
resources/oojs-ui/images/icons/accept.svg [deleted file]
resources/oojs-ui/images/icons/add-item.png [deleted file]
resources/oojs-ui/images/icons/add-item.svg [deleted file]
resources/oojs-ui/images/icons/advanced.png [deleted file]
resources/oojs-ui/images/icons/advanced.svg [deleted file]
resources/oojs-ui/images/icons/alert.png [deleted file]
resources/oojs-ui/images/icons/alert.svg [deleted file]
resources/oojs-ui/images/icons/arched-arrow-ltr.png [deleted file]
resources/oojs-ui/images/icons/arched-arrow-ltr.svg [deleted file]
resources/oojs-ui/images/icons/arched-arrow-rtl.png [deleted file]
resources/oojs-ui/images/icons/arched-arrow-rtl.svg [deleted file]
resources/oojs-ui/images/icons/check.png [deleted file]
resources/oojs-ui/images/icons/check.svg [deleted file]
resources/oojs-ui/images/icons/clear.png [deleted file]
resources/oojs-ui/images/icons/clear.svg [deleted file]
resources/oojs-ui/images/icons/close.png [deleted file]
resources/oojs-ui/images/icons/close.svg [deleted file]
resources/oojs-ui/images/icons/code.png [deleted file]
resources/oojs-ui/images/icons/code.svg [deleted file]
resources/oojs-ui/images/icons/collapse.png [deleted file]
resources/oojs-ui/images/icons/collapse.svg [deleted file]
resources/oojs-ui/images/icons/comment.png [deleted file]
resources/oojs-ui/images/icons/comment.svg [deleted file]
resources/oojs-ui/images/icons/expand.png [deleted file]
resources/oojs-ui/images/icons/expand.svg [deleted file]
resources/oojs-ui/images/icons/help.png [deleted file]
resources/oojs-ui/images/icons/help.svg [deleted file]
resources/oojs-ui/images/icons/history.png [deleted file]
resources/oojs-ui/images/icons/history.svg [deleted file]
resources/oojs-ui/images/icons/link.png [deleted file]
resources/oojs-ui/images/icons/link.svg [deleted file]
resources/oojs-ui/images/icons/menu.png [deleted file]
resources/oojs-ui/images/icons/menu.svg [deleted file]
resources/oojs-ui/images/icons/move-ltr.png [deleted file]
resources/oojs-ui/images/icons/move-ltr.svg [deleted file]
resources/oojs-ui/images/icons/move-rtl.png [deleted file]
resources/oojs-ui/images/icons/move-rtl.svg [deleted file]
resources/oojs-ui/images/icons/picture.png [deleted file]
resources/oojs-ui/images/icons/picture.svg [deleted file]
resources/oojs-ui/images/icons/remove-item.png [deleted file]
resources/oojs-ui/images/icons/remove-item.svg [deleted file]
resources/oojs-ui/images/icons/remove.png [deleted file]
resources/oojs-ui/images/icons/remove.svg [deleted file]
resources/oojs-ui/images/icons/search.png [deleted file]
resources/oojs-ui/images/icons/search.svg [deleted file]
resources/oojs-ui/images/icons/settings.png [deleted file]
resources/oojs-ui/images/icons/settings.svg [deleted file]
resources/oojs-ui/images/icons/tag.png [deleted file]
resources/oojs-ui/images/icons/tag.svg [deleted file]
resources/oojs-ui/images/icons/window.png [deleted file]
resources/oojs-ui/images/icons/window.svg [deleted file]
resources/oojs-ui/images/indicators/down.png [deleted file]
resources/oojs-ui/images/indicators/down.svg [deleted file]
resources/oojs-ui/images/indicators/required.png [deleted file]
resources/oojs-ui/images/indicators/required.svg [deleted file]
resources/oojs-ui/images/indicators/up.png [deleted file]
resources/oojs-ui/images/indicators/up.svg [deleted file]
resources/oojs-ui/images/tail.svg [deleted file]
resources/oojs-ui/images/textures/pending.gif [deleted file]
resources/oojs-ui/images/textures/transparency.png [deleted file]
resources/oojs-ui/images/toolbar-shadow.png [deleted file]
resources/oojs-ui/oojs-ui-agora.css [deleted file]
resources/oojs-ui/oojs-ui-apex.css [deleted file]
resources/oojs-ui/oojs-ui.js [deleted file]
resources/oojs-ui/oojs-ui.svg.css [deleted file]
resources/oojs-ui/update-oojs-ui.sh [deleted file]
resources/oojs/oojs.js [deleted file]
resources/oojs/update-oojs.sh [deleted file]
resources/package.json [deleted file]
resources/scripts/nodecheck.sh [deleted file]
resources/sinonjs/sinon-1.9.0.js [deleted file]
resources/sinonjs/sinon-ie-1.9.0.js [deleted file]
resources/src/jquery.tipsy/images/tipsy.png [new file with mode: 0644]
resources/src/jquery.tipsy/jquery.tipsy.css [new file with mode: 0644]
resources/src/jquery.tipsy/jquery.tipsy.js [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/close.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/titlebar-fade.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-anim_basic_16x16.gif [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-bg_flat_70_000000_40x100.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-icons_2694e8_256x240.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-icons_2e83ff_256x240.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-icons_3d80b3_256x240.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-icons_666666_256x240.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-icons_72a7cf_256x240.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/images/ui-icons_ffffff_256x240.png [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.accordion.css [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.autocomplete.css [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.button.css [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.core.css [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.datepicker.css [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.dialog.css [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.progressbar.css [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.resizable.css [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.selectable.css [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.slider.css [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.tabs.css [new file with mode: 0644]
resources/src/jquery.ui-themes/vector/jquery.ui.theme.css [new file with mode: 0644]
resources/src/jquery/images/jquery.arrowSteps.divider-ltr.png [new file with mode: 0644]
resources/src/jquery/images/jquery.arrowSteps.divider-rtl.png [new file with mode: 0644]
resources/src/jquery/images/jquery.arrowSteps.head-ltr.png [new file with mode: 0644]
resources/src/jquery/images/jquery.arrowSteps.head-rtl.png [new file with mode: 0644]
resources/src/jquery/images/jquery.arrowSteps.tail-ltr.png [new file with mode: 0644]
resources/src/jquery/images/jquery.arrowSteps.tail-rtl.png [new file with mode: 0644]
resources/src/jquery/images/marker.png [new file with mode: 0644]
resources/src/jquery/images/mask.png [new file with mode: 0644]
resources/src/jquery/images/sort_both.gif [new file with mode: 0644]
resources/src/jquery/images/sort_down.gif [new file with mode: 0644]
resources/src/jquery/images/sort_none.gif [new file with mode: 0644]
resources/src/jquery/images/sort_up.gif [new file with mode: 0644]
resources/src/jquery/images/spinner-large.gif [new file with mode: 0644]
resources/src/jquery/images/spinner.gif [new file with mode: 0644]
resources/src/jquery/images/wheel.png [new file with mode: 0644]
resources/src/jquery/jquery.arrowSteps.css [new file with mode: 0644]
resources/src/jquery/jquery.arrowSteps.js [new file with mode: 0644]
resources/src/jquery/jquery.autoEllipsis.js [new file with mode: 0644]
resources/src/jquery/jquery.badge.css [new file with mode: 0644]
resources/src/jquery/jquery.badge.js [new file with mode: 0644]
resources/src/jquery/jquery.byteLength.js [new file with mode: 0644]
resources/src/jquery/jquery.byteLimit.js [new file with mode: 0644]
resources/src/jquery/jquery.checkboxShiftClick.js [new file with mode: 0644]
resources/src/jquery/jquery.client.js [new file with mode: 0644]
resources/src/jquery/jquery.color.js [new file with mode: 0644]
resources/src/jquery/jquery.colorUtil.js [new file with mode: 0644]
resources/src/jquery/jquery.delayedBind.js [new file with mode: 0644]
resources/src/jquery/jquery.expandableField.js [new file with mode: 0644]
resources/src/jquery/jquery.farbtastic.css [new file with mode: 0644]
resources/src/jquery/jquery.farbtastic.js [new file with mode: 0644]
resources/src/jquery/jquery.footHovzer.css [new file with mode: 0644]
resources/src/jquery/jquery.footHovzer.js [new file with mode: 0644]
resources/src/jquery/jquery.getAttrs.js [new file with mode: 0644]
resources/src/jquery/jquery.hidpi.js [new file with mode: 0644]
resources/src/jquery/jquery.highlightText.js [new file with mode: 0644]
resources/src/jquery/jquery.localize.js [new file with mode: 0644]
resources/src/jquery/jquery.makeCollapsible.css [new file with mode: 0644]
resources/src/jquery/jquery.makeCollapsible.js [new file with mode: 0644]
resources/src/jquery/jquery.mw-jump.js [new file with mode: 0644]
resources/src/jquery/jquery.mwExtension.js [new file with mode: 0644]
resources/src/jquery/jquery.placeholder.js [new file with mode: 0644]
resources/src/jquery/jquery.qunit.completenessTest.js [new file with mode: 0644]
resources/src/jquery/jquery.spinner.css [new file with mode: 0644]
resources/src/jquery/jquery.spinner.js [new file with mode: 0644]
resources/src/jquery/jquery.suggestions.css [new file with mode: 0644]
resources/src/jquery/jquery.suggestions.js [new file with mode: 0644]
resources/src/jquery/jquery.tabIndex.js [new file with mode: 0644]
resources/src/jquery/jquery.tablesorter.css [new file with mode: 0644]
resources/src/jquery/jquery.tablesorter.js [new file with mode: 0644]
resources/src/jquery/jquery.textSelection.js [new file with mode: 0644]
resources/src/mediawiki.action/images/green-checkmark.png [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.js [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.preview.js [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.edit.styles.css [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.history.diff.css [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.history.js [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.view.dblClickEdit.js [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.view.metadata.js [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.view.postEdit.css [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.view.postEdit.js [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.view.redirectToFragment.js [new file with mode: 0644]
resources/src/mediawiki.action/mediawiki.action.view.rightClickEdit.js [new file with mode: 0644]
resources/src/mediawiki.api/mediawiki.api.category.js [new file with mode: 0644]
resources/src/mediawiki.api/mediawiki.api.edit.js [new file with mode: 0644]
resources/src/mediawiki.api/mediawiki.api.js [new file with mode: 0644]
resources/src/mediawiki.api/mediawiki.api.login.js [new file with mode: 0644]
resources/src/mediawiki.api/mediawiki.api.parse.js [new file with mode: 0644]
resources/src/mediawiki.api/mediawiki.api.watch.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/bs.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/dsb.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/fi.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/ga.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/he.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/hsb.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/hu.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/hy.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/la.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/os.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/ru.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/sl.js [new file with mode: 0644]
resources/src/mediawiki.language/languages/uk.js [new file with mode: 0644]
resources/src/mediawiki.language/mediawiki.cldr.js [new file with mode: 0644]
resources/src/mediawiki.language/mediawiki.language.init.js [new file with mode: 0644]
resources/src/mediawiki.language/mediawiki.language.js [new file with mode: 0644]
resources/src/mediawiki.language/mediawiki.language.months.js [new file with mode: 0644]
resources/src/mediawiki.language/mediawiki.language.numbers.js [new file with mode: 0644]
resources/src/mediawiki.less/mediawiki.mixins.animation.less [new file with mode: 0644]
resources/src/mediawiki.less/mediawiki.mixins.less [new file with mode: 0644]
resources/src/mediawiki.less/mediawiki.mixins.rotation.less [new file with mode: 0644]
resources/src/mediawiki.libs/CLDRPluralRuleParser.js [new file with mode: 0644]
resources/src/mediawiki.libs/mediawiki.libs.jpegmeta.js [new file with mode: 0644]
resources/src/mediawiki.page/mediawiki.page.gallery.js [new file with mode: 0644]
resources/src/mediawiki.page/mediawiki.page.image.pagination.js [new file with mode: 0644]
resources/src/mediawiki.page/mediawiki.page.patrol.ajax.js [new file with mode: 0644]
resources/src/mediawiki.page/mediawiki.page.ready.js [new file with mode: 0644]
resources/src/mediawiki.page/mediawiki.page.startup.js [new file with mode: 0644]
resources/src/mediawiki.page/mediawiki.page.watch.ajax.js [new file with mode: 0644]
resources/src/mediawiki.special/images/glyph-people-large.png [new file with mode: 0644]
resources/src/mediawiki.special/images/icon-contributors.png [new file with mode: 0644]
resources/src/mediawiki.special/images/icon-edits.png [new file with mode: 0644]
resources/src/mediawiki.special/images/icon-lock.png [new file with mode: 0644]
resources/src/mediawiki.special/images/icon-pages.png [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.block.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.block.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.changeemail.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.changeemail.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.changeslist.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.changeslist.legend.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.javaScriptTest.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.movePage.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.preferences.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.preferences.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.recentchanges.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.search.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.search.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.undelete.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.upload.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.userlogin.common.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.userlogin.common.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.userlogin.login.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.version.css [new file with mode: 0644]
resources/src/mediawiki.ui/components/default/buttons.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/default/forms.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/utilities.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/vector/buttons.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/vector/containers.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/vector/forms.less [new file with mode: 0644]
resources/src/mediawiki.ui/default.less [new file with mode: 0644]
resources/src/mediawiki.ui/mixins/effects.less [new file with mode: 0644]
resources/src/mediawiki.ui/mixins/forms.less [new file with mode: 0644]
resources/src/mediawiki.ui/mixins/type.less [new file with mode: 0644]
resources/src/mediawiki.ui/mixins/utilities.less [new file with mode: 0644]
resources/src/mediawiki.ui/settings/colors.less [new file with mode: 0644]
resources/src/mediawiki.ui/settings/typography.less [new file with mode: 0644]
resources/src/mediawiki.ui/styleguide.md [new file with mode: 0644]
resources/src/mediawiki.ui/vector.less [new file with mode: 0644]
resources/src/mediawiki/images/arrow-collapsed-ltr.png [new file with mode: 0644]
resources/src/mediawiki/images/arrow-collapsed-ltr.svg [new file with mode: 0644]
resources/src/mediawiki/images/arrow-collapsed-rtl.png [new file with mode: 0644]
resources/src/mediawiki/images/arrow-collapsed-rtl.svg [new file with mode: 0644]
resources/src/mediawiki/images/arrow-expanded.png [new file with mode: 0644]
resources/src/mediawiki/images/arrow-expanded.svg [new file with mode: 0644]
resources/src/mediawiki/mediawiki.Title.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.Uri.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.debug.init.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.debug.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.debug.less [new file with mode: 0644]
resources/src/mediawiki/mediawiki.debug.profile.css [new file with mode: 0644]
resources/src/mediawiki/mediawiki.debug.profile.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.feedback.css [new file with mode: 0644]
resources/src/mediawiki/mediawiki.feedback.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.feedback.spinner.gif [new file with mode: 0644]
resources/src/mediawiki/mediawiki.hidpi.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.hlist.css [new file with mode: 0644]
resources/src/mediawiki/mediawiki.hlist.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.htmlform.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.icon.less [new file with mode: 0644]
resources/src/mediawiki/mediawiki.inspect.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.jqueryMsg.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.jqueryMsg.peg [new file with mode: 0644]
resources/src/mediawiki/mediawiki.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.log.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.notification.css [new file with mode: 0644]
resources/src/mediawiki/mediawiki.notification.hideForPrint.css [new file with mode: 0644]
resources/src/mediawiki/mediawiki.notification.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.notify.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.searchSuggest.css [new file with mode: 0644]
resources/src/mediawiki/mediawiki.searchSuggest.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.toc.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.user.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.util.js [new file with mode: 0644]
resources/src/startup.js [new file with mode: 0644]
resources/startup.js [deleted file]
resources/styleguide-template/index.html [deleted file]
resources/styleguide-template/public/kss.less [deleted file]
resources/styleguide-template/public/less.js [deleted file]
skins/common/commonElements.css
skins/common/images/button_math.png [deleted file]
skins/common/images/feed-icon.svg
skins/common/images/question.svg
skins/common/shared.css
skins/common/wikibits.js
skins/vector/components/externalLinks.less
skins/vector/images/arrow-collapsed-ltr.svg
skins/vector/images/arrow-collapsed-rtl.svg
skins/vector/images/arrow-down-focus-icon.svg
skins/vector/images/arrow-down-icon.svg
skins/vector/images/arrow-expanded.svg
skins/vector/images/audio-icon.png [deleted file]
skins/vector/images/audio-icon.svg [deleted file]
skins/vector/images/document-icon.png [deleted file]
skins/vector/images/document-icon.svg [deleted file]
skins/vector/images/external-link-ltr-icon.svg
skins/vector/images/external-link-rtl-icon.svg
skins/vector/images/file-icon.png [deleted file]
skins/vector/images/file-icon.svg [deleted file]
skins/vector/images/lock-icon.png [deleted file]
skins/vector/images/lock-icon.svg [deleted file]
skins/vector/images/mail-icon.png [deleted file]
skins/vector/images/mail-icon.svg [deleted file]
skins/vector/images/news-icon.png [deleted file]
skins/vector/images/news-icon.svg [deleted file]
skins/vector/images/search-ltr.svg
skins/vector/images/search-rtl.svg
skins/vector/images/talk-icon.png [deleted file]
skins/vector/images/talk-icon.svg [deleted file]
skins/vector/images/unwatch-icon-hl.svg
skins/vector/images/unwatch-icon.svg
skins/vector/images/user-icon.svg
skins/vector/images/video-icon.png [deleted file]
skins/vector/images/video-icon.svg [deleted file]
skins/vector/images/watch-icon-hl.svg
skins/vector/images/watch-icon-loading.svg
skins/vector/images/watch-icon.svg
skins/vector/variables.less
tests/phpunit/MediaWikiPHPUnitTestListener.php
tests/phpunit/includes/TitleTest.php
tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php [new file with mode: 0644]
tests/phpunit/includes/title/MediaWikiTitleCodecTest.php [new file with mode: 0644]
tests/phpunit/includes/title/TitleValueTest.php [new file with mode: 0644]
tests/phpunit/includes/utils/UIDGeneratorTest.php
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.test.js

index 627f7ab..494890c 100644 (file)
@@ -1,39 +1,13 @@
 # Generated documentation
-docs/html/**
-docs/js/**
-resources/mediawiki.ui/docs/**
-
-# kss template for mediawiki ui documentation
-resources/styleguide-template/**
+docs/**
 
 # third-party libs
 extensions/**
 node_modules/**
-resources/jquery/jquery.appear.js
-resources/jquery/jquery.async.js
-resources/jquery/jquery.ba-throttle-debounce.js
-resources/jquery/jquery.cookie.js
-resources/jquery/jquery.cycle.all.js
-resources/jquery/jquery.farbtastic.js
-resources/jquery/jquery.form.js
-resources/jquery/jquery.fullscreen.js
-resources/jquery/jquery.hoverIntent.js
-resources/jquery/jquery.js
-resources/jquery/jquery.json.js
-resources/jquery/jquery.jStorage.js
-resources/jquery/jquery.mockjax.js
-resources/jquery/jquery.qunit.js
-resources/jquery/jquery.validate.js
-resources/jquery/jquery.xmldom.js
-resources/jquery.chosen/chosen.jquery.js
-resources/jquery.effects/**
-resources/jquery.tipsy/**
-resources/jquery.ui/**
-resources/mediawiki.libs/**
-resources/moment/**
-resources/oojs-ui/**
-resources/oojs/**
-resources/sinonjs/**
+resources/lib/**
+resources/src/jquery.tipsy/**
+resources/src/jquery/jquery.farbtastic.js
+resources/src/mediawiki.libs/**
 tests/frontend/node_modules/**
 
 # github.com/jshint/jshint/issues/729
index d430a4d..c231db6 100644 (file)
@@ -240,6 +240,8 @@ production.
 * (bug 42026) Deprecated uctoponly in favor of ucshow=top.
 * list=search no longer has a "srredirects" parameter. Redirects are now
   included in all searches.
+* Added list=prefixsearch that works like action=opensearch but can be used as
+  a generator.
 
 === Languages updated in 1.23 ===
 
@@ -326,6 +328,9 @@ changes to languages because of Bugzilla reports.
 * Special:Search no longer has an "include redirects" option on the advanced
   tab. Redirects are now included in all searches.
 * mediawiki.api.category's getCategories() 'async' parameter was deprecated.
+* The locations of resources have been split between upstream libraries, now in
+  resources/lib/, local libaries in resources/src/, and local forks of upstream
+  libraries, also in resources/src/.
 
 ==== Removed classes ====
 * FakeMemCachedClient (deprecated in 1.18)
diff --git a/docs/kss/Makefile b/docs/kss/Makefile
new file mode 100644 (file)
index 0000000..1b7aeb1
--- /dev/null
@@ -0,0 +1,19 @@
+MEDIAWIKI_LOAD_URL ?= http://localhost/w/load.php
+
+kss: nodecheck
+# FIXME: Use more up-to-date Ruby version
+
+# Generates CSS of mediawiki.ui and mediawiki.ui.button using ResourceLoader, then applies it to the
+# KSS style guide
+       $(eval KSS_RL_TMP := $(shell mktemp /tmp/tmp.XXXXXXXXXX))
+       @curl -sG "${MEDIAWIKI_LOAD_URL}?modules=mediawiki.ui|mediawiki.ui.button&only=styles" > $(KSS_RL_TMP)
+       @node_modules/.bin/kss-node mediawiki.ui mediawiki.ui/docs --css $(KSS_RL_TMP) -t styleguide-template
+       @rm $(KSS_RL_TMP)
+
+kssopen: kss
+       @echo Opening the generated style guide...
+       @command -v xdg-open >/dev/null 2>&1 || { open ${PWD}/mediawiki.ui/docs/index.html; exit 0; }
+       @xdg-open ${PWD}/mediawiki.ui/docs/index.html
+
+nodecheck:
+       @scripts/nodecheck.sh
diff --git a/docs/kss/README.txt b/docs/kss/README.txt
new file mode 100644 (file)
index 0000000..d91bf2a
--- /dev/null
@@ -0,0 +1,4 @@
+The Makefile, package.json, scripts, styleguide-template, and
+mediawiki.ui/styleguide.md files and directories in here support the automatic
+generation of CSS documentation from the source LESS files using kss for
+node.js, https://github.com/kneath/kss
diff --git a/docs/kss/package.json b/docs/kss/package.json
new file mode 100644 (file)
index 0000000..a1722b5
--- /dev/null
@@ -0,0 +1,13 @@
+{
+       "name": "mediawiki-ui-dependencies",
+       "description": "Node.js dependencies used for KSS generation",
+       "version": "0.0.1",
+       "dependencies": {
+               "kss": ">=0.3.6"
+       },
+       "repository" : {
+               "type" : "git",
+               "url" : "https://gerrit.wikimedia.org/r/p/mediawiki/core.git"
+       }
+
+}
diff --git a/docs/kss/scripts/nodecheck.sh b/docs/kss/scripts/nodecheck.sh
new file mode 100755 (executable)
index 0000000..3ee0f83
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+if command -v npm > /dev/null ; then
+  npm install
+else
+  echo "You need to install Node.JS!"
+  echo "See http://nodejs.org/"
+  exit 1
+fi
diff --git a/docs/kss/styleguide-template/index.html b/docs/kss/styleguide-template/index.html
new file mode 100644 (file)
index 0000000..99f3e4f
--- /dev/null
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html class="no-js" lang="en">
+<head>
+       <meta charset="utf-8">
+       <title>MediaWiki Living Styleguide</title>
+       <meta name="description" content="">
+       <meta name="generator" content="kss-node" />
+       <meta name="viewport" content="width=device-width">
+       <link rel="stylesheet" href="public/kss.css">
+       <link rel="stylesheet" href="public/style.css">
+</head>
+<body><div id="kss-wrapper">
+       <header id="kss-header">
+               <hgroup><h1>MediaWiki Living Styleguide</h1></hgroup>
+       </header>
+       <nav class="content">
+               <ul>
+               <li><a href="index.html">0.0: Overview</a></li>
+               {{#eachRoot}}
+               <li>
+                       <a href="section-{{reference}}.html">{{reference}}.0: {{header}}</a>
+               </li>
+               {{/eachRoot}}
+               </ul>
+       </nav>
+       <article>
+               {{#if overview}}
+                       {{html overview}}
+               {{else}}
+                       {{#eachSection rootNumber}}
+                               {{#whenDepth 1}}
+                                       <h1>{{ reference }}.0 - {{ header }}</h1>
+                               {{else}}
+                                       {{#whenDepth 2}}
+                                       <h2>{{ reference }} - {{ header }}</h2>
+                                       {{/whenDepth}}
+                                       {{#whenDepth 3}}
+                                       <h3>{{ reference }} - {{ header }}</h3>
+                                       {{/whenDepth}}
+                               {{/whenDepth}}
+                               {{#ifAny markup modifiers}}
+                                               <div>{{html description}}</div>
+                                               <strong>Default styling</strong><br>
+                                               {{modifierMarkup}}
+                                               {{#eachModifier}}
+                                               {{html description}}<br>
+                                               <p>{{name}}</p>
+                                               {{modifierMarkup}}
+                                               {{/eachModifier}}
+                                               <pre class="prettyprint lang-html">{{markup}}</pre>
+                               {{else}}
+                                               {{#if description}}
+                                                       {{html description}}
+                                               {{/if}}
+                               {{/ifAny}}
+                       {{/eachSection}}
+               {{/if}}
+       </article>
+</div></body>
+</html>
diff --git a/docs/kss/styleguide-template/public/kss.less b/docs/kss/styleguide-template/public/kss.less
new file mode 100644 (file)
index 0000000..431303d
--- /dev/null
@@ -0,0 +1,24 @@
+header {
+       padding: .8em 16px 0;
+}
+
+nav {
+       float: left;
+       width: 200px;
+}
+
+article {
+       margin-left: 250px;
+}
+
+.content.kss-no-margin {
+       margin: 0;
+}
+
+// FIXME: Remove when typography module in mediawiki-ui
+body {
+       font-family: "Nimbus Sans L", "Liberation Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
+}
+h1,h2,h3,h4,h5 {
+       font-family: "DejaVu Serif", Georgia, serif;
+}
diff --git a/docs/kss/styleguide-template/public/less.js b/docs/kss/styleguide-template/public/less.js
new file mode 100644 (file)
index 0000000..89b7637
--- /dev/null
@@ -0,0 +1,9 @@
+//
+// LESS - Leaner CSS v1.2.1
+// http://lesscss.org
+// 
+// Copyright (c) 2009-2011, Alexis Sellier
+// Licensed under the Apache 2.0 License.
+//
+(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b<a.length;b++)a[b].type.match(k)&&(new d.Parser).parse(a[b].innerHTML||"",function(c,d){var e=d.toCSS(),f=a[b];f.type="text/css",f.styleSheet?f.styleSheet.cssText=e:f.innerHTML=e})}function n(a,b){for(var c=0;c<d.sheets.length;c++)o(d.sheets[c],a,b,d.sheets.length-(c+1))}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i);var m=i.match(/([^\/]+)$/)[1];s(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())r(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type,filename:m})).parse(a,function(d,e){if(d)return w(d,i);try{c(d,e,a,b,{local:!1,lastModified:g,remaining:f}),u(document.getElementById("less-error-message:"+q(i)))}catch(d){w(d,i)}})}catch(h){w(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function q(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function r(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||q(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e='<li><label>{line}</label><pre class="{class}">{content}</pre></li>',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="<h3>"+(a.message||"There is an error in your .less file")+"</h3>"+'<p>in <a href="'+j+'">'+j+"</a> ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="<br/>"+a.stack.split("\n").slice(1).join("<br/>"):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":</p>"+"<ul>"+i.join("")+"</ul>"),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d<c;d++)d in this&&a.call(b,this[d],d,this)}),Array.prototype.map||(Array.prototype.map=function(a){var b=this.length>>>0,c=new Array(b),d=arguments[1];for(var e=0;e<b;e++)e in this&&(c[e]=a.call(d,this[e],e,this));return c}),Array.prototype.filter||(Array.prototype.filter=function(a){var b=[],c=arguments[1];for(var d=0;d<this.length;d++)a.call(c,this[d])&&b.push(this[d]);return b}),Array.prototype.reduce||(Array.prototype.reduce=function(a){var b=this.length>>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c<b;c++)c in this&&(d=a.call(null,d,this[c],c,this));return d}),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){var b=this.length,c=arguments[1]||0;if(!b)return-1;if(c>=b)return-1;c<0&&(c+=b);for(;c<b;c++){if(!Object.prototype.hasOwnProperty.call(this,c))continue;if(a===this[c])return c}return-1}),Object.keys||(Object.keys=function(a){var b=[];for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&b.push(c);return b}),String.prototype.trim||(String.prototype.trim=function(){return String(this).replace(/^\s\s*/,"").replace(/\s\s*$/,"")});var d,f;typeof environment=="object"&&{}.toString.call(environment)==="[object Environment]"?(typeof a=="undefined"?d={}:d=a.less={},f=d.tree={},d.mode="rhino"):typeof a=="undefined"?(d=exports,f=c("./tree"),d.mode="node"):(typeof a.less=="undefined"&&(a.less={}),d=a.less,f=a.less.tree={},d.mode="browser"),d.Parser=function(b){function t(){j=m[i],k=h,n=h}function u(){m[i]=j,h=k,n=h}function v(){h>n&&(m[i]=m[i].slice(h-n),n=h)}function w(a){var b,c,d,e,f,j,k,l;if(a instanceof Function)return a.call(o.parsers);if(typeof a=="string")b=g.charAt(h)===a?a:null,d=1,v();else{v();if(!(b=a.exec(m[i])))return null;d=b[0].length}if(b){l=h+=d,j=h+m[i].length-d;while(h<j){e=g.charCodeAt(h);if(e!==32&&e!==10&&e!==9)break;h++}return m[i]=m[i].slice(d+(h-l)),n=h,m[i].length===0&&i<m.length-1&&i++,typeof b=="string"?b:b.length===1?b[0]:b}}function x(a,b){var c=w(a);if(!!c)return c;y(b||(typeof a=="string"?"expected '"+a+"' got '"+g.charAt(h)+"'":"unexpected token"))}function y(a,b){throw{index:h,type:b||"Syntax",message:a}}function z(a){return typeof a=="string"?g.charAt(h)===a:a.test(m[i])?!0:!1}function A(a,b){return a.filename&&b.filename&&a.filename!==b.filename?o.imports.contents[a.filename]:g}function B(a,b){for(var c=a,d=-1;c>=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function C(a,b){var c=A(a,b),d=B(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&B(a.call,c)+1,this.callExtract=g[B(a.call,c)],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var g,h,i,j,k,l,m,n,o,q=this,r=function(){},s=this.imports={paths:b&&b.paths||[],queue:[],files:{},contents:{},mime:b&&b.mime,error:null,push:function(a,c){var e=this;this.queue.push(a),d.Parser.importer(a,this.paths,function(b,d,f){e.queue.splice(e.queue.indexOf(a),1),e.files[a]=d,e.contents[a]=f,b&&!e.error&&(e.error=b),c(b,d),e.queue.length===0&&r()},b)}};return this.env=b=b||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,o={imports:s,parse:function(a,e){var j,k,p,q,s,t,u=[],v,x=null;h=i=n=l=0,m=[],g=a.replace(/\r\n/g,"\n"),m=function(a){var c=0,d=/[^"'`\{\}\/\(\)]+/g,e=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,f=0,h,i=a[0],j,k;for(var l=0,m,n;l<g.length;l++){d.lastIndex=l,(h=d.exec(g))&&h.index===l&&(l+=h[0].length,i.push(h[0])),m=g.charAt(l),e.lastIndex=l,!k&&!j&&m==="/"&&(n=g.charAt(l+1),(n==="/"||n==="*")&&(h=e.exec(g))&&h.index===l&&(l+=h[0].length,i.push(h[0]),m=g.charAt(l)));if(m==="{"&&!k&&!j)f++,i.push(m);else if(m==="}"&&!k&&!j)f--,i.push(m),a[++c]=i=[];else if(m==="("&&!k&&!j)i.push(m),j=!0;else if(m===")"&&!k&&j)i.push(m),j=!1;else{if(m==='"'||m==="'"||m==="`")k?k=k===m?!1:k:k=m;i.push(m)}}if(f>0)throw{type:"Syntax",message:"Missing closing `}`",filename:b.filename};return a.map(function(a){return a.join("")})}([[]]);try{j=new f.Ruleset([],w(this.parsers.primary)),j.root=!0}catch(y){return e(new C(y,b))}j.toCSS=function(a){var e,g,h;return function(e,g){var h=[],i;e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var j=a.call(this,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(k){throw new C(k,b)}if(i=o.imports.error)throw i instanceof C?i:new C(i,b);return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):e.compress?j.replace(/(\s)+/g,"$1"):j}}(j.eval);if(h<g.length-1){h=l,t=g.split("\n"),s=(g.slice(0,h).match(/\n/g)||"").length+1;for(var z=h,A=-1;z>=0&&g.charAt(z)!=="\n";z--)A++;x={type:"Parse",message:"Syntax Error on line "+s,index:h,filename:b.filename,line:s,column:A,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?r=function(){e(x,j)}:e(x,j)},parsers:{primary:function(){var a,b=[];while((a=w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(g.charAt(h)!=="/")return;if(g.charAt(h+1)==="/")return new f.Comment(w(/^\/\/.*/),!0);if(a=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=='"'&&g.charAt(b)!=="'")return;c&&w("~");if(a=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],c)},keyword:function(){var a;if(a=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,c,d=h;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(m[i])))return;a=a[1].toLowerCase();if(a==="url")return null;h+=a.length;if(a==="alpha")return w(this.alpha);w("("),c=w(this.entities.arguments);if(!w(")"))return;if(a)return new f.Call(a,c,d,b.filename)},arguments:function(){var a=[],b;while(b=w(this.entities.assignment)||w(this.expression)){a.push(b);if(!w(","))break}return a},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)},assignment:function(){var a,b;if((a=w(/^\w+(?=\s?=)/i))&&w("=")&&(b=w(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(g.charAt(h)!=="u"||!w(/^url\(/))return;return a=w(this.entities.quoted)||w(this.entities.variable)||w(this.entities.dataURI)||w(/^[-\w%@$\/.&=:;#+?~]+/)||"",x(")"),new f.URL(a.value||a.data||a instanceof f.Variable?a:new f.Anonymous(a),s.paths)},dataURI:function(){var a;if(w(/^data:/)){a={},a.mime=w(/^[^\/]+\/[^,;)]+/)||"",a.charset=w(/^;\s*charset=[^,;)]+/)||"",a.base64=w(/^;\s*base64/)||"",a.data=w(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=h;if(g.charAt(h)==="@"&&(a=w(/^@@?[\w-]+/)))return new f.Variable(a,c,b.filename)},color:function(){var a;if(g.charAt(h)==="#"&&(a=w(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,b=g.charCodeAt(h);if(b>57||b<45||b===47)return;if(a=w(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=="`")return;c&&w("~");if(a=w(/^`([^`]*)`/))return new f.JavaScript(a[1],h,c)}},variable:function(){var a;if(g.charAt(h)==="@"&&(a=w(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!z(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=w(this.entity))&&w("/")&&(b=w(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,i=h,j=g.charAt(h),k=!1;if(j!=="."&&j!=="#")return;while(c=w(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,h)),d=w(">");w("(")&&(e=w(this.entities.arguments))&&w(")"),w(this.important)&&(k=!0);if(a.length>0&&(w(";")||z("}")))return new f.mixin.Call(a,e,i,b.filename,k)},definition:function(){var a,b=[],c,d,e,i,j;if(g.charAt(h)!=="."&&g.charAt(h)!=="#"||z(/^[^{]*(;|})/))return;t();if(c=w(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=c[1];while(e=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)){e instanceof f.Variable?w(":")?(i=x(this.expression,"expected expression"),b.push({name:e.name,value:i})):b.push({name:e.name}):b.push({value:e});if(!w(","))break}x(")"),w(/^when/)&&(j=x(this.conditions,"expected condition")),d=w(this.block);if(d)return new f.mixin.Definition(a,b,d,j);u()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||z("}")},alpha:function(){var a;if(!w(/^\(opacity=/i))return;if(a=w(/^\d+/)||w(this.entities.variable))return x(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=w(this.combinator),a=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||w("*")||w(this.attribute)||w(/^\([^)@]+\)/),a||w("(")&&(d=w(this.entities.variable))&&w(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,h);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,h)},combinator:function(){var a,b=g.charAt(h);if(b===">"||b==="+"||b==="~"){h++;while(g.charAt(h)===" ")h++;return new f.Combinator(b)}if(b==="&"){a="&",h++,g.charAt(h)===" "&&(a="& ");while(g.charAt(h)===" ")h++;return new f.Combinator(a)}if(b===":"&&g.charAt(h+1)===":"){h+=2;while(g.charAt(h)===" ")h++;return new f.Combinator("::")}return g.charAt(h-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,b,c=[],d,e;while(b=w(this.element)){d=g.charAt(h),c.push(b);if(d==="{"||d==="}"||d===";"||d===",")break}if(c.length>0)return new f.Selector(c)},tag:function(){return w(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||w("*")},attribute:function(){var a="",b,c,d;if(!w("["))return;if(b=w(/^[a-zA-Z-]+/)||w(this.entities.quoted))(d=w(/^[|~*$^]?=/))&&(c=w(this.entities.quoted)||w(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!w("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(w("{")&&(a=w(this.primary))&&w("}"))return a},ruleset:function(){var a=[],b,c,d;t();while(b=w(this.selector)){a.push(b),w(this.comment);if(!w(","))break;w(this.comment)}if(a.length>0&&(c=w(this.block)))return new f.Ruleset(a,c);l=h,u()},rule:function(){var a,b,c=g.charAt(h),d,e;t();if(c==="."||c==="#"||c==="&")return;if(a=w(this.variable)||w(this.property)){a.charAt(0)!="@"&&(e=/^([^@+\/'"*`(;{}-]*);/.exec(m[i]))?(h+=e[0].length-1,b=new f.Anonymous(e[1])):a==="font"?b=w(this.font):b=w(this.value),d=w(this.important);if(b&&w(this.end))return new f.Rule(a,b,d,k);l=h,u()}},"import":function(){var a,b,c=h;if(w(/^@import\s+/)&&(a=w(this.entities.quoted)||w(this.entities.url))){b=w(this.mediaFeatures);if(w(";"))return new f.Import(a,s,b,c)}},mediaFeature:function(){var a=[];do if(e=w(this.entities.keyword))a.push(e);else if(w("(")){p=w(this.property),e=w(this.entity);if(!w(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,h,!0)));else{if(!e)return null;a.push(new f.Paren(e))}}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=w(this.mediaFeature)){b.push(a);if(!w(","))break}return b.length>0?b:null},media:function(){var a;if(w(/^@media/)){a=w(this.mediaFeatures);if(rules=w(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,b,c,d,e,i;if(g.charAt(h)!=="@")return;if(b=w(this["import"])||w(this.media))return b;if(a=w(/^@page|@keyframes/)||w(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){d=(w(/^[^{]+/)||"").trim();if(c=w(this.block))return new f.Directive(a+" "+d,c)}else if(a=w(/^@[-a-z]+/))if(a==="@font-face"){if(c=w(this.block))return new f.Directive(a,c)}else if((b=w(this.entity))&&w(";"))return new f.Directive(a,b)},font:function(){var a=[],b=[],c,d,e,g;while(g=w(this.shorthand)||w(this.entity))b.push(g);a.push(new f.Expression(b));if(w(","))while(g=w(this.expression)){a.push(g);if(!w(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=w(this.expression)){b.push(a);if(!w(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(g.charAt(h)==="!")return w(/^! *important/)},sub:function(){var a;if(w("(")&&(a=w(this.expression))&&w(")"))return a},multiplication:function(){var a,b,c,d;if(a=w(this.operand)){while(!z(/^\/\*/)&&(c=w("/")||w("*"))&&(b=w(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,b,c,d;if(a=w(this.multiplication)){while((c=w(/^[-+]\s+/)||g.charAt(h-1)!=" "&&(w("+")||w("-")))&&(b=w(this.multiplication)))d=new f.Operation(c,[d||a,b]);return d||a}},conditions:function(){var a,b,c=h,d;if(a=w(this.condition)){while(w(",")&&(b=w(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=h,g=!1;w(/^not/)&&(g=!0),x("(");if(a=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(d=w(/^(?:>=|=<|[<=>])/))?(b=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?c=new f.Condition(d,a,b,e,g):y("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,g),x(")"),w(/^and/)?new f.Condition("and",c,w(this.condition)):c},operand:function(){var a,b=g.charAt(h+1);g.charAt(h)==="-"&&(b==="@"||b==="(")&&(a=w("-"));var c=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return a?new f.Operation("*",[new f.Dimension(-1),c]):c},expression:function(){var a,b,c=[],d;while(a=w(this.addition)||w(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=w(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e<c.length;e++)d=d.replace(/%[sda]/i,function(a){var b=a.match(/s/i)?c[e].value:c[e].toCSS();return a.match(/[A-Z]$/)?encodeURIComponent(b):b});return d=d.replace(/%%/g,"%"),new a.Quoted('"'+d+'"',d)},round:function(a){return this._math("round",a)},ceil:function(a){return this._math("ceil",a)},floor:function(a){return this._math("floor",a)},_math:function(b,d){if(d instanceof a.Dimension)return new a.Dimension(Math[b](c(d)),d.unit);if(typeof d=="number")return Math[b](d);throw{type:"Argument",message:"argument must be a number"}},argb:function(b){return new a.Anonymous(b.toARGB())},percentage:function(b){return new a.Dimension(b.value*100,"%")},color:function(b){if(b instanceof a.Quoted)return new a.Color(b.value.slice(1));throw{type:"Argument",message:"argument must be a string"}},iscolor:function(b){return this._isa(b,a.Color)},isnumber:function(b){return this._isa(b,a.Dimension)},isstring:function(b){return this._isa(b,a.Quoted)},iskeyword:function(b){return this._isa(b,a.Keyword)},isurl:function(b){return this._isa(b,a.URL)},ispixel:function(b){return b instanceof a.Dimension&&b.unit==="px"?a.True:a.False},ispercentage:function(b){return b instanceof a.Dimension&&b.unit==="%"?a.True:a.False},isem:function(b){return b instanceof a.Dimension&&b.unit==="em"?a.True:a.False},_isa:function(b,c){return b instanceof c?a.True:a.False}}})(c("./tree")),function(a){a.colors={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgrey:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",grey:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgrey:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"}}(c("./tree")),function(a){a.Alpha=function(a){this.value=a},a.Alpha.prototype={toCSS:function(){return"alpha(opacity="+(this.value.toCSS?this.value.toCSS():this.value)+")"},eval:function(a){return this.value.eval&&(this.value=this.value.eval(a)),this}}}(c("../tree")),function(a){a.Anonymous=function(a){this.value=a.value||a},a.Anonymous.prototype={toCSS:function(){return this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Assignment=function(a,b){this.key=a,this.value=b},a.Assignment.prototype={toCSS:function(){return this.key+"="+(this.value.toCSS?this.value.toCSS():this.value)},eval:function(a){return this.value.eval&&(this.value=this.value.eval(a)),this}}}(c("../tree")),function(a){a.Call=function(a,b,c,d){this.name=a,this.args=b,this.index=c,this.filename=d},a.Call.prototype={eval:function(b){var c=this.args.map(function(a){return a.eval(b)});if(!(this.name in a.functions))return new a.Anonymous(this.name+"("+c.map(function(a){return a.toCSS()}).join(", ")+")");try{return a.functions[this.name].apply(a.functions,c)}catch(d){throw{type:d.type||"Runtime",message:"error evaluating function `"+this.name+"`"+(d.message?": "+d.message:""),index:this.index,filename:this.filename}}},toCSS:function(a){return this.eval(a).toCSS()}}}(c("../tree")),function(a){a.Color=function(a,b){Array.isArray(a)?this.rgb=a:a.length==6?this.rgb=a.match(/.{2}/g).map(function(a){return parseInt(a,16)}):this.rgb=a.split("").map(function(a){return parseInt(a+a,16)}),this.alpha=typeof b=="number"?b:1},a.Color.prototype={eval:function(){return this},toCSS:function(){return this.alpha<1?"rgba("+this.rgb.map(function(a){return Math.round(a)}).concat(this.alpha).join(", ")+")":"#"+this.rgb.map(function(a){return a=Math.round(a),a=(a>255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b<c?6:0);break;case b:g=(c-a)/j+2;break;case c:g=(a-b)/j+4}g/=6}return{h:g*360,s:h,l:i,a:d}},toARGB:function(){var a=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+a.map(function(a){return a=Math.round(a),a=(a>255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else{if(!c.compare)throw{type:"Type",message:"Unable to perform comparison",index:d};e=c.compare(b)}switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value<this.value?1:0:-1}}}(c("../tree")),function(a){a.Directive=function(b,c,d){this.name=b,this.features=d&&new a.Value(d),Array.isArray(c)?(this.ruleset=new a.Ruleset([],c),this.ruleset.allowImports=!0):this.value=c},a.Directive.prototype={toCSS:function(a,b){var c=this.features?" "+this.features.toCSS(b):"";return this.ruleset?(this.ruleset.root=!0,this.name+c+(b.compress?"{":" {\n  ")+this.ruleset.toCSS(a,b).trim().replace(/\n/g,"\n  ")+(b.compress?"}":"\n}\n")):this.name+" "+this.value.toCSS()+";\n"},eval:function(a){return this.features=this.features&&this.features.eval(a),a.frames.unshift(this),this.ruleset=this.ruleset&&this.ruleset.eval(a),a.frames.shift(),this},variable:function(b){return a.Ruleset.prototype.variable.call(this.ruleset,b)},find:function(){return a.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.ruleset)}}}(c("../tree")),function(a){a.Element=function(b,c,d){this.combinator=b instanceof a.Combinator?b:new a.Combinator(b),typeof c=="string"?this.value=c.trim():c?this.value=c:this.value="",this.index=d},a.Element.prototype.eval=function(b){return new a.Element(this.combinator,this.value.eval?this.value.eval(b):this.value,this.index)},a.Element.prototype.toCSS=function(a){return this.combinator.toCSS(a||{})+(this.value.toCSS?this.value.toCSS(a):this.value)},a.Combinator=function(a){a===" "?this.value=" ":a==="& "?this.value="& ":this.value=a?a.trim():""},a.Combinator.prototype.toCSS=function(a){return{"":""," ":" ","&":"","& ":" ",":":" :","::":"::","+":a.compress?"+":" + ","~":a.compress?"~":" ~ ",">":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e<c.rules.length;e++)c.rules[e]instanceof a.Import&&Array.prototype.splice.apply(c.rules,[e,1].concat(c.rules[e].eval(b)));return this.features?new a.Directive("@media",c.rules,this.features.value):c.rules}}}(c("../tree")),function(a){a.JavaScript=function(a,b,c){this.escaped=c,this.expression=a,this.index=b},a.JavaScript.prototype={eval:function(b){var c,d=this,e={},f=this.expression.replace(/@\{([\w-]+)\}/g,function(c,e){return a.jsify((new a.Variable("@"+e,d.index)).eval(b))});try{f=new Function("return ("+f+")")}catch(g){throw{message:"JavaScript evaluation error: `"+
+f+"`",index:this.index}}for(var h in b.frames[0].variables())e[h.slice(1)]={value:b.frames[0].variables()[h].value,toJS:function(){return this.value.eval(b).toCSS()}};try{c=f.call(e)}catch(g){throw{message:"JavaScript evaluation error: '"+g.name+": "+g.message+"'",index:this.index}}return typeof c=="string"?new a.Quoted('"'+c+'"',c,this.escaped,this.index):Array.isArray(c)?new a.Anonymous(c.join(", ")):new a.Anonymous(c)}}}(c("../tree")),function(a){a.Keyword=function(a){this.value=a},a.Keyword.prototype={eval:function(){return this},toCSS:function(){return this.value},compare:function(b){return b instanceof a.Keyword?b.value===this.value?0:1:-1}},a.True=new a.Keyword("true"),a.False=new a.Keyword("false")}(c("../tree")),function(a){a.mixin={},a.mixin.Call=function(b,c,d,e,f){this.selector=new a.Selector(b),this.arguments=c,this.index=d,this.filename=e,this.important=f},a.mixin.Call.prototype={eval:function(a){var b,c,d=[],e=!1;for(var f=0;f<a.frames.length;f++)if((b=a.frames[f].find(this.selector)).length>0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g<b.length;g++)if(b[g].match(c,a))try{Array.prototype.push.apply(d,b[g].eval(a,this.arguments,this.important).rules),e=!0}catch(h){throw{message:h.message,index:h.index,filename:this.filename,stack:h.stack,call:this.index}}if(e)return d;throw{type:"Runtime",message:"No matching definition was found for `"+this.selector.toCSS().trim()+"("+this.arguments.map(function(a){return a.toCSS()}).join(", ")+")`",index:this.index,filename:this.filename}}throw{type:"Name",message:this.selector.toCSS().trim()+" is undefined",index:this.index,filename:this.filename}}},a.mixin.Definition=function(b,c,d,e){this.name=b,this.selectors=[new a.Selector([new a.Element(null,b)])],this.params=c,this.condition=e,this.arity=c.length,this.rules=d,this._lookups={},this.required=c.reduce(function(a,b){return!b.name||b.name&&!b.value?a+1:a},0),this.parent=a.Ruleset.prototype,this.frames=[]},a.mixin.Definition.prototype={toCSS:function(){return""},variable:function(a){return this.parent.variable.call(this,a)},variables:function(){return this.parent.variables.call(this)},find:function(){return this.parent.find.apply(this,arguments)},rulesets:function(){return this.parent.rulesets.apply(this)},evalParams:function(b,c){var d=new a.Ruleset(null,[]);for(var e=0,f;e<this.params.length;e++)if(this.params[e].name){if(!(f=c&&c[e]||this.params[e].value))throw{type:"Runtime",message:"wrong number of arguments for "+this.name+" ("+c.length+" for "+this.arity+")"};d.rules.unshift(new a.Rule(this.params[e].name,f.eval(b)))}return d},eval:function(b,c,d){var e=this.evalParams(b,c),f,g=[],h;for(var i=0;i<Math.max(this.params.length,c&&c.length);i++)g.push(c[i]||this.params[i].value);return e.rules.unshift(new a.Rule("@arguments",(new a.Expression(g)).eval(b))),h=d?this.rules.map(function(b){return new a.Rule(b.name,b.value,"!important",b.index)}):this.rules.slice(0),(new a.Ruleset(null,h)).eval({frames:[this,e].concat(this.frames,b.frames)})},match:function(a,b){var c=a&&a.length||0,d,e;if(c<this.required)return!1;if(this.required>0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;f<d;f++)if(!this.params[f].name&&a[f].eval(b).toCSS()!=this.params[f].value.eval(b).toCSS())return!1;return!0}}}(c("../tree")),function(a){a.Operation=function(a,b){this.op=a.trim(),this.operands=b},a.Operation.prototype.eval=function(b){var c=this.operands[0].eval(b),d=this.operands[1].eval(b),e;if(c instanceof a.Dimension&&d instanceof a.Color){if(this.op!=="*"&&this.op!=="+")throw{name:"OperationError",message:"Can't substract or divide a color from a number"};e=d,d=c,c=e}return c.operate(this.op,d)},a.operate=function(a,b,c){switch(a){case"+":return b+c;case"-":return b-c;case"*":return b*c;case"/":return b/c}}}(c("../tree")),function(a){a.Paren=function(a){this.value=a},a.Paren.prototype={toCSS:function(a){return"("+this.value.toCSS(a)+")"},eval:function(b){return new a.Paren(this.value.eval(b))}}}(c("../tree")),function(a){a.Quoted=function(a,b,c,d){this.escaped=c,this.value=b||"",this.quote=a.charAt(0),this.index=d},a.Quoted.prototype={toCSS:function(){return this.escaped?this.value:this.quote+this.value+this.quote},eval:function(b){var c=this,d=this.value.replace(/`([^`]+)`/g,function(d,e){return(new a.JavaScript(e,c.index,!0)).eval(b).value}).replace(/@\{([\w-]+)\}/g,function(d,e){var f=(new a.Variable("@"+e,c.index)).eval(b);return"value"in f?f.value:f.toCSS()});return new a.Quoted(this.quote+d+this.quote,d,this.escaped,this.index)}}}(c("../tree")),function(a){a.Rule=function(b,c,d,e,f){this.name=b,this.value=c instanceof a.Value?c:new a.Value([c]),this.important=d?" "+d.trim():"",this.index=e,this.inline=f||!1,b.charAt(0)==="@"?this.variable=!0:this.variable=!1},a.Rule.prototype.toCSS=function(a){return this.variable?"":this.name+(a.compress?":":": ")+this.value.toCSS(a)+this.important+(this.inline?"":";")},a.Rule.prototype.eval=function(b){return new a.Rule(this.name,this.value.eval(b),this.important,this.index,this.inline)},a.Shorthand=function(a,b){this.a=a,this.b=b},a.Shorthand.prototype={toCSS:function(a){return this.a.toCSS(a)+"/"+this.b.toCSS(a)},eval:function(){return this}}}(c("../tree")),function(a){a.Ruleset=function(a,b){this.selectors=a,this.rules=b,this._lookups={}},a.Ruleset.prototype={eval:function(b){var c=this.selectors&&this.selectors.map(function(a){return a.eval(b)}),d=new a.Ruleset(c,this.rules.slice(0));d.root=this.root,d.allowImports=this.allowImports,b.frames.unshift(d);if(d.root||d.allowImports)for(var e=0;e<d.rules.length;e++)d.rules[e]instanceof a.Import&&Array.prototype.splice.apply(d.rules,[e,1].concat(d.rules[e].eval(b)));for(var e=0;e<d.rules.length;e++)d.rules[e]instanceof a.mixin.Definition&&(d.rules[e].frames=b.frames.slice(0));for(var e=0;e<d.rules.length;e++)d.rules[e]instanceof a.mixin.Call&&Array.prototype.splice.apply(d.rules,[e,1].concat(d.rules[e].eval(b)));for(var e=0,f;e<d.rules.length;e++)f=d.rules[e],f instanceof a.mixin.Definition||(d.rules[e]=f.eval?f.eval(b):f);return b.frames.shift(),d},match:function(a){return!a||a.length===0},variables:function(){return this._variables?this._variables:this._variables=this.rules.reduce(function(b,c){return c instanceof a.Rule&&c.variable===!0&&(b[c.name]=c),b},{})},variable:function(a){return this.variables()[a]},rulesets:function(){return this._rulesets?this._rulesets:this._rulesets=this.rules.filter(function(b){return b instanceof a.Ruleset||b instanceof a.mixin.Definition})},find:function(b,c){c=c||this;var d=[],e,f,g=b.toCSS();return g in this._lookups?this._lookups[g]:(this.rulesets().forEach(function(e){if(e!==c)for(var g=0;g<e.selectors.length;g++)if(f=b.match(e.selectors[g])){b.elements.length>e.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j<this.rules.length;j++)i=this.rules[j],i.rules||i instanceof a.Directive?f.push(i.toCSS(g,c)):i instanceof a.Comment?i.silent||(this.root?f.push(i.toCSS(c)):e.push(i.toCSS(c))):i.toCSS&&!i.variable?e.push(i.toCSS(c)):i.value&&!i.variable&&e.push(i.value.toString());return f=f.join(""),this.root?d.push(e.join(c.compress?"":"\n")):e.length>0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n  ")+e.join(c.compress?"":"\n  ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d<c.length;d++)this.joinSelector(a,b,c[d])},joinSelector:function(b,c,d){var e=[],f=[],g=[],h=[],i=!1,j;for(var k=0;k<d.elements.length;k++)j=d.elements[k],j.combinator.value.charAt(0)==="&"&&(i=!0),i?h.push(j):g.push(j);i||(h=g,g=[]),g.length>0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l<c.length;l++)b.push(e.concat(c[l]).concat(f))}}}(c("../tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){var b=this.elements.length,c=a.elements.length,d=Math.min(b,c);if(b<c)return!1;for(var e=0;e<d;e++)if(this.elements[e].value!==a.elements[e].value)return!1;return!0},a.Selector.prototype.eval=function(b){return new a.Selector(this.elements.map(function(a){return a.eval(b)}))},a.Selector.prototype.toCSS=function(a){return this._css?this._css:this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("../tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(typeof a!="undefined"&&!/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(b.value)&&c.length>0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c<a.length;c++)if(d=b.call(a,a[c]))return d;return null},a.jsify=function(a){return Array.isArray(a.value)&&a.value.length>1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c,d,e){b&&r(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l<j.length;l++)(j[l].rel==="stylesheet/less"||j[l].rel.match(/stylesheet/)&&j[l].type.match(k))&&d.sheets.push(j[l]);d.refresh=function(a){var b,c;b=c=new Date,n(function(a,d,e,f,g){g.local?v("loading "+f.href+" from cache."):(v("parsed "+f.href+" successfully."),r(d.toCSS(),f,g.lastModified)),v("css for "+f.href+" generated in "+(new Date-c)+"ms"),g.remaining===0&&v("css generated in "+(new Date-b)+"ms"),c=new Date},a),m()},d.refreshStyles=m,d.refresh(d.env==="development")})(window);
\ No newline at end of file
index b7d7d8c..52b292f 100644 (file)
@@ -45,7 +45,6 @@ $wgAutoloadLocalClasses = array(
        'CategoryPage' => 'includes/CategoryPage.php',
        'CategoryViewer' => 'includes/CategoryViewer.php',
        'ChangesFeed' => 'includes/ChangesFeed.php',
-       'ChangesListSpecialPage' => 'includes/specialpage/ChangesListSpecialPage.php',
        'ChangeTags' => 'includes/ChangeTags.php',
        'ChannelFeed' => 'includes/Feed.php',
        'Collation' => 'includes/Collation.php',
@@ -80,7 +79,6 @@ $wgAutoloadLocalClasses = array(
        'FileDeleteForm' => 'includes/FileDeleteForm.php',
        'ForkController' => 'includes/ForkController.php',
        'FormOptions' => 'includes/FormOptions.php',
-       'FormSpecialPage' => 'includes/specialpage/FormSpecialPage.php',
        'GitInfo' => 'includes/GitInfo.php',
        'HistoryBlob' => 'includes/HistoryBlob.php',
        'HistoryBlobCurStub' => 'includes/HistoryBlob.php',
@@ -120,7 +118,6 @@ $wgAutoloadLocalClasses = array(
        'ImageQueryPage' => 'includes/ImageQueryPage.php',
        'ImportStreamSource' => 'includes/Import.php',
        'ImportStringSource' => 'includes/Import.php',
-       'IncludableSpecialPage' => 'includes/specialpage/IncludableSpecialPage.php',
        'IndexPager' => 'includes/Pager.php',
        'Interwiki' => 'includes/interwiki/Interwiki.php',
        'LCStore' => 'includes/cache/LocalisationCache.php',
@@ -168,8 +165,6 @@ $wgAutoloadLocalClasses = array(
        'QueryPage' => 'includes/QueryPage.php',
        'QuickTemplate' => 'includes/SkinTemplate.php',
        'RawMessage' => 'includes/Message.php',
-       'RedirectSpecialArticle' => 'includes/specialpage/RedirectSpecialPage.php',
-       'RedirectSpecialPage' => 'includes/specialpage/RedirectSpecialPage.php',
        'ReverseChronologicalPager' => 'includes/Pager.php',
        'RevisionItem' => 'includes/RevisionList.php',
        'RevisionItemBase' => 'includes/RevisionList.php',
@@ -183,22 +178,12 @@ $wgAutoloadLocalClasses = array(
        'SiteStatsInit' => 'includes/SiteStats.php',
        'Skin' => 'includes/Skin.php',
        'SkinTemplate' => 'includes/SkinTemplate.php',
-       'SpecialCreateAccount' => 'includes/specials/SpecialCreateAccount.php',
-       'SpecialListAdmins' => 'includes/specials/SpecialListusers.php',
-       'SpecialListBots' => 'includes/specials/SpecialListusers.php',
-       'SpecialMycontributions' => 'includes/specials/SpecialMyRedirectPages.php',
-       'SpecialMypage' => 'includes/specials/SpecialMyRedirectPages.php',
-       'SpecialMytalk' => 'includes/specials/SpecialMyRedirectPages.php',
-       'SpecialMyuploads' => 'includes/specials/SpecialMyRedirectPages.php',
-       'SpecialAllMyUploads' => 'includes/specials/SpecialMyRedirectPages.php',
-       'SpecialPage' => 'includes/specialpage/SpecialPage.php',
-       'SpecialPageFactory' => 'includes/specialpage/SpecialPageFactory.php',
-       'SpecialRedirectToSpecial' => 'includes/specialpage/RedirectSpecialPage.php',
        'SquidPurgeClient' => 'includes/SquidPurgeClient.php',
        'SquidPurgeClientPool' => 'includes/SquidPurgeClient.php',
        'StatCounter' => 'includes/StatCounter.php',
        'Status' => 'includes/Status.php',
        'StreamFile' => 'includes/StreamFile.php',
+       'StringPrefixSearch' => 'includes/PrefixSearch.php',
        'StubContLang' => 'includes/StubObject.php',
        'StubObject' => 'includes/StubObject.php',
        'StubUserLang' => 'includes/StubObject.php',
@@ -208,7 +193,7 @@ $wgAutoloadLocalClasses = array(
        'Title' => 'includes/Title.php',
        'TitleArray' => 'includes/TitleArray.php',
        'TitleArrayFromResult' => 'includes/TitleArrayFromResult.php',
-       'UnlistedSpecialPage' => 'includes/specialpage/UnlistedSpecialPage.php',
+       'TitlePrefixSearch' => 'includes/PrefixSearch.php',
        'UploadSourceAdapter' => 'includes/Import.php',
        'UppercaseCollation' => 'includes/Collation.php',
        'User' => 'includes/User.php',
@@ -343,6 +328,7 @@ $wgAutoloadLocalClasses = array(
        'ApiQueryPageProps' => 'includes/api/ApiQueryPageProps.php',
        'ApiQueryPagesWithProp' => 'includes/api/ApiQueryPagesWithProp.php',
        'ApiQueryPagePropNames' => 'includes/api/ApiQueryPagePropNames.php',
+       'ApiQueryPrefixSearch' => 'includes/api/ApiQueryPrefixSearch.php',
        'ApiQueryProtectedTitles' => 'includes/api/ApiQueryProtectedTitles.php',
        'ApiQueryQueryPage' => 'includes/api/ApiQueryQueryPage.php',
        'ApiQueryRandom' => 'includes/api/ApiQueryRandom.php',
@@ -930,6 +916,17 @@ $wgAutoloadLocalClasses = array(
        'Sites' => 'includes/site/SiteSQLStore.php',
        'SiteStore' => 'includes/site/SiteStore.php',
 
+       # includes/specialpage
+       'ChangesListSpecialPage' => 'includes/specialpage/ChangesListSpecialPage.php',
+       'FormSpecialPage' => 'includes/specialpage/FormSpecialPage.php',
+       'IncludableSpecialPage' => 'includes/specialpage/IncludableSpecialPage.php',
+       'RedirectSpecialArticle' => 'includes/specialpage/RedirectSpecialPage.php',
+       'RedirectSpecialPage' => 'includes/specialpage/RedirectSpecialPage.php',
+       'SpecialPage' => 'includes/specialpage/SpecialPage.php',
+       'SpecialPageFactory' => 'includes/specialpage/SpecialPageFactory.php',
+       'SpecialRedirectToSpecial' => 'includes/specialpage/RedirectSpecialPage.php',
+       'UnlistedSpecialPage' => 'includes/specialpage/UnlistedSpecialPage.php',
+
        # includes/specials
        'ActiveUsersPager' => 'includes/specials/SpecialActiveusers.php',
        'AllmessagesTablePager' => 'includes/specials/SpecialAllmessages.php',
@@ -978,6 +975,7 @@ $wgAutoloadLocalClasses = array(
        'ShortPagesPage' => 'includes/specials/SpecialShortpages.php',
        'SpecialActiveUsers' => 'includes/specials/SpecialActiveusers.php',
        'SpecialAllmessages' => 'includes/specials/SpecialAllmessages.php',
+       'SpecialAllMyUploads' => 'includes/specials/SpecialMyRedirectPages.php',
        'SpecialAllpages' => 'includes/specials/SpecialAllpages.php',
        'SpecialBlankpage' => 'includes/specials/SpecialBlankpage.php',
        'SpecialBlock' => 'includes/specials/SpecialBlock.php',
@@ -989,6 +987,7 @@ $wgAutoloadLocalClasses = array(
        'SpecialChangePassword' => 'includes/specials/SpecialChangePassword.php',
        'SpecialComparePages' => 'includes/specials/SpecialComparePages.php',
        'SpecialContributions' => 'includes/specials/SpecialContributions.php',
+       'SpecialCreateAccount' => 'includes/specials/SpecialCreateAccount.php',
        'SpecialDiff' => 'includes/specials/SpecialDiff.php',
        'SpecialEditWatchlist' => 'includes/specials/SpecialEditWatchlist.php',
        'SpecialEmailUser' => 'includes/specials/SpecialEmailuser.php',
@@ -997,12 +996,18 @@ $wgAutoloadLocalClasses = array(
        'SpecialFilepath' => 'includes/specials/SpecialFilepath.php',
        'SpecialImport' => 'includes/specials/SpecialImport.php',
        'SpecialJavaScriptTest' => 'includes/specials/SpecialJavaScriptTest.php',
+       'SpecialListAdmins' => 'includes/specials/SpecialListusers.php',
+       'SpecialListBots' => 'includes/specials/SpecialListusers.php',
        'SpecialListFiles' => 'includes/specials/SpecialListfiles.php',
        'SpecialListGroupRights' => 'includes/specials/SpecialListgrouprights.php',
        'SpecialListUsers' => 'includes/specials/SpecialListusers.php',
        'SpecialLockdb' => 'includes/specials/SpecialLockdb.php',
        'SpecialLog' => 'includes/specials/SpecialLog.php',
        'SpecialMergeHistory' => 'includes/specials/SpecialMergeHistory.php',
+       'SpecialMycontributions' => 'includes/specials/SpecialMyRedirectPages.php',
+       'SpecialMypage' => 'includes/specials/SpecialMyRedirectPages.php',
+       'SpecialMytalk' => 'includes/specials/SpecialMyRedirectPages.php',
+       'SpecialMyuploads' => 'includes/specials/SpecialMyRedirectPages.php',
        'SpecialNewFiles' => 'includes/specials/SpecialNewimages.php',
        'SpecialNewpages' => 'includes/specials/SpecialNewpages.php',
        'SpecialPasswordReset' => 'includes/specials/SpecialPasswordReset.php',
index 95a8386..a3d3691 100644 (file)
@@ -31,22 +31,22 @@ class Block {
                $mCreateAccount,
                $mParentBlockId;
 
-       /// @var User|String
+       /** @var User|String */
        protected $target;
 
-       // @var Integer Hack for foreign blocking (CentralAuth)
+       /** @var Integer Hack for foreign blocking (CentralAuth) */
        protected $forcedTargetID;
 
-       /// @var Block::TYPE_ constant.  Can only be USER, IP or RANGE internally
+       /** @var Integer Block::TYPE_ constant. Can only be USER, IP or RANGE internally */
        protected $type;
 
-       /// @var User
+       /** @var User */
        protected $blocker;
 
-       /// @var Bool
+       /** @var Bool */
        protected $isHardblock = true;
 
-       /// @var Bool
+       /** @var Bool */
        protected $isAutoblocking = true;
 
        # TYPE constants
@@ -312,7 +312,7 @@ class Block {
        /**
         * Get the component of an IP address which is certain to be the same between an IP
         * address and a rangeblock containing that IP address.
-        * @param  $hex String Hexadecimal IP representation
+        * @param $hex String Hexadecimal IP representation
         * @return String
         */
        protected static function getIpFragment( $hex ) {
@@ -362,7 +362,7 @@ class Block {
 
        /**
         * Create a new Block object from a database row
-        * @param  $row ResultWrapper row from the ipblocks table
+        * @param $row ResultWrapper row from the ipblocks table
         * @return Block
         */
        public static function newFromRow( $row ) {
@@ -862,7 +862,7 @@ class Block {
        /**
         * Get/set whether the Block is a hardblock (affects logged-in users on a given IP/range
         * @param $x Bool
-        * @return  Bool
+        * @return Bool
         */
        public function isHardblock( $x = null ) {
                wfSetVar( $this->isHardblock, $x );
index bb5d26d..eb8ba5c 100644 (file)
@@ -3362,7 +3362,7 @@ $wgResourceLoaderLESSFunctions = array(
  * @since 1.22
  */
 $wgResourceLoaderLESSImportPaths = array(
-       "$IP/resources/mediawiki.less/",
+       "$IP/resources/src/mediawiki.less/",
        "$IP/skins/vector/",
 );
 
@@ -6028,7 +6028,7 @@ $wgExtensionMessagesFiles = array();
  */
 $wgMessagesDirs = array(
        'core' => "$IP/languages/i18n",
-       'oojs-ui' => "$IP/resources/oojs-ui/i18n",
+       'oojs-ui' => "$IP/resources/lib/oojs-ui/i18n",
 );
 
 /**
index f57fc60..9b9e389 100644 (file)
@@ -910,14 +910,15 @@ class EditPage {
                                $preload = $wgRequest->getVal( 'preload',
                                        // Custom preload text for new sections
                                        $this->section === 'new' ? 'MediaWiki:addsection-preload' : '' );
+                               $params = $wgRequest->getArray( 'preloadparams', array() );
 
-                               $content = $this->getPreloadedContent( $preload );
+                               $content = $this->getPreloadedContent( $preload, $params );
                        }
                // For existing pages, get text based on "undo" or section parameters.
                } else {
                        if ( $this->section != '' ) {
                                // Get section edit text (returns $def_text for invalid sections)
-                               $orig = $this->getOriginalContent();
+                               $orig = $this->getOriginalContent( $wgUser );
                                $content = $orig ? $orig->getSection( $this->section ) : null;
 
                                if ( !$content ) {
@@ -999,7 +1000,7 @@ class EditPage {
                                }
 
                                if ( $content === false ) {
-                                       $content = $this->getOriginalContent();
+                                       $content = $this->getOriginalContent( $wgUser );
                                }
                        }
                }
@@ -1020,9 +1021,10 @@ class EditPage {
         * 'missing-revision' message.
         *
         * @since 1.19
+        * @param User $user The user to get the revision for
         * @return Content|null
         */
-       private function getOriginalContent() {
+       private function getOriginalContent( User $user ) {
                if ( $this->section == 'new' ) {
                        return $this->getCurrentContent();
                }
@@ -1035,7 +1037,7 @@ class EditPage {
 
                        return $handler->makeEmptyContent();
                }
-               $content = $revision->getContent();
+               $content = $revision->getContent( Revision::FOR_THIS_USER, $user );
                return $content;
        }
 
@@ -1116,12 +1118,13 @@ class EditPage {
         * an earlier setPreloadText() or by loading the given page.
         *
         * @param string $preload representing the title to preload from.
+        * @param Array $params Parameters to use (interface-message style) in the preloaded text
         *
         * @return Content
         *
         * @since 1.21
         */
-       protected function getPreloadedContent( $preload ) {
+       protected function getPreloadedContent( $preload, $params = array() ) {
                global $wgUser;
 
                if ( !empty( $this->mPreloadContent ) ) {
@@ -1175,7 +1178,7 @@ class EditPage {
                        $content = $converted;
                }
 
-               return $content->preloadTransform( $title, $parserOptions );
+               return $content->preloadTransform( $title, $parserOptions, $params );
        }
 
        /**
@@ -1734,7 +1737,7 @@ class EditPage {
                                        return $status;
                                }
                        } elseif ( !$this->allowBlankSummary
-                               && !$content->equals( $this->getOriginalContent() )
+                               && !$content->equals( $this->getOriginalContent( $wgUser ) )
                                && !$content->isRedirect()
                                && md5( $this->summary ) == $this->autoSumm
                        ) {
@@ -3417,15 +3420,6 @@ HTML
                                'tip'    => wfMessage( 'media_tip' )->text(),
                                'key'    => 'M'
                        ) : false,
-                       class_exists( 'MathRenderer' ) ? array(
-                               'image'  => $wgLang->getImageFile( 'button-math' ),
-                               'id'     => 'mw-editbutton-math',
-                               'open'   => "<math>",
-                               'close'  => "</math>",
-                               'sample' => wfMessage( 'math_sample' )->text(),
-                               'tip'    => wfMessage( 'math_tip' )->text(),
-                               'key'    => 'C'
-                       ) : false,
                        array(
                                'image'  => $wgLang->getImageFile( 'button-nowiki' ),
                                'id'     => 'mw-editbutton-nowiki',
index 5174b32..cef19e1 100644 (file)
@@ -1817,19 +1817,23 @@ function wfHostname() {
 }
 
 /**
- * Returns a HTML comment with the elapsed time since request.
- * This method has no side effects.
+ * Returns a script tag that stores the amount of time it took MediaWiki to
+ * handle the request in milliseconds as 'wgBackendResponseTime'.
+ *
+ * If $wgShowHostnames is true, the script will also set 'wgHostname' to the
+ * hostname of the server handling the request.
  *
  * @return string
  */
 function wfReportTime() {
        global $wgRequestTime, $wgShowHostnames;
 
-       $elapsed = microtime( true ) - $wgRequestTime;
-
-       return $wgShowHostnames
-               ? sprintf( '<!-- Served by %s in %01.3f secs. -->', wfHostname(), $elapsed )
-               : sprintf( '<!-- Served in %01.3f secs. -->', $elapsed );
+       $responseTime = round( ( microtime( true ) - $wgRequestTime ) * 1000 );
+       $reportVars = array( 'wgBackendResponseTime' => $responseTime );
+       if ( $wgShowHostnames ) {
+               $reportVars[ 'wgHostname' ] = wfHostname();
+       }
+       return Skin::makeVariablesScript( $reportVars );
 }
 
 /**
index 274d4a7..1fd437e 100644 (file)
@@ -205,7 +205,7 @@ class MWHttpRequest {
        protected $followRedirects = false;
 
        /**
-        * @var  CookieJar
+        * @var CookieJar
         */
        protected $cookieJar;
 
index 033926a..094a304 100644 (file)
@@ -742,7 +742,7 @@ class Linker {
 
        /**
         * @param $title Title
-        * @param  $file File
+        * @param $file File
         * @param array $frameParams
         * @param array $handlerParams
         * @param bool $time
@@ -1467,8 +1467,8 @@ class Linker {
 
        /**
         * @param $contextTitle Title
-        * @param  $target
-        * @param  $text
+        * @param $target
+        * @param $text
         * @return string
         */
        public static function normalizeSubpageLink( $contextTitle, $target, &$text ) {
index 377d406..e301cea 100644 (file)
@@ -512,7 +512,7 @@ class MagicWord {
        }
 
        /**
-        * @param  $text
+        * @param $text
         * @return bool
         */
        function matchStartAndRemove( &$text ) {
index 8542904..f469732 100644 (file)
@@ -1315,8 +1315,8 @@ class OutputPage extends ContextSource {
 
        /**
         * Set the highest level of CSS/JS untrustworthiness allowed
-        * @param  $type String ResourceLoaderModule TYPE_ constant
-        * @param  $level Int ResourceLoaderModule class constant
+        * @param $type String ResourceLoaderModule TYPE_ constant
+        * @param $level Int ResourceLoaderModule class constant
         */
        public function setAllowedModules( $type, $level ) {
                $this->mAllowedModules[$type] = $level;
@@ -1324,8 +1324,8 @@ class OutputPage extends ContextSource {
 
        /**
         * As for setAllowedModules(), but don't inadvertently make the page more accessible
-        * @param  $type String
-        * @param  $level Int ResourceLoaderModule class constant
+        * @param $type String
+        * @param $level Int ResourceLoaderModule class constant
         */
        public function reduceAllowedModules( $type, $level ) {
                $this->mAllowedModules[$type] = min( $this->getAllowedModules( $type ), $level );
@@ -2530,12 +2530,15 @@ $templates
                // jQuery can work correctly.
                $ret .= Html::element( 'meta', array( 'http-equiv' => 'X-UA-Compatible', 'content' => 'IE=EDGE' ) ) . "\n";
 
-               $ret .= implode( "\n", array(
-                       $this->getHeadLinks(),
-                       $this->buildCssLinks(),
-                       $this->getHeadScripts(),
+               $ret .= (
+                       $this->getHeadLinks() .
+                       "\n" .
+                       $this->buildCssLinks() .
+                       // No newline after buildCssLinks since makeResourceLoaderLink did that already
+                       $this->getHeadScripts() .
+                       "\n" .
                        $this->getHeadItems()
-               ) );
+               );
 
                $closeHead = Html::closeElement( 'head' );
                if ( $closeHead ) {
@@ -2586,22 +2589,28 @@ $templates
 
        /**
         * TODO: Document
-        * @param $modules Array/string with the module name(s)
+        * @param array|string $modules One or more module names
         * @param string $only ResourceLoaderModule TYPE_ class constant
-        * @param $useESI boolean
+        * @param boolean $useESI
         * @param array $extraQuery with extra query parameters to add to each request. array( param => value )
-        * @param $loadCall boolean If true, output an (asynchronous) mw.loader.load() call rather than a "<script src='...'>" tag
-        * @return string html "<script>" and "<style>" tags
+        * @param boolean $loadCall If true, output an (asynchronous) mw.loader.load() call rather than a "<script src='...'>" tag
+        * @return string The html "<script>", "<link>" and "<style>" tags
         */
        protected function makeResourceLoaderLink( $modules, $only, $useESI = false, array $extraQuery = array(), $loadCall = false ) {
                global $wgResourceLoaderUseESI;
 
                $modules = (array)$modules;
 
+               $links = array(
+                       'html' => '',
+                       'states' => array(),
+               );
+
                if ( !count( $modules ) ) {
-                       return '';
+                       return $links;
                }
 
+
                if ( count( $modules ) > 1 ) {
                        // Remove duplicate module requests
                        $modules = array_unique( $modules );
@@ -2610,13 +2619,15 @@ $templates
 
                        if ( ResourceLoader::inDebugMode() ) {
                                // Recursively call us for every item
-                               $links = '';
                                foreach ( $modules as $name ) {
-                                       $links .= $this->makeResourceLoaderLink( $name, $only, $useESI );
+                                       $link = $this->makeResourceLoaderLink( $name, $only, $useESI );
+                                       $links['html'] .= $link['html'];
+                                       $links['states'] += $link['states'];
                                }
                                return $links;
                        }
                }
+
                if ( !is_null( $this->mTarget ) ) {
                        $extraQuery['target'] = $this->mTarget;
                }
@@ -2644,7 +2655,6 @@ $templates
                        $groups[$group][$name] = $module;
                }
 
-               $links = '';
                foreach ( $groups as $group => $grpModules ) {
                        // Special handling for user-specific groups
                        $user = null;
@@ -2667,25 +2677,20 @@ $templates
                                $extraQuery
                        );
                        $context = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
+
                        // Extract modules that know they're empty
-                       $emptyModules = array();
                        foreach ( $grpModules as $key => $module ) {
+                               // Inline empty modules: since they're empty, just mark them as 'ready' (bug 46857)
+                               // If we're only getting the styles, we don't need to do anything for empty modules.
                                if ( $module->isKnownEmpty( $context ) ) {
-                                       $emptyModules[$key] = 'ready';
                                        unset( $grpModules[$key] );
+                                       if ( $only !== ResourceLoaderModule::TYPE_STYLES ) {
+                                               $links['states'][$key] = 'ready';
+                                       }
                                }
                        }
-                       // Inline empty modules: since they're empty, just mark them as 'ready'
-                       if ( count( $emptyModules ) > 0 && $only !== ResourceLoaderModule::TYPE_STYLES ) {
-                               // If we're only getting the styles, we don't need to do anything for empty modules.
-                               $links .= Html::inlineScript(
-                                               ResourceLoader::makeLoaderConditionalScript(
-                                                               ResourceLoader::makeLoaderStateScript( $emptyModules )
-                                               )
-                               ) . "\n";
-                       }
 
-                       // If there are no modules left, skip this group
+                       // If there are no non-empty modules, skip this group
                        if ( count( $grpModules ) === 0 ) {
                                continue;
                        }
@@ -2696,19 +2701,20 @@ $templates
                        // properly use them as dependencies (bug 30914)
                        if ( $group === 'private' ) {
                                if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
-                                       $links .= Html::inlineStyle(
+                                       $links['html'] .= Html::inlineStyle(
                                                $resourceLoader->makeModuleResponse( $context, $grpModules )
                                        );
                                } else {
-                                       $links .= Html::inlineScript(
+                                       $links['html'] .= Html::inlineScript(
                                                ResourceLoader::makeLoaderConditionalScript(
                                                        $resourceLoader->makeModuleResponse( $context, $grpModules )
                                                )
                                        );
                                }
-                               $links .= "\n";
+                               $links['html'] .= "\n";
                                continue;
                        }
+
                        // Special handling for the user group; because users might change their stuff
                        // on-wiki like user pages, or user preferences; we need to find the highest
                        // timestamp of these user-changeable modules so we can ensure cache misses on change
@@ -2756,18 +2762,56 @@ $templates
                                        );
                                } else {
                                        $link = Html::linkedScript( $url );
+
+                                       // For modules requested directly in the html via <link> or <script>,
+                                       // tell mw.loader they are being loading to prevent duplicate requests.
+                                       foreach ( $grpModules as $key => $module ) {
+                                               // Don't output state=loading for the startup module..
+                                               if ( $key !== 'startup' ) {
+                                                       $links['states'][$key] = 'loading';
+                                               }
+                                       }
                                }
                        }
 
                        if ( $group == 'noscript' ) {
-                               $links .= Html::rawElement( 'noscript', array(), $link ) . "\n";
+                               $links['html'] .= Html::rawElement( 'noscript', array(), $link ) . "\n";
                        } else {
-                               $links .= $link . "\n";
+                               $links['html'] .= $link . "\n";
                        }
                }
+
                return $links;
        }
 
+       /**
+        * Build html output from an array of links from makeResourceLoaderLink.
+        * @param array $links
+        * @return string HTML
+        */
+       protected static function getHtmlFromLoaderLinks( Array $links ) {
+               $html = '';
+               $states = array();
+               foreach ( $links as $link ) {
+                       if ( !is_array( $link ) ) {
+                               $html .= $link;
+                       } else {
+                               $html .= $link['html'];
+                               $states += $link['states'];
+                       }
+               }
+
+               if ( count( $states ) ) {
+                       $html = Html::inlineScript(
+                               ResourceLoader::makeLoaderConditionalScript(
+                                       ResourceLoader::makeLoaderStateScript( $states )
+                               )
+                       ) . "\n" . $html;
+               }
+
+               return $html;
+       }
+
        /**
         * JS stuff to put in the "<head>". This is the startup module, config
         * vars and modules marked with position 'top'
@@ -2778,10 +2822,11 @@ $templates
                global $wgResourceLoaderExperimentalAsyncLoading;
 
                // Startup - this will immediately load jquery and mediawiki modules
-               $scripts = $this->makeResourceLoaderLink( 'startup', ResourceLoaderModule::TYPE_SCRIPTS, true );
+               $links = array();
+               $links[] = $this->makeResourceLoaderLink( 'startup', ResourceLoaderModule::TYPE_SCRIPTS, true );
 
                // Load config before anything else
-               $scripts .= Html::inlineScript(
+               $links[] = Html::inlineScript(
                        ResourceLoader::makeLoaderConditionalScript(
                                ResourceLoader::makeConfigSetScript( $this->getJSVars() )
                        )
@@ -2791,18 +2836,18 @@ $templates
                // This needs to be TYPE_COMBINED so these modules are properly wrapped
                // in mw.loader.implement() calls and deferred until mw.user is available
                $embedScripts = array( 'user.options', 'user.tokens' );
-               $scripts .= $this->makeResourceLoaderLink( $embedScripts, ResourceLoaderModule::TYPE_COMBINED );
+               $links[] = $this->makeResourceLoaderLink( $embedScripts, ResourceLoaderModule::TYPE_COMBINED );
 
-               // Script and Messages "only" requests marked for top inclusion
+               // Scripts and messages "only" requests marked for top inclusion
                // Messages should go first
-               $scripts .= $this->makeResourceLoaderLink( $this->getModuleMessages( true, 'top' ), ResourceLoaderModule::TYPE_MESSAGES );
-               $scripts .= $this->makeResourceLoaderLink( $this->getModuleScripts( true, 'top' ), ResourceLoaderModule::TYPE_SCRIPTS );
+               $links[] = $this->makeResourceLoaderLink( $this->getModuleMessages( true, 'top' ), ResourceLoaderModule::TYPE_MESSAGES );
+               $links[] = $this->makeResourceLoaderLink( $this->getModuleScripts( true, 'top' ), ResourceLoaderModule::TYPE_SCRIPTS );
 
                // Modules requests - let the client calculate dependencies and batch requests as it likes
                // Only load modules that have marked themselves for loading at the top
                $modules = $this->getModules( true, 'top' );
                if ( $modules ) {
-                       $scripts .= Html::inlineScript(
+                       $links[] = Html::inlineScript(
                                ResourceLoader::makeLoaderConditionalScript(
                                        Xml::encodeJsCall( 'mw.loader.load', array( $modules ) )
                                )
@@ -2810,17 +2855,17 @@ $templates
                }
 
                if ( $wgResourceLoaderExperimentalAsyncLoading ) {
-                       $scripts .= $this->getScriptsForBottomQueue( true );
+                       $links[] = $this->getScriptsForBottomQueue( true );
                }
 
-               return $scripts;
+               return self::getHtmlFromLoaderLinks( $links );
        }
 
        /**
         * JS stuff to put at the 'bottom', which can either be the bottom of the "<body>"
         * or the bottom of the "<head>" depending on $wgResourceLoaderExperimentalAsyncLoading:
         * modules marked with position 'bottom', legacy scripts ($this->mScripts),
-        * user preferences, site JS and user JS
+        * user preferences, site JS and user JS.
         *
         * @param $inHead boolean If true, this HTML goes into the "<head>", if false it goes into the "<body>"
         * @return string
@@ -2828,14 +2873,15 @@ $templates
        function getScriptsForBottomQueue( $inHead ) {
                global $wgUseSiteJs, $wgAllowUserJs;
 
-               // Script and Messages "only" requests marked for bottom inclusion
+               // Scripts and messages "only" requests marked for bottom inclusion
                // If we're in the <head>, use load() calls rather than <script src="..."> tags
                // Messages should go first
-               $scripts = $this->makeResourceLoaderLink( $this->getModuleMessages( true, 'bottom' ),
+               $links = array();
+               $links[] = $this->makeResourceLoaderLink( $this->getModuleMessages( true, 'bottom' ),
                        ResourceLoaderModule::TYPE_MESSAGES, /* $useESI = */ false, /* $extraQuery = */ array(),
                        /* $loadCall = */ $inHead
                );
-               $scripts .= $this->makeResourceLoaderLink( $this->getModuleScripts( true, 'bottom' ),
+               $links[] = $this->makeResourceLoaderLink( $this->getModuleScripts( true, 'bottom' ),
                        ResourceLoaderModule::TYPE_SCRIPTS, /* $useESI = */ false, /* $extraQuery = */ array(),
                        /* $loadCall = */ $inHead
                );
@@ -2844,7 +2890,7 @@ $templates
                // Only load modules that have marked themselves for loading at the bottom
                $modules = $this->getModules( true, 'bottom' );
                if ( $modules ) {
-                       $scripts .= Html::inlineScript(
+                       $links[] = Html::inlineScript(
                                ResourceLoader::makeLoaderConditionalScript(
                                        Xml::encodeJsCall( 'mw.loader.load', array( $modules, null, true ) )
                                )
@@ -2852,88 +2898,40 @@ $templates
                }
 
                // Legacy Scripts
-               $scripts .= "\n" . $this->mScripts;
-
-               $defaultModules = array();
+               $links[] = "\n" . $this->mScripts;
 
                // Add site JS if enabled
-               if ( $wgUseSiteJs ) {
-                       $scripts .= $this->makeResourceLoaderLink( 'site', ResourceLoaderModule::TYPE_SCRIPTS,
-                               /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
-                       );
-                       $defaultModules['site'] = 'loading';
-               } else {
-                       // Site module is empty, save request by marking ready in advance (bug 46857)
-                       $defaultModules['site'] = 'ready';
-               }
+               $links[] = $this->makeResourceLoaderLink( 'site', ResourceLoaderModule::TYPE_SCRIPTS,
+                       /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
+               );
 
                // Add user JS if enabled
-               if ( $wgAllowUserJs ) {
-                       if ( $this->getUser()->isLoggedIn() ) {
-                               if ( $this->getTitle() && $this->getTitle()->isJsSubpage() && $this->userCanPreview() ) {
-                                       # XXX: additional security check/prompt?
-                                       // We're on a preview of a JS subpage
-                                       // Exclude this page from the user module in case it's in there (bug 26283)
-                                       $scripts .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS, false,
-                                               array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() ), $inHead
-                                       );
-                                       // Load the previewed JS
-                                       $scripts .= Html::inlineScript( "\n" . $this->getRequest()->getText( 'wpTextbox1' ) . "\n" ) . "\n";
-                                       // FIXME: If the user is previewing, say, ./vector.js, his ./common.js will be loaded
-                                       // asynchronously and may arrive *after* the inline script here. So the previewed code
-                                       // may execute before ./common.js runs. Normally, ./common.js runs before ./vector.js...
-                               } else {
-                                       // Include the user module normally, i.e., raw to avoid it being wrapped in a closure.
-                                       $scripts .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS,
-                                               /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
-                                       );
-                               }
-                               $defaultModules['user'] = 'loading';
-                       } else {
-                               // Non-logged-in users have an empty user module.
-                               // Save request by marking ready in advance (bug 46857)
-                               $defaultModules['user'] = 'ready';
-                       }
+               if ( $wgAllowUserJs && $this->getUser()->isLoggedIn() && $this->getTitle() && $this->getTitle()->isJsSubpage() && $this->userCanPreview() ) {
+                       # XXX: additional security check/prompt?
+                       // We're on a preview of a JS subpage
+                       // Exclude this page from the user module in case it's in there (bug 26283)
+                       $links[] = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS, false,
+                               array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() ), $inHead
+                       );
+                       // Load the previewed JS
+                       $links[] = Html::inlineScript( "\n" . $this->getRequest()->getText( 'wpTextbox1' ) . "\n" ) . "\n";
+
+                       // FIXME: If the user is previewing, say, ./vector.js, his ./common.js will be loaded
+                       // asynchronously and may arrive *after* the inline script here. So the previewed code
+                       // may execute before ./common.js runs. Normally, ./common.js runs before ./vector.js...
                } else {
-                       // User modules are disabled on this wiki.
-                       // Save request by marking ready in advance (bug 46857)
-                       $defaultModules['user'] = 'ready';
+                       // Include the user module normally, i.e., raw to avoid it being wrapped in a closure.
+                       $links[] = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS,
+                               /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
+                       );
                }
 
                // Group JS is only enabled if site JS is enabled.
-               if ( $wgUseSiteJs ) {
-                       if ( $this->getUser()->isLoggedIn() ) {
-                               $scripts .= $this->makeResourceLoaderLink( 'user.groups', ResourceLoaderModule::TYPE_COMBINED,
-                                       /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
-                               );
-                               $defaultModules['user.groups'] = 'loading';
-                       } else {
-                               // Non-logged-in users have no user.groups module.
-                               // Save request by marking ready in advance (bug 46857)
-                               $defaultModules['user.groups'] = 'ready';
-                       }
-               } else {
-                       // Site (and group JS) disabled
-                       $defaultModules['user.groups'] = 'ready';
-               }
+               $links[] = $this->makeResourceLoaderLink( 'user.groups', ResourceLoaderModule::TYPE_COMBINED,
+                       /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
+               );
 
-               $loaderInit = '';
-               if ( $inHead ) {
-                       // We generate loader calls anyway, so no need to fix the client-side loader's state to 'loading'.
-                       foreach ( $defaultModules as $m => $state ) {
-                               if ( $state == 'loading' ) {
-                                       unset( $defaultModules[$m] );
-                               }
-                       }
-               }
-               if ( count( $defaultModules ) > 0 ) {
-                       $loaderInit = Html::inlineScript(
-                               ResourceLoader::makeLoaderConditionalScript(
-                                       ResourceLoader::makeLoaderStateScript( $defaultModules )
-                               )
-                       ) . "\n";
-               }
-               return $loaderInit . $scripts;
+               return self::getHtmlFromLoaderLinks( $links );
        }
 
        /**
@@ -3399,7 +3397,7 @@ $templates
                        # If wanted, and the interface is right-to-left, flip the CSS
                        $style_css = CSSJanus::transform( $style_css, true, false );
                }
-               $this->mInlineStyles .= Html::inlineStyle( $style_css );
+               $this->mInlineStyles .= Html::inlineStyle( $style_css ) . "\n";
        }
 
        /**
@@ -3414,49 +3412,43 @@ $templates
                $this->getSkin()->setupSkinUserCss( $this );
 
                // Add ResourceLoader styles
-               // Split the styles into four groups
+               // Split the styles into these groups
                $styles = array( 'other' => array(), 'user' => array(), 'site' => array(), 'private' => array(), 'noscript' => array() );
+               $links = array();
                $otherTags = ''; // Tags to append after the normal <link> tags
                $resourceLoader = $this->getResourceLoader();
 
                $moduleStyles = $this->getModuleStyles();
 
                // Per-site custom styles
-               if ( $wgUseSiteCss ) {
-                       $moduleStyles[] = 'site';
-                       $moduleStyles[] = 'noscript';
-                       if ( $this->getUser()->isLoggedIn() ) {
-                               $moduleStyles[] = 'user.groups';
-                       }
-               }
+               $moduleStyles[] = 'site';
+               $moduleStyles[] = 'noscript';
+               $moduleStyles[] = 'user.groups';
 
                // Per-user custom styles
-               if ( $wgAllowUserCss ) {
-                       if ( $this->getTitle()->isCssSubpage() && $this->userCanPreview() ) {
-                               // We're on a preview of a CSS subpage
-                               // Exclude this page from the user module in case it's in there (bug 26283)
-                               $otherTags .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_STYLES, false,
-                                       array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() )
-                               );
-
-                               // Load the previewed CSS
-                               // If needed, Janus it first. This is user-supplied CSS, so it's
-                               // assumed to be right for the content language directionality.
-                               $previewedCSS = $this->getRequest()->getText( 'wpTextbox1' );
-                               if ( $this->getLanguage()->getDir() !== $wgContLang->getDir() ) {
-                                       $previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
-                               }
-                               $otherTags .= Html::inlineStyle( $previewedCSS );
-                       } else {
-                               // Load the user styles normally
-                               $moduleStyles[] = 'user';
+               if ( $wgAllowUserCss && $this->getTitle()->isCssSubpage() && $this->userCanPreview() ) {
+                       // We're on a preview of a CSS subpage
+                       // Exclude this page from the user module in case it's in there (bug 26283)
+                       $link = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_STYLES, false,
+                               array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() )
+                       );
+                       $otherTags .= $link['html'];
+
+                       // Load the previewed CSS
+                       // If needed, Janus it first. This is user-supplied CSS, so it's
+                       // assumed to be right for the content language directionality.
+                       $previewedCSS = $this->getRequest()->getText( 'wpTextbox1' );
+                       if ( $this->getLanguage()->getDir() !== $wgContLang->getDir() ) {
+                               $previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
                        }
+                       $otherTags .= Html::inlineStyle( $previewedCSS ) . "\n";
+               } else {
+                       // Load the user styles normally
+                       $moduleStyles[] = 'user';
                }
 
                // Per-user preference styles
-               if ( $wgAllowUserCssPrefs ) {
-                       $moduleStyles[] = 'user.cssprefs';
-               }
+               $moduleStyles[] = 'user.cssprefs';
 
                foreach ( $moduleStyles as $name ) {
                        $module = $resourceLoader->getModule( $name );
@@ -3464,34 +3456,33 @@ $templates
                                continue;
                        }
                        $group = $module->getGroup();
-                       // Modules in groups named "other" or anything different than "user", "site" or "private"
+                       // Modules in groups different than the ones listed on top (see $styles assignment)
                        // will be placed in the "other" group
-                       $styles[isset( $styles[$group] ) ? $group : 'other'][] = $name;
+                       $styles[ isset( $styles[$group] ) ? $group : 'other' ][] = $name;
                }
 
                // We want site, private and user styles to override dynamically added styles from modules, but we want
                // dynamically added styles to override statically added styles from other modules. So the order
                // has to be other, dynamic, site, private, user
                // Add statically added styles for other modules
-               $ret = $this->makeResourceLoaderLink( $styles['other'], ResourceLoaderModule::TYPE_STYLES );
+               $links[] = $this->makeResourceLoaderLink( $styles['other'], ResourceLoaderModule::TYPE_STYLES );
                // Add normal styles added through addStyle()/addInlineStyle() here
-               $ret .= implode( "\n", $this->buildCssLinksArray() ) . $this->mInlineStyles;
+               $links[] = implode( "\n", $this->buildCssLinksArray() ) . $this->mInlineStyles;
                // Add marker tag to mark the place where the client-side loader should inject dynamic styles
                // We use a <meta> tag with a made-up name for this because that's valid HTML
-               $ret .= Html::element( 'meta', array( 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' ) ) . "\n";
+               $links[] = Html::element( 'meta', array( 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' ) ) . "\n";
 
                // Add site, private and user styles
                // 'private' at present only contains user.options, so put that before 'user'
                // Any future private modules will likely have a similar user-specific character
                foreach ( array( 'site', 'noscript', 'private', 'user' ) as $group ) {
-                       $ret .= $this->makeResourceLoaderLink( $styles[$group],
-                                       ResourceLoaderModule::TYPE_STYLES
+                       $links[] = $this->makeResourceLoaderLink( $styles[$group],
+                               ResourceLoaderModule::TYPE_STYLES
                        );
                }
 
                // Add stuff in $otherTags (previewed user CSS if applicable)
-               $ret .= $otherTags;
-               return $ret;
+               return self::getHtmlFromLoaderLinks( $links ) . $otherTags;
        }
 
        /**
index 2d1529d..33d9333 100644 (file)
@@ -309,7 +309,7 @@ class Preferences {
                                'section' => 'personal/info',
                        );
                }
-               // Only show preferhttps if secure login is turned on
+               // Only show prefershttps if secure login is turned on
                if ( $wgSecureLogin && wfCanIPUseHTTPS( $context->getRequest()->getIP() ) ) {
                        $defaultPreferences['prefershttps'] = array(
                                'type' => 'toggle',
index 780cae5..957a119 100644 (file)
  *
  * @ingroup Search
  */
-class PrefixSearch {
+abstract class PrefixSearch {
        /**
         * Do a prefix search of titles and return a list of matching page names.
+        * @deprecated: Since 1.23, use TitlePrefixSearch or StringPrefixSearch classes
         *
         * @param $search String
         * @param $limit Integer
@@ -36,11 +37,24 @@ class PrefixSearch {
         * @return Array of strings
         */
        public static function titleSearch( $search, $limit, $namespaces = array() ) {
+               $search = new StringPrefixSearch;
+               return $search->search( $search, $limit, $namespaces );
+       }
+
+       /**
+        * Do a prefix search of titles and return a list of matching page names.
+        *
+        * @param $search String
+        * @param $limit Integer
+        * @param array $namespaces used if query is not explicitly prefixed
+        * @return Array of strings or Title objects
+        */
+       public function search( $search, $limit, $namespaces = array() ) {
                $search = trim( $search );
                if ( $search == '' ) {
                        return array(); // Return empty result
                }
-               $namespaces = self::validateNamespaces( $namespaces );
+               $namespaces = $this->validateNamespaces( $namespaces );
 
                // Find a Title which is not an interwiki and is in NS_MAIN
                $title = Title::newFromText( $search );
@@ -49,7 +63,7 @@ class PrefixSearch {
                        if ( $ns[0] == NS_MAIN ) {
                                $ns = $namespaces; // no explicit prefix, use default namespaces
                        }
-                       return self::searchBackend(
+                       return $this->searchBackend(
                                $ns, $title->getText(), $limit );
                }
 
@@ -57,14 +71,68 @@ class PrefixSearch {
                $title = Title::newFromText( $search . 'Dummy' );
                if ( $title && $title->getText() == 'Dummy'
                        && $title->getNamespace() != NS_MAIN
-                       && !$title->isExternal() ) {
-                       return self::searchBackend(
-                               array( $title->getNamespace() ), '', $limit );
+                       && !$title->isExternal() )
+               {
+                       $namespaces = array( $title->getNamespace() );
+                       $search = '';
                }
 
-               return self::searchBackend( $namespaces, $search, $limit );
+               return $this->searchBackend( $namespaces, $search, $limit );
+       }
+
+       /**
+        * Do a prefix search for all possible variants of the prefix
+        * @param $search String
+        * @param $limit Integer
+        * @param array $namespaces
+        *
+        * @return array
+        */
+       public function searchWithVariants( $search, $limit, array $namespaces ) {
+               wfProfileIn( __METHOD__ );
+               $searches = $this->search( $search, $limit, $namespaces );
+
+               // if the content language has variants, try to retrieve fallback results
+               $fallbackLimit = $limit - count( $searches );
+               if ( $fallbackLimit > 0 ) {
+                       global $wgContLang;
+
+                       $fallbackSearches = $wgContLang->autoConvertToAllVariants( $search );
+                       $fallbackSearches = array_diff( array_unique( $fallbackSearches ), array( $search ) );
+
+                       foreach ( $fallbackSearches as $fbs ) {
+                               $fallbackSearchResult = $this->search( $fbs, $fallbackLimit, $namespaces );
+                               $searches = array_merge( $searches, $fallbackSearchResult );
+                               $fallbackLimit -= count( $fallbackSearchResult );
+
+                               if ( $fallbackLimit == 0 ) {
+                                       break;
+                               }
+                       }
+               }
+               wfProfileOut( __METHOD__ );
+               return $searches;
        }
 
+       /**
+        * When implemented in a descendant class, receives an array of Title objects and returns
+        * either an unmodified array or an array of strings corresponding to titles passed to it.
+        *
+        * @param array $titles
+        * @return array
+        */
+       protected abstract function titles( array $titles );
+
+       /**
+        * When implemented in a descendant class, receives an array of titles as strings and returns
+        * either an unmodified array or an array of Title objects corresponding to strings received.
+        *
+        * @param array $strings
+        *
+        * @return array
+        */
+       protected abstract function strings( array $strings );
+
        /**
         * Do a prefix search of titles and return a list of matching page names.
         * @param $namespaces Array
@@ -72,20 +140,20 @@ class PrefixSearch {
         * @param $limit Integer
         * @return Array of strings
         */
-       protected static function searchBackend( $namespaces, $search, $limit ) {
+       protected function searchBackend( $namespaces, $search, $limit ) {
                if ( count( $namespaces ) == 1 ) {
                        $ns = $namespaces[0];
                        if ( $ns == NS_MEDIA ) {
                                $namespaces = array( NS_FILE );
                        } elseif ( $ns == NS_SPECIAL ) {
-                               return self::specialSearch( $search, $limit );
+                               return $this->titles( $this->specialSearch( $search, $limit ) );
                        }
                }
                $srchres = array();
                if ( wfRunHooks( 'PrefixSearchBackend', array( $namespaces, $search, $limit, &$srchres ) ) ) {
-                       return self::defaultSearchBackend( $namespaces, $search, $limit );
+                       return $this->titles( $this->defaultSearchBackend( $namespaces, $search, $limit ) );
                }
-               return $srchres;
+               return $this->strings( $srchres );
        }
 
        /**
@@ -95,7 +163,7 @@ class PrefixSearch {
         * @param $limit Integer: max number of items to return
         * @return Array
         */
-       protected static function specialSearch( $search, $limit ) {
+       protected function specialSearch( $search, $limit ) {
                global $wgContLang;
 
                # normalize searchKey, so aliases with spaces can be found - bug 25675
@@ -129,7 +197,7 @@ class PrefixSearch {
                                // localizes its input leading to searches for e.g. Special:All
                                // returning Spezial:MediaWiki-Systemnachrichten and returning
                                // Spezial:Alle_Seiten twice when $wgLanguageCode == 'de'
-                               $srchres[] = Title::makeTitleSafe( NS_SPECIAL, $page )->getPrefixedText();
+                               $srchres[] = Title::makeTitleSafe( NS_SPECIAL, $page );
                                wfRestoreWarnings();
                        }
 
@@ -150,38 +218,30 @@ class PrefixSearch {
         * @param array $namespaces namespaces to search in
         * @param string $search term
         * @param $limit Integer: max number of items to return
-        * @return Array of title strings
+        * @return Array of Title objects
         */
-       protected static function defaultSearchBackend( $namespaces, $search, $limit ) {
+       protected function defaultSearchBackend( $namespaces, $search, $limit ) {
                $ns = array_shift( $namespaces ); // support only one namespace
                if ( in_array( NS_MAIN, $namespaces ) ) {
                        $ns = NS_MAIN; // if searching on many always default to main
                }
 
-               // Prepare nested request
-               $req = new FauxRequest( array(
-                       'action' => 'query',
-                       'list' => 'allpages',
-                       'apnamespace' => $ns,
-                       'aplimit' => $limit,
-                       'apprefix' => $search
-               ));
-
-               // Execute
-               $module = new ApiMain( $req );
-               $module->execute();
-
-               // Get resulting data
-               $data = $module->getResultData();
-
-               // Reformat useful data for future printing by JSON engine
+               $t = Title::newFromText( $search, $ns );
+               $prefix = $t ? $t->getDBkey() : '';
+               $dbr = wfGetDB( DB_SLAVE );
+               $res = $dbr->select( 'page',
+                       array( 'page_id', 'page_namespace', 'page_title' ),
+                       array(
+                               'page_namespace' => $ns,
+                               'page_title ' . $dbr->buildLike( $prefix, $dbr->anyString() )
+                       ),
+                       __METHOD__,
+                       array( 'LIMIT' => $limit, 'ORDER BY' => 'page_title' )
+               );
                $srchres = array();
-               foreach ( (array)$data['query']['allpages'] as $pageinfo ) {
-                       // Note: this data will no be printable by the xml engine
-                       // because it does not support lists of unnamed items
-                       $srchres[] = $pageinfo['title'];
+               foreach ( $res as $row ) {
+                       $srchres[] = Title::newFromRow( $row );
                }
-
                return $srchres;
        }
 
@@ -191,7 +251,7 @@ class PrefixSearch {
         * @param $namespaces Array
         * @return Array (default: contains only NS_MAIN)
         */
-       protected static function validateNamespaces( $namespaces ) {
+       protected function validateNamespaces( $namespaces ) {
                global $wgContLang;
 
                // We will look at each given namespace against wgContLang namespaces
@@ -211,3 +271,37 @@ class PrefixSearch {
                return array( NS_MAIN );
        }
 }
+
+/**
+ * Performs prefix search, returning Title objects
+ * @ingroup Search
+ */
+class TitlePrefixSearch extends PrefixSearch {
+
+       protected function titles( array $titles ) {
+               return $titles;
+       }
+
+       protected function strings( array $strings ) {
+               $titles = array_map( 'Title::newFromText', $strings );
+               $lb = new LinkBatch( $titles );
+               $lb->setCaller( __METHOD__ );
+               $lb->execute();
+               return $titles;
+       }
+}
+
+/**
+ * Performs prefix search, returning strings
+ * @ingroup Search
+ */
+class StringPrefixSearch extends PrefixSearch {
+
+       protected function titles( array $titles ) {
+               return array_map( function( Title $t ) { return $t->getPrefixedText(); }, $titles );
+       }
+
+       protected function strings( array $strings ) {
+               return $strings;
+       }
+}
index 38c3623..9ec7c31 100644 (file)
@@ -1573,14 +1573,14 @@ abstract class Skin extends ContextSource {
         * Create a section edit link.  This supersedes editSectionLink() and
         * editSectionLinkForOther().
         *
-        * @param $nt      Title  The title being linked to (may not be the same as
+        * @param $nt Title  The title being linked to (may not be the same as
         *   the current page, if the section is included from a template)
         * @param string $section The designation of the section being pointed to,
         *   to be included in the link, like "&section=$section"
         * @param string $tooltip The tooltip to use for the link: will be escaped
         *   and wrapped in the 'editsectionhint' message
-        * @param $lang    string Language code
-        * @return         string HTML to use for edit link
+        * @param $lang string Language code
+        * @return string HTML to use for edit link
         */
        public function doEditSectionLink( Title $nt, $section, $tooltip = null, $lang = false ) {
                // HTML generated here should probably have userlangattributes
index 995deeb..d025f35 100644 (file)
@@ -4916,7 +4916,7 @@ class Title {
         * they will already be wrapped in paragraphs.
         *
         * @since 1.21
-        * @param int oldid Revision ID that's being edited
+        * @param int $oldid Revision ID that's being edited
         * @return Array
         */
        public function getEditNotices( $oldid = 0 ) {
index 5d5859d..00366e4 100644 (file)
@@ -38,7 +38,7 @@ class UserArrayFromResult extends UserArray implements Countable {
        }
 
        /**
-        * @param  $row
+        * @param $row
         * @return void
         */
        protected function setCurrent( $row ) {
index 18409b0..a5d66df 100644 (file)
@@ -1812,56 +1812,62 @@ class WikiPage implements Page, IDBAccessObject {
                                }
 
                                $dbw->begin( __METHOD__ );
+                               try {
 
-                               $prepStatus = $content->prepareSave( $this, $flags, $baseRevId, $user );
-                               $status->merge( $prepStatus );
+                                       $prepStatus = $content->prepareSave( $this, $flags, $baseRevId, $user );
+                                       $status->merge( $prepStatus );
 
-                               if ( !$status->isOK() ) {
-                                       $dbw->rollback( __METHOD__ );
+                                       if ( !$status->isOK() ) {
+                                               $dbw->rollback( __METHOD__ );
 
-                                       wfProfileOut( __METHOD__ );
-                                       return $status;
-                               }
+                                               wfProfileOut( __METHOD__ );
+                                               return $status;
+                                       }
+                                       $revisionId = $revision->insertOn( $dbw );
 
-                               $revisionId = $revision->insertOn( $dbw );
+                                       // Update page
+                                       //
+                                       // Note that we use $this->mLatest instead of fetching a value from the master DB
+                                       // during the course of this function. This makes sure that EditPage can detect
+                                       // edit conflicts reliably, either by $ok here, or by $article->getTimestamp()
+                                       // before this function is called. A previous function used a separate query, this
+                                       // creates a window where concurrent edits can cause an ignored edit conflict.
+                                       $ok = $this->updateRevisionOn( $dbw, $revision, $oldid, $oldIsRedirect );
 
-                               // Update page
-                               //
-                               // Note that we use $this->mLatest instead of fetching a value from the master DB
-                               // during the course of this function. This makes sure that EditPage can detect
-                               // edit conflicts reliably, either by $ok here, or by $article->getTimestamp()
-                               // before this function is called. A previous function used a separate query, this
-                               // creates a window where concurrent edits can cause an ignored edit conflict.
-                               $ok = $this->updateRevisionOn( $dbw, $revision, $oldid, $oldIsRedirect );
+                                       if ( !$ok ) {
+                                               // Belated edit conflict! Run away!!
+                                               $status->fatal( 'edit-conflict' );
 
-                               if ( !$ok ) {
-                                       // Belated edit conflict! Run away!!
-                                       $status->fatal( 'edit-conflict' );
+                                               $dbw->rollback( __METHOD__ );
 
-                                       $dbw->rollback( __METHOD__ );
-
-                                       wfProfileOut( __METHOD__ );
-                                       return $status;
-                               }
+                                               wfProfileOut( __METHOD__ );
+                                               return $status;
+                                       }
 
-                               wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, $baseRevId, $user ) );
-                               // Update recentchanges
-                               if ( !( $flags & EDIT_SUPPRESS_RC ) ) {
-                                       // Mark as patrolled if the user can do so
-                                       $patrolled = $wgUseRCPatrol && !count(
+                                       wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, $baseRevId, $user ) );
+                                       // Update recentchanges
+                                       if ( !( $flags & EDIT_SUPPRESS_RC ) ) {
+                                               // Mark as patrolled if the user can do so
+                                               $patrolled = $wgUseRCPatrol && !count(
                                                $this->mTitle->getUserPermissionsErrors( 'autopatrol', $user ) );
-                                       // Add RC row to the DB
-                                       $rc = RecentChange::notifyEdit( $now, $this->mTitle, $isminor, $user, $summary,
-                                               $oldid, $this->getTimestamp(), $bot, '', $oldsize, $newsize,
-                                               $revisionId, $patrolled
-                                       );
+                                               // Add RC row to the DB
+                                               $rc = RecentChange::notifyEdit( $now, $this->mTitle, $isminor, $user, $summary,
+                                                       $oldid, $this->getTimestamp(), $bot, '', $oldsize, $newsize,
+                                                       $revisionId, $patrolled
+                                               );
 
-                                       // Log auto-patrolled edits
-                                       if ( $patrolled ) {
-                                               PatrolLog::record( $rc, true, $user );
+                                               // Log auto-patrolled edits
+                                               if ( $patrolled ) {
+                                                       PatrolLog::record( $rc, true, $user );
+                                               }
                                        }
+                                       $user->incEditCount();
+                               } catch ( MWException $e ) {
+                                       $dbw->rollback( __METHOD__ );
+                                       // Question: Would it perhaps be better if this method turned all
+                                       // exceptions into $status's?
+                                       throw $e;
                                }
-                               $user->incEditCount();
                                $dbw->commit( __METHOD__ );
                        } else {
                                // Bug 32948: revision ID must be set to page {{REVISIONID}} and
@@ -1891,74 +1897,80 @@ class WikiPage implements Page, IDBAccessObject {
                        $status->value['new'] = true;
 
                        $dbw->begin( __METHOD__ );
+                       try {
 
-                       $prepStatus = $content->prepareSave( $this, $flags, $baseRevId, $user );
-                       $status->merge( $prepStatus );
+                               $prepStatus = $content->prepareSave( $this, $flags, $baseRevId, $user );
+                               $status->merge( $prepStatus );
 
-                       if ( !$status->isOK() ) {
-                               $dbw->rollback( __METHOD__ );
+                               if ( !$status->isOK() ) {
+                                       $dbw->rollback( __METHOD__ );
 
-                               wfProfileOut( __METHOD__ );
-                               return $status;
-                       }
+                                       wfProfileOut( __METHOD__ );
+                                       return $status;
+                               }
 
-                       $status->merge( $prepStatus );
+                               $status->merge( $prepStatus );
 
-                       // Add the page record; stake our claim on this title!
-                       // This will return false if the article already exists
-                       $newid = $this->insertOn( $dbw );
+                               // Add the page record; stake our claim on this title!
+                               // This will return false if the article already exists
+                               $newid = $this->insertOn( $dbw );
 
-                       if ( $newid === false ) {
-                               $dbw->rollback( __METHOD__ );
-                               $status->fatal( 'edit-already-exists' );
+                               if ( $newid === false ) {
+                                       $dbw->rollback( __METHOD__ );
+                                       $status->fatal( 'edit-already-exists' );
 
-                               wfProfileOut( __METHOD__ );
-                               return $status;
-                       }
+                                       wfProfileOut( __METHOD__ );
+                                       return $status;
+                               }
 
-                       // Save the revision text...
-                       $revision = new Revision( array(
-                               'page'       => $newid,
-                               'title'      => $this->getTitle(), // for determining the default content model
-                               'comment'    => $summary,
-                               'minor_edit' => $isminor,
-                               'text'       => $serialized,
-                               'len'        => $newsize,
-                               'user'       => $user->getId(),
-                               'user_text'  => $user->getName(),
-                               'timestamp'  => $now,
-                               'content_model' => $content->getModel(),
-                               'content_format' => $serialisation_format,
-                       ) );
-                       $revisionId = $revision->insertOn( $dbw );
+                               // Save the revision text...
+                               $revision = new Revision( array(
+                                       'page'       => $newid,
+                                       'title'      => $this->getTitle(), // for determining the default content model
+                                       'comment'    => $summary,
+                                       'minor_edit' => $isminor,
+                                       'text'       => $serialized,
+                                       'len'        => $newsize,
+                                       'user'       => $user->getId(),
+                                       'user_text'  => $user->getName(),
+                                       'timestamp'  => $now,
+                                       'content_model' => $content->getModel(),
+                                       'content_format' => $serialisation_format,
+                               ) );
+                               $revisionId = $revision->insertOn( $dbw );
 
-                       // Bug 37225: use accessor to get the text as Revision may trim it
-                       $content = $revision->getContent(); // sanity; get normalized version
+                               // Bug 37225: use accessor to get the text as Revision may trim it
+                               $content = $revision->getContent(); // sanity; get normalized version
 
-                       if ( $content ) {
-                               $newsize = $content->getSize();
-                       }
+                               if ( $content ) {
+                                       $newsize = $content->getSize();
+                               }
 
-                       // Update the page record with revision data
-                       $this->updateRevisionOn( $dbw, $revision, 0 );
+                               // Update the page record with revision data
+                               $this->updateRevisionOn( $dbw, $revision, 0 );
 
-                       wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) );
+                               wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) );
 
-                       // Update recentchanges
-                       if ( !( $flags & EDIT_SUPPRESS_RC ) ) {
-                               // Mark as patrolled if the user can do so
-                               $patrolled = ( $wgUseRCPatrol || $wgUseNPPatrol ) && !count(
-                                       $this->mTitle->getUserPermissionsErrors( 'autopatrol', $user ) );
-                               // Add RC row to the DB
-                               $rc = RecentChange::notifyNew( $now, $this->mTitle, $isminor, $user, $summary, $bot,
-                                       '', $newsize, $revisionId, $patrolled );
+                               // Update recentchanges
+                               if ( !( $flags & EDIT_SUPPRESS_RC ) ) {
+                                       // Mark as patrolled if the user can do so
+                                       $patrolled = ( $wgUseRCPatrol || $wgUseNPPatrol ) && !count(
+                                               $this->mTitle->getUserPermissionsErrors( 'autopatrol', $user ) );
+                                       // Add RC row to the DB
+                                       $rc = RecentChange::notifyNew( $now, $this->mTitle, $isminor, $user, $summary, $bot,
+                                               '', $newsize, $revisionId, $patrolled );
 
-                               // Log auto-patrolled edits
-                               if ( $patrolled ) {
-                                       PatrolLog::record( $rc, true, $user );
+                                       // Log auto-patrolled edits
+                                       if ( $patrolled ) {
+                                               PatrolLog::record( $rc, true, $user );
+                                       }
                                }
+                               $user->incEditCount();
+
+                       } catch ( MWException $e ) {
+                               $dbw->rollback( __METHOD__ );
+                               throw $e;
                        }
-                       $user->incEditCount();
                        $dbw->commit( __METHOD__ );
 
                        // Update links, etc.
index 45441fd..3b82c64 100644 (file)
@@ -901,7 +901,7 @@ class XmlSelect {
         * label => value
         * label => ( label => value, label => value )
         *
-        * @param  $options
+        * @param $options
         */
        public function addOptions( $options ) {
                $this->options[] = $options;
@@ -912,7 +912,7 @@ class XmlSelect {
         * label => value
         * label => ( label => value, label => value )
         *
-        * @param  $options
+        * @param $options
         * @param bool $default
         * @return string
         */
index 974ee94..73bf187 100644 (file)
@@ -91,7 +91,7 @@ abstract class FormAction extends Action {
         * Process the form on POST submission.  If you return false from getFormFields(),
         * this will obviously never be reached.  If you don't want to do anything with the
         * form, just return false here
-        * @param  $data Array
+        * @param $data Array
         * @return Bool|Array true for success, false for didn't-try, array of errors on failure
         */
        abstract public function onSubmit( $data );
index e1b5d52..2c7502e 100644 (file)
@@ -82,7 +82,14 @@ class WatchAction extends FormAction {
        protected function checkCanExecute( User $user ) {
                // Must be logged in
                if ( $user->isAnon() ) {
-                       throw new ErrorPageError( 'watchnologin', 'watchnologintext' );
+                       $loginreqlink = Linker::linkKnown(
+                               SpecialPage::getTitleFor( 'Userlogin' ),
+                               $this->msg( 'loginreqlink' )->escaped(),
+                               array(),
+                               array( 'returnto' => $this->getPageTitle(), 'returntoquery' => 'action=' . $this->getName() )
+                       );
+                       $reasonMsg = $this->msg( 'watchlistanontext' )->rawParams( $loginreqlink );
+                       throw new UserNotLoggedIn( $reasonMsg, 'watchnologin' );
                }
 
                return parent::checkCanExecute( $user );
index 72b1f88..fc1bfd1 100644 (file)
@@ -896,7 +896,7 @@ abstract class ApiBase extends ContextSource {
        /**
         * Callback function used in requireOnlyOneParameter to check whether required parameters are set
         *
-        * @param  $x object Parameter to check is not null/false
+        * @param $x object Parameter to check is not null/false
         * @return bool
         */
        private function parameterNotEmpty( $x ) {
@@ -1322,8 +1322,8 @@ abstract class ApiBase extends ContextSource {
        /**
         * Adds a warning to the output, else dies
         *
-        * @param  $msg String Message to show as a warning, or error message if dying
-        * @param  $enforceLimits Boolean Whether this is an enforce (die)
+        * @param $msg String Message to show as a warning, or error message if dying
+        * @param $enforceLimits Boolean Whether this is an enforce (die)
         */
        private function warnOrDie( $msg, $enforceLimits = false ) {
                if ( $enforceLimits ) {
index f1c1bf3..9062ad9 100644 (file)
@@ -80,6 +80,10 @@ class ApiFeedRecentChanges extends ApiBase {
        public function getFeedObject( $feedFormat, $specialClass ) {
                if ( $specialClass === 'SpecialRecentchangeslinked' ) {
                        $title = Title::newFromText( $this->params['target'] );
+                       if ( !$title ) {
+                               $this->dieUsageMsg( array( 'invalidtitle', $this->params['target'] ) );
+                       }
+
                        $feed = new ChangesFeed( $feedFormat, false );
                        $feedObj = $feed->getFeedObject(
                                $this->msg( 'recentchangeslinked-title', $title->getPrefixedText() )
index e584d0d..ed64cd5 100644 (file)
@@ -107,8 +107,8 @@ class ApiHelp extends ApiBase {
        }
 
        /**
-        * @param  $module ApiBase
-        * @param  $type String What type of request is this? e.g. action, query, list, prop, meta, format
+        * @param $module ApiBase
+        * @param $type String What type of request is this? e.g. action, query, list, prop, meta, format
         * @return string
         */
        private function buildModuleHelp( $module, $type ) {
index 10b655f..1190781 100644 (file)
@@ -148,8 +148,8 @@ class ApiMove extends ApiBase {
        /**
         * @param Title $fromTitle
         * @param Title $toTitle
-        * @param  $reason
-        * @param  $noredirect
+        * @param $reason
+        * @param $noredirect
         * @return array
         */
        public function moveSubpages( $fromTitle, $toTitle, $reason, $noredirect ) {
index f2bf754..68b62af 100644 (file)
@@ -60,28 +60,8 @@ class ApiOpenSearch extends ApiBase {
                        $this->getMain()->setCacheMaxAge( $wgSearchSuggestCacheExpiry );
                        $this->getMain()->setCacheMode( 'public' );
 
-                       $searches = PrefixSearch::titleSearch( $search, $limit,
-                               $namespaces );
-
-                       // if the content language has variants, try to retrieve fallback results
-                       $fallbackLimit = $limit - count( $searches );
-                       if ( $fallbackLimit > 0 ) {
-                               global $wgContLang;
-
-                               $fallbackSearches = $wgContLang->autoConvertToAllVariants( $search );
-                               $fallbackSearches = array_diff( array_unique( $fallbackSearches ), array( $search ) );
-
-                               foreach ( $fallbackSearches as $fbs ) {
-                                       $fallbackSearchResult = PrefixSearch::titleSearch( $fbs, $fallbackLimit,
-                                               $namespaces );
-                                       $searches = array_merge( $searches, $fallbackSearchResult );
-                                       $fallbackLimit -= count( $fallbackSearchResult );
-
-                                       if ( $fallbackLimit == 0 ) {
-                                               break;
-                                       }
-                               }
-                       }
+                       $searcher = new StringPrefixSearch;
+                       $searches = $searcher->searchWithVariants( $search, $limit, $namespaces );
                }
                // Set top level elements
                $result = $this->getResult();
index c6ae611..0a95fba 100644 (file)
@@ -86,6 +86,7 @@ class ApiQuery extends ApiBase {
                'logevents' => 'ApiQueryLogEvents',
                'pageswithprop' => 'ApiQueryPagesWithProp',
                'pagepropnames' => 'ApiQueryPagePropNames',
+               'prefixsearch' => 'ApiQueryPrefixSearch',
                'protectedtitles' => 'ApiQueryProtectedTitles',
                'querypage' => 'ApiQueryQueryPage',
                'random' => 'ApiQueryRandom',
index f738c50..58db035 100644 (file)
@@ -494,8 +494,8 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                        'Operates in three modes:',
                        ' 1) List deleted revisions for the given title(s), sorted by timestamp.',
                        ' 2) List deleted contributions for the given user, sorted by timestamp (no titles specified).',
-                       " 3) List all deleted revisions in the given namespace, sorted by title and timestamp',
-                       '    (no titles specified, {$p}user not set).",
+                       ' 3) List all deleted revisions in the given namespace, sorted by title and timestamp',
+                       "    (no titles specified, {$p}user not set).",
                        'Certain parameters only apply to some modes and are ignored in others.',
                        'For instance, a parameter marked (1) only applies to mode 1 and is ignored in modes 2 and 3.',
                );
diff --git a/includes/api/ApiQueryPrefixSearch.php b/includes/api/ApiQueryPrefixSearch.php
new file mode 100644 (file)
index 0000000..dfe0eec
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 1.23
+ */
+
+/**
+ * @ingroup API
+ */
+class ApiQueryPrefixSearch extends ApiQueryGeneratorBase {
+       public function __construct( $query, $moduleName ) {
+               parent::__construct( $query, $moduleName, 'ps' );
+       }
+
+       public function execute() {
+               $this->run();
+       }
+
+       public function executeGenerator( $resultPageSet ) {
+               $this->run( $resultPageSet );
+       }
+
+       /**
+        * @param $resultPageSet ApiPageSet
+        */
+       private function run( $resultPageSet = null ) {
+               $params = $this->extractRequestParams();
+               $search = $params['search'];
+               $limit = $params['limit'];
+               $namespaces = $params['namespace'];
+
+               $searcher = new TitlePrefixSearch;
+               $titles = $searcher->searchWithVariants( $search, $limit, $namespaces );
+               if ( $resultPageSet ) {
+                       $resultPageSet->populateFromTitles( $titles );
+               } else {
+                       $result = $this->getResult();
+                       foreach ( $titles as $title ) {
+                               if ( !$limit-- ) {
+                                       break;
+                               }
+                               $vals = array(
+                                       'ns' => intval( $title->getNamespace() ),
+                                       'title' => $title->getPrefixedText(),
+                               );
+                               if ( $title->isSpecialPage() ) {
+                                       $vals['special'] = '';
+                               } else {
+                                       $vals['pageid'] = intval( $title->getArticleId() );
+                               }
+                               $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals );
+                               if ( !$fit ) {
+                                       break;
+                               }
+                       }
+                       $result->setIndexedTagName_internal(
+                               array( 'query', $this->getModuleName() ), $this->getModulePrefix()
+                       );
+               }
+       }
+
+       public function getCacheMode( $params ) {
+               return 'public';
+       }
+
+       public function getAllowedParams() {
+                       return array(
+                               'search' => array(
+                                       ApiBase::PARAM_TYPE => 'string',
+                                       ApiBase::PARAM_REQUIRED => true,
+                               ),
+                               'namespace' => array(
+                                       ApiBase::PARAM_DFLT => NS_MAIN,
+                                       ApiBase::PARAM_TYPE => 'namespace',
+                                       ApiBase::PARAM_ISMULTI => true,
+                               ),
+                               'limit' => array(
+                                       ApiBase::PARAM_DFLT => 10,
+                                       ApiBase::PARAM_TYPE => 'limit',
+                                       ApiBase::PARAM_MIN => 1,
+                                       ApiBase::PARAM_MAX => 100, // Non-standard value for compatibility
+                                                                  // with action=opensearch
+                                       ApiBase::PARAM_MAX2 => 200,
+                               ),
+                       );
+       }
+
+       public function getParamDescription() {
+               return array(
+                       'search' => 'Search string',
+                       'limit' => 'Maximum amount of results to return',
+                       'namespace' => 'Namespaces to search',
+               );
+       }
+
+       public function getDescription() {
+               return 'Perform a prefix search for page titles';
+       }
+
+       public function getExamples() {
+               return array(
+                       'api.php?action=query&list=prefixsearch&pssearch=meaning',
+               );
+       }
+
+       public function getHelpUrls() {
+               return 'https://www.mediawiki.org/wiki/API:Prefixsearch';
+       }
+}
index 5f85e0e..ad26cce 100644 (file)
@@ -46,11 +46,11 @@ class ApiQueryRandom extends ApiQueryGeneratorBase {
        }
 
        /**
-        * @param  $randstr
-        * @param  $limit
-        * @param  $namespace
+        * @param $randstr
+        * @param $limit
+        * @param $namespace
         * @param $resultPageSet ApiPageSet
-        * @param  $redirect
+        * @param $redirect
         * @return void
         */
        protected function prepareQuery( $randstr, $limit, $namespace, &$resultPageSet, $redirect ) {
index 0284916..79a8dc9 100644 (file)
@@ -69,8 +69,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
        }
 
        /**
-        * @param  $pageid
-        * @param  $title
+        * @param $pageid
+        * @param $title
         * @param $rc RecentChange (optional)
         * @return bool|string
         */
index 6c310fd..2587b1d 100644 (file)
@@ -3,8 +3,8 @@
 use Composer\Package\Package;
 use Composer\Script\Event;
 
-$GLOBALS['IP'] = __DIR__ . '/../';
-require_once '../AutoLoader.php';
+$GLOBALS['IP'] = __DIR__ . '/../../';
+require_once __DIR__ . '/../AutoLoader.php';
 
 /**
  * @licence GNU GPL v2+
index f2f0c9d..77d3542 100644 (file)
@@ -375,7 +375,7 @@ abstract class AbstractContent implements Content {
         *
         * @see Content::preloadTransform
         */
-       public function preloadTransform( Title $title, ParserOptions $popts ) {
+       public function preloadTransform( Title $title, ParserOptions $popts, $params = array() ) {
                return $this;
        }
 
index 075635d..e9c6ac0 100644 (file)
@@ -437,10 +437,11 @@ interface Content {
         *
         * @param Title $title
         * @param ParserOptions $parserOptions
+        * @param array $params
         *
         * @return Content
         */
-       public function preloadTransform( Title $title, ParserOptions $parserOptions );
+       public function preloadTransform( Title $title, ParserOptions $parserOptions, $params = array() );
 
        /**
         * Prepare Content for saving. Called before Content is saved by WikiPage::doEditContent() and in
index 605222e..13ef1b9 100644 (file)
@@ -154,14 +154,15 @@ class WikitextContent extends TextContent {
         *
         * @param Title $title
         * @param ParserOptions $popts
+        * @param array $params
         *
         * @return Content
         */
-       public function preloadTransform( Title $title, ParserOptions $popts ) {
+       public function preloadTransform( Title $title, ParserOptions $popts, $params = array() ) {
                global $wgParser;
 
                $text = $this->getNativeData();
-               $plt = $wgParser->getPreloadText( $text, $title, $popts );
+               $plt = $wgParser->getPreloadText( $text, $title, $popts, $params );
 
                return new WikitextContent( $plt );
        }
index 50b7158..faed996 100644 (file)
@@ -164,8 +164,7 @@ class DatabaseMssql extends DatabaseBase {
         * @throws DBUnexpectedError
         */
        protected function doQuery( $sql ) {
-               global $wgDebugDumpSql;
-               if ( $wgDebugDumpSql ) {
+               if ( $this->debug() ) {
                        wfDebug( "SQL: [$sql]\n" );
                }
                $this->offset = 0;
index 6e0490d..0d13433 100644 (file)
@@ -1133,8 +1133,8 @@ class DatabaseOracle extends DatabaseBase {
 
        /**
         * @throws DBUnexpectedError
-        * @param  string $table
-        * @param  string $field
+        * @param string $table
+        * @param string $field
         * @return ORAField
         */
        function fieldInfo( $table, $field ) {
index fcce870..eca9564 100644 (file)
@@ -243,7 +243,10 @@ class LBFactorySimple extends LBFactory {
                        global $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, $wgDBtype, $wgDebugDumpSql;
                        global $wgDBssl, $wgDBcompress;
 
-                       $flags = ( $wgDebugDumpSql ? DBO_DEBUG : 0 ) | DBO_DEFAULT;
+                       $flags = DBO_DEFAULT;
+                       if ( $wgDebugDumpSql ) {
+                               $flags |= DBO_DEBUG;
+                       }
                        if ( $wgDBssl ) {
                                $flags |= DBO_SSL;
                        }
index 09d18c4..121af04 100644 (file)
@@ -40,7 +40,7 @@ abstract class SqlDataUpdate extends DataUpdate {
        /** @var bool Whether a transaction is open on this object (internal use only!) */
        private $mHasTransaction;
 
-       /** @var  bool Whether this update should be wrapped in a transaction */
+       /** @var bool Whether this update should be wrapped in a transaction */
        protected $mUseTransaction;
 
        /**
index 414b9f8..f77a4eb 100644 (file)
@@ -53,16 +53,16 @@ class DifferenceEngine extends ContextSource {
        /** @var Language */
        protected $mDiffLang;
 
-       /** @var  Title */
+       /** @var Title */
        public $mOldPage;
 
-       /** @var  Title */
+       /** @var Title */
        public $mNewPage;
 
        /** @var Revision */
        public $mOldRev;
 
-       /** @var  Revision */
+       /** @var Revision */
        public $mNewRev;
 
        /** @var bool Have the revisions IDs been loaded */
index 3ab9f5d..0464e03 100644 (file)
@@ -36,7 +36,7 @@
  * @since 1.20
  */
 abstract class FileJournal {
-       /** @var  string */
+       /** @var string */
        protected $backend;
 
        /** @var int */
index 7a9e617..267dbd5 100644 (file)
@@ -1399,6 +1399,12 @@ class LocalFile extends File {
                #       to after $wikiPage->doEdit has been called.
                $dbw->commit( __METHOD__ );
 
+               # Save to memcache.
+               # We shall not saveToCache before the commit since otherwise
+               # in case of a rollback there is an usable file from memcached
+               # which in fact doesn't really exist (bug 24978)
+               $this->saveToCache();
+
                if ( $exists ) {
                        # Invalidate the cache for the description page
                        $descTitle->invalidateCache();
@@ -1431,11 +1437,6 @@ class LocalFile extends File {
 
                wfProfileOut( __METHOD__ . '-edit' );
 
-               # Save to cache and purge the squid
-               # We shall not saveToCache before the commit since otherwise
-               # in case of a rollback there is an usable file from memcached
-               # which in fact doesn't really exist (bug 24978)
-               $this->saveToCache();
 
                if ( $reupload ) {
                        # Delete old thumbnails
index 237fa32..7baab66 100644 (file)
@@ -50,7 +50,7 @@ class HTMLCheckField extends HTMLFormField {
        }
 
        /**
-        * @param  $request WebRequest
+        * @param $request WebRequest
         *
         * @return String
         */
index 3cf3188..f802771 100644 (file)
@@ -70,7 +70,7 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable
        }
 
        /**
-        * @param  $request WebRequest
+        * @param $request WebRequest
         *
         * @return String
         */
index 564927f..4f501f7 100644 (file)
@@ -60,7 +60,7 @@ class HTMLSelectAndOtherField extends HTMLSelectField {
        }
 
        /**
-        * @param  $request WebRequest
+        * @param $request WebRequest
         *
         * @return Array("<overall message>","<select value>","<text field value>")
         */
index e8bcb5b..21f3b77 100644 (file)
@@ -62,7 +62,7 @@ class HTMLSelectOrOtherField extends HTMLTextField {
        }
 
        /**
-        * @param  $request WebRequest
+        * @param $request WebRequest
         *
         * @return String
         */
index 2d43324..4c72528 100644 (file)
@@ -100,7 +100,9 @@ class MysqlInstaller extends DatabaseInstaller {
 
        public function submitConnectForm() {
                // Get variables from the request.
-               $newValues = $this->setVarsFromRequest( array( 'wgDBserver', 'wgDBname', 'wgDBprefix' ) );
+               $newValues = $this->setVarsFromRequest( array(
+                       'wgDBserver', 'wgDBname', 'wgDBprefix', '_InstallUser', '_InstallPassword'
+               ) );
 
                // Validate them.
                $status = Status::newGood();
@@ -115,6 +117,12 @@ class MysqlInstaller extends DatabaseInstaller {
                if ( !preg_match( '/^[a-z0-9_-]*$/i', $newValues['wgDBprefix'] ) ) {
                        $status->fatal( 'config-invalid-db-prefix', $newValues['wgDBprefix'] );
                }
+               if ( !strlen( $newValues['_InstallUser'] ) ) {
+                       $status->fatal( 'config-db-username-empty' );
+               }
+               if (!strlen( $newValues['_InstallPassword'] ) ) {
+                       $status->fatal( 'config-db-password-empty', $newValues['_InstallUser'] );
+               }
                if ( !$status->isOK() ) {
                        return $status;
                }
index 2cf4156..780431a 100644 (file)
@@ -83,8 +83,10 @@ class PostgresInstaller extends DatabaseInstaller {
 
        function submitConnectForm() {
                // Get variables from the request
-               $newValues = $this->setVarsFromRequest( array( 'wgDBserver', 'wgDBport',
-                       'wgDBname', 'wgDBmwschema' ) );
+               $newValues = $this->setVarsFromRequest( array(
+                       'wgDBserver', 'wgDBport','wgDBname', 'wgDBmwschema',
+                       '_InstallUser', '_InstallPassword'
+               ) );
 
                // Validate them
                $status = Status::newGood();
@@ -96,6 +98,12 @@ class PostgresInstaller extends DatabaseInstaller {
                if ( !preg_match( '/^[a-zA-Z0-9_]*$/', $newValues['wgDBmwschema'] ) ) {
                        $status->fatal( 'config-invalid-schema', $newValues['wgDBmwschema'] );
                }
+               if ( !strlen( $newValues['_InstallUser'] ) ) {
+                       $status->fatal( 'config-db-username-empty' );
+               }
+               if ( !strlen( $newValues['_InstallPassword'] ) ) {
+                       $status->fatal( 'config-db-password-empty', $newValues['_InstallUser'] );
+               }
 
                // Submit user box
                if ( $status->isOK() ) {
index 4bc6cad..69a460a 100644 (file)
@@ -1144,8 +1144,7 @@ class WebInstaller_Options extends WebInstallerPage {
                        'wgEmailAuthentication', 'wgMainCacheType', '_MemCachedServers',
                        'wgUseInstantCommons' ) );
 
-               if ( !in_array( $this->getVar( '_RightsProfile' ),
-                       array_keys( $this->parent->rightsProfiles ) )
+               if ( !array_key_exists( $this->getVar( '_RightsProfile' ), $this->parent->rightsProfiles )
                ) {
                        reset( $this->parent->rightsProfiles );
                        $this->setVar( '_RightsProfile', key( $this->parent->rightsProfiles ) );
@@ -1158,7 +1157,7 @@ class WebInstaller_Options extends WebInstallerPage {
 
                                return false;
                        }
-               } elseif ( in_array( $code, array_keys( $this->parent->licenses ) ) ) {
+               } elseif ( array_key_exists( $code, $this->parent->licenses ) ) {
                        // Messages:
                        // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa,
                        // config-license-cc-0, config-license-pd, config-license-gfdl, config-license-none,
index 45149c5..32a9912 100644 (file)
@@ -97,6 +97,7 @@
     "config-db-username": "Database username:",
     "config-db-password": "Database password:",
     "config-db-password-empty": "Please enter a password for the new database user: $1.\nWhile it may be possible to create users with no passwords, it is not secure.",
+    "config-db-username-empty": "You must enter a value for \"Database username\"",
     "config-db-install-username": "Enter the username that will be used to connect to the database during the installation process.\nThis is not the username of the MediaWiki account; this is the username for your database.",
     "config-db-install-password": "Enter the password that will be used to connect to the database during the installation process.\nThis is not the password for the MediaWiki account; this is the password for your database.",
     "config-db-install-help": "Enter the username and password that will be used to connect to the database during the installation process.",
index 0663853..3f610a6 100644 (file)
@@ -79,6 +79,7 @@
     "config-db-wiki-settings": "This is more acurate: \"Enter identifying or distinguishing data for this wiki\" since a MySQL database can host tables of several wikis.",
     "config-db-account-oracle-warn": "A \"[[:wikipedia:Front and back ends|backend]]\" is a system or component that ordinary users don't interact with directly and don't need to know about, and that is responsible for a distinct task or service - for example, a storage back-end is a generic system for storing data which other applications can use. Possible alternatives for back-end are \"system\" or \"service\", or (depending on context and language) even leave it untranslated.",
     "config-db-password-empty": "Used as error message. Parameters:\n* $1 - database username",
+    "config-db-username-empty": "Used as error message. Shown when the database username is not entered by the user.",
     "config-db-account-lock": "It might be easier to translate ''normal operation'' as \"also after the installation process\"",
     "config-mysql-old": "Used as error message. Parameters:\n* $1 - minimum version\n* $2 - the version of MySQL that has been installed",
     "config-pg-test-error": "* $1 - database name\n* $2 - error message",
index a537861..2d7103c 100644 (file)
@@ -376,7 +376,7 @@ abstract class JobQueue {
                // Flag this job as an old duplicate based on its "root" job...
                try {
                        if ( $job && $this->isRootJobOldDuplicate( $job ) ) {
-                               JobQueue::incrStats( 'job-pop-duplicate', $this->type );
+                               JobQueue::incrStats( 'job-pop-duplicate', $this->type, 1, $this->wiki );
                                $job = DuplicateJob::newFromJob( $job ); // convert to a no-op
                        }
                } catch ( MWException $e ) {
@@ -715,11 +715,15 @@ abstract class JobQueue {
         * @param string $key Event type
         * @param string $type Job type
         * @param int $delta
+        * @param string $wiki Wiki ID (added in 1.23)
         * @since 1.22
         */
-       public static function incrStats( $key, $type, $delta = 1 ) {
+       public static function incrStats( $key, $type, $delta = 1, $wiki = null ) {
                wfIncrStats( $key, $delta );
                wfIncrStats( "{$key}-{$type}", $delta );
+               if ( $wiki !== null ) {
+                       wfIncrStats( "{$key}-{$type}-{$wiki}", $delta );
+               }
        }
 
        /**
index e83c26d..5f1ca14 100644 (file)
@@ -258,11 +258,12 @@ class JobQueueDB extends JobQueue {
                        foreach ( array_chunk( $rows, 50 ) as $rowBatch ) {
                                $dbw->insert( 'job', $rowBatch, $method );
                        }
-                       JobQueue::incrStats( 'job-insert', $this->type, count( $rows ) );
+                       JobQueue::incrStats( 'job-insert', $this->type, count( $rows ), $this->wiki );
                        JobQueue::incrStats(
                                'job-insert-duplicate',
                                $this->type,
-                               count( $rowSet ) + count( $rowList ) - count( $rows )
+                               count( $rowSet ) + count( $rowList ) - count( $rows ),
+                               $this->wiki
                        );
                } catch ( DBError $e ) {
                        if ( $flags & self::QOS_ATOMIC ) {
@@ -313,7 +314,7 @@ class JobQueueDB extends JobQueue {
                                        $this->cache->set( $this->getCacheKey( 'empty' ), 'true', self::CACHE_TTL_LONG );
                                        break; // nothing to do
                                }
-                               JobQueue::incrStats( 'job-pop', $this->type );
+                               JobQueue::incrStats( 'job-pop', $this->type, 1, $this->wiki );
                                // Get the job object from the row...
                                $title = Title::makeTitleSafe( $row->job_namespace, $row->job_title );
                                if ( !$title ) {
@@ -684,8 +685,9 @@ class JobQueueDB extends JobQueue {
                                                        'job_id' => $ids ),
                                                __METHOD__
                                        );
-                                       $count += $dbw->affectedRows();
-                                       JobQueue::incrStats( 'job-recycle', $this->type, $dbw->affectedRows() );
+                                       $affected = $dbw->affectedRows();
+                                       $count += $affected;
+                                       JobQueue::incrStats( 'job-recycle', $this->type, $affected, $this->wiki );
                                        $this->cache->set( $this->getCacheKey( 'empty' ), 'false', self::CACHE_TTL_LONG );
                                }
                        }
@@ -710,8 +712,9 @@ class JobQueueDB extends JobQueue {
                        );
                        if ( count( $ids ) ) {
                                $dbw->delete( 'job', array( 'job_id' => $ids ), __METHOD__ );
-                               $count += $dbw->affectedRows();
-                               JobQueue::incrStats( 'job-abandon', $this->type, $dbw->affectedRows() );
+                               $affected = $dbw->affectedRows();
+                               $count += $affected;
+                               JobQueue::incrStats( 'job-abandon', $this->type, $affected, $this->wiki );
                        }
 
                        $dbw->unlock( "jobqueue-recycle-{$this->type}", __METHOD__ );
index c785cb2..135a61d 100644 (file)
@@ -237,9 +237,9 @@ class JobQueueRedis extends JobQueue {
 
                                return false;
                        }
-                       JobQueue::incrStats( 'job-insert', $this->type, count( $items ) );
+                       JobQueue::incrStats( 'job-insert', $this->type, count( $items ), $this->wiki );
                        JobQueue::incrStats( 'job-insert-duplicate', $this->type,
-                               count( $items ) - $failed - $pushed );
+                               count( $items ) - $failed - $pushed, $this->wiki );
                } catch ( RedisException $e ) {
                        $this->throwRedisException( $conn, $e );
                }
@@ -331,7 +331,7 @@ LUA;
                                        break; // no jobs; nothing to do
                                }
 
-                               JobQueue::incrStats( 'job-pop', $this->type );
+                               JobQueue::incrStats( 'job-pop', $this->type, 1, $this->wiki );
                                $item = $this->unserialize( $blob );
                                if ( $item === false ) {
                                        wfDebugLog( 'JobQueueRedis', "Could not unserialize {$this->type} job." );
@@ -715,8 +715,8 @@ LUA;
                        if ( $res ) {
                                list( $released, $abandoned, $pruned, $undelayed ) = $res;
                                $count += $released + $pruned + $undelayed;
-                               JobQueue::incrStats( 'job-recycle', $this->type, $released );
-                               JobQueue::incrStats( 'job-abandon', $this->type, $abandoned );
+                               JobQueue::incrStats( 'job-recycle', $this->type, $released, $this->wiki );
+                               JobQueue::incrStats( 'job-abandon', $this->type, $abandoned, $this->wiki );
                        }
                } catch ( RedisException $e ) {
                        $this->throwRedisException( $conn, $e );
index 19b0558..9e9bda6 100644 (file)
@@ -112,6 +112,8 @@ class AssembleUploadChunksJob extends Job {
                                )
                        );
                        $this->setLastError( get_class( $e ) . ": " . $e->getText() );
+                       // To be extra robust.
+                       MWExceptionHandler::rollbackMasterChangesAndLog( $e );
 
                        return false;
                }
index d7667f3..918a392 100644 (file)
@@ -125,6 +125,9 @@ class PublishStashedFileJob extends Job {
                                )
                        );
                        $this->setLastError( get_class( $e ) . ": " . $e->getText() );
+                       // To prevent potential database referential integrity issues.
+                       // See bug 32551.
+                       MWExceptionHandler::rollbackMasterChangesAndLog( $e );
 
                        return false;
                }
index 4f44d75..ed3a8da 100644 (file)
@@ -77,10 +77,10 @@ class LogFormatter {
        /** @var LogEntryBase */
        protected $entry;
 
-       /// Integer constant for handling log_deleted
+       /** @var Integer Constant for handling log_deleted */
        protected $audience = self::FOR_PUBLIC;
 
-       /// Whether to output user tool links
+       /** @var bool Whether to output user tool links */
        protected $linkFlood = false;
 
        /**
index 0e8d1de..2ec4f69 100644 (file)
@@ -358,10 +358,10 @@ class LogPage {
 
        /**
         * @todo Document
-        * @param  string $type
-        * @param  Language|null $lang
-        * @param  Title $title
-        * @param  array $params
+        * @param string $type
+        * @param Language|null $lang
+        * @param Title $title
+        * @param array $params
         * @return string
         */
        protected static function getTitleLink( $type, $lang, $title, &$params ) {
index 15ec794..d296269 100644 (file)
@@ -32,7 +32,7 @@
 class BitmapHandler_ClientOnly extends BitmapHandler {
        /**
         * @param $image File
-        * @param  $params
+        * @param $params
         * @return bool
         */
        function normaliseParams( $image, &$params ) {
index 1cb5542..b39e042 100644 (file)
@@ -319,13 +319,13 @@ class Exif {
                $this->mFilteredExifData = array();
 
                foreach ( array_keys( $this->mRawExifData ) as $section ) {
-                       if ( !in_array( $section, array_keys( $this->mExifTags ) ) ) {
+                       if ( !array_key_exists( $section, $this->mExifTags ) ) {
                                $this->debug( $section, __FUNCTION__, "'$section' is not a valid Exif section" );
                                continue;
                        }
 
                        foreach ( array_keys( $this->mRawExifData[$section] ) as $tag ) {
-                               if ( !in_array( $tag, array_keys( $this->mExifTags[$section] ) ) ) {
+                               if ( !array_key_exists( $tag, $this->mExifTags[$section] ) ) {
                                        $this->debug( $tag, __FUNCTION__, "'$tag' is not a valid tag in '$section'" );
                                        continue;
                                }
index bde889c..5992be1 100644 (file)
@@ -78,7 +78,7 @@ class GIFHandler extends BitmapHandler {
        /**
         * @todo Add unit tests
         *
-        * @param File$image
+        * @param File $image
         * @return bool
         */
        function getImageArea( $image ) {
index 87acb53..e4bbb43 100644 (file)
@@ -168,9 +168,6 @@ class MemcachedBagOStuff extends BagOStuff {
         * Send a debug message to the log
         */
        protected function debugLog( $text ) {
-               if ( substr( $text, -1 ) !== "\n" ) {
-                       $text .= "\n";
-               }
                wfDebugLog( 'memcached', $text );
        }
 }
index d9ea54c..d39b288 100644 (file)
@@ -102,8 +102,8 @@ class MWMemcached {
        /**
         * Command statistics
         *
-        * @var     array
-        * @access  public
+        * @var array
+        * @access public
         */
        var $stats;
 
@@ -113,112 +113,112 @@ class MWMemcached {
        /**
         * Cached Sockets that are connected
         *
-        * @var     array
-        * @access  private
+        * @var array
+        * @access private
         */
        var $_cache_sock;
 
        /**
         * Current debug status; 0 - none to 9 - profiling
         *
-        * @var     boolean
-        * @access  private
+        * @var boolean
+        * @access private
         */
        var $_debug;
 
        /**
         * Dead hosts, assoc array, 'host'=>'unixtime when ok to check again'
         *
-        * @var     array
-        * @access  private
+        * @var array
+        * @access private
         */
        var $_host_dead;
 
        /**
         * Is compression available?
         *
-        * @var     boolean
-        * @access  private
+        * @var boolean
+        * @access private
         */
        var $_have_zlib;
 
        /**
         * Do we want to use compression?
         *
-        * @var     boolean
-        * @access  private
+        * @var boolean
+        * @access private
         */
        var $_compress_enable;
 
        /**
         * At how many bytes should we compress?
         *
-        * @var     integer
-        * @access  private
+        * @var integer
+        * @access private
         */
        var $_compress_threshold;
 
        /**
         * Are we using persistent links?
         *
-        * @var     boolean
-        * @access  private
+        * @var boolean
+        * @access private
         */
        var $_persistent;
 
        /**
         * If only using one server; contains ip:port to connect to
         *
-        * @var     string
-        * @access  private
+        * @var string
+        * @access private
         */
        var $_single_sock;
 
        /**
         * Array containing ip:port or array(ip:port, weight)
         *
-        * @var     array
-        * @access  private
+        * @var array
+        * @access private
         */
        var $_servers;
 
        /**
         * Our bit buckets
         *
-        * @var     array
-        * @access  private
+        * @var array
+        * @access private
         */
        var $_buckets;
 
        /**
         * Total # of bit buckets we have
         *
-        * @var     integer
-        * @access  private
+        * @var integer
+        * @access private
         */
        var $_bucketcount;
 
        /**
         * # of total servers we have
         *
-        * @var     integer
-        * @access  private
+        * @var integer
+        * @access private
         */
        var $_active;
 
        /**
         * Stream timeout in seconds. Applies for example to fread()
         *
-        * @var     integer
-        * @access  private
+        * @var integer
+        * @access private
         */
        var $_timeout_seconds;
 
        /**
         * Stream timeout in microseconds
         *
-        * @var     integer
-        * @access  private
+        * @var integer
+        * @access private
         */
        var $_timeout_microseconds;
 
@@ -243,7 +243,7 @@ class MWMemcached {
         *
         * @param array $args Associative array of settings
         *
-        * @return  mixed
+        * @return mixed
         */
        public function __construct( $args ) {
                $this->set_servers( isset( $args['servers'] ) ? $args['servers'] : array() );
@@ -708,7 +708,7 @@ class MWMemcached {
         *
         * @param string $sock socket to close
         *
-        * @access  private
+        * @access private
         */
        function _close_sock( $sock ) {
                $host = array_search( $sock, $this->_cache_sock );
@@ -725,8 +725,8 @@ class MWMemcached {
         * @param $sock Integer: socket to connect
         * @param string $host Host:IP to connect to
         *
-        * @return  boolean
-        * @access  private
+        * @return boolean
+        * @access private
         */
        function _connect_sock( &$sock, $host ) {
                list( $ip, $port ) = preg_split( '/:(?=\d)/', $host );
@@ -767,7 +767,7 @@ class MWMemcached {
         *
         * @param string $sock socket to mark as dead
         *
-        * @access  private
+        * @access private
         */
        function _dead_sock( $sock ) {
                $host = array_search( $sock, $this->_cache_sock );
index 6dda64c..dfe3c80 100644 (file)
@@ -27,7 +27,7 @@
  * @ingroup Parser
  */
 class CacheTime {
-       /** @var  array|bool ParserOptions which have been taken into account to
+       /** @var array|bool ParserOptions which have been taken into account to
         * produce output or false if not available.
         */
        public $mUsedOptions;
index ad6bc0f..8fa39fa 100644 (file)
@@ -92,7 +92,7 @@ class CoreParserFunctions {
 
        /**
         * @param $parser Parser
-        * @param  $date
+        * @param $date
         * @param null $defaultPref
         * @return mixed|string
         */
@@ -787,7 +787,7 @@ class CoreParserFunctions {
 
        /**
         * @param $parser Parser
-        * @param  $text
+        * @param $text
         * @return string
         */
        static function anchorencode( $parser, $text ) {
index 0fefe69..3b448e4 100644 (file)
@@ -650,9 +650,13 @@ class Parser {
         * @param $text String
         * @param $title Title
         * @param $options ParserOptions
+        * @param $params Array
         * @return String
         */
-       public function getPreloadText( $text, Title $title, ParserOptions $options ) {
+       public function getPreloadText( $text, Title $title, ParserOptions $options, $params = array() ) {
+               $msg = new RawMessage( $text );
+               $text = $msg->params( $params )->plain();
+
                # Parser (re)initialisation
                $this->startParse( $title, $options, self::OT_PLAIN, true );
 
@@ -1731,10 +1735,10 @@ class Parser {
         * @param $url String
         * @return String
         *
-        * @todo  This can merge genuinely required bits in the path or query string,
-        *        breaking legit URLs. A proper fix would treat the various parts of
-        *        the URL differently; as a workaround, just use the output for
-        *        statistical records, not for actual linking/output.
+        * @todo This can merge genuinely required bits in the path or query string,
+        *       breaking legit URLs. A proper fix would treat the various parts of
+        *       the URL differently; as a workaround, just use the output for
+        *       statistical records, not for actual linking/output.
         */
        static function replaceUnusualEscapes( $url ) {
                return preg_replace_callback( '/%[0-9A-Fa-f]{2}/',
index deaf288..d6edb21 100644 (file)
@@ -1619,7 +1619,7 @@ class PPNode_Hash_Tree implements PPNode {
        }
 
        /**
-        * @param  $i
+        * @param $i
         * @return bool
         */
        function item( $i ) {
index 5f3f18e..5b94453 100644 (file)
@@ -97,7 +97,7 @@ class StripState {
        }
 
        /**
-        * @param  $text
+        * @param $text
         * @return mixed
         */
        function unstripBoth( $text ) {
index 1bc10f2..5c88239 100644 (file)
@@ -267,7 +267,7 @@ LUA;
 
        /**
         * @param RedisConnRef $conn
-        * @param float UNIX timestamp
+        * @param float $now UNIX timestamp
         * @return string|bool False on failure
         */
        protected function initAndPopPoolSlotList( RedisConnRef $conn, $now ) {
index 12c452a..b2fb902 100644 (file)
@@ -98,21 +98,26 @@ class ResourceLoader {
                // Set modules' dependencies
                $modulesWithDeps = array();
                foreach ( $res as $row ) {
-                       $this->getModule( $row->md_module )->setFileDependencies( $skin,
-                               FormatJson::decode( $row->md_deps, true )
-                       );
-                       $modulesWithDeps[] = $row->md_module;
+                       $module = $this->getModule( $row->md_module );
+                       if ( $module ) {
+                               $module->setFileDependencies( $skin, FormatJson::decode( $row->md_deps, true ) );
+                               $modulesWithDeps[] = $row->md_module;
+                       }
                }
 
                // Register the absence of a dependency row too
                foreach ( array_diff( $modules, $modulesWithDeps ) as $name ) {
-                       $this->getModule( $name )->setFileDependencies( $skin, array() );
+                       $module = $this->getModule( $name );
+                       if ( $module ) {
+                               $this->getModule( $name )->setFileDependencies( $skin, array() );
+                       }
                }
 
                // Get message blob mtimes. Only do this for modules with messages
                $modulesWithMessages = array();
                foreach ( $modules as $name ) {
-                       if ( count( $this->getModule( $name )->getMessages() ) ) {
+                       $module = $this->getModule( $name );
+                       if ( $module && count( $module->getMessages() ) ) {
                                $modulesWithMessages[] = $name;
                        }
                }
@@ -124,13 +129,18 @@ class ResourceLoader {
                                ), __METHOD__
                        );
                        foreach ( $res as $row ) {
-                               $this->getModule( $row->mr_resource )->setMsgBlobMtime( $lang,
-                                       wfTimestamp( TS_UNIX, $row->mr_timestamp ) );
-                               unset( $modulesWithoutMessages[$row->mr_resource] );
+                               $module = $this->getModule( $row->mr_resource );
+                               if ( $module ) {
+                                       $module->setMsgBlobMtime( $lang, wfTimestamp( TS_UNIX, $row->mr_timestamp ) );
+                                       unset( $modulesWithoutMessages[$row->mr_resource] );
+                               }
                        }
                }
                foreach ( array_keys( $modulesWithoutMessages ) as $name ) {
-                       $this->getModule( $name )->setMsgBlobMtime( $lang, 0 );
+                       $module = $this->getModule( $name );
+                       if ( $module ) {
+                               $module->setMsgBlobMtime( $lang, 0 );
+                       }
                }
        }
 
@@ -269,21 +279,19 @@ class ResourceLoader {
                        }
 
                        // Attach module
-                       if ( is_object( $info ) ) {
-                               // Old calling convention
-                               // Validate the input
-                               if ( !( $info instanceof ResourceLoaderModule ) ) {
-                                       wfProfileOut( __METHOD__ );
-                                       throw new MWException( 'ResourceLoader invalid module error. ' .
-                                               'Instances of ResourceLoaderModule expected.' );
-                               }
-
+                       if ( $info instanceof ResourceLoaderModule ) {
                                $this->moduleInfos[$name] = array( 'object' => $info );
                                $info->setName( $name );
                                $this->modules[$name] = $info;
-                       } else {
+                       } elseif ( is_array( $info ) ) {
                                // New calling convention
                                $this->moduleInfos[$name] = $info;
+                       } else {
+                               wfProfileOut( __METHOD__ );
+                               throw new MWException(
+                                       'ResourceLoader module info type error for module \'' . $name .
+                                       '\': expected ResourceLoaderModule or array (got: ' . gettype( $info ) . ')'
+                               );
                        }
                }
 
@@ -400,8 +408,13 @@ class ResourceLoader {
        /**
         * Get the ResourceLoaderModule object for a given module name.
         *
+        * If an array of module parameters exists but a ResourceLoaderModule object has not
+        * yet been instantiated, this method will instantiate and cache that object such that
+        * subsequent calls simply return the same object.
+        *
         * @param string $name Module name
-        * @return ResourceLoaderModule if module has been registered, null otherwise
+        * @return ResourceLoaderModule|null If module has been registered, return a
+        *  ResourceLoaderModule instance. Otherwise, return null.
         */
        public function getModule( $name ) {
                if ( !isset( $this->modules[$name] ) ) {
@@ -471,8 +484,8 @@ class ResourceLoader {
                $modules = array();
                $missing = array();
                foreach ( $context->getModules() as $name ) {
-                       if ( isset( $this->moduleInfos[$name] ) ) {
-                               $module = $this->getModule( $name );
+                       $module = $this->getModule( $name );
+                       if ( $module ) {
                                // Do not allow private modules to be loaded from the web.
                                // This is a security issue, see bug 34907.
                                if ( $module->getGroup() === 'private' ) {
index 5ee6bd2..005081c 100644 (file)
@@ -176,7 +176,11 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                                continue;
                        }
 
-                       if ( !count( $data['dependencies'] ) && $data['group'] === null && $data['source'] === 'local' ) {
+                       if (
+                               !count( $data['dependencies'] ) &&
+                               $data['group'] === null &&
+                               $data['source'] === 'local'
+                       ) {
                                // Modules without dependencies, a group or a foreign source;
                                // call mw.loader.register(name, timestamp)
                                $registrations[] = array( $name, $data['version'] );
@@ -265,7 +269,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
        public function getScript( ResourceLoaderContext $context ) {
                global $IP, $wgLegacyJavaScriptGlobals;
 
-               $out = file_get_contents( "$IP/resources/startup.js" );
+               $out = file_get_contents( "$IP/resources/src/startup.js" );
                if ( $context->getOnly() === 'scripts' ) {
 
                        // Startup function
@@ -274,7 +278,8 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        // Fix indentation
                        $registrations = str_replace( "\n", "\n\t", trim( $registrations ) );
                        $out .= "var startUp = function () {\n" .
-                               "\tmw.config = new " . Xml::encodeJsCall( 'mw.Map', array( $wgLegacyJavaScriptGlobals ) ) . "\n" .
+                               "\tmw.config = new " .
+                               Xml::encodeJsCall( 'mw.Map', array( $wgLegacyJavaScriptGlobals ) ) . "\n" .
                                "\t$registrations\n" .
                                "\t" . Xml::encodeJsCall( 'mw.config.set', array( $configuration ) ) .
                                "};\n";
@@ -315,7 +320,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
 
                $time = max(
                        wfTimestamp( TS_UNIX, $wgCacheEpoch ),
-                       filemtime( "$IP/resources/startup.js" ),
+                       filemtime( "$IP/resources/src/startup.js" ),
                        $this->getHashMtime( $context )
                );
 
index 4505ee1..b0b2253 100644 (file)
@@ -33,10 +33,10 @@ class RevisionDeleteUser {
 
        /**
         * Update *_deleted bitfields in various tables to hide or unhide usernames
-        * @param  $name String username
-        * @param  $userId Int user id
-        * @param  $op String operator '|' or '&'
-        * @param  $dbw null|DatabaseBase, if you happen to have one lying around
+        * @param $name String username
+        * @param $userId Int user id
+        * @param $op String operator '|' or '&'
+        * @param $dbw null|DatabaseBase, if you happen to have one lying around
         * @return bool
         */
        private static function setUsernameBitfields( $name, $userId, $op, $dbw ) {
index 02e1dda..bea8460 100644 (file)
@@ -207,7 +207,7 @@ class RevisionDeleter {
         * so that this key can be used instead.
         *
         * @param $title Title
-        * @param  $revid
+        * @param $revid
         * @return bool|mixed
         */
        public static function checkRevisionExistence( $title, $revid ) {
index 507a520..687f9a4 100644 (file)
@@ -37,7 +37,7 @@ class SearchEngine {
        var $namespaces = array( NS_MAIN );
        protected $showSuggestion = true;
 
-       /// Feature values
+       /** @var Array Feature values */
        protected $features = array();
 
        /**
index 11141e0..7bf933c 100644 (file)
@@ -193,7 +193,7 @@ class SiteSQLStore implements SiteStore {
         *
         * @since 1.22
         *
-        * @param Site
+        * @param Site $site
         *
         * @return ORMRow
         */
index 90f82e0..7496262 100644 (file)
@@ -113,7 +113,7 @@ abstract class FormSpecialPage extends SpecialPage {
 
        /**
         * Process the form on POST submission.
-        * @param  $data Array
+        * @param $data Array
         * @return Bool|Array true for success, false for didn't-try, array of errors on failure
         */
        abstract public function onSubmit( array $data );
index d9340b4..f7fcc7a 100644 (file)
@@ -476,8 +476,6 @@ class SpecialPage {
         * @deprecated in 1.23, use SpecialPage::getPageTitle
         */
        function getTitle( $subpage = false ) {
-               wfDeprecated( __METHOD__, '1.23' );
-
                return $this->getPageTitle( $subpage );
        }
 
index 97e7238..70949d4 100644 (file)
@@ -97,7 +97,7 @@ class SpecialAllpages extends IncludableSpecialPage {
                $namespaces = $this->getContext()->getLanguage()->getNamespaces();
 
                $out->setPageTitle(
-                       ( $namespace > 0 && in_array( $namespace, array_keys( $namespaces ) ) ) ?
+                       ( $namespace > 0 && array_key_exists( $namespace, $namespaces ) ) ?
                                $this->msg( 'allinnamespace', str_replace( '_', ' ', $namespaces[$namespace] ) ) :
                                $this->msg( 'allarticles' )
                );
@@ -375,7 +375,7 @@ class SpecialAllpages extends IncludableSpecialPage {
 
                if ( !$fromList || !$toList ) {
                        $out = $this->msg( 'allpagesbadtitle' )->parseAsBlock();
-               } elseif ( !in_array( $namespace, array_keys( $namespaces ) ) ) {
+               } elseif ( !array_key_exists( $namespace, $namespaces ) ) {
                        // Show errormessage and reset to NS_MAIN
                        $out = $this->msg( 'allpages-bad-ns', $namespace )->parse();
                        $namespace = NS_MAIN;
index 57f23d3..57637c9 100644 (file)
@@ -32,19 +32,19 @@ class SpecialBlock extends FormSpecialPage {
         * or as subpage (Special:Block/Foo) */
        protected $target;
 
-       /// @var Block::TYPE_ constant
+       /** @var Integer Block::TYPE_ constant */
        protected $type;
 
-       /// @var  User|String the previous block target
+       /** @var User|String the previous block target */
        protected $previousTarget;
 
-       /// @var Bool whether the previous submission of the form asked for HideUser
+       /** @var Bool whether the previous submission of the form asked for HideUser */
        protected $requestedHideUser;
 
-       /// @var Bool
+       /** @var Bool */
        protected $alreadyBlocked;
 
-       /// @var Array
+       /** @var Array */
        protected $preErrors = array();
 
        public function __construct() {
@@ -593,8 +593,8 @@ class SpecialBlock extends FormSpecialPage {
 
        /**
         * Given the form data, actually implement a block
-        * @param  $data Array
-        * @param  $context IContextSource
+        * @param $data Array
+        * @param $context IContextSource
         * @return Bool|String
         */
        public static function processForm( array $data, IContextSource $context ) {
@@ -947,7 +947,7 @@ class SpecialBlock extends FormSpecialPage {
 
        /**
         * Process the form on POST submission.
-        * @param  $data Array
+        * @param $data Array
         * @return Bool|Array true for success, false for didn't-try, array of errors on failure
         */
        public function onSubmit( array $data ) {
index 29722c8..1bd4228 100644 (file)
@@ -448,8 +448,8 @@ class ImportReporter extends ContextSource {
         * @param Title $title
         * @param Title $origTitle
         * @param int $revisionCount
-        * @param  $successCount
-        * @param  $pageInfo
+        * @param $successCount
+        * @param $pageInfo
         * @return void
         */
        function reportPage( $title, $origTitle, $revisionCount, $successCount, $pageInfo ) {
index 8137651..f13fc59 100644 (file)
@@ -66,7 +66,7 @@ class SpecialPrefixindex extends SpecialAllpages {
 
                $namespaces = $wgContLang->getNamespaces();
                $out->setPageTitle(
-                       ( $namespace > 0 && in_array( $namespace, array_keys( $namespaces ) ) )
+                       ( $namespace > 0 && array_key_exists( $namespace, $namespaces ) )
                                ? $this->msg( 'prefixindex-namespace', str_replace( '_', ' ', $namespaces[$namespace] ) )
                                : $this->msg( 'prefixindex' )
                );
@@ -166,7 +166,7 @@ class SpecialPrefixindex extends SpecialAllpages {
 
                if ( !$prefixList || !$fromList ) {
                        $out = $this->msg( 'allpagesbadtitle' )->parseAsBlock();
-               } elseif ( !in_array( $namespace, array_keys( $namespaces ) ) ) {
+               } elseif ( !array_key_exists( $namespace, $namespaces ) ) {
                        // Show errormessage and reset to NS_MAIN
                        $out = $this->msg( 'allpages-bad-ns', $namespace )->parse();
                        $namespace = NS_MAIN;
index 0c45281..104cd54 100644 (file)
@@ -152,6 +152,7 @@ class SpecialRunJobs extends UnlistedSpecialPage {
                                }
                        } while ( --$n && $job );
                } catch ( MWException $e ) {
+                       MWExceptionHandler::rollbackMasterChangesAndLog( $e );
                        // We don't want exceptions thrown during job execution to
                        // be reported to the user since the output is already sent.
                        // Instead we just log them.
index d4c47e8..ec8d754 100644 (file)
@@ -34,20 +34,20 @@ class SpecialSearch extends SpecialPage {
         * For users tt replaces the set of enabled namespaces from the query
         * string when applicable. Extensions can add new profiles with hooks
         * with custom search options just for that profile.
-        * null|string
+        * @var null|string
         */
        protected $profile;
 
-       /// Search engine
+       /** @var SearchEngine Search engine */
        protected $searchEngine;
 
-       /// Search engine type, if not default
+       /** @var String Search engine type, if not default */
        protected $searchEngineType;
 
-       /// For links
+       /** @var Array For links */
        protected $extraParams = array();
 
-       /// No idea, apparently used by some other classes
+       /** @var String No idea, apparently used by some other classes */
        protected $mPrefix;
 
        /**
index db9a992..f8e5c84 100644 (file)
@@ -682,7 +682,7 @@ class UserrightsPage extends SpecialPage {
        }
 
        /**
-        * @param  $group String: the name of the group to check
+        * @param $group String: the name of the group to check
         * @return bool Can we remove the group?
         */
        private function canRemove( $group ) {
index c8add01..5c3f509 100644 (file)
 class SpecialVersion extends SpecialPage {
        protected $firstExtOpened = false;
 
+       /**
+        * Stores the current rev id/SHA hash of MediaWiki core
+        */
+       protected $coreId = '';
+
        protected static $extensionTypes = false;
 
        protected static $viewvcUrls = array(
@@ -616,20 +621,43 @@ class SpecialVersion extends SpecialPage {
                }
 
                if ( isset( $extension['path'] ) ) {
-                       $extensionPath = dirname( $extension['path'] );
-                       $gitInfo = new GitInfo( $extensionPath );
-                       $vcsVersion = $gitInfo->getHeadSHA1();
-                       if ( $vcsVersion !== false ) {
-                               $vcsVersion = substr( $vcsVersion, 0, 7 );
-                               $vcsLink = $gitInfo->getHeadViewUrl();
-                               $vcsDate = $gitInfo->getHeadCommitDate();
-                       } else {
-                               $svnInfo = self::getSvnInfo( $extensionPath );
-                               if ( $svnInfo !== false ) {
-                                       $vcsVersion = $this->msg( 'version-svn-revision', $svnInfo['checkout-rev'] )->text();
-                                       $vcsLink = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
+                       global $IP;
+                       if ( $this->coreId == '' ) {
+                               wfDebug( 'Looking up core head id' );
+                               $coreHeadSHA1 = self::getGitHeadSha1( $IP );
+                               if ( $coreHeadSHA1 ) {
+                                       $this->coreId = $coreHeadSHA1;
+                               } else {
+                                       $svnInfo = self::getSvnInfo( $IP );
+                                       if ( $svnInfo !== false ) {
+                                               $this->coreId = $svnInfo['checkout-rev'];
+                                       }
                                }
                        }
+                       $cache = wfGetCache( CACHE_ANYTHING );
+                       $memcKey = wfMemcKey( 'specialversion-ext-version-text', $extension['path'], $this->coreId );
+                       list( $vcsVersion, $vcsLink, $vcsDate ) = $cache->get( $memcKey );
+
+                       if ( !$vcsVersion ) {
+                               wfDebug( "Getting VCS info for extension $extensionName" );
+                               $extensionPath = dirname( $extension['path'] );
+                               $gitInfo = new GitInfo( $extensionPath );
+                               $vcsVersion = $gitInfo->getHeadSHA1();
+                               if ( $vcsVersion !== false ) {
+                                       $vcsVersion = substr( $vcsVersion, 0, 7 );
+                                       $vcsLink = $gitInfo->getHeadViewUrl();
+                                       $vcsDate = $gitInfo->getHeadCommitDate();
+                               } else {
+                                       $svnInfo = self::getSvnInfo( $extensionPath );
+                                       if ( $svnInfo !== false ) {
+                                               $vcsVersion = $this->msg( 'version-svn-revision', $svnInfo['checkout-rev'] )->text();
+                                               $vcsLink = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
+                                       }
+                               }
+                               $cache->set( $memcKey, array( $vcsVersion, $vcsLink, $vcsDate ), 60 * 60 * 24 );
+                       } else {
+                               wfDebug( "Pulled VCS info for extension $extensionName from cache" );
+                       }
                }
 
                $versionString = Html::rawElement(
index e60293b..0eac06e 100644 (file)
@@ -30,6 +30,7 @@ class UIDGenerator {
        /** @var UIDGenerator */
        protected static $instance = null;
 
+       protected $nodeIdFile; // string; local file path
        protected $nodeId32; // string; node ID in binary (32 bits)
        protected $nodeId48; // string; node ID in binary (48 bits)
 
@@ -43,8 +44,11 @@ class UIDGenerator {
        const QUICK_VOLATILE = 2; // use an APC like in-memory counter if available
 
        protected function __construct() {
-               $idFile = wfTempDir() . '/mw-' . __CLASS__ . '-UID-nodeid';
-               $nodeId = is_file( $idFile ) ? file_get_contents( $idFile ) : '';
+               $this->nodeIdFile = wfTempDir() . '/mw-' . __CLASS__ . '-UID-nodeid';
+               $nodeId = '';
+               if ( is_file( $this->nodeIdFile ) ) {
+                       $nodeId = file_get_contents( $this->nodeIdFile );
+               }
                // Try to get some ID that uniquely identifies this machine (RFC 4122)...
                if ( !preg_match( '/^[0-9a-f]{12}$/i', $nodeId ) ) {
                        wfSuppressWarnings();
@@ -66,7 +70,7 @@ class UIDGenerator {
                                $nodeId = MWCryptRand::generateHex( 12, true );
                                $nodeId[1] = dechex( hexdec( $nodeId[1] ) | 0x1 ); // set multicast bit
                        }
-                       file_put_contents( $idFile, $nodeId ); // cache
+                       file_put_contents( $this->nodeIdFile, $nodeId ); // cache
                }
                $this->nodeId32 = wfBaseConvert( substr( sha1( $nodeId ), 0, 8 ), 16, 2, 32 );
                $this->nodeId48 = wfBaseConvert( $nodeId, 16, 2, 48 );
@@ -338,11 +342,12 @@ class UIDGenerator {
         */
        protected function getTimestampAndDelay( $lockFile, $clockSeqSize, $counterSize ) {
                // Get the UID lock file handle
-               if ( isset( $this->fileHandles[$lockFile] ) ) {
-                       $handle = $this->fileHandles[$lockFile];
+               $path = $this->$lockFile;
+               if ( isset( $this->fileHandles[$path] ) ) {
+                       $handle = $this->fileHandles[$path];
                } else {
-                       $handle = fopen( $this->$lockFile, 'cb+' );
-                       $this->fileHandles[$lockFile] = $handle ?: null; // cache
+                       $handle = fopen( $path, 'cb+' );
+                       $this->fileHandles[$path] = $handle ?: null; // cache
                }
                // Acquire the UID lock file
                if ( $handle === false ) {
@@ -450,6 +455,50 @@ class UIDGenerator {
                return array( (int)$sec, (int)( $msec * 1000 ) );
        }
 
+       /**
+        * Delete all cache files that have been created.
+        *
+        * This is a cleanup method primarily meant to be used from unit tests to
+        * avoid poluting the local filesystem. If used outside of a unit test
+        * environment it should be used with caution as it may destroy state saved
+        * in the files.
+        *
+        * @see unitTestTearDown
+        * @since 1.23
+        */
+       protected function deleteCacheFiles() {
+               // Bug: 44850
+               foreach ( $this->fileHandles as $path => $handle ) {
+                       if ( $handle !== null ) {
+                               fclose( $handle );
+                       }
+                       if ( is_file( $path ) ) {
+                               unlink( $path );
+                       }
+                       unset( $this->fileHandles[$path] );
+               }
+               if ( is_file( $this->nodeIdFile ) ) {
+                       unlink( $this->nodeIdFile );
+               }
+       }
+
+       /**
+        * Cleanup resources when tearing down after a unit test.
+        *
+        * This is a cleanup method primarily meant to be used from unit tests to
+        * avoid poluting the local filesystem. If used outside of a unit test
+        * environment it should be used with caution as it may destroy state saved
+        * in the files.
+        *
+        * @see deleteCacheFiles
+        * @since 1.23
+        */
+       public static function unitTestTearDown() {
+               // Bug: 44850
+               $gen = self::singleton();
+               $gen->deleteCacheFiles();
+       }
+
        function __destruct() {
                array_map( 'fclose', $this->fileHandles );
        }
index 2b98a18..1ad2b7a 100644 (file)
@@ -814,7 +814,7 @@ class Language {
        }
 
        /**
-        * @param  $image
+        * @param $image
         * @return array|null
         */
        function getImageFile( $image ) {
@@ -829,7 +829,7 @@ class Language {
        }
 
        /**
-        * @param  $tog
+        * @param $tog
         * @return string
         */
        function getUserToggle( $tog ) {
index 6385ed1..a0b428f 100644 (file)
     "search-section": "(bideuëng $1)",
     "search-suggest": "Kadang meukeusud Droëneuh nakeuh: $1",
     "search-interwiki-caption": "Buët la’én",
-    "search-interwiki-default": "Hasé $1:",
+    "search-interwiki-default": "Hasé nibak $1:",
     "search-interwiki-more": "(lom)",
     "searchrelated": "meusambat",
     "searchall": "ban dum",
     "prefs-skin": "Kulét",
     "skin-preview": "Eu dilèe",
     "datedefault": "Hana geunalak",
-    "prefs-beta": "Fitur bèta",
     "prefs-datetime": "Uroe ngön jeum",
     "prefs-user-pages": "Laman ureueng ngui",
     "prefs-personal": "Profil ureueng ngui",
     "yourlanguage": "Bahsa:",
     "yournick": "Tanda jaroe barô:",
     "prefs-help-signature": "Komèntar bak ôn marit suwah neubôh \"<nowiki>~~~~</nowiki>\", nyang eunteuk meugantoe keu tanda jaroe droeneuh ngön watèe jinoe.",
-    "badsiglength": "Tanda jaroë droëneuh panyang that.\nBèk neupeuleubèh nibak $1 {{PLURAL:$1|haraih|haraih}}.",
+    "badsiglength": "Tanda jaroë droëneuh panyang that.\nBèk leubèh nibak $1 {{PLURAL:$1|karakter}}.",
     "gender-unknown": "Hana geupeunyata",
     "gender-male": "Ureueng agam",
     "gender-female": "Ureueng inöng",
index f27f487..8dffa7f 100644 (file)
     "prefs-skin": "Omslag",
     "skin-preview": "Voorskou",
     "datedefault": "Geen voorkeur",
-    "prefs-beta": "Beta-funksies",
     "prefs-datetime": "Datum en tyd",
     "prefs-labs": "Labs-funksies",
     "prefs-user-pages": "Gebruikersbladsye",
     "nowatchlist": "U het geen items in u dophoulys nie.",
     "watchlistanontext": "$1 is noodsaaklik om u dophoulys te sien of te wysig.",
     "watchnologin": "Nie ingeteken nie",
-    "watchnologintext": "U moet [[Special:UserLogin|aangemeld]] wees om u dophoulys te verander.",
     "addwatch": "Voeg by dophoulys",
     "addedwatchtext": "Die bladsy \"[[:$1]]\" is by u [[Special:Watchlist|dophoulys]] bygevoeg.\nToekomstige wysigings aan hierdie bladsy en sy bybehorende besprekingsblad sal hier gelys word.",
     "removewatch": "Verwyder van dophoulys",
     "allmessagesname": "Naam",
     "allmessagesdefault": "Verstekteks",
     "allmessagescurrent": "Huidige teks",
-    "allmessagestext": "Hier is 'n lys boodskappe wat in die ''MediaWiki''-naamruimte teenwoordig is.\nGaan na [https://www.mediawiki.org/wiki/Localisation MediaWiki-lokalisasie] en [//translatewiki.net translatewiki.net] as u wil help om MediaWiki te vertaal.",
+    "allmessagestext": "Hier is 'n lys boodskappe wat in die ''MediaWiki''-naamruimte teenwoordig is.\nGaan na [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki-lokalisasie] en [//translatewiki.net translatewiki.net] as u wil help om MediaWiki te vertaal.",
     "allmessagesnotsupportedDB": "Daar is geen ondersteuning vir '''{{ns:special}}:Allmessages''' omdat '''$wgUseDatabaseMessages''' uitgeskakel is.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filtreer op staat van verandering:",
index ce2e154..e655c6e 100644 (file)
     "prefs-skin": "Doka",
     "skin-preview": "Parapâmja",
     "datedefault": "S'ka parapëlqim",
-    "prefs-beta": "karakteristika Beta",
     "prefs-datetime": "Data dhe ora",
     "prefs-labs": "Laboratorë karakteristika",
     "prefs-personal": "Profili i përdoruesit",
index d84788b..ba2aaab 100644 (file)
     "nowatchlist": "ዝርዝርዎ ባዶ ነው። ምንም ገጽ ገና አልተጨመረም።",
     "watchlistanontext": "የሚከታተሉት ገጾች ዝርዝርዎን ለመመልከት ወይም ለማስተካከል እባክዎ $1።",
     "watchnologin": "ገና አልገቡም",
-    "watchnologintext": "የሚከታተሏቸውን ገጾች ዝርዝር ለመቀየር [[Special:UserLogin|መግባት]] ይኖርብዎታል።",
     "addedwatchtext": "ገጹ «$1» [[Special:Watchlist|ለሚከታተሉት ገጾች]] ተጨምሯል። ወደፊት ይህ ገጽ ወይም የውይይቱ ገጽ ሲቀየር፣ በዚያ ዝርዝር ላይ ይታያል። በተጨማሪም [[Special:RecentChanges|«በቅርብ ጊዜ በተለወጡ» ገጾች]] ዝርዝር፣ በቀላሉ እንዲታይ በ'''ጉልህ ፊደላት''' ተጽፎ ይገኛል።\n\nበኋላ ጊዜ ገጹን ከሚከታተሉት ገጾች ለማስወግድ የፈለጉ እንደሆነ፣ በጫፉ ዳርቻ «አለመከታተል» የሚለውን ይጫኑ።",
     "removedwatchtext": "ይህ ገፅ \"[[:$1]]\" ከ [[Special:Watchlist|your watchlist]] ተወግዷል።",
     "watch": "ለመከታተል",
     "allmessagesname": "የመልእክት ስም",
     "allmessagesdefault": "የቆየው ጽሕፈት",
     "allmessagescurrent": "ያሁኑ ጽሕፈት",
-    "allmessagestext": "በ«MediaWiki» ክፍለ-ዊኪ ያሉት የድረገጽ መልክ መልእክቶች ሙሉ ዝርዝር ይህ ነው።\nPlease visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
+    "allmessagestext": "በ«MediaWiki» ክፍለ-ዊኪ ያሉት የድረገጽ መልክ መልእክቶች ሙሉ ዝርዝር ይህ ነው።\nPlease visit [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' ስለ ተዘጋ '''{{ns:special}}:Allmessages''' ሊጠቀም አይችልም።",
     "allmessages-filter-legend": "ማጣሪያ",
     "allmessages-filter-all": "ሁሉ",
index 32c37b0..054ba5c 100644 (file)
     "prefs-skin": "Aparencia",
     "skin-preview": "Fer una prebatina",
     "datedefault": "Sin de preferencias",
-    "prefs-beta": "Caracteristicas beta",
     "prefs-datetime": "Calendata y hora",
     "prefs-labs": "Caracteristicas experimentals",
     "prefs-personal": "Datos presonals",
     "nowatchlist": "No tien garra pachina en a lista de seguimiento.",
     "watchlistanontext": "Ha de $1 ta veyer u editar as dentradas d'a suya lista de seguimiento.",
     "watchnologin": "No ha encetato a sesión",
-    "watchnologintext": "Ha d'estar [[Special:UserLogin|identificato]] ta poder cambiar a suya lista de seguimiento.",
     "addwatch": "Adhibir ta la lista de seguimiento",
     "addedwatchtext": "A pachina «[[:$1]]» s'ha adhibito t'a suya [[Special:Watchlist|lista de seguimiento]]. Os cambios esdevenideros en ista pachina y en a suya pachina de descusión asociata s'indicarán astí, y a pachina amanixerá '''en negreta''' en a [[Special:RecentChanges|lista de cambios recients]] ta que se veiga millor. <p>Si nunca quiere borrar a pachina d'a suya lista de seguimiento, punche \"Deixar de cosirar\" en o menú.",
     "removewatch": "Sacar d'a lista de seguimiento",
     "allmessagesname": "Nombre",
     "allmessagesdefault": "texto por defecto",
     "allmessagescurrent": "texto actual",
-    "allmessagestext": "Ista ye una lista de totz os mensaches disponibles en o espacio de nombres MediaWiki.\nVesite por favor [https://www.mediawiki.org/wiki/Localisation a pachina sobre localización de MediaWiki] y  [//translatewiki.net translatewiki.net] si deseya contrebuyir t'a localización cheneral de MediaWiki.",
+    "allmessagestext": "Ista ye una lista de totz os mensaches disponibles en o espacio de nombres MediaWiki.\nVesite por favor [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation a pachina sobre localización de MediaWiki] y  [//translatewiki.net translatewiki.net] si deseya contrebuyir t'a localización cheneral de MediaWiki.",
     "allmessagesnotsupportedDB": "Ista pachina no ye disponible porque wgUseDatabaseMessages ye desactivato.",
     "allmessages-filter-legend": "Filtro",
     "allmessages-filter": "Filtrar por estau de personalización:",
index 9e85baa..2218c08 100644 (file)
@@ -1,6 +1,48 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            ";Hiba;1",
+            "Abanima",
+            "Achraf94",
+            "Aiman titi",
+            "Alexknight12",
+            "Ali1",
+            "Alnokta",
+            "Amire80",
+            "Antime",
+            "Arjanizary",
+            "Asaifm",
+            "Avocato",
+            "Bachounda",
+            "Basharh",
+            "Bassem JARKAS",
+            "Ciphers",
+            "Claw eg",
+            "DRIHEM",
+            "Gharbeia",
+            "Houcinee1",
+            "Ibrahim.ID",
+            "Majid Al-Dharrab",
+            "Meno25",
+            "Mido",
+            "Mo7amedsalim",
+            "OsamaK",
+            "Reedy",
+            "Samer",
+            "TTMTT",
+            "Tarawneh",
+            "Tux-tn",
+            "Zanatos",
+            "أحمد",
+            "ترجمان05",
+            "روخو",
+            "زكريا",
+            "عمرو",
+            "محمد أحمد عبد الفتاح",
+            "مشعل الحربي",
+            "نصوح",
+            "وهراني"
+        ]
     },
     "tog-underline": "سطر تحت الوصلات:",
     "tog-hideminor": "أخف التعديلات الطفيفة في أحدث التغييرات",
     "prefs-skin": "واجهة",
     "skin-preview": "عرض مسبق",
     "datedefault": "لا تفضيل",
-    "prefs-beta": "مزايا تجريبية",
     "prefs-datetime": "وقت وتاريخ",
     "prefs-labs": "مزايا مختبرية",
     "prefs-user-pages": "صفحات المستخدمين",
     "nowatchlist": "لا توجد مدخلات في قائمة مراقبتك.",
     "watchlistanontext": "الرجاء $1 لعرض أو تعديل الصفحات في قائمة مراقبتك.",
     "watchnologin": "غير مسجل الدخول",
-    "watchnologintext": "يجب أن تكون [[Special:UserLogin|مسجل الدخول]] لتعدل قائمة مراقبتك.",
     "addwatch": "إضافة إلى قائمة المراقبة",
     "addedwatchtext": "أضيفت الصفحة  \"[[:$1]]\" إلى [[Special:Watchlist|قائمة مراقبتك]].\nالتغييرات القادمة على هذه الصفحة وصفحة نقاشها سيتم وضعها هناك.",
     "removewatch": "إزالة من قائمة المراقبة",
     "allmessagesname": "الاسم",
     "allmessagesdefault": "النص الافتراضي",
     "allmessagescurrent": "النص الحالي",
-    "allmessagestext": "هذه قائمة برسائل النظام المتوفرة في نطاق ميدياويكي.\nمن فضلك زر [https://www.mediawiki.org/wiki/Localisation ترجمة ميدياويكي] و [//translatewiki.net بيتاويكي] لو كنت ترغب في المساهمة في ترجمة ميدياويكي الأساسية.",
+    "allmessagestext": "هذه قائمة برسائل النظام المتوفرة في نطاق ميدياويكي.\nمن فضلك زر [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation ترجمة ميدياويكي] و [//translatewiki.net بيتاويكي] لو كنت ترغب في المساهمة في ترجمة ميدياويكي الأساسية.",
     "allmessagesnotsupportedDB": "هذه الصفحة لا يمكن استخدامها لأن '''$wgUseDatabaseMessages''' تم تعطيله.",
     "allmessages-filter-legend": "المرشح",
     "allmessages-filter": "رشح حسب حالة التخصيص:",
     "version-entrypoints": "نقطة دخول روابط المواقع",
     "version-entrypoints-header-entrypoint": "تقطة دخول",
     "version-entrypoints-header-url": "المسار",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath مسار المقالات]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath مسار السكريبت]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath مسار المقالات]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath مسار السكريبت]",
     "redirect": "تحويل حسب رقم الملف أو رقم المستخدم أو رقم الصفحة أو رقم مراجعة",
     "redirect-legend": "تحويل إلى ملف أو صفحة",
     "redirect-summary": "هذه الصفحة الخاصة تحوّل إلى ملف (باسمه) أو صفحة (برقم إحدى مراجعاتها) أو إلى صفحة مستخدم (برقمه التعريفي). الاستخدام [[{{#Special:Redirect}}/file/Example.jpg]] أو [[{{#Special:Redirect}}/revision/328429]] أو [[{{#Special:Redirect}}/user/101]].",
index 3a8ba17..3f3ce11 100644 (file)
     "prefs-skin": "الوش",
     "skin-preview": "بروفه",
     "datedefault": "مافبش تفضيل",
-    "prefs-beta": "خصايص Beta",
     "prefs-datetime": "وقت وتاريخ",
     "prefs-labs": "خصايص Labs",
     "prefs-personal": "الپروفيل بتاع اليوزر",
     "nowatchlist": "مافيش حاجة فى لستة مراقبتك.",
     "watchlistanontext": "لو سمحت $1 لعرض أو تعديل الصفحات فى لستة مراقبتك.",
     "watchnologin": "مش متسجل",
-    "watchnologintext": "لازم تكون [[Special:UserLogin|مسجل الدخول]] علشان تعدل لستة المراقبة بتاعتك.",
     "addedwatchtext": "تمت إضافة الصفحه  \"$1\"  [[Special:Watchlist|للستة الصفحات اللى بتراقبها]].\nالتعديلات اللى بعد كده ها تتحط على الصفحه دى، وصفحة المناقش الخاصه بها ها تتحط هناك. واسم الصفحة هايظهر  بخط <b>عريض</b> فى صفحة [[Special:RecentChanges|أحدث التعديلات]] لتسهيل تحديدها واكتشافها.",
     "removedwatchtext": "الصفحه دى اتشالت \"[[:$1]]\" من [[Special:Watchlist|لستة الصفحات اللى بتراقبها]].",
     "watch": "راقب",
     "allmessagesname": "اسم",
     "allmessagesdefault": "النص الاوتوماتيكي",
     "allmessagescurrent": "النص دلوقتى",
-    "allmessagestext": "دى لستة برسايل النظام المتوفرة فى نطاق ميدياويكي.\nلو سمحت تزور[https://www.mediawiki.org/wiki/Localisation ترجمة ميدياويكي] و [//translatewiki.net بيتاويكي] لو كنت عايز تساهم فى ترجمة ميدياويكى الاصلية.",
+    "allmessagestext": "دى لستة برسايل النظام المتوفرة فى نطاق ميدياويكي.\nلو سمحت تزور[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation ترجمة ميدياويكي] و [//translatewiki.net بيتاويكي] لو كنت عايز تساهم فى ترجمة ميدياويكى الاصلية.",
     "allmessagesnotsupportedDB": "الصفحة دى مش يمكن حد يستعملها علشان'''$wgUseDatabaseMessages''' متعطل.",
     "allmessages-filter-legend": "فيلتر",
     "allmessages-filter": "فلتره بحالة التهيئه:",
index b7337a2..389d48f 100644 (file)
     "pool-timeout": "বন্ধ কৰাৰ বাবে অপেক্ষা কৰাৰ সময় উকলি গৈছে",
     "pool-queuefull": "পুল কিউ (pool queue) পূৰ্ণ",
     "pool-errorunknown": "অপৰিচিত ত্ৰুটি",
+    "pool-servererror": "পুল কাউণ্টাৰ সেৱা উপলব্ধ নহয় ($1)।",
     "aboutsite": "{{SITENAME}}ৰ বিষয়ে",
     "aboutpage": "Project:ইতিবৃত্ত",
     "copyright": "আন একো উল্লেখ নাথাকিলে এই বিষয়বস্তু $1 ৰ আওতাত উপলব্ধ।",
     "gotaccountlink": "প্ৰৱেশ",
     "userlogin-resetlink": "আপোনাৰ প্ৰৱেশ তথ্য পাহৰিছে?",
     "userlogin-resetpassword-link": "আপোনাৰ গুপ্তশব্দ পাহৰিছে?",
+    "userlogin-helplink2": "প্ৰৱেশ সংক্ৰান্তীয় সাহায্য",
     "userlogin-loggedin": "আপুনি ইতিমধ্যে {{GENDER:$1|$1}} হিচাপে প্ৰৱেশ কৰিছে। তলৰ আন সদস্যৰূপে প্ৰৱেশ কৰিবলৈ তলৰ প্ৰপত্ৰ ব্যৱহাৰ কৰক।",
     "userlogin-createanother": "আন এটা একাউণ্ট সৃষ্টি কৰক",
     "createacct-join": "আপোনাৰ তথ্যসমূহ তলত লিখক।",
     "loginlanguagelabel": "ভাষা: $1",
     "suspicious-userlogout": "আপোনাৰ প্ৰস্থানৰ অনুৰোধ বাতিল কৰা হৈছে কাৰণ হয়তো আপোনাৰ ব্ৰাউজাৰ অসম্পূৰ্ণ নতুবা পূৰ্বৱতী তথ্য পঠাইছে ।",
     "createacct-another-realname-tip": "প্ৰকৃত নাম দিয়াটো বৈকল্পিক।\nআপুনি নামটো দিলে সেইটো আপোনাৰ বৰঙণিসমূহৰ বাবে স্বীকৃতি প্ৰদানত ব্যৱহাৰ কৰা হ'ব।",
+    "pt-login": "প্ৰৱেশ",
     "pt-login-button": "প্ৰৱেশ",
+    "pt-createaccount": "একাউণ্ট সৃষ্টি কৰক",
+    "pt-userlogout": "প্ৰস্থান",
     "php-mail-error-unknown": "পি.এইছ.পি মেইল () কাৰ্যত অজ্ঞাত ত্ৰুটি ।",
     "user-mail-no-addy": "ই-মেইল ঠিকনা নোহোৱাকৈয়ে ই-মেইল পঠিওৱাৰ চেষ্টা কৰা হৈছে ।",
     "user-mail-no-body": "কোনো সমল নোহোৱাকৈ বা অতি সংক্ষিপ্ত কথাৰে ইমেইল পঠিয়াবলৈ চেষ্টা কৰিছিল।",
     "changepassword": "গুপ্তশব্দ সলনি কৰক",
-    "resetpass_announce": "à¦\86পà§\81নি à¦\87-মà§\87à¦\87লত à¦ªà§\8bৱা à¦\85সà§\8dথায়à§\80 à¦\97à§\81পà§\8dতশবà§\8dদৰà§\87 à¦ªà§\8dৰৱà§\87শ à¦\95ৰিà¦\9bà§\87।\nপà§\8dৰৱà§\87শ à¦¸à¦®à§\8dপà§\82ৰà§\8dণ à¦\95ৰিবলà§\88, à¦\86পà§\81নি à¦\8fà¦\9fা à¦¨à¦¤à§\81ন à¦\97à§\81পà§\8dতশবà§\8dদ à¦¦à¦¿à¦¬ à¦²à¦¾à¦\97িব:",
+    "resetpass_announce": "পà§\8dৰৱà§\87শ à¦¸à¦®à§\8dপà§\82ৰà§\8dণ à¦\95ৰিবলà§\88 à¦\86পà§\81নি à¦\8fà¦\9fা à¦¨à¦¤à§\81ন à¦\97à§\81পà§\8dতশবà§\8dদ à¦¦à¦¿à¦¬ à¦²à¦¾à¦\97িব।",
     "resetpass_header": "গুপ্তশব্দ সলনি কৰক",
     "oldpassword": "পুৰণি গুপ্তশব্দ:",
     "newpassword": "নতুন গুপ্তশব্দ:",
     "resetpass-submit-loggedin": "গুপ্তশব্দ সলনি কৰক",
     "resetpass-submit-cancel": "বাতিল কৰক",
     "resetpass-wrong-oldpass": "অস্থায়ী বা সাম্প্ৰতিক গুপ্তশব্দ গ্ৰহণযোগ্য নহয় ।\nহয়টো আপুনি ইতিমধ্যেই সফলভাবে আপুনাৰ গুপ্তশব্দ সলনি কৰিছিল বা এটা নতুন অস্থায়ী গুপ্তশব্দৰ বাবে অনুৰোধ কৰিছিল ।",
+    "resetpass-recycled": "অনুগ্ৰহ কৰি এতিয়াৰ গুপ্তশব্দটোৰ সলনি আন এটা গুপ্তশব্দ নিৰ্ধাৰণ কৰক।",
+    "resetpass-temp-emailed": "আপুনি এটা অস্থায়ী ইমেইল যোগে প্ৰাপ্ত সংকেতেৰে প্ৰৱেশ কৰিছে।\nপ্ৰৱেশ সম্পূৰ্ণ কৰিবলৈ আপুনি ইয়াত এটা নতুন গুপ্তশব্দ নিৰ্ধাৰণ কৰিব লাগিব:",
     "resetpass-temp-password": "অস্থায়ী গুপ্তশব্দ:",
     "resetpass-abort-generic": "এটা এক্সটেন্‌ছনৰদ্বাৰা গুপ্তশব্দ সলনি কাৰ্য বাতিল কৰা হৈছে।",
+    "resetpass-expired": "আপোনাৰ গুপ্তশব্দৰ ম্যাদ উকলি গৈছে। অনুগ্ৰহ কৰি প্ৰৱেশৰ বাবে এটা নতুন গুপ্তশব্দ নিৰ্ধাৰণ কৰক।",
+    "resetpass-expired-soft": "আপোনাৰ গুপ্তশব্দৰ ম্যাদ উকলি গৈছে আৰু নতুন এটা নিৰ্ধাৰণ কৰাৰ প্ৰয়োজন। অনুগ্ৰহ কৰি এতিয়া এটা নতুন গুপ্তশব্দ বাছনি কৰক বা পিছত নিৰ্ধাৰণ কৰিবলৈ \"{{int:resetpass-submit-cancel}}\" বুটামত ক্লিক কৰক।",
     "passwordreset": "গুপ্তশব্দ ন-কৈ বহুৱাওক",
     "passwordreset-text-one": "আপোনাৰ গুপ্তশব্দ ন-কৈ বহুৱাবলৈ এই প্ৰপত্ৰ পূৰণ কৰক।",
     "passwordreset-text-many": "{{PLURAL:$1|ইমেইলত এটা অস্থায়ী গুপ্তশব্দ পাবলৈ এই তথ্যসমূহৰ যিকোনো এটা দিয়ক।}}",
     "prefs-skin": "আৱৰণ",
     "skin-preview": "খচৰা",
     "datedefault": "কোনো পছন্দ নাই",
-    "prefs-beta": "বিটা বৈশিষ্টসমূহ",
     "prefs-datetime": "তাৰিখ আৰু সময়",
     "prefs-labs": "পৰীক্ষাগাৰ বৈশিষ্টসমূহ",
     "prefs-user-pages": "সদস্য পৃষ্ঠাসমূহ",
     "rcnotefrom": "তলত '''$2''' ৰ পৰা হোৱা ('''$1''' লৈকে) পৰিৱৰ্তন দেখুৱা হৈছে ।",
     "rclistfrom": "$1ৰ পৰা নতুন সালসলনি দেখুৱাওক",
     "rcshowhideminor": "$1 -সংখ্যক নগণ্য সম্পাদনা",
+    "rcshowhideminor-show": "দেখুৱাওক",
+    "rcshowhideminor-hide": "লুকুৱাওক",
     "rcshowhidebots": "ব'ট $1",
+    "rcshowhidebots-show": "দেখুৱাওক",
+    "rcshowhidebots-hide": "লুকুৱাওক",
     "rcshowhideliu": "$1 পঞ্জীভুক্ত সদস্য",
+    "rcshowhideliu-show": "দেখুৱাওক",
+    "rcshowhideliu-hide": "লুকুৱাওক",
     "rcshowhideanons": "বেনামী সদস্য $1",
+    "rcshowhideanons-show": "দেখুৱাওক",
+    "rcshowhideanons-hide": "লুকুৱাওক",
     "rcshowhidepatr": "$1 নিৰীক্ষিত সম্পাদনা",
+    "rcshowhidepatr-show": "দেখুৱাওক",
+    "rcshowhidepatr-hide": "লুকুৱাওক",
     "rcshowhidemine": "মোৰ সম্পাদনা $1",
+    "rcshowhidemine-show": "দেখুৱাওক",
+    "rcshowhidemine-hide": "লুকুৱাওক",
     "rclinks": "যোৱা $2 দিনত হোৱা $1 টা সাল-সলনি চাওক ।<br />$3",
     "diff": "পাৰ্থক্য",
     "hist": "ইতিবৃত্ত",
     "protectedpages-cascade": "কেৱল প্ৰপাতাকাৰ সুৰক্ষা",
     "protectedpages-noredirect": "পুনঃনিৰ্দেশ লুকুৱাওক",
     "protectedpagesempty": "এই পাৰামিটাৰবোৰেৰে কোনো পৃষ্ঠা এতিয়া সুৰক্ষিত কৰা হোৱা নাই ।",
+    "protectedpages-page": "পৃষ্ঠা",
+    "protectedpages-expiry": "ম্যাদ উকলিব",
     "protectedtitles": "সুৰক্ষিত শিৰোনামাসমূহ",
     "protectedtitlesempty": "এই পাৰামিটাৰবোৰেৰে কোনো শিৰোনামা এতিয়া সুৰক্ষিত কৰা হোৱা নাই ।",
     "listusers": "সদস্য তালিকা",
     "nowatchlist": "আপোনাৰ নিৰীক্ষণ তালিকাত একো নাই ।",
     "watchlistanontext": "আপোনাৰ লক্ষ্য তালিকাত থকা বস্তুবোৰ চাবলৈ বা সম্পাদনা কৰিবলৈ অনুগ্ৰহ কৰি $1 কৰক।",
     "watchnologin": "প্ৰৱেশ কৰা নাই",
-    "watchnologintext": "নিৰীক্ষণ তালিকা পৰিৱৰ্তন কৰিবলৈ আপুনি আগতে [[Special:UserLogin|প্ৰৱেশ]] কৰিব লাগিব ।",
     "addwatch": "লক্ষ্য-তালিকাত অন্তৰ্ভুক্ত কৰক",
     "addedwatchtext": "আপোনাৰ [[Special:Watchlist|লক্ষ্য তালিকাত ]] \"[[:$1]]\" পৃষ্ঠাটো অন্তৰ্ভুক্ত কৰা হ'ল।\nভৱিষ্যতে এই পৃষ্ঠা বা ইয়াৰ আলোচনা পৃষ্ঠাত হোৱা সাল-সলনি আপুনি আপোনাৰ লক্ষ্য তালিকাত দেখিব।",
     "removewatch": "লক্ষ্য-তালিকাৰ পৰা আঁতৰাওক",
     "allmessagesname": "নাম",
     "allmessagesdefault": "সাধাৰণ বাৰ্তা পাঠ্য",
     "allmessagescurrent": "বৰ্তমানৰ বাৰ্তাৰ পাঠ",
-    "allmessagestext": "মিডিয়াৱিকি নামস্থানত থকা প্ৰণালী বাৰ্তাসমূহৰ তালিকা ইয়াত দিয়া হৈছে ।\nযদি আপুনি মিডিয়াৱিকিৰ স্থানীয়কৰণত আগ্ৰহী, তেন্তে অনুগ্ৰহ কৰি [https://www.mediawiki.org/wiki/Localisation মিডিয়াৱিকি স্থানীয়কৰণ] আৰু [//translatewiki.net translatewiki.net] চাওক ।",
+    "allmessagestext": "মিডিয়াৱিকি নামস্থানত থকা প্ৰণালী বাৰ্তাসমূহৰ তালিকা ইয়াত দিয়া হৈছে ।\nযদি আপুনি মিডিয়াৱিকিৰ স্থানীয়কৰণত আগ্ৰহী, তেন্তে অনুগ্ৰহ কৰি [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation মিডিয়াৱিকি স্থানীয়কৰণ] আৰু [//translatewiki.net translatewiki.net] চাওক ।",
     "allmessagesnotsupportedDB": "এই পৃষ্ঠা ব্যৱহাৰ কৰিব নোৱাৰি কাৰণ '''$wgUseDatabaseMessages''' নিষ্ক্ৰিয় কৰা হৈছে ।",
     "allmessages-filter-legend": "ছেকনী",
     "allmessages-filter": "স্বনিৰ্বাচন অৱস্থাৰে পৰিস্ৰাৱন কৰক:",
index 66427ff..a4135fa 100644 (file)
     "pool-timeout": "Tiempu escosáu esperando pal bloquéu",
     "pool-queuefull": "La cola de trabayu ta enllena",
     "pool-errorunknown": "Fallu desconocíu",
+    "pool-servererror": "El serviciu de contador de recursos compartíos nun ta disponible ($1).",
     "aboutsite": "Tocante a {{SITENAME}}",
     "aboutpage": "Project:Tocante a",
     "copyright": "El conteníu ta disponible baxo los términos de la $1 si nun s'indica otra cosa.",
     "prefs-skin": "Apariencia",
     "skin-preview": "Vista previa",
     "datedefault": "Ensin preferencia",
-    "prefs-beta": "Carauterístiques beta",
     "prefs-datetime": "Fecha y hora",
     "prefs-labs": "Carauterístiques esperimentales",
     "prefs-user-pages": "Páxines d'usuariu",
     "listgrouprights-removegroup-self": "Desaniciar {{PLURAL:$2|grupu|grupos}} de la cuenta propia: $1",
     "listgrouprights-addgroup-self-all": "Amestar tolos grupos a la cuenta propia",
     "listgrouprights-removegroup-self-all": "Desaniciar tolos grupos de la cuenta propia",
+    "trackingcategories": "Categoríes de siguimientu",
+    "trackingcategories-summary": "Esta páxina llista les categoríes de siguimientu que rellena automáticamente'l software de MediaWiki. Puen camudase los nomes alterando los mensaxes del sistema correspondientes nel espaciu de nomes {{ns:8}}.",
+    "trackingcategories-msg": "Categoría de siguimientu",
+    "trackingcategories-name": "Nome del mensaxe",
+    "trackingcategories-desc": "Criterios d'inclusión de categoría",
+    "noindex-category-desc": "La páxina contién una pallabra máxica <nowiki>__NOINDEX__</nowiki> (y ta nun espaciu de nomes nel que se permite esta marca) y, poro, los robots nun la indexarán.",
+    "index-category-desc": "La páxina contién una pallabra máxica <nowiki>__INDEX__</nowiki> (y ta nun espaciu de nomes nel que se permite esta marca) y, poro, los robots la indexarán anque normalmente nun lo faigan.",
+    "post-expand-template-inclusion-category-desc": "Después de espander toles plantíes, el tamañu de la páxina ye mayor que $wgMaxArticleSize; de mou qu'algunes plantíes nun s'espandieron.",
+    "post-expand-template-argument-category-desc": "Después d'espander l'argumentu d'una plantía (daqué ente llaves triples, como {{{Daqué}}}), la páxina ye mayor que $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "Hai demasiaes funciones analítiques costoses (como <code>#ifexist</code>) incluíes nuna páxina. Vea [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Categoría amestada si la páxina contién un enllaz de ficheru frañáu (un enllaz pa incrustar un ficheru cuando'l ficheru nun esiste).",
+    "hidden-category-category-desc": "Esta ye una categoría que contién la pallabra máxica <nowiki>__HIDDENCAT__</nowiki>, que torga que s'amuese de mou predetermináu nel cuadru d'enllaces de categoría de les páxines.",
+    "trackingcategories-nodesc": "Nun hai una descripción disponible.",
+    "trackingcategories-disabled": "La categoría ta desactivada",
     "mailnologin": "Ensin direición d'unviu",
     "mailnologintext": "Has tener [[Special:UserLogin|sesión aniciada]] y una direición de corréu válida nes tos [[Special:Preferences|preferencies]] pa poder unviar correos a otros usuarios.",
     "emailuser": "Manda-y un corréu a esti usuariu",
     "nowatchlist": "La to llista de vixilancia ta vacia.",
     "watchlistanontext": "Por favor $1 pa ver o editar entraes na to llista de vixilancia.",
     "watchnologin": "Non identificáu",
-    "watchnologintext": "Tienes que tar [[Special:UserLogin|identificáu]] pa poder camudar la to llista de vixilancia.",
     "addwatch": "Amestar a la llista de vixilancia",
     "addedwatchtext": "La páxina \"[[:$1]]\" s'amestó a la to [[Special:Watchlist|llista de vixilancia]].\nLos futuro cambeos nesta páxina y na so páxina d'alderique asociada apaecerán allí.",
     "removewatch": "Desaniciar de la llista de vixilancia",
     "sp-contributions-newbies-sub": "Namái les cuentes nueves",
     "sp-contributions-newbies-title": "Contribuciones d'usuariu pa cuentes nueves",
     "sp-contributions-blocklog": "rexistru de bloqueos",
+    "sp-contributions-suppresslog": "collaboraciones del usuariu desaniciaes",
     "sp-contributions-deleted": "Contribuciones d'usuariu desaniciaes",
     "sp-contributions-uploads": "xubes",
     "sp-contributions-logs": "rexistros",
     "sp-contributions-blocked-notice": "Esti usuariu anguaño ta bloquiáu.\nLa cabera entrada del rexistru de bloqueos s'ufre darréu pa referencia:",
     "sp-contributions-blocked-notice-anon": "Esta IP anguaño ta bloquiada.\nLa cabera entrada del rexistru de bloqueos s'ufre darréu pa referencia:",
     "sp-contributions-search": "Buscar contribuciones",
-    "sp-contributions-suppresslog": "collaboraciones del usuariu desaniciaes",
     "sp-contributions-username": "Direición IP o nome d'usuariu:",
     "sp-contributions-toponly": "Amosar namái les ediciones que son les caberes revisiones",
     "sp-contributions-newonly": "Amosar namái les ediciones que son creaciones de páxines",
     "allmessagesname": "Nome",
     "allmessagesdefault": "Testu predetermináu",
     "allmessagescurrent": "Testu actual",
-    "allmessagestext": "Esta ye una llista de los mensaxes de sistema disponibles nel espaciu de nomes de MediaWiki.\nPor favor visita [https://www.mediawiki.org/wiki/Localisation Llocalización de MediaWiki] y [//translatewiki.net translatewiki.net] si quies contribuyer a la llocalización xenérica de MediaWiki.",
+    "allmessagestext": "Esta ye una llista de los mensaxes de sistema disponibles nel espaciu de nomes de MediaWiki.\nPor favor visita [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Llocalización de MediaWiki] y [//translatewiki.net translatewiki.net] si quies contribuyer a la llocalización xenérica de MediaWiki.",
     "allmessagesnotsupportedDB": "Nun pue usase '''{{ns:special}}:Allmessages''' porque '''$wgUseDatabaseMessages''' ta deshabilitáu.",
     "allmessages-filter-legend": "Peñerar",
     "allmessages-filter": "Peñerar por estáu de personalización:",
index 1e69c3c..cf8b130 100644 (file)
     "nowatchlist": "Rinafi suzdasiki va nedoy teliz ruldar.",
     "watchlistanontext": "Ta wira ik betara va ra ke rinafi suzdasiki vay $1.",
     "watchnologin": "Dogluyariskaf",
-    "watchnologintext": "Ta betara va suzdasiki gotil [[Special:UserLogin|dogluyarakiraf]].",
     "addedwatchtext": "« $1 » bu ko rinafi [[Special:Watchlist|Suzdasiki]] fu zo loplekur.\nVa moniyaf betareem va batu bu is dofu prilarabu batlize zo bonjatad, ise ta lokaliafa tcalutera telu '''ton bold''' koe bu dem [[Special:RecentChanges|noeltaf betakseem]] turowinaweter.\n\nTa sulara va batu bu div rinafi suzdasiki, koe grablexo va « Mea suzdá » vulegal.",
     "removedwatchtext": "« [[:$1]] » bu div rinafi suzdasiki al zo sular.",
     "watch": "Suzdá",
     "allmessagesname": "Yolt",
     "allmessagesdefault": "Omavaf krent",
     "allmessagescurrent": "Noelaf krent",
-    "allmessagestext": "Batcoba tir vexala dem bolkstakseem koe MediaWiki yoltxo.\n\nVa [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] is [//translatewiki.net translatewiki.net] vay woral ede va tulizukara va Mediawiki co-rowebel.",
+    "allmessagestext": "Batcoba tir vexala dem bolkstakseem koe MediaWiki yoltxo.\n\nVa [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] is [//translatewiki.net translatewiki.net] vay woral ede va tulizukara va Mediawiki co-rowebel.",
     "allmessagesnotsupportedDB": "Batu bu me zo rofaver kire '''$wgUseDatabaseMessages''' mea tir tegis.",
     "thumbnail-more": "Tulogijara",
     "filemissing": "Gracaf iyeltak",
index 0067835..9e25590 100644 (file)
     "template-protected": "(mühafizə)",
     "template-semiprotected": "(yarım-mühafizə)",
     "hiddencategories": "Bu səhifə {{PLURAL:$1|1 gizli kateqoriyaya|$1 gizli kateqoriyaya}} aiddir:",
+    "edittools": "<!-- Buradakı mətn redaktə və quraşdırma formalarının altında göstəriləcək. -->",
     "edittools-upload": "-",
     "nocreatetext": "{{SITENAME}} saytında yeni səhifələrin yaradılması imkanları məhdudlaşdırılıb.\nSiz geri qayıdıb mövcud səhifəni və ya  [[Special:UserLogin|sistemə təqdim olunma və ya yeni hesab açmaq]] səhifəsini redaktə edə bilərsiniz.",
     "nocreate-loggedin": "Sizin yeni səhifələr yaratmaq üçün icazəniz yoxdur.",
     "prefs-skin": "Cild",
     "skin-preview": "Sınaq görüntüsü",
     "datedefault": "Seçim yoxdur",
-    "prefs-beta": "Beta xüsusiyyətlər",
     "prefs-datetime": "Tarix və vaxt",
     "prefs-labs": "eksperimental imkanlar",
     "prefs-personal": "İstifadəçi profili",
     "nowatchlist": "İzləmə siyahınız böşdur.",
     "watchlistanontext": "Lütfən, izlədiyiniz səhifələri görmək və ya redaktə etmək üçün $1.",
     "watchnologin": "Daxil olmamısınız",
-    "watchnologintext": "İzləmə siyahınızda dəyişiklik aparmaq üçün [[Special:UserLogin|daxil olmalısınız]].",
     "addwatch": "İzləmə siyahısına əlavə et",
     "addedwatchtext": "\"[[:$1]]\" səhifəsi [[Special:Watchlist|izlədiyiniz səhifələr]] siyahısına əlavə edildi. Bu səhifədə və əlaqəli müzakirə səhifəsindəki bütün dəyişikliklər orada göstəriləcək və səhifə asanlıqla seçiləbilmək üçün [[Special:RecentChanges|son dəyişikliklərdə]] qalın şriftlərlə görünəcəkdir. <p> Səhifəni izləmə siyahınızdan çıxarmaq üçün yan lövhədəki \"izləmə\" düyməsinə vurun.",
     "removewatch": "Bu səhifəni İzlədiyim səhifələr siyahısından çıxar",
     "allmessagesname": "Ad",
     "allmessagesdefault": "İlkin mətn",
     "allmessagescurrent": "İndiki mətn",
-    "allmessagestext": "Bu MediaWiki-də olan sistem mesajlarının siyahısıdır. Əgər MediaWiki-ni lokallaşdırmaq işində kömək etmək isəyirsinizsə, lütfən [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] və [//translatewiki.net translatewiki.net]-ə baş çəkin.",
+    "allmessagestext": "Bu MediaWiki-də olan sistem mesajlarının siyahısıdır. Əgər MediaWiki-ni lokallaşdırmaq işində kömək etmək isəyirsinizsə, lütfən [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] və [//translatewiki.net translatewiki.net]-ə baş çəkin.",
     "allmessages-filter-legend": "Filtr",
     "allmessages-filter-unmodified": "Dəyişdirilməmiş",
     "allmessages-filter-all": "Hamısı",
index 2788f01..3ed9ff5 100644 (file)
@@ -9,7 +9,8 @@
             "Ebraminio",
             "Erdemaslancan",
             "Mousa",
-            "Shirayuki"
+            "Shirayuki",
+            "Microchip08"
         ]
     },
     "tog-underline": "باغلانتی‌لارین آلتینی خطله:",
@@ -19,9 +20,9 @@
     "tog-extendwatchlist": "ایزله‌دیکلری، بوتون دیشیکلیکلری گؤسترمک اوچون گئنیشلندیر",
     "tog-usenewrc": "دَییشیکلیکلری سون دَییشیکلیکلر صحیفه‌سینده ایزله‌دیکلر صحیفه‌سینده گروپ‌لا (جاوااسکریپت لازیم‌دیر)",
     "tog-numberheadings": "باشلیق‌لاری اوتوماتیک نومره‌له",
-    "tog-showtoolbar": "دَییشدیرمه آراج چوبوغونو گؤستر (جاوااسکریپت لازیم‌دیر)",
-    "tog-editondblclick": "صحیفه‌‌لری ایکی کلیکله دَییشدیر (جاوااسکریپت لازیم‌دیر)",
-    "tog-editsectiononrightclick": "بؤلوم‌لرین دیشدیرمه‌سینی، باشلیقلارین اوزرینده ساغ‌کلیک ائتمک‌له ایجازه وئر (جاوااسکریپت لازیم‌دیر)",
+    "tog-showtoolbar": "دَییشدیرمه آراج چوبوغونو گؤستر",
+    "tog-editondblclick": "صحیفه‌‌لری ایکی کلیک‌ده دَییشدیر",
+    "tog-editsectiononrightclick": "بؤلوم‌لرین دیشدیرمه‌سینی، باشلیقلارین اوزرینده ساغ‌کلیک ائتمک‌له ایجازه وئر",
     "tog-rememberpassword": "منیم گیریشیمی بو بیلگی‌سایاردا یاددا ساخلا (چوخو {{PLURAL:$1|بیر گونه|$1 گونه}} کیمی)",
     "tog-watchcreations": "ياراتدیغیم صحیفه‌‌لری و يوکله‌دیگیم فايل‌لاری ایزله‌مه‌لریمه آرتیر",
     "tog-watchdefault": "دَییشدیردیگیم صحیفه‌‌لری و فايل‌لاری ایزله‌دیکلریمه آرتیر",
@@ -37,7 +38,7 @@
     "tog-shownumberswatching": "ایزله‌ين ایستیفاده‌چیلرین سایینی گؤستر",
     "tog-oldsig": "ایندی‌کی ایمضا:",
     "tog-fancysig": "ویکی متن کیمی ایمضا (اوتوماتیک باغلانتی‌سیز)",
-    "tog-uselivepreview": "دÛ\8cرÛ\8c Ø§Ø¤Ù\86â\80\8cگؤسترÛ\8cØ´ Ø§Û\8cØ´Ù\84د (جاÙ\88ااسکرÛ\8cپت Ù\84ازÛ\8cÙ\85â\80\8cدÛ\8cر)(تست مرحله‌سینده)",
+    "tog-uselivepreview": "دÛ\8cرÛ\8c Ø§Ø¤Ù\86â\80\8cگؤسترÛ\8cØ´ Ø§Û\8cØ´Ù\84ت (تست مرحله‌سینده)",
     "tog-forceeditsummary": "دَییشیکلیک قیساسی بوش قالاندا منی بیلدیر",
     "tog-watchlisthideown": "منیم دَییشیکلیکلریمی ایزله‌دیکلردن گیزلت",
     "tog-watchlisthidebots": "بوت دَییشیکلیکلرینی ایزله‌دیکلردن گیزلت",
@@ -50,6 +51,7 @@
     "tog-showhiddencats": "گیزلی بؤلمه‌لری گؤستر",
     "tog-norollbackdiff": "قایتاراندان سونرا موقاییسه گؤسترمه",
     "tog-useeditwarning": "دَییشدیرمه صحیفه‌سینده چیخیش زامانی، آچیق و قئید اولمایان دَییشدیرمه صحیفه وارسا منه هشدار وئریلسین",
+    "tog-prefershttps": "هر زامان گیریش ائتمگه امن باغلانتی ایشلت",
     "underline-always": "همیشه",
     "underline-never": "هئچ واخت",
     "underline-default": "دیفالت قابیق یوخسا براوزر",
     "oct": "اوکتوبر",
     "nov": "نووامبر",
     "dec": "دئسامبر",
+    "january-date": "ژانویه‌نین $1-ی",
     "february-date": "$1 فئوریه",
+    "march-date": "مارسین $1-ی",
+    "april-date": "آوریلین $1-ی",
     "may-date": "$1 مئی",
+    "june-date": "ژوئنین $1-ی",
     "july-date": "$1 ژولای",
     "august-date": "$1 آقوست",
     "september-date": "$1 سئپتامبر",
     "newwindow": "(یئنی پنجره‌ده آچیلیر)",
     "cancel": "لغو ائت",
     "moredotdotdot": "داها...",
-    "morenotlisted": "داÙ\87ا Ø¢Ø±ØªÛ\8cÙ\82 Ù\84Û\8cست Ø§Ù\88Ù\84Ù\88Ù\86Ù\85اÛ\8cÛ\8cبâ\80\8cدÛ\8cر...",
+    "morenotlisted": "بÙ\88 Ù\84Û\8cست Ú©Ø§Ù\85Ù\84 Ø¯Ø¦Û\8cÛ\8cÙ\84.",
     "mypage": "مقاله",
     "mytalk": "دانیشیق",
     "anontalk": "بو آی‌پی آدرسینه دانیشیق",
     "articlepage": "مقاله‌یه باخین",
     "talk": "دانیشیق",
     "views": "گؤرونوشلر",
-    "toolbox": "آراجلار قوتوسو",
+    "toolbox": "آراجلار",
     "userpage": "ایستیفاده‌چی صحیفه‌‌سینی باخین",
     "projectpage": "پروژه صحیفه‌سینه باخین",
     "imagepage": "فایل صحیفه‌سینه باخین",
     "youhavenewmessages": "سیزین $1 ($2) وارینیزدیر.",
     "youhavenewmessagesfromusers": "سیزین {{PLURAL:$3|بیر آیری ایستیفاده‌چی‌دن|$3 ایستیفاده‌چی‌دن}} $1 وارینیزدیر ($2).",
     "youhavenewmessagesmanyusers": "سیزین چوخلو ایشلدنلردن $1 وارینیزدیر ($2).",
-    "newmessageslinkplural": "{{PLURAL:$1|بیر یئنی مئساژ|یئنی مئساژلار}}",
-    "newmessagesdifflinkplural": "سون {{PLURAL:$1|دَییشیکلیک|دَییشیکلیکلر}}",
+    "newmessageslinkplural": "{{PLURAL:$1|بیر یئنی مئساژ|999=یئنی مئساژلار}}",
+    "newmessagesdifflinkplural": "سون {{PLURAL:$1|دَییشیکلیک|999=دَییشیکلیکلر}}",
     "youhavenewmessagesmulti": "$1-دا یئنی بیلدیرینیز وار.",
     "editsection": "دَییشدیر",
     "editold": "دَییشدیر",
     "login-abort-generic": "سیزین گیریشینیز باشاری‌سیز اولدو - دایاندیریلدی",
     "loginlanguagelabel": "دیل: $1",
     "suspicious-userlogout": "سیزین چیخیش ایستگینیز رد اولوندو. بو، براوزرین یا پروکسی-کَشلمه‌سینین دوزگون ایشله‌مه‌مه‌سین‌دن قایناق‌لانیر.",
+    "pt-login": "گیریش ائت",
+    "pt-login-button": "گیریش ائت",
+    "pt-createaccount": "حساب یارات",
+    "pt-userlogout": "چیخیش",
     "php-mail-error-unknown": "پی‌اچ‌پی‌نین mail() فونکسیاسیندا تانینمامیش خطا.",
     "user-mail-no-addy": "ایمیل آدرسی اولماماق‌لا، ایمیل گؤندرمگه چالیشدی",
     "user-mail-no-body": "بیر بوش یا چوخ قیسا یازیسی اولان ایمیل گؤندرمگه چالیشیلدی.",
     "changepassword": "رمزی دَییشدیر",
-    "resetpass_announce": "سیز بیر گئچرلی ایمیل اولونان کود ایله گیرمیسینیز.\nگیرمگی قورتارماق اوچون، یئنی بیر رمز قویمالیسینیز:",
+    "resetpass_announce": "گیرمگی قورتارماق اوچون، یئنی بیر رمز قویمالیسینیز.",
     "resetpass_header": "حساب رمزینی دَییشدیر",
     "oldpassword": "اسکی رمز",
     "newpassword": "یئنی رمز",
     "retypenew": "یئنی رمزی یئنی‌دن یازین:",
     "resetpass_submit": "رمز یارادین و گیریش ائدین",
-    "changepassword-success": "رمزینیز باشاری‌لا دَییشدیرلدی! ایندی گیریرسینیز...",
+    "changepassword-success": "رمزینیز باشاری‌لا دَییشدیرلدی!",
+    "changepassword-throttled": "سیزین چوخ گیریش چالیشماغینیز اولوب‌دور.\nلوطفاً یئنی‌دن چالیشماق‌دان اؤنجه $1 دؤزون.",
     "resetpass_forbidden": "رمزلر دَییشیلمز",
     "resetpass-no-info": "بو صحیفه‌نی دوغرو گؤردوگونوز اوچون سیستمه گیرمه‌لیسینیز.",
     "resetpass-submit-loggedin": "رمزی دَییشدیر",
     "session_fail_preview_html": "'''اوزر ایستییریک! داخیل وئری‌سی‌نین ایتمه‌سین‌دن گؤره تنظیملمه‌نیزی اعمال کئچیره بیلمیجیی.' '\n\n' چونکی {{SITENAME}} سایتیندا raw هتمل تأثیرین‌دیر،تا جاوااسکریپت هوجوم‌لارینا تدبیر اولا‌راق گیزلنمیش‌دیر.'\n\n' 'گر بو حاق‌لی بیر تنظیملمه گیریش میسئ، لطفاً یئنی‌دن جهد ائدین. اگر هله چالیشمازسا، [[Special:UserLogout|خارج شوید]] یئنی‌دن ایجلاس آچماغی یوخلایین.' '",
     "token_suffix_mismatch": "'' ' ديَیشیکلیگی‌نین گئری چئوریلدی، چونکی آلیجی‌نین تنزیمله‌مه کوتوجوغونداکی دورغو ایشاره‌لرینی پوزدو. \nديَیشیکلیگی‌نین، صحیفه‌‌ متنینده پوزولماغی اؤنله‌مک اوچون گئری چئوریلدی. \nاگر پروبلئملی بیر wئب-باسئد آنونیم پروکسی خیدمتی ایستیفاده بو حادثه‌‌ بضا رئاللاشا بیلر.'' '",
     "edit_form_incomplete": "'''دییشیک‌لیک فورماسی اوچون بعضی سئروئرلره ایشلمه‌دی؛ ائتدیگینیز دییشیک‌لیک‌لر بوزولمامیشتیر، نظردن کئچیریب یئنی‌دن سینایین.'",
-    "editing": "<font style=\"color:red\">$1</font> دییشدیریلیر",
+    "editing": "$1 دییشدیریلیر",
     "creating": "$1 یارادیلیر",
     "editingsection": "$1 دَییشدیریلیر (بؤلوم)",
     "editingcomment": "$1 دَییشدیریلیر (یئنی بؤلوم)",
     "prefs-skin": "قابیق",
     "skin-preview": "اؤن‌گؤستریش",
     "datedefault": "سئچیم‌سیز",
-    "prefs-beta": "بئتا اؤزل‌لیکلر",
     "prefs-datetime": "تاریخ و واخت",
     "prefs-labs": "آزماییشی اؤزل‌لیکلر",
     "prefs-user-pages": "ایستیفاده‌چی صحیفه‌لری",
     "nowatchlist": "ایزلمه سیاهینیز بؤش‌دور.",
     "watchlistanontext": "لطفاً، ایزلدیگینیز صحیفه‌لری گؤرمک و یا رئداکته ائتمک اوچون $1.",
     "watchnologin": "داخیل اولمامیسینیز",
-    "watchnologintext": "ایزلمه سیاهینیزدا دییشیک‌لیک آپارماق اوچون [[Special:UserLogin|داخیل اولمالیسینیز]].",
     "addwatch": "ایزلمه سیاهی‌سینا علاوه ائت",
     "addedwatchtext": "\"[[:$1]]\" صحیفه‌سی [[Special:Watchlist|ایزله‌دیکلرینیزه]] آرتیریلدی. بو صحیفه‌ده و ایلگیلی دانیشیق صحیفه‌سین‌ده‌کی بوتون دییشیکلیکلر اوردا گؤستریله‌جکلر.",
     "removewatch": "بو صحیفنی ایزلدیگیم صحیفه‌لر سیاهی‌سین‌دان چیخار",
     "allmessagesname": "آد",
     "allmessagesdefault": "دفالت دانیشیق متنی",
     "allmessagescurrent": "ایندیکی متن",
-    "allmessagestext": "بو مئدیا ویکی-ده اولان سیستئم مئساژلارینین سیاهی‌سی‌دیر. اگر مئدیا ویکی-نی لوکاللاش‌دیرماق ایشینده کؤمک ائتمک ایسییرسینیزسه، لطفاً [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] و [//translatewiki.net translatewiki.net]-ا باش چکین.",
+    "allmessagestext": "بو مئدیا ویکی-ده اولان سیستئم مئساژلارینین سیاهی‌سی‌دیر. اگر مئدیا ویکی-نی لوکاللاش‌دیرماق ایشینده کؤمک ائتمک ایسییرسینیزسه، لطفاً [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] و [//translatewiki.net translatewiki.net]-ا باش چکین.",
     "allmessagesnotsupportedDB": "'''$ wgUseDatabaseMessages''' باغ‌لی اولدوغو اوچون '{{ns:special}}: Allmessages ایستیفاده‌یه آچیق دئییل.",
     "allmessages-filter-legend": "سۆزگَج",
     "allmessages-filter": "خصوصی ائتمک وضعیتینه گؤره فیلترلی:",
index 69cdc76..f46335d 100644 (file)
     "prefs-skin": "Күренеш",
     "skin-preview": "Алдан байҡау",
     "datedefault": "Ғәҙәттәге",
-    "prefs-beta": "Бета версияһы мөмкинлектәре",
     "prefs-datetime": "Көн һәм ваҡыт",
     "prefs-labs": "Һынау өсөн мөмкинлектәр",
     "prefs-user-pages": "Ҡатнашыусы бите",
     "nowatchlist": "Һеҙҙең күҙәтеү исемлегегеҙ буш.",
     "watchlistanontext": "Күҙәтеү исемлеген ҡарау йәки мөхәррирләү өсөн $1 кәрәк.",
     "watchnologin": "Үҙегеҙҙе танытырға кәрәк",
-    "watchnologintext": "Күҙәтеү исемлегегеҙҙе мөхәррирләү өсөн, һеҙгә [[Special:UserLogin|танылырға]] кәрәк.",
     "addwatch": "Күҙәтеү исемлегенә өҫтәргә",
     "addedwatchtext": "\"[[:$1]]\" бите [[Special:Watchlist|күҙәтеү исемлегегеҙгә]] өҫтәлде.\nБыл биттә һәм уның фекер алышыу битендә буласаҡ бар үҙгәртеүҙәр ундағы исемлектә күрһәтеләсәк.",
     "removewatch": "Күҙәтеү исемлегенән сығарырға",
     "allmessagesname": "Хәбәр",
     "allmessagesdefault": "Ғәҙәттәге яҙма",
     "allmessagescurrent": "Хәҙерге яҙма",
-    "allmessagestext": "Түбәндә MediaWiki исемдәр арауығында ҡулланылған система хәбәрҙәре исемлеге килтерелгән.\nӘгәр MediaWiki программаһын дөйөм локалләштереү эшенә үҙ өлөшөгөҙҙө керетергә теләһәгеҙ, [https://www.mediawiki.org/wiki/Localisation MediaWiki программаһын локалләштереү] битен һәм [//translatewiki.net translatewiki.net] проектын ҡарап сығығыҙ.",
+    "allmessagestext": "Түбәндә MediaWiki исемдәр арауығында ҡулланылған система хәбәрҙәре исемлеге килтерелгән.\nӘгәр MediaWiki программаһын дөйөм локалләштереү эшенә үҙ өлөшөгөҙҙө керетергә теләһәгеҙ, [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki программаһын локалләштереү] битен һәм [//translatewiki.net translatewiki.net] проектын ҡарап сығығыҙ.",
     "allmessagesnotsupportedDB": "Был бит ҡулланыла алмай, сөнки '''$wgUseDatabaseMessages''' мөмкинлеге һүндерелгән.",
     "allmessages-filter-legend": "Һайлау",
     "allmessages-filter": "Үҙгәртеү торошо буйынса һайлау:",
index 68ef7bd..aedb2b3 100644 (file)
     "nowatchlist": "Es gibt koane Eihträg auf deiner Beówochtungslisten.",
     "watchlistanontext": "Du muasst dé $1, um deih Beówchtungslisten z' seeng óder Eihträg borweiten z' kenner.",
     "watchnologin": "Du bist néd auhgmödt",
-    "watchnologintext": "Du muasst [[Special:UserLogin|auhgmödt]] seih, um deih Beówochtungslisten beorweiten z' kenner.",
     "addwatch": "Zua Beówochtungslisten dazuadoah",
     "addedwatchtext": "Dé Seiten „[[:$1]]“ is zua deiner [[Special:Watchlist|Beówochtungslisten]] dazuadauh worn.\nÄnderrungen an derer Seiten und voh da Dischkrierseiten wern do glistt und in da Ywersicht voh dé [[Special:RecentChanges|létzden Änderrungen]] auf Fettschrieft auhzoagt.\n\nWaunnst dé Seiten wieder voh deiner Beówochtungslisten weggerddoah mechst, druck oafoch auf da jeeweiling Seiten auf „nimmer beówochten“.",
     "removewatch": "Voh da Beówochtungslisten wegdoah",
     "allmessagesname": "Nama:",
     "allmessagesdefault": "Standardtext",
     "allmessagescurrent": "Aktuella Text",
-    "allmessagestext": "Des is a Listen vo de MediaWiki-Systemtextt.\nBsuach bittschee de Saiten [https://www.mediawiki.org/wiki/Localisation MediaWiki-Lokalisiarung] und [//translatewiki.net translatewiki.net], wånn du de ån da Lokalisiarung vo MediaWiki betailing mechadst.",
+    "allmessagestext": "Des is a Listen vo de MediaWiki-Systemtextt.\nBsuach bittschee de Saiten [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki-Lokalisiarung] und [//translatewiki.net translatewiki.net], wånn du de ån da Lokalisiarung vo MediaWiki betailing mechadst.",
     "allmessagesnotsupportedDB": "'''Special:Allmessages''' is im Moment net möglich, wei de Datenbank offline is.",
     "thumbnail-more": "vagressan",
     "thumbnail_error": "Fehla ban Estejn vom Vorschaubuidl: $1",
index 05f63f4..fefa486 100644 (file)
     "nowatchlist": "شما را هچ چیزی ته وتی لیست چارگ نیست.",
     "watchlistanontext": "لطفا  $1 په دیستن یا اصلاح ایتیمان ته وتی لیست چارگء",
     "watchnologin": "وارد نه بی تگیت",
-    "watchnologintext": "شما بایدن  [[Special:UserLogin|وارد بیت]] په تغییر داتن وتی لیست چارگء",
     "addedwatchtext": "صفحه  \"[[:$1]]\"  په شمی [[Special:Watchlist|watchlist]] هور بیت.\nدیمگی تغییرات په ای صفحه و آیاء صفحه گپ ادان لیست بنت، و صفحه پررنگ جاه کیت ته [[Special:RecentChanges|لیست نوکیت تغییرات]] په راحتر کتن شی که آی زورگ بیت.",
     "removedwatchtext": "صفحه\"[[:$1]]\"  چه [[Special:Watchlist|شمی لیست چارگ]]. دربیت.",
     "watch": "به چار",
     "allmessagesname": "نام",
     "allmessagesdefault": "پیش فرضین متن",
     "allmessagescurrent": "هنوکین متن",
-    "allmessagestext": "شی یک لیستی چه کوله یان موجود ته نام فضای مدیا وی کی انت.\nلطفا بچاریت  [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] و [//translatewiki.net translatewiki.net] اگر شما لوٹیت ته ملکی کتن مدیا وی کی کمک کنیت.",
+    "allmessagestext": "شی یک لیستی چه کوله یان موجود ته نام فضای مدیا وی کی انت.\nلطفا بچاریت  [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] و [//translatewiki.net translatewiki.net] اگر شما لوٹیت ته ملکی کتن مدیا وی کی کمک کنیت.",
     "allmessagesnotsupportedDB": "ای صفحه نه تونیت استفاده بیت په چی که'''$wgUseDatabaseMessages''' غیر فعالنت.",
     "allmessages-filter-legend": "فیلتر",
     "allmessages-filter": "فیلتر گون حالت دلواهی",
index 393efef..07b3fd6 100644 (file)
     "prefs-skin": "''Skin''",
     "skin-preview": "Tânawon",
     "datedefault": "Mayong kabôtan",
-    "prefs-beta": "Mga posturang yaon sa beta",
     "prefs-datetime": "Petsa asin oras",
     "prefs-labs": "Mga posturang yaon sa Labs",
     "prefs-user-pages": "Paragamit na mga pahina",
     "nowatchlist": "Mayo ka man na mga bagay saimong lista nin pigbabantayan.",
     "watchlistanontext": "Mag $1 tabi para mahiling o maghira nin mga bagay saimong lista nin mga pigbabantayan.",
     "watchnologin": "Mayô sa laog",
-    "watchnologintext": "Dapat ika si [[Special:UserLogin|nakalaog]] para puede kang magribay kan saimong lista nin mga pigbabantayán.",
     "addwatch": "Idagdag sa bantay-listahan",
     "addedwatchtext": "Ining pahina \"[[:$1]]\" dinadagdag sa saimong mga [[Special:Watchlist|Bantay-listahan]].\nAn maabot na mga pagbabâgo sa páhinang ini asin sa asosyadong páhina nin olay paglilistahon duman.",
     "removewatch": "Halion gikan sa bantay-listahan",
     "allmessagesname": "Pangaran",
     "allmessagesdefault": "Panugmad na tekstong mensahe",
     "allmessagescurrent": "Presenteng teksto",
-    "allmessagestext": "Ini sarong listahan nin pansistemang mga mensahe na mananagboan sa espasyong-pangaran kan MediaWiki.\nPakibisita an [https://www.mediawiki.org/wiki/Localisation Mediawiki Lokalisasyon] asin [//translatewiki.net translatewiki.net] kun boot mong mag-ambag sa henerikong lokalisasyon kan MediaWiki.",
+    "allmessagestext": "Ini sarong listahan nin pansistemang mga mensahe na mananagboan sa espasyong-pangaran kan MediaWiki.\nPakibisita an [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Mediawiki Lokalisasyon] asin [//translatewiki.net translatewiki.net] kun boot mong mag-ambag sa henerikong lokalisasyon kan MediaWiki.",
     "allmessagesnotsupportedDB": "Dai pwedeng gamiton an '''{{ns:special}}:Allmessages''' ta sarado an '''$wgUseDatabaseMessages'''.",
     "allmessages-filter-legend": "An Pansara",
     "allmessages-filter": "Pansara sa paagi kan estado nin kustomisasyon:",
index b7f0422..675057d 100644 (file)
     "prefs-skin": "Афармленьне",
     "skin-preview": "Папярэдні прагляд",
     "datedefault": "Па змоўчаньні",
-    "prefs-beta": "Тэставыя магчымасьці",
     "prefs-datetime": "Дата і час",
     "prefs-labs": "Экспэрымэнтальныя магчымасьці",
     "prefs-user-pages": "Старонкі ўдзельніка",
     "deadendpagestext": "Наступныя старонкі не спасылаюцца на іншыя старонкі {{GRAMMAR:родны|{{SITENAME}}}}.",
     "protectedpages": "Абароненыя старонкі",
     "protectedpages-indef": "Толькі бестэрміновыя абароны",
+    "protectedpages-summary": "На гэтай старонцы пералічаныя старонкі, якія цяпер абароненыя. Для сьпісу назваў, якія забароненыя для стварэньня, глядзіце [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
     "protectedpages-cascade": "Толькі каскадныя абароны",
     "protectedpages-noredirect": "Схаваць перанакіраваньні",
     "protectedpagesempty": "Цяпер няма абароненых старонак з пазначанымі парамэтрамі.",
     "listgrouprights-removegroup-self": "можа выдаліць уласны рахунак з {{PLURAL:$2|1=групы|групаў}}: $1",
     "listgrouprights-addgroup-self-all": "Можа дадаць уласны рахунак да ўсіх груп",
     "listgrouprights-removegroup-self-all": "Можа выдаліць уласны рахунак з ўсіх груп",
+    "trackingcategories": "Катэгорыі, якія патрабуюць увагі",
+    "trackingcategories-summary": "На гэтай старонцы пералічаныя катэгорыя, які патрабуюць увагі і якія аўтаматычна запаўняюцца праграмным забесьяпчэньнем MediaWiki. Іх назвы могуць быць зьмененыя рэдагаваньнем сыстэмных паведамленьняў у прасторы назваў {{ns:8}}.",
     "mailnologin": "Няма адрасу атрымальніка",
     "mailnologintext": "Вам неабходна [[Special:UserLogin|ўвайсьці ў сыстэму]] і мець пацьверджаны адрас электроннай пошты ў Вашых [[Special:Preferences|наладах]], каб дасылаць лісты іншым удзельнікам.",
     "emailuser": "Даслаць ліст",
     "nowatchlist": "Ваш сьпіс назіраньня пусты.",
     "watchlistanontext": "Вам патрэбна $1, каб праглядаць альбо рэдагаваць сьпіс назіраньня.",
     "watchnologin": "Вы не ўвайшлі ў сыстэму",
-    "watchnologintext": "Вам неабходна [[Special:UserLogin|ўвайсьці ў сыстэму]], каб зьмяніць Ваш сьпіс назіраньня.",
     "addwatch": "Дадаць ў сьпіс назіраньня",
     "addedwatchtext": "Старонка «[[:$1]]» была дададзеная да Вашага [[Special:Watchlist|сьпісу назіраньня]].\nНаступныя зьмены ў гэтай старонцы і зьвязанай зь ёю старонцы абмеркаваньняў будуць бачныя там.",
     "removewatch": "Выдаліць са сьпісу назіраньня",
     "sp-contributions-newbies-sub": "Унёсак пачынаючых",
     "sp-contributions-newbies-title": "Унёсак удзельнікаў з новых рахункаў",
     "sp-contributions-blocklog": "журнал блякаваньняў",
+    "sp-contributions-suppresslog": "выдалены ўнёсак удзельніка",
     "sp-contributions-deleted": "выдалены ўнёсак удзельніка",
     "sp-contributions-uploads": "загрузкі",
     "sp-contributions-logs": "журналы падзеяў",
     "sp-contributions-blocked-notice": "{{GENDER:$1|Гэты ўдзельнік у дадзены момант заблякаваны|Гэтая ўдзельніца ў дадзены момант заблякаваная}}. Апошні запіс з журнала блякаваньняў пададзены ніжэй для даведкі:",
     "sp-contributions-blocked-notice-anon": "Гэты IP-адрас у дадзены момант заблякаваны.\nАпошні запіс з журнала блякаваньняў пададзены ніжэй для даведкі:",
     "sp-contributions-search": "Пошук унёску",
-    "sp-contributions-suppresslog": "выдалены ўнёсак удзельніка",
     "sp-contributions-username": "IP-адрас альбо імя ўдзельніка/ўдзельніцы:",
     "sp-contributions-toponly": "Паказваць толькі зьмены, якія зьяўляюцца апошнімі вэрсіямі",
     "sp-contributions-newonly": "Паказваць толькі праўкі, якімі былі створаныя старонкі",
     "allmessagesname": "Назва",
     "allmessagesdefault": "Тэкст па змоўчаньні",
     "allmessagescurrent": "Цяперашні тэкст",
-    "allmessagestext": "Сьпіс усіх сыстэмных паведамленьняў, якія існуюць у прасторы назваў MediaWiki.\nКалі ласка, наведайце [https://www.mediawiki.org/wiki/Localisation старонку пра лякалізацыю MediaWiki] і [//translatewiki.net translatewiki.net], калі Вы жадаеце ўдзельнічаць у перакладзе MediaWiki.",
+    "allmessagestext": "Сьпіс усіх сыстэмных паведамленьняў, якія існуюць у прасторы назваў MediaWiki.\nКалі ласка, наведайце [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation старонку пра лякалізацыю MediaWiki] і [//translatewiki.net translatewiki.net], калі Вы жадаеце ўдзельнічаць у перакладзе MediaWiki.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:AllMessages''' не падтрымліваецца, таму што адключанае '''$wgUseDatabaseMessages'''.",
     "allmessages-filter-legend": "Фільтар",
     "allmessages-filter": "Фільтар па стане зьменаў:",
     "version-entrypoints": "Уваходныя адрасы",
     "version-entrypoints-header-entrypoint": "Пункт уваходу",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Шлях да артыкула]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Пуць да скрыпту]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Шлях да артыкула]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Пуць да скрыпту]",
     "redirect": "Перанакіраваньне да файла, удзельніка, старонкі або вэрсіі старонкі",
     "redirect-legend": "Перанакіраваньне да файла або старонкі",
     "redirect-summary": "Гэтая спэцыяльная старонка перанакіруе да файла (паводле імя файла), старонкі (паводле нумару вэрсіі або старонкі) або старонкі ўдзельніка (паводле нумару ўдзельніка). Ужываньне: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] або [[{{#Special:Redirect}}/user/101]].",
     "expand_templates_remove_comments": "Выдаліць камэнтары",
     "expand_templates_remove_nowiki": "Падаўляць тэгі <nowiki> у выніку",
     "expand_templates_generate_xml": "Паказаць дрэва аналізу XML",
-    "expand_templates_preview": "Папярэдні прагляд",
-    "trackingcategories": "Катэгорыі, якія патрабуюць увагі"
+    "expand_templates_preview": "Папярэдні прагляд"
 }
index c740de1..1b89b97 100644 (file)
     "prefs-skin": "Вокладка",
     "skin-preview": "перадпаказ",
     "datedefault": "Не вызначана",
-    "prefs-beta": "Бэта магчымасці",
     "prefs-datetime": "Дата і час",
     "prefs-labs": "Эксперыментальныя магчымасці",
     "prefs-personal": "Удзельнік",
     "nowatchlist": "Ваш спіс назірання зараз пусты.",
     "watchlistanontext": "Каб паглядзець ці змяніць спіс назірання, трэба $1.",
     "watchnologin": "Без прадстаўлення",
-    "watchnologintext": "Каб правіць свой спіс назірання, трэба [[Special:UserLogin|ўвайсці ў сістэму]].",
     "addwatch": "Дадаць у спіс назірання",
     "addedwatchtext": "Старонка \"[[:$1]]\" была дададзена да [[Special:Watchlist|назіраных]] вамі.\nЗмяненні, якія адбудуцца з гэтай старонкай і з Размовай пра яе, будуць паказвацца там, і старонка будзе '''вылучацца шрыфтам''' у [[Special:RecentChanges|спісе нядаўніх змяненняў]], каб лягчэй пазнаваць яе.\n\nКалі вы не пажадаеце больш назіраць за гэтай старонкай, націсніце \"Не назіраць\" у бакоўцы.",
     "removewatch": "Выдаліць са спіса назірання",
index a2909b1..c391f8c 100644 (file)
     "prefs-skin": "Облик",
     "skin-preview": "предварителен преглед",
     "datedefault": "Без предпочитание",
-    "prefs-beta": "Функционалности на Бета",
     "prefs-datetime": "Дата и час",
     "prefs-labs": "Функционалности на Labs",
     "prefs-user-pages": "Потребителски страници",
     "nowatchlist": "Списъкът ви за наблюдение е празен.",
     "watchlistanontext": "За преглеждане и редактиране на списъка за наблюдение се изисква $1 в системата.",
     "watchnologin": "Не сте влезли",
-    "watchnologintext": "Необходимо е да [[Special:UserLogin|влезете]], за да може да променяте списъка си за наблюдение.",
     "addwatch": "Добавяне към списъка за наблюдение",
     "addedwatchtext": "Страницата „'''[[:$1]]'''“ беше добавена към [[Special:Watchlist|списъка ви за наблюдение]].\nНейните бъдещи промени, както и на съответната й дискусионна страница, ще се описват там.",
     "removewatch": "Премахване от списъка за наблюдение",
     "allmessagesname": "Име",
     "allmessagesdefault": "Текст по подразбиране",
     "allmessagescurrent": "Текущ текст",
-    "allmessagestext": "Тази страница съдържа списък на системните съобщения от именното пространство „МедияУики“.\nПосетете [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] и [//translatewiki.net translatewiki.net], ако желаете да допринесете за общата локализация на софтуера МедияУики.",
+    "allmessagestext": "Тази страница съдържа списък на системните съобщения от именното пространство „МедияУики“.\nПосетете [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] и [//translatewiki.net translatewiki.net], ако желаете да допринесете за общата локализация на софтуера МедияУики.",
     "allmessagesnotsupportedDB": "Тази страница не може да бъде използвана, тъй като е изключена възможността '''$wgUseDatabaseMessages'''.",
     "allmessages-filter-legend": "Филтър",
     "allmessages-filter": "Филтриране по ниво на персонализация:",
index 2d97315..63d6f96 100644 (file)
     "prefs-skin": "Kulimbit",
     "skin-preview": "Titilikan",
     "datedefault": "Kadada katujuan",
-    "prefs-beta": "Fitur Beta",
     "prefs-datetime": "Tanggal wan waktu",
     "prefs-labs": "Fitur Labs",
     "prefs-personal": "Data awak",
     "nowatchlist": "Pian kada baisi apa pun pada daptar itihan Pian.",
     "watchlistanontext": "Muhun $1 hagan maniringi atawa mambabak nang dalam daptar itihan Pian.",
     "watchnologin": "Baluman babuat log",
-    "watchnologintext": "Pian musti [[Special:UserLogin|babuat log]] amun handak magaganti daptar itihan Pian.",
     "addwatch": "Tambahi ka daptar itihan",
     "addedwatchtext": "Tungkaran \"[[:$1]]\" sudah ditambahakan ka [[Special:Watchlist|daptar itihan]] Pian.\nPaubahan-paubahan salanjutnya pada tungkaran ngini dan tungkaran pamandiran taraitnya akan takambit di sini, wan tungkaran itu akan ditampaiakan '''kandal''' pada [[Special:RecentChanges|daptar paubahan pahanyarnya]] cagar labih mudah diitihi.",
     "removewatch": "Buang matan daptar itihan",
     "allmessagesname": "Ngaran",
     "allmessagesdefault": "Naskah baku pasan",
     "allmessagescurrent": "Naskah pasan wayahini.",
-    "allmessagestext": "Ngini adalah sabuah daptar pasan sistem tasadia dalam ruang-ngaran MediaWiki.\nMuhun ilangi [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] wan [//translatewiki.net translatewiki.net] amun Pian hakun manyumbang palukalan umum MediaWiki.",
+    "allmessagestext": "Ngini adalah sabuah daptar pasan sistem tasadia dalam ruang-ngaran MediaWiki.\nMuhun ilangi [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] wan [//translatewiki.net translatewiki.net] amun Pian hakun manyumbang palukalan umum MediaWiki.",
     "allmessagesnotsupportedDB": "Tungkaran ngini kada kawa dipuruk karana '''$wgUseDatabaseMessages''' sudah dipajahakan.",
     "allmessages-filter-legend": "Saringan",
     "allmessages-filter": "Saringan lawan kaadaan kustom:",
index c06413b..744d873 100644 (file)
     "prefs-skin": "আবরণ (Skin)",
     "skin-preview": "প্রাকদর্শন",
     "datedefault": "কোন পছন্দ নেই",
-    "prefs-beta": "বেটা বৈশিষ্টসমূহ",
     "prefs-datetime": "তারিখ ও সময়",
     "prefs-labs": "পরীক্ষাগার বৈশিষ্টসমূহ",
     "prefs-user-pages": "ব্যবহারকারীর পাতা",
     "nowatchlist": "আপনার নজরতালিকা খালি।",
     "watchlistanontext": "আপনার নজরতালিকার আইটেমগুলি দেখতে বা সম্পাদনা করতে অনুগ্রহ করে $1।",
     "watchnologin": "আপনি এখনও লগ-ইন করেননি।",
-    "watchnologintext": "আপনার নজর তালিকা পরিবর্তনের জন্য আপনাকে অবশ্যই অ্যাকাউন্টে [[Special:UserLogin|প্রবেশ করতে হবে]]।",
     "addwatch": "নজরতালিকায় যোগ করো",
     "addedwatchtext": "\"[[:$1]]\" পাতাটি আপনার [[Special:Watchlist|নজরতালিকাতে]] যোগ করা হয়েছে।\nভবিষ্যতে এই পাতা ও এই পাতার সাথে সম্পর্কিত আলোচনা পাতায় সংঘটিত যাবতীয় পরিবর্তন এখানে তালিকাভুক্ত হবে।",
     "removewatch": "নজরতালিকা থেকে অপসারণ",
     "sp-contributions-newbies-sub": "নতুন অ্যাকাউন্টের জন্য",
     "sp-contributions-newbies-title": "নতুন অ্যাকাউন্টের ব্যবহারকারী অবদান",
     "sp-contributions-blocklog": "বাধা দানের লগ",
+    "sp-contributions-suppresslog": "মুছে ফেলা ব্যবহারকারী অবদান",
     "sp-contributions-deleted": "মুছে ফেলা ব্যবহারকারী অবদান",
     "sp-contributions-uploads": "আপলোডসমূহ",
     "sp-contributions-logs": "লগসমূহ",
     "sp-contributions-blocked-notice": "এই ব্যবহারকারী বর্তমানে বাধাদানকৃত অবস্থায় রয়েছেন।\nতথ্যসূত্র হিসেবে সাম্প্রতিক বাধাদান লগে ভুক্তিটি নিচে দেওয়া হলো:",
     "sp-contributions-blocked-notice-anon": "এই আইপি ঠিকানাটি বর্তমানে বাধাদানকৃত অবস্থায় রয়েছে।\nতথ্যসূত্র হিসেবে সাম্প্রতিক বাধাদান লগের ভুক্তিটি নিচে দেওয়া হলো:",
     "sp-contributions-search": "অবদানসমূহের জন্য অনুসন্ধান",
-    "sp-contributions-suppresslog": "মুছে ফেলা ব্যবহারকারী অবদান",
     "sp-contributions-username": "আইপি (IP) ঠিকানা অথবা ব্যবহারকারীর নাম:",
     "sp-contributions-toponly": "শুধুমাত্র সেই সম্পাদনাগুলি দেখাও যেগুলো সাম্প্রতিক সংস্করণের অন্তর্ভুক্ত",
     "sp-contributions-newonly": "শুধুমাত্র পাতা সৃষ্টি করা সম্পাদনাগুলি দেখাও",
     "allmessagesname": "নাম",
     "allmessagesdefault": "আদি টেক্সট",
     "allmessagescurrent": "বর্তমান টেক্সট",
-    "allmessagestext": "এটি মিডিয়াউইকি নামস্থানে অন্তর্ভুক্ত সিস্টেম বার্তাগুলোর একটি তালিকা।\nআপনি যদি সাধারণ মিডিয়াউইকির স্থানীয়করণে অবদান রাখতে আগ্রহী হন, অনুগ্রহ করে [https://www.mediawiki.org/wiki/Localisation মিডিয়াউইকি স্থানীয়করণ] এবং [//translatewiki.net translatewiki.net] দেখুন।",
+    "allmessagestext": "এটি মিডিয়াউইকি নামস্থানে অন্তর্ভুক্ত সিস্টেম বার্তাগুলোর একটি তালিকা।\nআপনি যদি সাধারণ মিডিয়াউইকির স্থানীয়করণে অবদান রাখতে আগ্রহী হন, অনুগ্রহ করে [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation মিডিয়াউইকি স্থানীয়করণ] এবং [//translatewiki.net translatewiki.net] দেখুন।",
     "allmessagesnotsupportedDB": "এই পাতা ব্যবহার করা যাবে না কারণ '''$wgUseDatabaseMessages''' বন্ধ করে রাখা আছে।",
     "allmessages-filter-legend": "ছাকনী",
     "allmessages-filter": "Filter by customization state:",
index 3f818db..7af7f0d 100644 (file)
     "prefs-skin": "সরহান",
     "skin-preview": "আগচা",
     "datedefault": "পছন করাতা নেই",
-    "prefs-beta": "বেটার বৈশিষ্টহানি",
     "prefs-datetime": "তারিখ বারো সময়",
     "prefs-labs": "পরীক্ষাগারর বৈশিষ্টহানি",
     "prefs-rc": "হাদি এহানর পতানি",
     "allmessagesname": "নাং",
     "allmessagesdefault": "আদ্যকার টেক্সট",
     "allmessagescurrent": "হাদি এহানর ৱাহি",
-    "allmessagestext": "তলে মিডিয়াউইকির নাঙরথাকে পানা একরের সিস্টেম পৌহানির তালিকাহান দেনা ইল।\nকৃপা করিয়া [https://www.mediawiki.org/wiki/Localisation মিডিয়াউইকি অনুবাদর হেইচা পাতাত] বারো [//translatewiki.net translatewiki.net] মিডিয়াউইকি অনুবাদ করানির কা যানা পারর।",
+    "allmessagestext": "তলে মিডিয়াউইকির নাঙরথাকে পানা একরের সিস্টেম পৌহানির তালিকাহান দেনা ইল।\nকৃপা করিয়া [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation মিডিয়াউইকি অনুবাদর হেইচা পাতাত] বারো [//translatewiki.net translatewiki.net] মিডিয়াউইকি অনুবাদ করানির কা যানা পারর।",
     "allmessages-filter-legend": "সাক",
     "allmessages-filter-unmodified": "নাসিলথাইতে",
     "allmessages-filter-all": "হাব্বি",
index 4121bc7..367c57b 100644 (file)
     "prefs-skin": "Gwiskadur",
     "skin-preview": "Rakwelet",
     "datedefault": "Dre ziouer",
-    "prefs-beta": "Perzhioù beta",
     "prefs-datetime": "Deiziad hag eur",
     "prefs-labs": "Perzhioù \"labs\"",
     "prefs-user-pages": "Pajennoù implijer",
     "listgrouprights-removegroup-self": "Gallout a ra tennañ {{PLURAL:$2|ar strollad|strolladoù}} eus kont an-unan : $1",
     "listgrouprights-addgroup-self-all": "Gallout a ra ouzhpennañ an holl strolladoù da gont an-unan",
     "listgrouprights-removegroup-self-all": "Gallout a ra tennañ kuit an holl strolladoù eus kont an-unan.",
+    "trackingcategories-nodesc": "N'eus deskrivadur ebet.",
+    "trackingcategories-disabled": "Diweredekaet eo ar rummad",
     "mailnologin": "Chomlec'h ebet",
     "mailnologintext": "Ret eo deoc'h bezañ [[Special:UserLogin|kevreet]]\nha bezañ merket ur chomlec'h postel reizh en ho [[Special:Preferences|penndibaboù]]\nevit gallout kas ur postel d'un implijer all.",
     "emailuser": "Kas ur postel d'an implijer-mañ",
     "nowatchlist": "N'eus pennad ebet en ho roll evezhiañ.",
     "watchlistanontext": "Ret eo deoc'h $1 evit gwelet pe kemmañ an elfennoù zo en ho roll evezhiañ.",
     "watchnologin": "Digevreet",
-    "watchnologintext": "Ret eo deoc'h bezañ [[Special:UserLogin|kevreet]]\na-benn gellout kemmañ ho roll evezhiañ.",
     "addwatch": "Ouzhpennañ d'ar roll evezhiañ",
     "addedwatchtext": "Ouzh ho [[Special:Watchlist|rollad evezhiañ]] eo bet ouzhpennet ar bajenn \"[[:$1]]\".\nAmañ e vo rollet ar c'hemmoù da zont evit ar bajenn-mañ hag ar bajenn gaozeal stag outi.",
     "removewatch": "Lemel a-ziwar ar roll evezhiañ",
     "sp-contributions-newbies-sub": "Evit an implijerien nevez",
     "sp-contributions-newbies-title": "Degasadennoù implijer evit ar c'hontoù nevez",
     "sp-contributions-blocklog": "Roll ar stankadennoù",
+    "sp-contributions-suppresslog": "degasadennoù diverket un implijer",
     "sp-contributions-deleted": "Degasadennoù diverket",
     "sp-contributions-uploads": "Enporzhiadennoù",
     "sp-contributions-logs": "marilhoù",
     "sp-contributions-blocked-notice": "Stanket eo an implijer-mañ evit poent. Dindan emañ merket moned diwezhañ marilh ar stankadennoù, d'ho kelaouiñ :",
     "sp-contributions-blocked-notice-anon": "Stanket eo ar chomlec'h IP-mañ evit ar mare.\nDindan emañ merket enmont diwezhañ marilh ar stankadennoù, d'ho kelaouiñ :",
     "sp-contributions-search": "Klask degasadennoù",
-    "sp-contributions-suppresslog": "degasadennoù diverket un implijer",
     "sp-contributions-username": "Anv implijer pe chomlec'h IP :",
     "sp-contributions-toponly": "Na ziskouez nemet an adweladennoù diwezhañ",
     "sp-contributions-newonly": "Diskouez an aozadennoù a zo krouidigezhioù pajennoù hepken",
     "allmessagesname": "Anv",
     "allmessagesdefault": "Kemennadenn dre ziouer",
     "allmessagescurrent": "Kemennadenn zo bremañ",
-    "allmessagestext": "Setu roll ar c'hemennadennoù reizhiad a c'haller kaout en esaouennoù anv MediaWiki.\nKit da welet [https://www.mediawiki.org/wiki/Localisation Lec'heladur MediaWiki] ha [//translatewiki.net translatewiki.net] mar fell deoc'h kemer perzh e lec'heladur boutin MediaWiki.",
+    "allmessagestext": "Setu roll ar c'hemennadennoù reizhiad a c'haller kaout en esaouennoù anv MediaWiki.\nKit da welet [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Lec'heladur MediaWiki] ha [//translatewiki.net translatewiki.net] mar fell deoc'h kemer perzh e lec'heladur boutin MediaWiki.",
     "allmessagesnotsupportedDB": "N'haller ket kaout {{ns:special}}:AllMessages rak diweredekaet eo bet wgUseDatabaseMessages.",
     "allmessages-filter-legend": "Sil",
     "allmessages-filter": "Silañ dre stad ar c'hemmoù",
index 08051cb..c750203 100644 (file)
     "prefs-skin": "Koža",
     "skin-preview": "Pregled",
     "datedefault": "Nije bitno",
-    "prefs-beta": "Beta mogućnosti",
     "prefs-datetime": "Datum i vrijeme",
     "prefs-labs": "Eksperimentalne mogućnosti",
     "prefs-user-pages": "Korisničke stranice",
     "nowatchlist": "Nemate ništa na svom spisku praćenih članaka.",
     "watchlistanontext": "Molimo da $1 da možete vidjeti ili urediti stavke na Vašem spisku praćenja.",
     "watchnologin": "Niste prijavljeni",
-    "watchnologintext": "Morate biti [[Special:UserLogin|prijavljeni]] da bi ste mijenjali spisak praćenih članaka.",
     "addwatch": "Dodaj na spisak praćenja",
     "addedwatchtext": "Stranica \"[[:$1]]\" je dodata vašem [[Special:Watchlist|spisku praćenih članaka]]. \nBuduće promjene ove stranice i njoj pridružene stranice za razgovor će biti navedene ovde.",
     "removewatch": "Ukloni sa spiska praćenja",
     "allmessagesname": "Naziv",
     "allmessagesdefault": "Uobičajeni tekst",
     "allmessagescurrent": "Trenutni tekst",
-    "allmessagestext": "Ovo je spisak svih sistemskih poruka u dostupnih u MediaWiki imenskom prostoru.\nMolimo posjetite [https://www.mediawiki.org/wiki/Localisation MediaWiki lokalizaciju] i [//translatewiki.net translatewiki.net] ako želite doprinijeti općoj lokalizaciji MediaWikija.",
+    "allmessagestext": "Ovo je spisak svih sistemskih poruka u dostupnih u MediaWiki imenskom prostoru.\nMolimo posjetite [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki lokalizaciju] i [//translatewiki.net translatewiki.net] ako želite doprinijeti općoj lokalizaciji MediaWikija.",
     "allmessagesnotsupportedDB": "Ova stranica ne može biti korištena jer je <i>wgUseDatabaseMessages</i> isključen.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filter po stanju podešavanja:",
index 52a0e1a..e2fe757 100644 (file)
     "gotaccountlink": "Inicia una sessió",
     "userlogin-resetlink": "Heu oblidat les vostres dades d'accés?",
     "userlogin-resetpassword-link": "Has oblidat la teva contrasenya?",
+    "userlogin-helplink2": "Ajuda amb el registre",
     "userlogin-loggedin": "Heu iniciat una sessió com {{GENDER:$1|$1}}.\nFeu servir el formulari de sota per iniciar la sessió com un altre usuari.",
     "userlogin-createanother": "Crea un altre compte",
     "createacct-join": "Introduïu les vostres dades.",
     "suspicious-userlogout": "S'ha denegat la vostra petició per tancar la sessió ja què sembla que va ser enviada per un navegador defectuós o un proxy cau.",
     "createacct-another-realname-tip": "El nom real és opcional.\nSi decidiu proporcionar-lo, s'utilitzarà per a reconèixer a l'usuari el seu treball.",
     "pt-login": "Inicia la sessió",
+    "pt-login-button": "Inicia sessió",
     "pt-createaccount": "Crea un compte",
     "pt-userlogout": "Finalitza la sessió",
     "php-mail-error-unknown": "Error desconegut en la funció mail() de PHP",
     "search-file-match": "(coincideix amb el contingut del fitxer)",
     "search-suggest": "Volíeu dir: $1",
     "search-interwiki-caption": "Projectes germans",
-    "search-interwiki-default": "$1 resultats:",
+    "search-interwiki-default": "Resultats de $1:",
     "search-interwiki-more": "(més)",
     "search-relatedarticle": "Relacionat",
     "searcheverything-enable": "Cerca a tots els espais de noms",
     "prefs-skin": "Aparença",
     "skin-preview": "prova",
     "datedefault": "Cap preferència",
-    "prefs-beta": "Característiques beta",
     "prefs-datetime": "Data i hora",
     "prefs-labs": "Característiques de laboratori",
     "prefs-user-pages": "Pàgines d'usuari",
     "download": "baixada",
     "unwatchedpages": "Pàgines desateses",
     "listredirects": "Llista de redireccions",
+    "listduplicatedfiles": "Llista de fitxers amb duplicats",
     "unusedtemplates": "Plantilles no utilitzades",
     "unusedtemplatestext": "Aquesta pàgina mostra les pàgines en l'espai de noms {{ns:template}}, que no estan incloses en cap altra pàgina. Recordeu de comprovar les pàgines que hi enllacen abans d'esborrar-les.",
     "unusedtemplateswlh": "altres enllaços",
     "listgrouprights-removegroup-self": "Abandona {{PLURAL:$2|el grup|els grups:}} $1",
     "listgrouprights-addgroup-self-all": "Afegir-se a qualsevol grup",
     "listgrouprights-removegroup-self-all": "Abandona tots els grups",
+    "trackingcategories": "Categories de seguiment",
+    "trackingcategories-msg": "Categoria de seguiment",
+    "trackingcategories-name": "Nom del missatge",
+    "trackingcategories-desc": "Criteris d'inclusió de categoria",
+    "trackingcategories-nodesc": "Sense descripció disponible.",
+    "trackingcategories-disabled": "La categoria està inhabilitada",
     "mailnologin": "Cap adreça de remitent",
     "mailnologintext": "Heu d'[[Special:UserLogin|iniciar una sessió]] i tenir una adreça electrònica vàlida en les vostres [[Special:Preferences|preferències]] per poder enviar correus a altres usuaris.",
     "emailuser": "Envia un missatge de correu electrònic a aquest usuari",
     "nowatchlist": "No teniu cap element en la vostra llista de seguiment.",
     "watchlistanontext": "Premeu $1 per a visualitzar o modificar elements de la vostra llista de seguiment.",
     "watchnologin": "No heu iniciat la sessió",
-    "watchnologintext": "Heu d'[[Special:UserLogin|entrar]]\nper modificar el vostre llistat de seguiment.",
     "addwatch": "Afegeix a llista de seguiment",
     "addedwatchtext": "S'ha afegit la pàgina \"[[:$1]]\" a la vostra [[Special:Watchlist|llista de seguiment]].\nS'hi mostraran els canvis futurs que tinguin lloc en aquesta pàgina i la corresponent discussió.",
     "removewatch": "Treu de la llista de seguiment",
     "protect-locked-blocked": "No podeu canviar els nivells de protecció mentre estigueu bloquejats. Ací hi ha els\nparàmetres actuals de la pàgina '''$1''':",
     "protect-locked-dblock": "No poden canviar-se els nivells de protecció a casa d'un bloqueig actiu de la base de dades.\nAcí hi ha els paràmetres actuals de la pàgina '''$1''':",
     "protect-locked-access": "El vostre compte no té permisos per a canviar els nivells de protecció de la pàgina.\nAcí es troben els paràmetres actuals de la pàgina '''$1''':",
-    "protect-cascadeon": "Aquesta pàgina es troba protegida perquè està inclosa en {{PLURAL:$1|la següent pàgina que té|les següents pàgines que tenen}} activada una protecció en cascada. Podeu canviar el nivell de protecció d'aquesta pàgina però això no afectarà la protecció en cascada.",
+    "protect-cascadeon": "Aquesta pàgina es troba protegida actualment perquè està inclosa en {{PLURAL:$1|la següent pàgina que té|les següents pàgines que tenen}} activada una protecció en cascada. \nCanviar el nivell de protecció d'aquesta pàgina no afectarà la protecció en cascada.",
     "protect-default": "Permet tots els usuaris",
     "protect-fallback": "Permetre només a usuaris amb permisos de \"$1\"",
     "protect-level-autoconfirmed": "Permetre només usuaris autoconfirmats",
     "sp-contributions-newbies-sub": "Per a novells",
     "sp-contributions-newbies-title": "Contribucions dels comptes d'usuari més nous",
     "sp-contributions-blocklog": "Registre de bloquejos",
+    "sp-contributions-suppresslog": "contribucions suprimides de l'usuari",
     "sp-contributions-deleted": "contribucions d'usuari esborrades",
     "sp-contributions-uploads": "pujades",
     "sp-contributions-logs": "registres",
     "sp-contributions-blocked-notice": "En aquests moments, aquest compte d'usuari es troba blocat.\nPer més detalls, la última entrada del registre es mostra a continuació:",
     "sp-contributions-blocked-notice-anon": "En aquests moments, aquesta adreça IP es troba blocada.\nPer més detalls, la última entrada del registre es mostra a continuació:",
     "sp-contributions-search": "Cerca les contribucions",
-    "sp-contributions-suppresslog": "contribucions suprimides de l'usuari",
     "sp-contributions-username": "Adreça IP o nom d'usuari:",
     "sp-contributions-toponly": "Mostra només revisions superiors",
     "sp-contributions-newonly": "Mostra només modificacions que són creacions de pàgina",
     "allmessagesname": "Nom",
     "allmessagesdefault": "Text per defecte",
     "allmessagescurrent": "Text actual",
-    "allmessagestext": "Tot seguit hi ha una llista dels missatges del sistema que es troben a l'espai de noms ''MediaWiki''. La traducció genèrica d'aquests missatges no s'hauria de fer localment sinó a la traducció del programari MediaWiki. Si voleu ajudar-hi visiteu [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] i [//translatewiki.net translatewiki.net].",
+    "allmessagestext": "Tot seguit hi ha una llista dels missatges del sistema que es troben a l'espai de noms ''MediaWiki''. La traducció genèrica d'aquests missatges no s'hauria de fer localment sinó a la traducció del programari MediaWiki. Si voleu ajudar-hi visiteu [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] i [//translatewiki.net translatewiki.net].",
     "allmessagesnotsupportedDB": "No es pot processar '''{{ns:special}}:Allmessages''' perquè la variable '''$wgUseDatabaseMessages''' està desactivada.",
     "allmessages-filter-legend": "Filtre",
     "allmessages-filter": "Filtra per l'estat de personalització:",
index 5f90778..5b050f0 100644 (file)
@@ -3,7 +3,8 @@
         "authors": [
             "Xiaomingyan",
             "Xqt",
-            "Yejianfei"
+            "Yejianfei",
+            "Hakka"
         ]
     },
     "tog-underline": "下劃綫鏈接",
     "allmessagesname": "名",
     "allmessagesdefault": "默認其消息文字",
     "allmessagescurrent": "現時其文字",
-    "allmessagestext": "茲是敆媒體維基命名空間底裏系統消息其蜀萆單單。\n如果汝卜想貢獻通用其媒體維基本地化服務,請訪問[https://www.mediawiki.org/wiki/Localisation 媒體維基本地化]共[//translatewiki.net translatewiki.net]。",
+    "allmessagestext": "茲是敆媒體維基命名空間底裏系統消息其蜀萆單單。\n如果汝卜想貢獻通用其媒體維基本地化服務,請訪問[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation 媒體維基本地化]共[//translatewiki.net translatewiki.net]。",
     "allmessagesnotsupportedDB": "茲蜀頁𣍐使其,因為'''$wgUseDatabaseMessages'''已經乞禁止去了。",
     "thumbnail-more": "放大",
     "tooltip-pt-userpage": "汝其用戶頁",
index fbefe03..15f7c1d 100644 (file)
@@ -9,7 +9,7 @@
             "Умар"
         ]
     },
-    "tog-underline": "Кlел сиз хьака хьажориган:",
+    "tog-underline": "КӀел сиз хьакха хьажорган:",
     "tog-hideminor": "Къайладаха кигийра нисдарш оц могӀама керла хийцамехь",
     "tog-hidepatrolled": "Къайладаха гӀаролладина нисдарш оц могӀама керла нисдаршкахь",
     "tog-newpageshidepatrolled": "Къайлайаха гlароллайина агlонаш оц могlама керла агlонашкахь",
     "prefs-skin": "Кечяран тема",
     "skin-preview": "Хьалха муха ю хьажа",
     "datedefault": "Iад йитарца",
-    "prefs-beta": "Бета-таронаш",
     "prefs-datetime": "Терахь а хан а",
     "prefs-labs": "Муха ю хьажарна таронаш",
     "prefs-user-pages": "Декъашхочун агӀо",
     "year": "Шерачохь (я хьалхе):",
     "sp-contributions-newbies": "Гайта бекъ къинхьегам, керла дlабазбиначара бина болу",
     "sp-contributions-blocklog": "блоктоьхарш",
+    "sp-contributions-suppresslog": "Декъашхочун дӀабаьккхина къинхьегам",
     "sp-contributions-deleted": "дӀадяхна нийсдарш",
     "sp-contributions-uploads": "Файлаш",
     "sp-contributions-logs": "тéптарш",
     "sp-contributions-blocked-notice": "ХӀара декъашхочун дӀаяздар блоктоьхна ду.\nЛахахь гойту блоктохаршан тептар чура тӀаьхьарлера дӀаяздар:",
     "sp-contributions-blocked-notice-anon": "ХӀара IP-адрес хӀинца блоктоьхна ду.\nЛахахь гойту блоктохаршан тептар чура тӀаьхьарлера дӀаяздар:",
     "sp-contributions-search": "Къинхьегам лахар",
-    "sp-contributions-suppresslog": "Декъашхочун дӀабаьккхина къинхьегам",
     "sp-contributions-username": "IP-адрес я декъашхочун цӀе:",
     "sp-contributions-toponly": "ТӀаьхьара бина хийцамаш гайта",
     "sp-contributions-newonly": "АгӀонаш кхоллар бен ма гайта",
     "nolinkshere": "ХӀокху '''[[:$1]]''' агӀона тӀе кхечу агӀонашкахь хьажорагаш яц.",
     "nolinkshere-ns": "Хаьржинчу анахь яц '''[[:$1]]''' цӀе йолу агӀонаш",
     "isredirect": "агӀо-дӀасахьажайар",
-    "istemplate": "лата йe",
+    "istemplate": "юкъаялийнарш",
     "isimage": "Файлан хьажораг",
     "whatlinkshere-prev": "{{PLURAL:$1|1=хьалхайодарг|хьалхайодарш}} $1",
     "whatlinkshere-next": "{{PLURAL:$1|тlаьхьайогlург|тlаьхьайогlурш|тlаьхьайогlурш}} $1",
     "allmessagesname": "Хаам",
     "allmessagesdefault": "Ӏад дитарца йоза",
     "allmessagescurrent": "Карарчу хенан йоза",
-    "allmessagestext": "ХӀара «MediaWiki» цӀерийн меттигера системан хаамийн могӀа бу.\nХьайна MediaWiki тая лууш делахь, дехар до, проект [//translatewiki.net translatewiki.net] [https://www.mediawiki.org/wiki/Localisation юьйцучу хьажа].",
+    "allmessagestext": "ХӀара «MediaWiki» цӀерийн меттигера системан хаамийн могӀа бу.\nХьайна MediaWiki тая лууш делахь, дехар до, проект [//translatewiki.net translatewiki.net] [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation юьйцучу хьажа].",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' дӀаяйина хилар бахьнехь хӀара агӀо дӀачӀаьгӀна ю.",
     "allmessages-filter-legend": "Литтар",
     "allmessages-filter": "Литтар оцу хьола хийцамца:",
     "thumbnail_error_remote": "ГӀалатах хаам $1:\n$2",
     "import": "АгӀонаш чуяхар",
     "import-interwiki-source": "Вики-хьост/агlо:",
-    "import-interwiki-templates": "Ð\9bаÑ\82а Ð´Ðµ массо кепаш",
+    "import-interwiki-templates": "ЮкÑ\8aайиÑ\85ка массо кепаш",
     "import-interwiki-submit": "Импорт ян",
     "import-upload-filename": "Файлан цӀе:",
     "import-comment": "Билгалдаккхар:",
     "version-software-version": "Верси",
     "version-entrypoints": "ЧугӀо адресин тӀадамаш",
     "version-entrypoints-header-entrypoint": "Яздаран тӀадам",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath АгӀона тӀе некъ]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Скриптан тӀе некъ]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath АгӀона тӀе некъ]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Скриптан тӀе некъ]",
     "redirect": "Декъашхочун файлан тӀера дӀасхьажор",
     "redirect-legend": "Файлан я агӀона тӀера дӀасхьажор",
     "redirect-summary": "ХӀара агӀо лело йиш ю файлан я агӀона тӀера дӀасхьажош.",
index b89cda9..6c18875 100644 (file)
@@ -19,7 +19,7 @@
     "tog-hidepatrolled": "لە دوایین گۆڕانکارییەکاندا دەستکارییە پاس دراوەکان بشارەوە",
     "tog-newpageshidepatrolled": "لە پێرستی پەڕە نوێکاندا پەڕە پاس دراوەکان بشارەوە",
     "tog-extendwatchlist": "لیستی چاودێری درێژبکەرەوە بۆ نیشان دانی ھەموو گۆڕانکارییەکان، نەک تەنھا دوایینەکان.",
-    "tog-usenewrc": "Ú¯Û\86Ú\95اÙ\86کارÛ\8cÛ\8cÛ\95کاÙ\86 Ù\84Û\95 Ø¯Ù\88اÛ\8cÛ\8cÙ\86 Ú¯Û\86Ú\95اÙ\86کارÛ\8cÛ\8cÛ\95کاÙ\86 Ù\88 Ù\84Û\8cستÛ\8c Ú\86اÙ\88دÛ\8eرÛ\8cدا Ø¨Û\95 Ù¾Û\8eÛ\8c Ù¾Û\95Ú\95Û\95 Ù¾Û\86Ù\84Û\8eÙ\86 Ø¨Ú©Û\95 (Ù¾Û\8eÙ\88Û\8cستÛ\8c Ø¨Û\95 Ø¬Ø§Ú¤Ø§Ø³Ú©Ø±Û\8cپتÛ\95)",
+    "tog-usenewrc": "Ú¯Û\86Ú\95اÙ\86کارÛ\8cÛ\8cÛ\95کاÙ\86 Ù\84Û\95 Ø¯Ù\88اÛ\8cÛ\8cÙ\86 Ú¯Û\86Ú\95اÙ\86کارÛ\8cÛ\8cÛ\95کاÙ\86 Ù\88 Ù¾Û\8eرستÛ\8c Ú\86اÙ\88دÛ\8eرÛ\8cدا Ø¨Û\95Ù¾Û\8eÛ\8c Ù¾Û\95Ú\95Û\95 Ù¾Û\86Ù\84Û\8eÙ\86 Ø¨Ú©Û\95",
     "tog-numberheadings": "ژمارەکردنی خۆگەڕی سەردێڕەکان",
     "tog-showtoolbar": "تووڵامرازی دەستکاری نیشان بدە",
     "tog-editondblclick": "دەستکاریی پەڕە بە دووکرتە",
     "pool-errorunknown": "هەڵەی نەزانراو",
     "aboutsite": "سەبارەت بە {{SITENAME}}",
     "aboutpage": "Project:سەبارەت",
-    "copyright": "ناوەرۆک لە ژێر $1 لەبەردەستدایە، دەنا تێبینیی دەکرا",
+    "copyright": "ناوەرۆک لە ژێر $1 لەبەردەستدایە، مەگەر بێجگە لەمە وترابێ.",
     "copyrightpage": "{{ns:project}}:مافەکانی لەبەرگرتنەوە",
     "currentevents": "ڕووداوە ھەنووکەییەکان",
     "currentevents-url": "Project:ڕووداوە بەردەوامەکان",
     "mypreferencesprotected": "دەسەڵاتی دەستکارییکردنی هەڵبژاردنەکانی خۆتت نییە.",
     "ns-specialprotected": "تۆ ناتوانی لاپەڕە تایبەتەکان دەستکاریی بکەی.",
     "titleprotected": "ئەم سەرناوە پارێزراوە لە دروستکران لە لایەن [[User:$1|$1]].\nھۆکاری ئەمە بریتیە لە \"''$2''\".",
-    "invalidtitle-knownnamespace": "سÛ\95ردÛ\8eÚ\95Û\8c Ù\87Û\95ÚµÛ\95 Ù\84Û\95Ú¯Û\95Úµ Ù\86اÙ\88Û\95بÛ\86شاÛ\8cÛ\8c \"$2\" Ù\88 Ø¯Û\95Ù\82Û\8c \"$3\"",
+    "invalidtitle-knownnamespace": "سÛ\95ردÛ\8eÚ\95Û\8c Ù\86ادرÙ\88ست Ø¨Û\95 Ø¨Û\86شاÛ\8cÛ\8c Ù\86اÙ\88Û\8c Â«$2» Ù\88 Ø¯Û\95Ù\82Û\8c Â«$3»",
     "invalidtitle-unknownnamespace": "سەردێڕی هەڵە لەگەڵ ناوەبۆشایی نەناسراوی ژمارە $1 و دەقی \"$2\"",
     "exception-nologin": "لەژوورەوە نیت",
     "exception-nologin-text": "تکایە [[Special:Userlogin|بچۆ ژوورەوە]] تا بتوانیت بچیتە نێو ئەم پەڕەیە یان ئەم کردەیە ئەنجام بدەیت.",
     "virus-badscanner": "پێکەربەندیی نابەجێ: ڤایرس سکەنێری نەناسراو: ''$1''",
     "virus-scanfailed": "سکەن ئەنجام نەدرا(کۆد $1)",
     "virus-unknownscanner": "دژەڤایرس نەناسراوە:",
-    "logouttext": "'''تÛ\86 Ø¦Û\8eستا Ù\84Û\95دÛ\95رÛ\95Ù\88Û\95Û\8cت.'''\n\nتÛ\8eبÛ\8cÙ\86Û\8cÛ\8c Ø¦Û\95Ù\88Û\95 Ø¨Ú©Û\95 Ú©Û\95 Ù\87Û\95Ù\86دÛ\8eÚ© Ù\84Û\95 Ù¾Û\95Ú\95Û\95کاÙ\86 Ø¨Û\95ردÛ\95Ù\88اÙ\85 Ù\88ا Ø¯Û\95ردÛ\95Ú©Û\95Ù\88Ù\86 Ú©Û\95 Ù\87Û\8eشتا Ù\84Û\95Ú\98Ù\88Ù\88رÛ\95Ù\88Û\95 Ø¨Û\8cتØ\8c Ù\87Û\95تا Ø¦Û\95Ù\88 Ø¯Û\95Ù\85Û\95Û\8c Ú©Û\95Ø´Û\8c Ù\88Û\8eبگÛ\95Ú\95Û\95Ú©Û\95ت Ù¾Ø§Ú© Ø¯Û\95Ú©Û\95Û\8cتÛ\95Ù\88Û\95.",
+    "logouttext": "'''ئÛ\8eستا Ú\86Ù\88Ù\88Û\8cتÛ\95 Ø¯Û\95رÛ\95Ù\88Û\95.'''\n\nئاگادار Ø¨Û\95 Ú¾Û\95تا Ø¦Û\95Ù\88 Ú©Ø§ØªÛ\95Û\8c Ú©Û\95Ø´Û\8c Ù\88Û\8eبگÛ\95Ú\95Û\95Ú©Û\95ت Ù¾Ø§Ú© Ø¯Û\95Ú©Û\95Û\8cتÛ\95Ù\88Û\95Ø\8c Ù\84Û\95Ù\88اÙ\86Û\95Û\8cÛ\95 Ú¾Û\95Ù\86دÛ\8eÚ© Ù\84Û\95 Ù¾Û\95Ú\95Û\95کاÙ\86 Ù\88ا Ù¾Û\8eشاÙ\86 Ø¨Ø¯Ø±Û\8eÙ\86 Ú©Û\95 Ú¾Û\8eشتا Ù\84Û\95 Ú\98Ù\88Ù\88رÛ\95Ù\88Û\95 Ø¨Û\8cت.",
     "welcomeuser": "بەخێربێیت، $1!",
     "welcomecreation-msg": "ھەژمارەکەت دروست کرا.\nلە بیرت نەچێت [[Special:Preferences|ھەڵبژاردەکانی {{SITENAME}}]]ت بگۆڕی.",
     "yourname": "ناوی بەکارھێنەری:",
     "gotaccount": "ھەژمارت ھەیە لێرە؟ $1.",
     "gotaccountlink": "بچۆ ژوورەوە",
     "userlogin-resetlink": "وردەکارییەکانی چوونەژوورەوەتت لە بیر کردووە؟",
-    "userlogin-resetpassword-link": "تێپەڕەووشەکەت لەبیر کردووە؟",
+    "userlogin-resetpassword-link": "تێپەڕوشەکەت بیر کردووە؟",
     "userlogin-helplink2": "یارمەتی بۆ چوونەژوورەوە",
     "userlogin-loggedin": "تۆ ھەر ئێستا بە ناوی {{GENDER:$1|$1}} چوویتە ژوورەوە.\nفۆرمی ژێرەوە بەکاربھێنە بۆ چوونەژوورەوە وەک بەکارھێنەرێکی تر.",
     "userlogin-createanother": "ھەژمارێکی تر دروست بکە",
     "createacct-emailoptional": "ناونیشانی ئیمەیل (دڵخوازانە)",
     "createacct-email-ph": "ناونیشانی ئیمەیلەکەت بنووسە",
     "createacct-another-email-ph": "ناونیشانی ئیمەیڵەکەت بنووسە",
-    "createaccountmail": "تێپەڕوشەیەکی هەڕەمەکیی کاتی بەکاربھێنە و بینێرە بۆ ناونیشانی ئیمەیڵی دیاریکراو",
+    "createaccountmail": "تێپەڕوشەیەکی ھەڕەمەکیی کاتی بەکاربھێنە و بینێرە بۆ ناونیشانی ئیمەیلی دیاریکراو",
     "createacct-realname": "ناوی ڕاستی (دڵخوازانە)",
     "createaccountreason": "هۆکار:",
     "createacct-reason": "ھۆکار",
     "passwordsent": "تێپەڕوشەیەکی نوێ ناردرا بۆ ئەدرەسی ئیمەیلی تۆمارکراوی «$1».\nتکایە دوای وەرگرتنی دیسان بچۆ ژوورەوە.",
     "blocked-mailpassword": "ئادرەسی ئای‌پی تۆ بۆ دەستکاری کردن بەستراوه بۆیە بۆ بەرگری لە بەکارهێنانی نابەجێ ئەنجامی گەڕانەوەی تێپەڕوشە ڕیگە نەدراوە.",
     "eauthentsent": "ئیمەیلێکی پشتڕاستکردنەوە بۆ ناونیشانی ئیمەیلی دیاریکراو ناردرا.\nپێش ئەوەی ئیمەیلی تر بۆ ئەم هەژمارە بنێردرێ، بۆ پشتڕاستکردنەوەی ئەمەی ئەم هەژمارە بەڕاستی ھی تۆیە، دەبێ پەیڕەوی ڕێکارەکانی ناو ئیمەیلەکە بکەیت.",
-    "throttled-mailpassword": "نامەی بەدەستهێنانەوەی تێپەڕەووشە نێردراوە لە ماوەی {{PLURAL:$1|کاتژمێر}}ی ڕابردوودا.\nبۆ ڕێگریی لە بەکارهێنانی خراپ، تاکە یەک نامەی بەدەستهێنانەوەی تێپەڕەووشە هەموو {{PLURAL:$1|کاتژمێر}}ێک دەنێردرێت.",
+    "throttled-mailpassword": "ئیمەیلێکی ڕیکخستنەوەی تێپەڕوشە لە ماوەی {{PLURAL:$1|ساعەت}}ی ڕابردوودا نێردراوە.\nبۆ ڕێگری لە بەکارھێنانی خراپ، ھەر {{PLURAL:$1|ساعەت}} تاکە یەک ئیمەیلی ڕیکخستنەوەی تێپەڕوشە دەنێردرێت.",
     "mailerror": "هەڵە ڕوویدا لە ناردنی ئیمەیل: $1",
     "acct_creation_throttle_hit": "بینەرانی ویکی بەکەڵک وەرگرتن لەم ئای‌پی ئەدرەسەی تۆ لە ڕۆژانی ڕابردوودا، دەستیان کردە بە درووست‌کردنی {{PLURAL:$1|هەژمارە}}، کە زۆرینە ڕیگەپێدان لە یەک ماوە‌دایە.\nوەک ئەنجامی ئەو ڕووداوە، ئەو بینەرانی لەم ئای‌پی ئەدرەسە کەڵک وەر دەگرن لەم کاتەدا ناتوانن هەژماری دیکە درووست‌بکەن.",
     "emailauthenticated": "ناونیشانی ئیمەیلەکەت پشتڕاست کرایەوە لە $3ی $2دا.",
     "prefs-skin": "پێستە",
     "skin-preview": "پێش بینین",
     "datedefault": "ھەڵنەبژێردراو",
-    "prefs-beta": "تایبەتمەندییەکانی بیتا",
     "prefs-datetime": "کات و ڕێکەوت",
     "prefs-labs": "کەرەسەکانی تاقیگەکان",
     "prefs-user-pages": "پەڕە بەکارھێنەرییەکان",
     "group-user": "بەکارهێنەران",
     "group-autoconfirmed": "بەکارھێنەرانی پەسندکراوی خۆگەڕ",
     "group-bot": "بۆتەکان",
-    "group-sysop": "بەڕێوبەران",
+    "group-sysop": "بەڕێوەبەران",
     "group-bureaucrat": "بیوروکراتەکان",
     "group-suppress": "چاودێرەکان",
     "group-all": "(ھەموو)",
     "statistics-header-hooks": "ئامارەکانی دیکە",
     "statistics-articles": "پەڕە بە ناوەڕۆکەکان",
     "statistics-pages": "پەڕەکان",
-    "statistics-pages-desc": "گشت Ù¾Û\95Ú\95Û\95کاÙ\86Û\8c Ù\88Û\8cÚ©Û\8cØ\8c Ø¨Û\95 Ù\84Û\95Ø®Û\86گرتÙ\86Û\8c Ù¾Û\95Ú\95Û\95کاÙ\86Û\8c Ù\88تÙ\88Ù\88Û\8eÚ\98Ø\8c Ú\95Û\95Ù\88اÙ\86Û\95کراÙ\88ەکان و ھتد.",
+    "statistics-pages-desc": "گشت Ù¾Û\95Ú\95Û\95کاÙ\86Û\8c Ù\88Û\8cÚ©Û\8cØ\8c Ø¨Û\95 Ù\84Û\95Ø®Û\86گرتÙ\86Û\8c Ù¾Û\95Ú\95Û\95کاÙ\86Û\8c Ù\84Û\8eدÙ\88اÙ\86Ø\8c Ú\95Û\95Ù\88اÙ\86Û\95Ú©Û\95رەکان و ھتد.",
     "statistics-files": "پەڕگە بارکراوەکان",
     "statistics-edits": "دەستکارییەکانی پەڕەکان لە کاتی دامەزراندنی {{SITENAME}}ەوە",
-    "statistics-edits-average": "نێونجی ژمارەی دەستکارییەکان لە پەڕەیەک دا",
+    "statistics-edits-average": "ناونجیی دەستکارییەکان بۆ ھەر پەڕە",
     "statistics-views-total": "دیتنی هەموو",
     "statistics-views-peredit": "دیتنی هەر دەستکارییەک",
     "statistics-users": "[[Special:ListUsers|بەکارھێنەر]]ە تۆمارکراوەکان",
     "statistics-users-active": "ئەندامە چالاکەکان",
-    "statistics-users-active-desc": "ئەو بەکارھێنەرانە کە لە {{PLURAL:$1|ڕۆژ|$1 ڕۆژ}}ی ڕابردوودا کارێکیان جێبەجێ کردبێت.",
+    "statistics-users-active-desc": "ئەو بەکارھێنەرانەی لە {{PLURAL:$1|ڕۆژ|$1 ڕۆژ}}ی ڕابردوودا کردەوەیەکیان بەڕێوە بردووە",
     "statistics-mostpopular": "زۆرترین لاپەڕە بینراوەکان",
     "pageswithprop": "پەڕەکان بە تایبەتمەندیی پەڕە",
     "pageswithprop-legend": "پەڕەکان بە تایبەتمەندیی پەڕە",
     "nowatchlist": "لە لیستی چاودێڕییەکانتدا ھیچ نیە.",
     "watchlistanontext": "بۆ دیتن و دەستکاریی بابەتەکانی  ناو پێرستی چاودێرییەکەتدا دەبێ $1.",
     "watchnologin": "لە ژوورەوە نیت.",
-    "watchnologintext": "دەبی لە [[Special:UserLogin|ژوورەوە]] بیت بۆ ئەوەی بتوانی گۆڕانکاری بکەیت لە لیستی چاودێریەکەت‌دا.",
     "addwatch": "بیخە سەر لیستی چاودێری",
     "addedwatchtext": "پەڕەی «[[:$1]]» خرایە ژێر [[Special:Watchlist|پێرستی چاودێری]]یەکەت.\nگۆڕانکارییەکانی داھاتووی ئەم پەڕەیە و پەڕەی وتووێژەکەی، لەوێدا پێرست دەکرێت.",
     "removewatch": "لەلیستی چاودێری لایبە",
     "protectexpiry": "ھەتا:",
     "protect_expiry_invalid": "کاتی بەسەرچوون نادروستە:",
     "protect_expiry_old": "کاتی بەسەرچوون ڕابردووە",
+    "protect-unchain-permissions": "ھەڵبژاردەکانی تری پاراستن بکەوە",
     "protect-text": "دەتوانی لێرەوە ئاستی پاراستنی پەڕەی '''$1''' ببینی و بیشیگۆڕی.",
     "protect-locked-blocked": "ناتوانیت ئاستی پاراستن بگۆڕیت کاتێ بەستراوە.\nئەوە هەڵبژاردەکانی ئێستای ڕێکخستنی بۆ لاپەڕە '''$1''':",
     "protect-locked-dblock": "ئاستەکانی پاراستن ناگۆڕدرێن کاتێ بنکەدراوی چالاک داخرابێت.\nئەوە هەڵبژاردەکانی ئێستای ڕێکخستنی بۆ لاپەڕە '''$1''':",
     "sp-contributions-blocked-notice-anon": "ھەنووکە ئەم ناونیشانەی IPیە بەربەست کراوە.\nدوایین بابەتی لۆگی بەربەستن لە ژێرەوە ھاتووە:",
     "sp-contributions-search": "گەڕان بۆ بەشدارییەکان",
     "sp-contributions-username": "ناونیشانی ئایپی یان ناوی‌ بەکارھێنەر:",
-    "sp-contributions-toponly": "تەنیا ئەو دەستکارییانە نیشانبدە کە دوایین پیاچوونەوەن",
+    "sp-contributions-toponly": "تەنیا ئەو دەستکارییانە نیشان بدە کە دوایین پێداچوونەوەن",
+    "sp-contributions-newonly": "تەنیا ئەو دەستکارییانە نیشان بدە کە دروستکردنی پەڕەن",
     "sp-contributions-submit": "بگەڕێ",
     "whatlinkshere": "بەسراوەکان بە ئێرەوە",
     "whatlinkshere-title": "ئەو پەڕانەی بەستەریان ھەیە بۆ «$1»",
     "allmessagesname": "ناو",
     "allmessagesdefault": "دەقی بنەڕەتی",
     "allmessagescurrent": "دەقی ھەنووکە",
-    "allmessagestext": "ئەمە لیستێکە لە پەیامەکانی بەردەست لە بۆشایی‌ناوی میدیاویکی.\nتکایە سەردانی [https://www.mediawiki.org/wiki/Localisation ناوچەیی‌کردنی میدیاویکی] و [//translatewiki.net translatewiki.net] بکە ئەگەر دەتەوێ لە ناوچەیی‌کردنی میدیاویکی بە گشتی بەشداری بکەیت.",
+    "allmessagestext": "ئەمە لیستێکە لە پەیامەکانی بەردەست لە بۆشایی‌ناوی میدیاویکی.\nتکایە سەردانی [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation ناوچەیی‌کردنی میدیاویکی] و [//translatewiki.net translatewiki.net] بکە ئەگەر دەتەوێ لە ناوچەیی‌کردنی میدیاویکی بە گشتی بەشداری بکەیت.",
     "allmessagesnotsupportedDB": "ئەم لاپەڕە ناتوانی بەکاربێت لەبەر ئەوەی '''$wgUseDatabaseMessages''' لەکار خستراوە.",
     "allmessages-filter-legend": "پاڵێو",
     "allmessages-filter-unmodified": "نەگۆڕدراو",
index a1e5420..137a6f5 100644 (file)
     "version-specialpages": "Pagine spiciale",
     "specialpages": "Pagine spiciale",
     "tags-edit": "mudificà",
+    "logentry-delete-delete": "$1 ha cancellatu a pagina $3",
     "logentry-move-move": "$1 {{GENDER:$2|hà spustatu}} a pagina $3 à $4",
     "rightsnone": "(nessunu)",
     "expand_templates_output": "Risultatu"
index 10a17c4..bfeba72 100644 (file)
     "nowatchlist": "Сизинъ козетюв джедвелинъиз боштыр.",
     "watchlistanontext": "Козетюв джедвелини бакъмакъ я да денъиштирмек ичюн $1 борджлусынъыз.",
     "watchnologin": "Отурым ачмакъ керек",
-    "watchnologintext": "Озь козетюв джедвелинъизни денъиштирмек ичюн [[Special:UserLogin|отурым ачынъыз]]",
     "addedwatchtext": "\"[[:$1]]\" саифеси [[Special:Watchlist|козетюв джевделинъизге]] кирсетильди.\nБундан сонъ, бу саифеде ве онынъ музакере саифесинде япыладжакъ денъиштирмелер анда косьтериледжек.",
     "removedwatchtext": "\"[[:$1]]\" саифеси [[Special:Watchlist|козетюв джедвелинъизден]] ёкъ этильди.",
     "watch": "Козет",
     "allmessagesname": "Исим",
     "allmessagesdefault": "Оригиналь метин",
     "allmessagescurrent": "Шимди къулланылгъан метин",
-    "allmessagestext": "Ишбу джедвель MediaWiki-де мевджут олгъан бутюн система беянатларынынъ джедвелидир.\nMediaWiki интерфейсининъ чешит тиллерге терджиме этювде иштирак этмеге истесенъиз [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] ве [//translatewiki.net translatewiki.net] саифелерине зиярет этинъиз.",
+    "allmessagestext": "Ишбу джедвель MediaWiki-де мевджут олгъан бутюн система беянатларынынъ джедвелидир.\nMediaWiki интерфейсининъ чешит тиллерге терджиме этювде иштирак этмеге истесенъиз [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] ве [//translatewiki.net translatewiki.net] саифелерине зиярет этинъиз.",
     "thumbnail-more": "Буют",
     "filemissing": "Файл тапылмады",
     "thumbnail_error": "Кичик ресим (thumbnail) яратылгъанда бир хата чыкъты: $1",
index c28bcc8..185a959 100644 (file)
     "privacypage": "Project:Gizlilik esası",
     "badaccess": "İzin hatası",
     "badaccess-group0": "Yapacaq olğan areketiñizni yapmağa aqqıñız yoq.",
-    "badaccess-groups": "Yapacaq olğan areketiñizni tek aşağıdaki {{PLURAL:$2|1|$2}} gruppağa aza оlğan qullanıcıları yapıp olalar: $1.",
+    "badaccess-groups": "Yapacaq olğan areketiñizni tek aşağıdaki {{PLURAL:$2|1|$2}} gruppağa aza olğan qullanıcıları yapıp ola: $1.",
     "versionrequired": "MediaWikiniñ $1 versiyası kerek",
     "versionrequiredtext": "Bu saifeni qullanmaq içün MediaWikiniñ $1 versiyası kerek. [[Special:Version|Versiya]] saifesine baq.",
     "ok": "Ok",
     "youhavenewmessagesmulti": "$1 saifesinde yañı beyanatıñız bar.",
     "editsection": "deñiştir",
     "editold": "deñiştir",
-    "viewsourceold": "menba kоdunı köster",
+    "viewsourceold": "menba kodunı köster",
     "editlink": "deñiştir",
-    "viewsourcelink": "menba kоdunı köster",
+    "viewsourcelink": "menba kodunı köster",
     "editsectionhint": "Deñiştirilgen bölük: $1",
     "toc": "Münderice",
     "showtoc": "köster",
     "restorelink": "yoq etilgen {{PLURAL:$1|1|$1}} deñiştirmesi",
     "feedlinks": "Bu şekilde:",
     "feed-invalid": "Abune kanalınıñ çeşiti yañlıştır.",
-    "feed-unavailable": "Sindikatsiya lentaları qullanılıp оlamay.",
+    "feed-unavailable": "Sindikatsiya lentaları qullanılıp olamay.",
     "site-rss-feed": "$1 RSS lentası",
     "site-atom-feed": "$1 Atom lentası",
     "page-rss-feed": "\"$1\" - RSS lentası",
     "page-atom-feed": "\"$1\" - Atom lentası",
-    "red-link-title": "$1 (böyle saife yоq)",
+    "red-link-title": "$1 (böyle saife yoq)",
     "sort-descending": "Eksilmesi sayın sırala",
     "sort-ascending": "Artması sayın sırala",
     "nstab-main": "Saife",
     "nstab-help": "Yardım",
     "nstab-category": "Kategoriya",
     "nosuchaction": "Böyle bir areket yoq",
-    "nosuchactiontext": "URL-de bildirilgen areket ruhsetsiz.\nBelki de URL-ni yañlış yazğandırsız, ya da doğru olmağan bir bağlantını qullanğandırsız.\nBu, {{SITENAME}} saytındaki bir hatanı da kösterip оla.",
+    "nosuchactiontext": "URL-de bildirilgen areket ruhsetsiz.\nBelki de URL-ni yañlış yazğandırsız, ya da doğru olmağan bir bağlantını qullanğandırsız.\nBu, {{SITENAME}} saytındaki bir hatanı da kösterip ola.",
     "nosuchspecialpage": "Bu isimde bir mahsus saife yoq",
     "nospecialpagetext": "<strong>Tapılmağan bir mahsus saifege kirdiñiz.</strong>\n\nBar olğan bütün mahsus saifelerni [[Special:SpecialPages|{{int:specialpages}}]] saifesinde körip olursıñız.",
     "error": "Hata",
     "fileexistserror": "\"$1\" faylı saqlanıp olamay, fayl endi bar.",
     "unexpected": "beklenmegen deger: \"$1\"=\"$2\".",
     "formerror": "Hata: formanıñ malümatını yollamaqnıñ iç çaresi yoq",
-    "badarticleerror": "Siz yapmağa istegen işlev bu saifede yapılıp оlamay.",
+    "badarticleerror": "Siz yapmağa istegen işlev bu saifede yapılıp olamay.",
     "cannotdelete": "\"$1\" saife ya da faylı yoq etilip olamadı. Başqa bir qullanıcı tarafından yoq etilgen ola bile.",
     "cannotdelete-title": "\"$1\" saifesini yoq etmege olmaz",
     "delete-hook-aborted": "Yoq etüv çengel protsedurasınen toqtatıldı.\nİç bir izaat berilmedi.",
     "nouserspecified": "Qullanıcı adını kirsetmek kereksiñiz.",
     "login-userblocked": "Bu qullanıcı blok etilgen. Kirmege ruhset etilmey.",
     "wrongpassword": "Kirsetken paroliñiz yañlıştır. Lütfen, tekrar etiñiz.",
-    "wrongpasswordempty": "Kirsetken parоliñiz bоştır.\nLütfen, tekrar etiñiz.",
+    "wrongpasswordempty": "Kirsetken paroliñiz boştır.\nLütfen, tekrar etiñiz.",
     "passwordtooshort": "Paroliñizde eñ az {{PLURAL:$1|1|$1}} işaret olmalı.",
     "password-name-match": "Paroliñiz qullanıcı adıñızdan farqlı olmalı.",
     "password-login-forbidden": "Bu qullanıcı adı ve parolni qullanmaq yasaqtır.",
     "resetpass-no-info": "Bu saifege doğrudan irişmek içün oturım açmaq kereksiñiz.",
     "resetpass-submit-loggedin": "Parolni deñiştir",
     "resetpass-submit-cancel": "Lâğu",
-    "resetpass-wrong-oldpass": "Ruhsetsiz muvaqqat ya da şimdiki parоl.\nParоliñizni endi muvafaqiyetnen deñiştirdiñiz ya da yañı bir muvaqqat parоl istediñiz.",
+    "resetpass-wrong-oldpass": "Ruhsetsiz muvaqqat ya da şimdiki parol.\nParoliñizni endi muvafaqiyetnen deñiştirdiñiz ya da yañı bir muvaqqat parol istediñiz.",
     "resetpass-temp-password": "Muvaqqat parol:",
     "bold_sample": "Qalın yazılış",
     "bold_tip": "Qalın yazılış",
     "viewpagelogs": "Bu saifeniñ jurnallarını köster",
     "nohistory": "Bu saifeniñ keçmiş versiyası yoq.",
     "currentrev": "Şimdiki versiya",
-    "currentrev-asof": "$1 tarihında sоñki kere deñiştirilgen saifeniñ şimdiki alı",
+    "currentrev-asof": "$1 tarihında soñki kere deñiştirilgen saifeniñ şimdiki alı",
     "revisionasof": "Saifeniñ $1 tarihındaki alı",
     "revision-info": "Saifeniñ $2 tarafından yazılğan $1 tarihındaki alı",
     "previousrevision": "← Evelki alı",
     "search-suggest": "Bunımı demege istediñiz: $1",
     "search-interwiki-caption": "Qardaş leyhalar",
     "search-interwiki-default": "$1 netice:",
-    "search-interwiki-more": "(daa çоq)",
+    "search-interwiki-more": "(daa çoq)",
     "search-relatedarticle": "Bağlı",
     "searcheverything-enable": "Bütün isim fezalarında qıdır",
     "searchrelated": "bağlı",
     "editinguser": "'''[[User:$1|$1]]''' $2 qullanıcısınıñ izinlerini deñiştireyatasız",
     "userrights-editusergroup": "Qullanıcı gruppaları nizamla",
     "saveusergroups": "Qullanıcı gruppalarını saqla",
-    "userrights-groupsmember": "Azası оlğan gruppalarıñız:",
+    "userrights-groupsmember": "Azası olğan gruppalarıñız:",
     "group": "Gruppa:",
     "group-user": "Qullanıcılar",
     "group-autoconfirmed": "Avtomatik tasdıqlanğan qullanıcılar",
     "grouppage-bureaucrat": "{{ns:project}}:Bürokratlar",
     "grouppage-suppress": "{{ns:project}}:Teftişçiler",
     "newuserlogpage": "Yañı qullanıcı jurnalı",
-    "newuserlogpagetext": "Eñ sоñki qayd оlğan qullanıcı jurnalı.",
+    "newuserlogpagetext": "Eñ soñki qayd olğan qullanıcı jurnalı.",
     "rightslog": "Qullanıcınıñ aqları jurnalı",
     "action-edit": "bu saifeni deñiştirmege",
     "nchanges": "$1 {{PLURAL:$1|deñiştirme}}",
     "upload-prohibited": "Yasaqlı fayl çeşitleri: $1.",
     "uploadlog": "yükleme jurnalı",
     "uploadlogpage": "Fayl yükleme jurnalı",
-    "uploadlogpagetext": "Aşağıda eñ soñki qоşulğan fayllarnıñ cedveli buluna.\nDaa körgezmeli körüniş içün [[Special:NewFiles|yañı fayllar galereyasına]] baqıñız.",
+    "uploadlogpagetext": "Aşağıda eñ soñki qoşulğan fayllarnıñ cedveli buluna.\nDaa körgezmeli körüniş içün [[Special:NewFiles|yañı fayllar galereyasına]] baqıñız.",
     "filename": "Fayl",
     "filedesc": "Faylğa ait qısqa tarif",
     "fileuploadsummary": "Qısqa tarif:",
     "imagelinks": "Fayl bağlantıları",
     "linkstoimage": "Bu faylğa bağlantı olğan {{PLURAL:$1|1|$1}} saife:",
     "nolinkstoimage": "Bu faylğa bağlanğan saife yoq.",
-    "sharedupload": "Bu fayl $1 saytından ve diger leyhalarda da qullanılıp оla.",
+    "sharedupload": "Bu fayl $1 saytından ve diger leyhalarda da qullanılıp ola.",
     "uploadnewversion-linktext": "Faylnıñ yañısını yükleñiz",
     "shared-repo-from": "$1nden",
     "shared-repo": "ortaq tutulğan yeri",
     "wantedcategories": "İstenilgen kategoriyalar",
     "wantedpages": "İstenilgen saifeler",
     "wantedfiles": "İstenilgen fayllar",
-    "wantedtemplates": "İstenilgen şablоnlar",
+    "wantedtemplates": "İstenilgen şablonlar",
     "mostlinked": "Özüne eñ ziyade bağlantı berilgen saifeler",
     "mostlinkedcategories": "Eñ çoq saifege saip kategoriyalar",
     "mostlinkedtemplates": "Özüne eñ ziyade bağlantı berilgen şablonlar",
     "nowatchlist": "Siziñ közetüv cedveliñiz boştır.",
     "watchlistanontext": "Közetüv cedvelini baqmaq ya da deñiştirmek içün $1 borclusıñız.",
     "watchnologin": "Oturım açmaq kerek",
-    "watchnologintext": "Öz közetüv cedveliñizni deñiştirmek içün [[Special:UserLogin|oturım açıñız]]",
     "addedwatchtext": "\"[[:$1]]\" saifesi [[Special:Watchlist|közetüv cevdeliñizge]] kirsetildi.\nBundan soñ, bu saifede ve onıñ muzakere saifesinde yapılacaq deñiştirmeler anda kösterilecek.",
     "removedwatchtext": "\"[[:$1]]\" saifesi [[Special:Watchlist|közetüv cedveliñizden]] yoq etildi.",
     "watch": "Közet",
     "undeletelink": "köster/keri ketir",
     "undeletecomment": "Sebep:",
     "undeletedrevisions": "Toplam {{PLURAL:$1|1 qayd|$1 qayd}} keri ketirildi.",
-    "undelete-header": "Keçenlerde yоq etilgen saifelerni körmek içün [[Special:Log/delete|yоq etüv jurnalına]] baqıñız.",
+    "undelete-header": "Keçenlerde yoq etilgen saifelerni körmek içün [[Special:Log/delete|yoq etüv jurnalına]] baqıñız.",
     "namespace": "İsim fezası:",
     "invert": "Saylanğan tışındakilerni sayla",
     "blanknamespace": "(Esas)",
     "allmessagesname": "İsim",
     "allmessagesdefault": "Original metin",
     "allmessagescurrent": "Şimdi qullanılğan metin",
-    "allmessagestext": "İşbu cedvel MediaWikide mevcut olğan bütün sistema beyanatlarınıñ cedvelidir.\nMediaWiki interfeysiniñ çeşit tillerge tercime etüvde iştirak etmege isteseñiz [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] ve [//translatewiki.net translatewiki.net] saifelerine ziyaret etiñiz.",
+    "allmessagestext": "İşbu cedvel MediaWikide mevcut olğan bütün sistema beyanatlarınıñ cedvelidir.\nMediaWiki interfeysiniñ çeşit tillerge tercime etüvde iştirak etmege isteseñiz [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] ve [//translatewiki.net translatewiki.net] saifelerine ziyaret etiñiz.",
     "thumbnail-more": "Büyüt",
     "filemissing": "Fayl tapılmadı",
     "thumbnail_error": "Kiçik resim (thumbnail) yaratılğanda bir hata çıqtı: $1",
     "seconds-abbrev": "$1san.",
     "minutes-abbrev": "$1daq.",
     "hours-abbrev": "$1saat",
-    "bad_image_list": "Format böyle olmalı:\n\nEr satır * işaretinen başlamalı. Satırnıñ birinci bağlantısı qоşmağa yasaqlanğan faylğa bağlanmalı.\nŞu satırda ilerideki bağlantılar istisna olurlar, yani şu saifelerde işbu fayl qullanmaq mümkün.",
+    "bad_image_list": "Format böyle olmalı:\n\nEr satır * işaretinen başlamalı. Satırnıñ birinci bağlantısı qoşmağa yasaqlanğan faylğa bağlanmalı.\nŞu satırda ilerideki bağlantılar istisna olur, yani şu saifelerde işbu fayl qullanmaq mümkün.",
     "metadata": "Resim detalleri",
-    "metadata-help": "Faylda (adetince raqamlı kamera ve skanerlernen qоşulğan) ilâve malümatı bar. Eger bu fayl yaratılğandan soñ deñiştirilse edi, belki de bazı parametrler eskirdi.",
+    "metadata-help": "Faylda (adetince raqamlı kamera ve skanerlernen qoşulğan) ilâve malümatı bar. Eger bu fayl yaratılğandan soñ deñiştirilse edi, belki de bazı parametrler eskirdi.",
     "metadata-expand": "Tafsilâtnı köster",
     "metadata-collapse": "Tafsilâtnı kösterme",
     "metadata-fields": "Bu cedveldeki EXIF meta malümatı resim saifesinde kösterilecek, başqaları ise gizlenecek.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
     "namespacesall": "Episi",
     "monthsall": "Episi",
     "confirmemail": "E-mail adresini tasdıqla",
-    "confirmemail_noemail": "[[Special:Preferences|Qullanıcı sazlamalarıñızda]] dоğru bir e-mail adresiñiz yoq.",
+    "confirmemail_noemail": "[[Special:Preferences|Qullanıcı sazlamalarıñızda]] doğru bir e-mail adresiñiz yoq.",
     "confirmemail_text": "{{SITENAME}} saytınıñ e-mail funktsiyalarını qullanmazdan evel e-mail adresiñizniñ tasdıqlanması kerek. Adresiñizge tasdıq e-mail mektübini yollamaq içün aşağıdaki dögmeni basıñız. Yollanacaq beyanatta adresiñizni tasdıqlamaq içün brauzeriñiznen irişip olacaq, tasdıq kodu olğan bir bağlantı olacaq.",
     "confirmemail_pending": "Tasdıq kodu endi sizge yollandı.\nEger esabıñıznı keçenleri açsa ediñiz, belki de yañnı kodnı bir daa sorağanıñızda, biraz beklemek kerek olur.",
     "confirmemail_send": "Tasdıq kodunı yolla",
     "fileduplicatesearch-filename": "Fayl adı:",
     "fileduplicatesearch-submit": "Qıdır",
     "fileduplicatesearch-info": "$1 × $2 piksel<br />Fayl büyükligi: $3<br />MIME çeşiti: $4",
-    "fileduplicatesearch-result-1": "\"$1\" faylınıñ iç kоpiyası yоq.",
-    "fileduplicatesearch-result-n": "\"$1\" faylınıñ {{PLURAL:$2|bir kоpiyası|$2 kоpiyası}} bar.",
+    "fileduplicatesearch-result-1": "\"$1\" faylınıñ iç kopiyası yoq.",
+    "fileduplicatesearch-result-n": "\"$1\" faylınıñ {{PLURAL:$2|bir kopiyası|$2 kopiyası}} bar.",
     "specialpages": "Mahsus saifeler",
     "specialpages-group-maintenance": "Baqım esabatları",
     "specialpages-group-other": "Diger mahsus saifeler",
     "specialpages-group-changes": "Soñki deñişiklikler ve jurnallar",
     "specialpages-group-media": "Fayl esabatları ve yükleme",
     "specialpages-group-users": "Qullanıcılar ve aqları",
-    "specialpages-group-highuse": "Çоq qullanılğan saifeler",
+    "specialpages-group-highuse": "Çoq qullanılğan saifeler",
     "specialpages-group-pages": "Saifeler cedveli",
     "specialpages-group-pagetools": "Saife aletleri",
     "specialpages-group-wiki": "Viki malümat ve aletler",
     "specialpages-group-redirects": "Yollama mahsus saifeler",
     "specialpages-group-spam": "Spamğa qarşı aletler",
-    "blankpage": "Bоş saife",
+    "blankpage": "Boş saife",
     "intentionallyblankpage": "Bu saife aselet boş qaldırılğan",
     "comparepages": "Saifelerni teñeştirüv",
     "compare-submit": "Teñeştir",
index d44af39..ecc7b36 100644 (file)
@@ -1,6 +1,32 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "Chmee2",
+            "Danny B.",
+            "DemonioCZ",
+            "Geitost",
+            "Helix84",
+            "Jezevec",
+            "Jkjk",
+            "Kaganer",
+            "Kuvaly",
+            "Li-sung",
+            "Littledogboy",
+            "Martin Kozák",
+            "Matěj Grabovský",
+            "Matěj Suchánek",
+            "Mercy",
+            "Michawiki",
+            "Mormegil",
+            "Mr. Richard Bolla",
+            "Paxt",
+            "Quinn",
+            "Reaperman",
+            "Utar",
+            "Vks",
+            "YjM",
+            "לערי ריינהארט"
+        ]
     },
     "tog-underline": "Podtrhávat odkazy:",
     "tog-hideminor": "Skrýt malé editace v posledních změnách",
@@ -17,7 +43,7 @@
     "tog-watchdefault": "Přidávat mnou editované stránky a soubory ke sledovaným",
     "tog-watchmoves": "Přidávat mnou přesouvané stránky a soubory mezi sledované",
     "tog-watchdeletion": "Přidávat stránky a soubory, které smažu, mezi sledované",
-    "tog-minordefault": "Označit editaci implicitně jako malá editace",
+    "tog-minordefault": "Označit editace implicitně jako malé editace",
     "tog-previewontop": "Zobrazovat náhled před editačním oknem (ne za ním)",
     "tog-previewonfirst": "Zobrazit při první editaci náhled",
     "tog-enotifwatchlistpages": "Poslat e-mail při změně sledované stránky nebo souboru",
     "pool-timeout": "Při čekání na zámek vypršel časový limit",
     "pool-queuefull": "Fronta ve fondu je plná",
     "pool-errorunknown": "Neznámá chyba",
+    "pool-servererror": "Služba řídící přístup k serverům není dostupná ($1).",
     "aboutsite": "O&nbsp;{{grammar:6sg|{{SITENAME}}}}",
     "aboutpage": "Project:{{SITENAME}}",
     "copyright": "Obsah je dostupný pod $1, pokud není uvedeno jinak.",
     "prefs-skin": "Vzhled",
     "skin-preview": "Náhled",
     "datedefault": "Implicitní",
-    "prefs-beta": "Funkce z betaverze",
     "prefs-datetime": "Datum a čas",
     "prefs-labs": "Funkce z Labs",
     "prefs-user-pages": "Uživatelské stránky",
     "listgrouprights-removegroup-self": "Vyřazení svého účtu ze {{PLURAL:$2|skupiny|skupin}} $1",
     "listgrouprights-addgroup-self-all": "Přidání svého účtu do libovolné skupiny",
     "listgrouprights-removegroup-self-all": "Vyřazení svého účtu z libovolné skupiny",
+    "trackingcategories": "Sledovací kategorie",
+    "trackingcategories-summary": "Tato stránka obsahuje seznam sledovacích kategorií, které automaticky přidává software MediaWiki. Jejich jména lze změnit úpravou příslušných systémových hlášení ve jmenném prostoru {{ns:8}}.",
+    "trackingcategories-msg": "Sledovací kategorie",
+    "trackingcategories-name": "Název hlášení",
+    "trackingcategories-desc": "Kritéria pro vložení do kategorie",
+    "noindex-category-desc": "Stránka obsahuje kouzelné slovo <nowiki>__NOINDEX__</nowiki> (a je ve jmenném prostoru, ve kterém je tento příznak dovolen), takže není indexována roboty.",
+    "index-category-desc": "Stránka obsahuje kouzelné slovo <nowiki>__INDEX__</nowiki> (a je ve jmenném prostoru, ve kterém je tento příznak dovolen), takže je indexována roboty, přestože by normálně nebyla.",
+    "post-expand-template-inclusion-category-desc": "Po rozbalení všech šablon je stránka větší než $wgMaxArticleSize, takže některé šablony rozbaleny nebyly.",
+    "post-expand-template-argument-category-desc": "Po rozbalení argumentu šablony (něco v trojitých závorkách, např. {{{Foo}}}) je stránka větší než $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "Na stránce je použito příliš mnoho náročných funkcí parseru (jako <code>#ifexist</code>). Vizte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Kategorie přidaná pokud stránka obsahuje nefunkční odkaz na soubor (odkaz pro vložení souboru, který neexistuje).",
+    "hidden-category-category-desc": "Toto je kategorie, která obsahuje <nowiki>__HIDDENCAT__</nowiki>, což způsobuje, že se na stránkách implicitně nezobrazuje v rámečku odkazů na kategorie.",
+    "trackingcategories-nodesc": "Popis není k dispozici.",
+    "trackingcategories-disabled": "Kategorie je vypnuta",
     "mailnologin": "Bez odesílací adresy",
     "mailnologintext": "Pokud chcete posílat e-maily jiným uživatelům, musíte se [[Special:UserLogin|přihlásit]] a mít platnou e-mailovou adresu ve svém [[Special:Preferences|nastavení]].",
     "emailuser": "Poslat e-mail",
     "nowatchlist": "Na svém seznamu sledovaných stránek nemáte žádné položky.",
     "watchlistanontext": "Pro prohlížení či úpravu seznamu sledovaných stránek se musíte $1.",
     "watchnologin": "Nejste přihlášen(a)",
-    "watchnologintext": "Pro sledování stránek se musíte [[Special:UserLogin|přihlásit]].",
     "addwatch": "Přidat do sledovaných stránek",
     "addedwatchtext": "Stránka „[[:$1]]“ byla přidána mezi stránky, které sledujete.\nVe [[Special:Watchlist|sledovaných stránkách]] se tak budou objevovat budoucí změny této stránky a přidružené diskuse.",
     "removewatch": "Vyřadit ze sledovaných stránek",
     "sp-contributions-newbies-sub": "Noví uživatelé",
     "sp-contributions-newbies-title": "Příspěvky nových uživatelů",
     "sp-contributions-blocklog": "kniha zablokování",
+    "sp-contributions-suppresslog": "utajené příspěvky uživatele",
     "sp-contributions-deleted": "smazané editace uživatele",
     "sp-contributions-uploads": "načtené soubory",
     "sp-contributions-logs": "protokolovací záznamy",
     "sp-contributions-blocked-notice": "Tento uživatel je momentálně zablokován. Zde je pro přehled zobrazen nejnovější záznam z knihy zablokování:",
     "sp-contributions-blocked-notice-anon": "Tato IP adresa je momentálně zablokována.\nZde je pro přehled zobrazen nejnovější záznam z knihy zablokování:",
     "sp-contributions-search": "Zobrazení příspěvků",
-    "sp-contributions-suppresslog": "utajené příspěvky uživatele",
     "sp-contributions-username": "IP adresa nebo uživatelské jméno:",
     "sp-contributions-toponly": "Zobrazit pouze editace na aktuální revizi",
     "sp-contributions-newonly": "Zobrazovat pouze editace zakládající stránku",
     "allmessagesname": "Označení hlášení",
     "allmessagesdefault": "Původní text",
     "allmessagescurrent": "Aktuální text",
-    "allmessagestext": "Toto je seznam všech hlášení dostupných ve jmenném prostoru MediaWiki.\nPokud si přejete přispívat k lokalizaci softwaru MediaWiki, navštivte [https://www.mediawiki.org/wiki/Localisation lokalizační stránku na mediawiki.org] a [//translatewiki.net server translatewiki.net].",
+    "allmessagestext": "Toto je seznam všech hlášení dostupných ve jmenném prostoru MediaWiki.\nPokud si přejete přispívat k lokalizaci softwaru MediaWiki, navštivte [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation lokalizační stránku na mediawiki.org] a [//translatewiki.net server translatewiki.net].",
     "allmessagesnotsupportedDB": "{{ns:special}}:AllMessages není podporováno, neboť wgUseDatabaseMessages je vypnuto.",
     "allmessages-filter-legend": "Filtr",
     "allmessages-filter": "Filtr podle stavu:",
     "group-bot.css": "/* Zde uvedené CSS bude ovlivňovat pouze boty */",
     "group-sysop.css": "/* Zde uvedené CSS bude ovlivňovat pouze správce */",
     "group-bureaucrat.css": "/* Zde uvedené CSS bude ovlivňovat pouze byrokraty */",
-    "common.js": "/* Zde uvedený JavaScript bude použit pro všechny uživatele při načtení každé stránky.  */",
+    "common.js": "/* Zde uvedený JavaScript bude použit pro všechny uživatele při načtení každé stránky. */",
     "cologneblue.js": "/* JavaScript pro uživatele používající vzhled „Kolínská modř“  */",
     "monobook.js": "/* JavaScript pro uživatele používající vzhled MonoBook */",
     "modern.js": "/* JavaScript pro uživatele používající vzhled „Moderní“ */",
     "version-entrypoints": "URL vstupních bodů",
     "version-entrypoints-header-entrypoint": "Vstupní bod",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Cesta k článkům]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Cesta ke skriptům]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Cesta k článkům]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Cesta ke skriptům]",
     "redirect": "Přesměrování podle souboru, uživatele, stránky nebo ID revize",
     "redirect-legend": "Přesměrování na soubor či stránku",
     "redirect-summary": "Tato speciální stránka přesměrovává na soubor (podle názvu), stránku (podle ID stránky nebo revize) nebo uživatele (podle číselného uživatelského ID). Použití: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] nebo [[{{#Special:Redirect}}/user/101]].",
     "expand_templates_remove_nowiki": "Potlačit ve výsledku značky <nowiki>",
     "expand_templates_generate_xml": "Zobrazit syntaktický strom v XML",
     "expand_templates_generate_rawhtml": "Zobrazit surové HTML",
-    "expand_templates_preview": "Náhled",
-    "trackingcategories": "Sledovací kategorie",
-    "trackingcategories-summary": "Tato stránka obsahuje seznam sledovacích kategorií, které automaticky přidává software MediaWiki. Jejich jména lze změnit úpravou příslušných systémových hlášení ve jmenném prostoru {{ns:8}}.",
-    "trackingcategories-msg": "Sledovací kategorie",
-    "trackingcategories-name": "Název hlášení",
-    "trackingcategories-desc": "Kritéria pro vložení do kategorie",
-    "noindex-category-desc": "Stránka obsahuje kouzelné slovo <nowiki>__NOINDEX__</nowiki> (a je ve jmenném prostoru, ve kterém je tento příznak dovolen), takže není indexována roboty.",
-    "index-category-desc": "Stránka obsahuje kouzelné slovo <nowiki>__INDEX__</nowiki> (a je ve jmenném prostoru, ve kterém je tento příznak dovolen), takže je indexována roboty, přestože by normálně nebyla.",
-    "post-expand-template-inclusion-category-desc": "Po rozbalení všech šablon je stránka větší než $wgMaxArticleSize, takže některé šablony rozbaleny nebyly.",
-    "post-expand-template-argument-category-desc": "Po rozbalení argumentu šablony (něco v trojitých závorkách, např. {{{Foo}}}) je stránka větší než $wgMaxArticleSize.",
-    "expensive-parserfunction-category-desc": "Na stránce je použito příliš mnoho náročných funkcí parseru (jako #ifexists). Vizte [https://www.mediawiki.org/wiki/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-    "broken-file-category-desc": "Kategorie přidaná pokud stránka obsahuje nefunkční odkaz na soubor (odkaz pro vložení souboru, který neexistuje).",
-    "hidden-category-category-desc": "Toto je kategorie, která obsahuje <nowiki>__HIDDENCAT__</nowiki>, což způsobuje, že se na stránkách implicitně nezobrazuje v rámečku odkazů na kategorie.",
-    "trackingcategories-nodesc": "Popis není k dispozici.",
-    "trackingcategories-disabled": "Kategorie je vypnuta"
+    "expand_templates_preview": "Náhled"
 }
index 745ab42..b4ea12e 100644 (file)
     "allmessagesname": "Miono",
     "allmessagesdefault": "Domëslny tekst",
     "allmessagescurrent": "Aktualny tekst",
-    "allmessagestext": "To je zestôwk systemòwëch ògłosów przistãpnëch w rumie mionów MediaWiki.\nProszã zazdrzë na [https://www.mediawiki.org/wiki/Localisation Lokalizacëjô MediaWiki] ë [//translatewiki.net translatewiki.net] jeżlë chcesz dolmaczëc softwôrã MediaWiki.",
+    "allmessagestext": "To je zestôwk systemòwëch ògłosów przistãpnëch w rumie mionów MediaWiki.\nProszã zazdrzë na [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Lokalizacëjô MediaWiki] ë [//translatewiki.net translatewiki.net] jeżlë chcesz dolmaczëc softwôrã MediaWiki.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:Allmessages''' nie mòże bëc brëkòwónô, temù że '''$wgUseDatabaseMessages''' je wëłączony.",
     "thumbnail-more": "Zwiszi",
     "import": "Impòrtëjë starnë",
index b37f41a..3d5a736 100644 (file)
     "prefs-skin": "Gwedd",
     "skin-preview": "Rhagolwg",
     "datedefault": "Dim dewisiad",
-    "prefs-beta": "Nodweddion Beta",
     "prefs-datetime": "Dyddiad ac amser",
     "prefs-labs": "Nodweddion Labs",
     "prefs-user-pages": "Tudalennau defnyddwyr",
     "nowatchlist": "Mae eich rhestr wylio'n wag.",
     "watchlistanontext": "Rhaid $1 er mwyn gweld neu ddiwygio'ch rhestr wylio.",
     "watchnologin": "Nid ydych wedi mewngofnodi",
-    "watchnologintext": "Mae'n rhaid i chi [[Special:UserLogin|fewngofnodi]] er mwyn newid eich rhestr wylio.",
     "addwatch": "Ychwanegu at y rhestr wylio",
     "addedwatchtext": "Mae'r dudalen \"[[:$1|$1]]\" wedi cael ei hychwanegu at eich [[Special:Watchlist|rhestr wylio]].\nPan fydd y dudalen hon, neu ei thudalen sgwrs, yn newid, fe fyddant yn ymddangos ar y rhestr honno.",
     "removewatch": "Tynnu oddi ar eich rhestr wylio",
     "allmessagesname": "Enw",
     "allmessagesdefault": "Testun rhagosodedig",
     "allmessagescurrent": "Testun cyfredol",
-    "allmessagestext": "Dyma restr o'r holl negeseuon yn y parth MediaWici.\nOs ydych am gyfrannu at y gwaith o gyfieithu ar gyfer holl prosiectau MediaWiki ar y cyd, mae croeso i chi ymweld â [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] a [//translatewiki.net translatewiki.net].",
+    "allmessagestext": "Dyma restr o'r holl negeseuon yn y parth MediaWici.\nOs ydych am gyfrannu at y gwaith o gyfieithu ar gyfer holl prosiectau MediaWiki ar y cyd, mae croeso i chi ymweld â [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] a [//translatewiki.net translatewiki.net].",
     "allmessagesnotsupportedDB": "Nid yw '''{{ns:special}}:PobNeges''' yn cael ei gynnal gan fod '''$wgUseDatabaseMessages''' wedi ei ddiffodd.",
     "allmessages-filter-legend": "Hidl",
     "allmessages-filter": "Hidlo yn ôl eu cyflwr addasu:",
index 25293de..6ed6759 100644 (file)
     "prefs-skin": "Udseende",
     "skin-preview": "Forhåndsvisning",
     "datedefault": "Standard",
-    "prefs-beta": "Betafunktioner",
     "prefs-datetime": "Dato og klokkeslæt",
     "prefs-labs": "Testfunktioner",
     "prefs-user-pages": "Brugerside",
     "nowatchlist": "Du har ingenting i din overvågningsliste.",
     "watchlistanontext": "Du skal $1, for at se din overvågningsliste eller ændre indholdet af den.",
     "watchnologin": "Ikke logget på",
-    "watchnologintext": "Du skal være [[Special:UserLogin|logget på]] for at kunne ændre din overvågningsliste.",
     "addwatch": "Tilføj til overvågningsliste",
     "addedwatchtext": "Siden \"[[:$1]]\" er blevet tilføjet til din [[Special:Watchlist|overvågningsliste]].\nFremtidige ændringer af denne side og dens tilknyttede diskussionsside vil blive vist der.",
     "removewatch": "Fjern fra overvågningsliste",
     "sp-contributions-newbies-sub": "Fra nye kontoer",
     "sp-contributions-newbies-title": "Brugerbidrag fra nye konti",
     "sp-contributions-blocklog": "blokeringslog",
+    "sp-contributions-suppresslog": "undertrykte brugerbidrag",
     "sp-contributions-deleted": "slettede brugerbidrag",
     "sp-contributions-uploads": "uploads",
     "sp-contributions-logs": "loglister",
     "sp-contributions-blocked-notice": "Denne bruger er i øjeblikket blokeret. Loggen over den seneste blokering kan ses nedenfor:",
     "sp-contributions-blocked-notice-anon": "Denne IP-adresse er i øjeblikket blokeret.\nDen seneste post i blokeringsloggen vises nedenfor:",
     "sp-contributions-search": "Søg efter bidrag",
-    "sp-contributions-suppresslog": "undertrykte brugerbidrag",
     "sp-contributions-username": "IP-adresse eller brugernavn:",
     "sp-contributions-toponly": "Vis kun redigeringer, der er aktuelle versioner",
     "sp-contributions-newonly": "Vis kun redigeringer, der er sideoprettelser",
     "allmessagesname": "Navn",
     "allmessagesdefault": "Standardtekst",
     "allmessagescurrent": "Nuværende tekst",
-    "allmessagestext": "Dette er en liste med alle systembeskeder i MediaWiki-navnerummet.\nBesøg venligst [https://www.mediawiki.org/wiki/Localisation MediaWiki-lokalisering] og [//translatewiki.net translatewiki.net] hvis du ønsker at bidrage til den generelle lokalisering (oversættelse og andre lokale tilpasninger) af MediaWiki.",
+    "allmessagestext": "Dette er en liste med alle systembeskeder i MediaWiki-navnerummet.\nBesøg venligst [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki-lokalisering] og [//translatewiki.net translatewiki.net] hvis du ønsker at bidrage til den generelle lokalisering (oversættelse og andre lokale tilpasninger) af MediaWiki.",
     "allmessagesnotsupportedDB": "{{ns:special}}:AllMessages ikke understøttet fordi wgUseDatabaseMessages er slået fra.",
     "allmessages-filter-legend": "Filtrér",
     "allmessages-filter": "Filtrér efter tilpasningsstatus:",
index b8c6932..e36c757 100644 (file)
     "pool-timeout": "Zeitablauf während des Wartens auf die Sperrung",
     "pool-queuefull": "Poolwarteschlange ist voll",
     "pool-errorunknown": "Unbekannter Fehler",
+    "pool-servererror": "Der Poolzählerdienst ist nicht verfügbar ($1).",
     "aboutsite": "Über {{SITENAME}}",
     "aboutpage": "Project:Über_{{SITENAME}}",
     "copyright": "Der Inhalt ist verfügbar unter der Lizenz $1, sofern nicht anders angegeben.",
     "prefs-skin": "Benutzeroberfläche",
     "skin-preview": "Vorschau",
     "datedefault": "Standard",
-    "prefs-beta": "Beta-Funktionen",
     "prefs-datetime": "Datum und Zeit",
     "prefs-labs": "Alpha-Funktionen",
     "prefs-user-pages": "Benutzerseiten",
     "listgrouprights-removegroup-self": "Eigenes Benutzerkonto aus {{PLURAL:$2|dieser Gruppe|diesen Gruppen}} entfernen: $1",
     "listgrouprights-addgroup-self-all": "Kann alle Gruppen zum eigenen Konto hinzufügen",
     "listgrouprights-removegroup-self-all": "Kann alle Gruppen vom eigenen Konto entfernen",
+    "trackingcategories": "Tracking-Kategorien",
+    "trackingcategories-summary": "Diese Seite listet Tracking-Kategorien auf, die von der MediaWiki-Software automatisch eingepflegt werden. Ihre Namen können durch Änderung der entsprechenden Systemnachrichten im {{ns:8}}-Namensraum angepasst werden.",
+    "trackingcategories-msg": "Tracking-Kategorie",
+    "trackingcategories-name": "Name der Nachricht",
+    "trackingcategories-desc": "Kategorieeinbindungskriterien",
+    "noindex-category-desc": "Die Seite hat das magische Wort <nowiki>__NOINDEX__</nowiki> und befindet sich in einem Namensraum, wo dieses Flag erlaubt ist und wird daher nicht von Bots indexiert.",
+    "index-category-desc": "Die Seite enthält ein <nowiki>__INDEX__</nowiki> und befindet sich in einem Namensraum, in dem dieses Flag nicht erlaubt ist und wird daher von Bots ausnahmsweise indexiert.",
+    "post-expand-template-inclusion-category-desc": "Nach dem Expandieren aller Vorlagen ist die Seitengröße größer als $wgMaxArticleSize, sodass einige Vorlagen nicht expandiert werden.",
+    "post-expand-template-argument-category-desc": "Nach dem Expandieren eines Vorlagenargumentes (etwas in dreifach geschweiften Klammern, z.&nbsp;B. {{{Foo}}}) ist die Seite größer als $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "Zu viele aufwändige Parserfunktionen (wie <code>#ifexist</code>) sind in der Seite eingebunden. Siehe das [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Benutzerhandbuch].",
+    "broken-file-category-desc": "Kategorie, die hinzugefügt wird, falls die Seite einen defekten Dateilink enthält (einen Link zu einer eingebetteten Datei, die nicht vorhanden ist).",
+    "hidden-category-category-desc": "Dies ist eine Kategorie mit <nowiki>__HIDDENCAT__</nowiki>, die standardmäßig nicht auf Seiten im Kategorienbereich angezeigt wird.",
+    "trackingcategories-nodesc": "Keine Beschreibung verfügbar.",
+    "trackingcategories-disabled": "Kategorie ist deaktiviert",
     "mailnologin": "Fehler beim E-Mail-Versand",
     "mailnologintext": "Du musst [[Special:UserLogin|angemeldet sein]] und eine bestätigte E-Mail-Adresse in deinen [[Special:Preferences|Einstellungen]] eingetragen haben, um anderen Benutzern E-Mails schicken zu können.",
     "emailuser": "E-Mail an diesen Benutzer",
     "nowatchlist": "Es befinden sich keine Einträge auf deiner Beobachtungsliste.",
     "watchlistanontext": "Du musst dich $1, um deine Beobachtungsliste sehen oder Einträge auf ihr bearbeiten zu können.",
     "watchnologin": "Du bist nicht angemeldet",
-    "watchnologintext": "Du musst [[Special:UserLogin|angemeldet]] sein, um deine Beobachtungsliste bearbeiten zu können.",
     "addwatch": "Zur Beobachtungsliste hinzufügen",
     "addedwatchtext": "Die Seite „[[:$1]]“ wurde zu deiner [[Special:Watchlist|Beobachtungsliste]] hinzugefügt.\nSpätere Änderungen an dieser Seite und der zugehörigen Diskussionsseite werden dort gelistet.",
     "removewatch": "Von der Beobachtungsliste entfernen",
     "sp-contributions-newbies-sub": "Von neuen Benutzern",
     "sp-contributions-newbies-title": "Benutzerbeiträge von neuen Benutzern",
     "sp-contributions-blocklog": "Sperr-Logbuch",
+    "sp-contributions-suppresslog": "Unterdrückte Benutzerbeiträge",
     "sp-contributions-deleted": "Gelöschte Beiträge",
     "sp-contributions-uploads": "Hochgeladene Dateien",
     "sp-contributions-logs": "Logbücher",
     "sp-contributions-blocked-notice": "{{GENDER:$1|Dieser Benutzer|Diese Benutzerin|Dieser Benutzer}} ist derzeit gesperrt. Es folgt der aktuelle Eintrag aus dem Benutzersperr-Logbuch:",
     "sp-contributions-blocked-notice-anon": "Diese IP-Adresse ist zurzeit gesperrt.\nZur Information folgt der aktuelle Auszug aus dem Sperr-Logbuch:",
     "sp-contributions-search": "Suche nach Benutzerbeiträgen",
-    "sp-contributions-suppresslog": "Unterdrückte Benutzerbeiträge",
     "sp-contributions-username": "IP-Adresse oder Benutzername:",
     "sp-contributions-toponly": "Nur aktuelle Versionen zeigen",
     "sp-contributions-newonly": "Nur Seitenerstellungen anzeigen",
     "allmessagesname": "Name",
     "allmessagesdefault": "Standardtext",
     "allmessagescurrent": "Aktueller Text",
-    "allmessagestext": "Dies ist eine Liste der MediaWiki-Systemtexte.\nBitte besuche die Seiten [https://www.mediawiki.org/wiki/Localisation MediaWiki-Lokalisierung] und [//translatewiki.net translatewiki.net], sofern du dich an der Lokalisierung von MediaWiki beteiligen möchtest.",
+    "allmessagestext": "Dies ist eine Liste der MediaWiki-Systemtexte.\nBitte besuche die Seiten [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki-Lokalisierung] und [//translatewiki.net translatewiki.net], sofern du dich an der Lokalisierung von MediaWiki beteiligen möchtest.",
     "allmessagesnotsupportedDB": "Diese Spezialseite steht nicht zur Verfügung, da sie über den Parameter <tt>$wgUseDatabaseMessages</tt> deaktiviert wurde.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filter für angepassten Zustand:",
     "version-entrypoints": "URLs der Einstiegspunkte",
     "version-entrypoints-header-entrypoint": "Einstiegspunkt",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Artikelpfad]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Skriptpfad]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Artikelpfad]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Skriptpfad]",
     "redirect": "Weiterleitung auf Benutzerseite, Seite, Seitenversion oder Datei",
     "redirect-legend": "Weiterleitung auf eine Benutzerseite, Seite, Seitenversion oder Datei",
     "redirect-summary": "Diese Spezialseite leitet auf eine Benutzerseite (numerische Benutzerkennung angegeben), Seite (Seitenkennung angegeben), Seitenversion (Versionskennung angegeben) oder Datei (Dateiname angegeben) weiter. Benutzung: [[{{#Special:Redirect}}/user/101]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] oder [[{{#Special:Redirect}}/file/Example.jpg]].",
     "expand_templates_remove_nowiki": "<nowiki>-Tags in der Ausgabe unterdrücken",
     "expand_templates_generate_xml": "XML-Parser-Baum zeigen",
     "expand_templates_generate_rawhtml": "Rohes HTML anzeigen",
-    "expand_templates_preview": "Vorschau",
-    "trackingcategories": "Tracking-Kategorien",
-    "trackingcategories-summary": "Diese Seite listet Tracking-Kategorien auf, die von der MediaWiki-Software automatisch eingepflegt werden. Ihre Namen können durch Änderung der entsprechenden Systemnachrichten im {{ns:8}}-Namensraum angepasst werden.",
-    "trackingcategories-msg": "Tracking-Kategorie",
-    "trackingcategories-name": "Name der Nachricht",
-    "trackingcategories-desc": "Kategorieeinbindungskriterien",
-    "noindex-category-desc": "Die Seite hat das magische Wort <nowiki>__NOINDEX__</nowiki> und befindet sich in einem Namensraum, wo dieses Flag erlaubt ist und wird daher nicht von Bots indexiert.",
-    "index-category-desc": "Die Seite enthält ein <nowiki>__INDEX__</nowiki> und befindet sich in einem Namensraum, in dem dieses Flag nicht erlaubt ist und wird daher von Bots ausnahmsweise indexiert.",
-    "post-expand-template-inclusion-category-desc": "Nach dem Expandieren aller Vorlagen ist die Seitengröße größer als $wgMaxArticleSize, sodass einige Vorlagen nicht expandiert werden.",
-    "post-expand-template-argument-category-desc": "Nach dem Expandieren eines Vorlagenargumentes (etwas in dreifach geschweiften Klammern, z.&nbsp;B. {{{Foo}}}) ist die Seite größer als $wgMaxArticleSize.",
-    "expensive-parserfunction-category-desc": "Zu viele aufwändige Parserfunktionen (wie #ifexists) sind in der Seite eingebunden. Siehe das [https://www.mediawiki.org/wiki/Manual:$wgExpensiveParserFunctionLimit Benutzerhandbuch].",
-    "broken-file-category-desc": "Kategorie, die hinzugefügt wird, falls die Seite einen defekten Dateilink enthält (einen Link zu einer eingebetteten Datei, die nicht vorhanden ist).",
-    "hidden-category-category-desc": "Dies ist eine Kategorie mit <nowiki>__HIDDENCAT__</nowiki>, die standardmäßig nicht auf Seiten im Kategorienbereich angezeigt wird.",
-    "trackingcategories-nodesc": "Keine Beschreibung verfügbar.",
-    "trackingcategories-disabled": "Kategorie ist deaktiviert"
+    "expand_templates_preview": "Vorschau"
 }
index de5c9c3..32bd957 100644 (file)
@@ -16,7 +16,9 @@
             "Olvörg",
             "Reedy",
             "Sahim",
-            "Xoser"
+            "Xoser",
+            "Geitost",
+            "Microchip08"
         ]
     },
     "tog-underline": "Bınê gırey de xete bance:",
     "media_tip": "Gıreyê dosya",
     "sig_tip": "İmzay şıma be morê zemani",
     "hr_tip": "Xeta verardiye (teserrufın bıgureyne/bıxebetne)",
-    "summary": "<font style=\"color:Blue\">'''Xulasa:'''</font>",
+    "summary": "Xulasa:",
     "subject": "Mewzu/sernuşte:",
     "minoredit": "No vırnayışê do werdiyo",
     "watchthis": "'''Ena pele seyr ke'''",
     "session_fail_preview_html": "'''Ma meluli! Sebayê vindbiyayişê datasistemi ma vurnayişê şıma nêeşkeni qaydker.'''\n\n''Çunke keyepelê {{SITENAME}} de raw HTML aqtifo, seyrkerdışê verqayd semedê galayê (alızyayiş) JavaScript ri nımıyayo.''\n\n'''Eke no vurnayiş heqê şımayo, newe ra tesel bıker (bıcerebi). eke hona zi nêxebıtya, [[Special:UserLogout|vec]] newe ra hesabê xo aker.'''",
     "token_suffix_mismatch": "'''Vurnayişê şıma tepeya ameyo çunke qutiyê imla xerıbya.\nVurnayişê şıma qey nêxerepyayişê peli tepeya geyra a.\nEke şıma servisê proksi yo anonim şuxulneni sebebê ey noyo.'''",
     "edit_form_incomplete": "'''Qandê form dê vurnayışa tay wastera ma nêreşti; Vurnayışê ke şıma kerdê nêalızyayê, çım ra ravyarnê u fına bıcerbnê.'''",
-    "editing": "Şımayê <font style=\"color:red\">$1</font> vurnenê",
-    "creating": "Pela <font style=\"color:blue\">$1</font> vırazê",
+    "editing": "Şımayê $1 vurnenê",
+    "creating": "Pela $1 vırazê",
     "editingsection": "Per da $1 de şımaye kenê ke leti bıvurnê",
     "editingcomment": "$1 vuryeno (qısmo newe)",
     "editconflict": "Vurnayişê ke yewbini nêtepışeni: $1",
     "log-fulllog": "Temamê rocaneyi bıvine",
     "edit-hook-aborted": "Vurnayiş vınderiya.\nYew sebeb beyan nibı.",
     "edit-gone-missing": "Pel rocanebiyaye niyo.\nHewna kerde aseno.",
-    "edit-conflict": "Vurnayişê pêverdiyaye .",
+    "edit-conflict": "Vurnayişê pêverdiyaye.",
     "edit-no-change": "Vurnayişê şıma qebul nêbı, çunke nuşte de yew vurnayiş n3evıraziya.",
     "postedit-confirmation": "Vurnayışê to qeyd bi.",
     "edit-already-exists": "Pelo newe nêvıraziyeno.\nPel ca ra esto.",
     "prefs-skin": "Çerme",
     "skin-preview": "Verasayış",
     "datedefault": "Tercih çıniyo",
-    "prefs-beta": "Hacetê beta",
     "prefs-datetime": "Tarix u wext",
     "prefs-labs": "Xacetê labs",
     "prefs-user-pages": "Pela Karberi",
     "nowatchlist": "listeya temaşa kerdıişê şıma de yew madde zi çina.",
     "watchlistanontext": "qey vurnayişê maddeya listeya temaşakerdişi $1.",
     "watchnologin": "Şıma cıkewtış nêvıraşto",
-    "watchnologintext": "qey vurnayişê listeya temaşakerdışi [[Special:UserLogin|gani şıma hesab akeri]].",
     "addwatch": "Listeyê seyri deke",
     "addedwatchtext": "Ma pele \"[[:$1]]\" zerri [[Special:Watchlist|watchlist]]ê tı kerd de.\nEna deme ra, ma qe vurnayışan ser ena pele tı haberdar keni.",
     "removewatch": "Listedê mınê seyr kerdışi ra hewad",
     "allmessagesname": "Name",
     "allmessagesdefault": "Metnê mesacê hesabiyayey",
     "allmessagescurrent": "Nuşteyê mesacê rocaney",
-    "allmessagestext": "na liste, listeya mesajê cayê nameyê wikimedya yo.\neke şıma qayili paşt bıdi mahalli kerdışê wikimedyayi, kerem kerê pelê [https://www.mediawiki.org/wiki/Localisation mahalli kerdışê wikimedyayi] u [//translatewiki.net translatewiki.net] ziyaret bıkerê.",
+    "allmessagestext": "na liste, listeya mesajê cayê nameyê wikimedya yo.\neke şıma qayili paşt bıdi mahalli kerdışê wikimedyayi, kerem kerê pelê [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation mahalli kerdışê wikimedyayi] u [//translatewiki.net translatewiki.net] ziyaret bıkerê.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' qefelnaye yo u ey ra '''{{ns:special}}:Allmessages''' karkerdışi re akerde niyo.",
     "allmessages-filter-legend": "Avrêc",
     "allmessages-filter": "goreyê xususi kerdışi re filtre bıker",
     "version-entrypoints": "heruna dekewtış de GRE'i",
     "version-entrypoints-header-entrypoint": "Heruna dekewtışi",
     "version-entrypoints-header-url": "GRE",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Article path]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Script path]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Article path]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Script path]",
     "redirect": "Serşıkıtena dosya, karberi, pele ya ki revizyonê kamiya dosya",
     "redirect-legend": "Hetenayışa dosya yana pela",
     "redirect-summary": "Na pela xase to hetê jû dosya (namey dosya daeyo), jû pele (kamiya revizyoni ya ki pele daiya) ya ki jû pela karberi (kamiya karberia reqemkiye daiya) ser şıknena. Gurenayış: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], ya ki  [[{{#Special:Redirect}}/user/101]].",
     "logentry-rights-rights": "$1 qandê $3 rê ezayiya grube $4 ra $5 {{GENDER:$2|vuriye}}",
     "logentry-rights-rights-legacy": "$1 qandê $3 rê ezayiya grube {{GENDER:$2|vuriye}}",
     "logentry-rights-autopromote": "$1 otomatikmen $4 ra $5 {{GENDER:$2|terfi bi}}",
-    "rightsnone": "(çino)",
+    "rightsnone": "(çıniyo)",
     "feedback-bugornote": "Jew mersela teferruato teknik esta şıma reca malumatê şıma hazıro se [ $1  jew xırab rapor] bıvinê.Zewbi zi, formê cerê xo rê şenê karfiyê. Vatışê xo pela da \"[ $3  $2 ]\", namey karber dê xoya piya u wasteriya karfiye.",
     "feedback-subject": "Mewzu:",
     "feedback-message": "Mesac:",
index 00041bf..421f2c4 100644 (file)
     "prefs-skin": "Šat",
     "skin-preview": "Pśeglěd",
     "datedefault": "Standard",
-    "prefs-beta": "Preizkusne funkcije",
     "prefs-datetime": "Datum a cas",
     "prefs-labs": "Laborowe funkcije",
     "prefs-user-pages": "Wužywarske boki",
     "nowatchlist": "Žedne zapise w twójej wobglědowańce.",
     "watchlistanontext": "Dejš $1, aby mógał swóju wobglědowańku wiźeś abo zapise w njej wobźěłaś.",
     "watchnologin": "Njepśizjawjony(a)",
-    "watchnologintext": "Musyš [[Special:UserLogin|pśizjawjony]] byś, aby mógał swóju wobglědowańku wobźěłaś.",
     "addwatch": "K wobglědowańce dodaś",
     "addedwatchtext": "Bok \"[[:$1]]\" jo se k twójej [[Special:Watchlist|wobglědowańce]] dodał.\nPózdźejšne změny na toś tom boku a w pśisłušecej diskusiji se tam nalicuju.",
     "removewatch": "Z wobglědowańki wulašowaś",
     "sp-contributions-newbies-sub": "Za nowackow",
     "sp-contributions-newbies-title": "Wužywarske pśinoski nowych kontow",
     "sp-contributions-blocklog": "Protokol blokěrowanjow",
+    "sp-contributions-suppresslog": "pódtłocone wužywarske pśinoski",
     "sp-contributions-deleted": "Wulašowane wužywarske pśinoski",
     "sp-contributions-uploads": "nagraśa",
     "sp-contributions-logs": "protokole",
     "sp-contributions-blocked-notice": "Toś ten wužywaŕ jo tuchylu blokěrowany. Nejnowšy zapisk blokěrowańskego protokola pódawa se dołojce ako referenca:",
     "sp-contributions-blocked-notice-anon": "Toś ta IP-adresa jo tuchylu zablokěrowana.\nNejnowšy zapisk protokola blokěrowanjow pódawa se dołojce ako referenca:",
     "sp-contributions-search": "Pśinoski pytaś",
-    "sp-contributions-suppresslog": "pódtłocone wužywarske pśinoski",
     "sp-contributions-username": "IP-adresa abo wužywarske mě:",
     "sp-contributions-toponly": "Jano wuše wersije pokazaś",
     "sp-contributions-newonly": "Jano změny pokazaś, kótarež su napóranja bokow",
     "allmessagesname": "Mě",
     "allmessagesdefault": "Standardny tekst",
     "allmessagescurrent": "Aktualny tekst",
-    "allmessagestext": "How jo lisćina systemowych powěsćow w mjenowem rumje MediaWiki.\nPšosym wobglědaj [https://www.mediawiki.org/wiki/Localisation lokalizaciju MediaWiki] a [//translatewiki.net translatewiki.net], jolic coš k lokalizaciji MediaWiki pśinosowaś.",
+    "allmessagestext": "How jo lisćina systemowych powěsćow w mjenowem rumje MediaWiki.\nPšosym wobglědaj [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation lokalizaciju MediaWiki] a [//translatewiki.net translatewiki.net], jolic coš k lokalizaciji MediaWiki pśinosowaś.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:Allmessages''' njejo tuchylu móžno, dokulaž jo datowa banka offline.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Pó pśiměrjeńskem stawje filtrěrowaś:",
index f136209..d8c7bc5 100644 (file)
@@ -2,7 +2,8 @@
     "@metadata": {
         "authors": [
             "Lévi",
-            "Reder"
+            "Reder",
+            "Geitost"
         ]
     },
     "tog-underline": "Tîra 'na rîga sòta i colegamèint.",
     "pool-timeout": "Tèimp che gh'é da spetêr préma dal sblôch.",
     "pool-queuefull": "A ghé la fîla, trôpa gînta a vōl vèder la pàgina, prōva tra soquânt minût",
     "pool-errorunknown": "Erōr mìa cgnusû",
+    "pool-servererror": "Al servési cuntadōr di pool an n'é mìa léber per èser druvê",
     "aboutsite": "Infurmasiòun só {{SITENAME}}",
     "aboutpage": "Project:Infurmasiòun",
     "copyright": "Còl che gh' é che dèinter a 's pōl druvêr sòta licèinsa $1, s' an gh'é mia scrét diversamèint.",
     "accmailtitle": "Cêva 'd ingrès spidîda.",
     "accmailtext": "'Na cêva 'd ingrés l'è stêda fâta a chêş per [[User talk:$1|$1]] e l'è stêda spidîda a $2. Cla cêva 'd ingrès ché la pōl èser cambiêda int la pàgina per ''[[Special:ChangePassword|cambiêr la cêva 'd ingrès]]'' subét dôp avèir fât l'ingrès.",
     "newarticle": "(Nōv)",
-    "newarticletext": "Al colegamèint apèina fât al cumbîna cun 'na pàgina ch' an n'é mìa incòra stêda fâta. S'ét vō fêr la pàgina adès, l'é asê cumincêr a scréver al tèst int la caşèla ché sòt (per vedèr infurmasiòun pió precîşi guêrda la [$1 pàgina 'd ajót]). Se al colegamèint  l'é stê avêrt per erōr, l'é asê clichêr al pulsânt \"Indrē\" dal tó navigadōr.",
+    "newarticletext": "Al colegamèint apèina fât al cumbîna cun 'na pàgina ch' an n'é mìa incòra stêda fâta. S'ét vō fêr la pàgina adès, l'é asê cumincêr a scréver al tèst int la caşèla ché sòt (per vedèr infurmasiòun pió precîşi guêrda la [{{MediaWiki:Helppage}}| pàgina 'd ajót]). Se al colegamèint  l'é stê avêrt per erōr, l'é asê clichêr al pulsânt \"Indrē\" dal tó navigadōr.",
     "anontalkpagetext": "----'' Còsta l'è la pàgina 'd discusiòun ed 'n utèint sèinsa nòm, ch' an n' à mìa incòra fât 'n' utèinsa o in tót al manēri an n'è mìa drē druvêrla. Per arcgnòsrel l'è dòunca necesâri druvê al só indirés IP. J indirés IP a pōlen èser spartî cun êter utèint. Se t'è un utèint sèinsa nòm e 't pèins che i cumèint in cla pàgina ché an riguêrden mìa tè, [[Special:UserLogin/signup|fa 'n' utèinsa nōva]] o [[Special:UserLogin|vîn dèinter cun còla ch' ét gh'ê bèle]] per schivşêr, in futûr,  'd èser cunfûş cun 'd j êter utèint sèinsa nòm.''",
     "noarticletext": "In cól mumèint ché la pàgina serchêda l'é vōda. L'é pusébil [[Special:Search/{{PAGENAME}}|serchêr sté tétol]] int al j êtri pàgini dal sît, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} serchêr int i regéster coleghê] opór  [{{fullurl:{{FULLPAGENAME}}|action=edit}} mudifichêr la pàgina adèsa]</span>.",
     "noarticletext-nopermission": "In cól mumèint ché la pàgina serchêda l'é vōda. L'é pusébil [[Special:Search/{{PAGENAME}}|serchêr sté tétol]] int al j êtri pàgini dal sît o<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} serchêr int i regéster coleghê] <span>, mó an 't gh'ê mìa al permès ed fêr cla pàgina ché.",
     "log-fulllog": "Guêrda la stòria dal registrasiòun",
     "edit-hook-aborted": "La mudéfica l'é stêda scanşlêda da l' hook.\nAn n'é mìa stê dê nisóna spiegasiòun.",
     "edit-gone-missing": "Impusébil arnuvêr la pàgina. \nA sèmbra ch'la sìa stêda scanşlêda.",
-    "edit-conflict": "Cuntrâst 'd edisiòun",
+    "edit-conflict": "Cuntrâst 'd edisiòun.",
     "edit-no-change": "La mudéfica an n'é mìa stêda cunsidrêda perchè an n'é mìa stê fât di cambiamèint al tèst.",
     "postedit-confirmation": "La mudéfica l'é stêda salvêda.",
     "edit-already-exists": "L'é impusébil fêr 'na pàgina nōva.\nLa ghé bèle.",
     "editpage-notsupportedcontentformat-text": "La fōrma dal scrét in $1 la rispèta mìa al mudèl scrét in $2.",
     "content-model-wikitext": "wikitèst",
     "content-model-text": "tèst normêl",
+    "content-model-javascript": "linguâg JavaScript",
+    "content-model-css": "fòj de stîl CSS",
     "expensive-parserfunction-warning": "'''Atensiòun:''' cla pàgina ché la gh'à trôpi ciamêdi ala funsiòun parse. A n' in duvré avèir mēno 'd $2, adèsa a {{PLURAL:$1|'gh n'é $1}}.",
     "expensive-parserfunction-category": "Pàgini cun trôpi ciamêdi a la funsiòun parser.",
     "post-expand-template-inclusion-warning": "'''Atensiòun:''' la grandèsa di mudē més dèinter l'é trôp grôsa. Soquânt mudē gnirâ mìa més dèinter.",
     "expansion-depth-exceeded-category": "Pàgini 'n dó vî pasê al fònd de şlargamèint",
     "expansion-depth-exceeded-warning": "Cla pàgina ché la pasê al fònd de şlargamèint",
     "parser-unstrip-loop-warning": "Catê sèria 'd Unistrip",
+    "parser-unstrip-recursion-limit": "A s'é pasê i lémit 'd arciâm 'd Unstrip ($1)",
+    "converter-manual-rule-error": "È stê catê un erōr int la règola a mân ed cambiamèint ed la léngua",
+    "undo-success": "Cla mudéfica ché la pō, èser scanşlêda., Cuntròla che sòta al diferèinsi che gh'é tr' al dō versiòun per èser sicûr che còl che gh'é scrét al cumbîna cun còl ch'ét vō, e dòunca salvêr al mudéfici per finîr la scanşladûra.",
+    "undo-failure": "Imposébil scanşlêr la mudéfica a câşva 'd un cuntrâst cun dal mudéfichi fâti dôp.",
+    "undo-norev": "La mudéfica l'an pōl mìa èser scanşlêda perchè l' an gh'é pió o l'é bèle stêda scanşlêda.",
+    "undo-nochange": "A sèmbra che la mudéfica la sìa bèle stêda scanşlêda.",
+    "undo-summary": "Scanşlê la mudéfica $1 ed [[Special:Contributions/$2|$2]]\n([[User talk:$2|discusiòun]])",
+    "undo-summary-username-hidden": "Scanşlê la modéfica $1 ed 'n utèin lughê",
+    "cantcreateaccounttitle": "Impusébil registrêr un utèint",
+    "cantcreateaccount-text": "La registrasiòun ed cl'indirés IP ché ('''$1''') l'é stêda bluchêda da [[User:$3|$3]]. \n\nAl mutîv dal blôch dê da $3 l'é còst: ''$2''.",
+    "cantcreateaccount-range-text": "La registrasiòun da indirés IP int l'intervâl '''$1''', in dó gh'é dèinter al tó  ('''$4'''), l'é stêda bluchêda da [[User:$3|$3]]. \n\nAl mutîv dê da $3 l'é ''$2''",
     "viewpagelogs": "Guêrda la stòria 'd cla pàgina ché",
+    "nohistory": "L'elèinch ed la stôria dal versiòun ed cla pàgina ché an 's câta mìa.",
     "currentrev": "Ûltma versiòun",
     "currentrev-asof": "Ûltma versiòun dal $1",
     "revisionasof": "Versiòun dal $1",
     "prefs-skin": "Aspèt grâfich (skin)",
     "skin-preview": "Guêrda préma",
     "datedefault": "Nisóna preferèinsa",
-    "prefs-beta": "Funsionamèint 'beta'",
     "saveprefs": "Sêlva",
     "prefs-editing": "Caşèla 'd mudéfica",
     "rows": "Rîghi",
index 2482ce0..e044a54 100644 (file)
@@ -1,6 +1,41 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "AK",
+            "Assassingr",
+            "Astralnet",
+            "Axil",
+            "Badseed",
+            "Chomwitt",
+            "Consta",
+            "Crazymadlover",
+            "Dada",
+            "Dead3y3",
+            "Evropi",
+            "Flyax",
+            "FocalPoint",
+            "Geraki",
+            "Glavkos",
+            "Grondin",
+            "Kaganer",
+            "Kiolalis",
+            "Kiriakos",
+            "Kongr43gpen",
+            "Lou",
+            "MF-Warburg",
+            "Nikosguard",
+            "Omnipaedista",
+            "Protnet",
+            "Reedy",
+            "Remember the dot",
+            "Sinopeus",
+            "Tifa93",
+            "Xaris333",
+            "ZaDiak",
+            "Απεργός",
+            "Περίεργος",
+            "לערי ריינהארט"
+        ]
     },
     "tog-underline": "Υπογράμμιση συνδέσμων:",
     "tog-hideminor": "Απόκρυψη μικροεπεξεργασιών στις πρόσφατες αλλαγές",
     "loginlanguagelabel": "Γλώσσα: $1",
     "suspicious-userlogout": "Το αίτημα αποσύνδεσής σας απερρίφθη επειδή φαίνεται ότι στάλθηκε από ένα λανθασμένο φυλλομετρητή (browser) ή διακομιστή προσωρινής αποθήκευσης.",
     "createacct-another-realname-tip": "Το πραγματικό όνομα είναι προαιρετικό\nΑν επιλέξετε να το δώσετε, αυτό θα μπορεί να χρησιμοποιηθεί για να αναγνωριστεί η δουλειά σας.",
+    "pt-login": "Σύνδεση",
+    "pt-login-button": "Σύνδεση",
+    "pt-createaccount": "Δημιουργία λογαριασμού",
+    "pt-userlogout": "Αποσύνδεση;",
     "php-mail-error-unknown": "Άγνωστο σφάλμα στη συνάρτηση mail() της PHP.",
     "user-mail-no-addy": "Προσπαθήσατε να στείλετε e-mail χωρίς μια διεύθυνση e-mail.",
     "user-mail-no-body": "Προσπάθησε να στείλει e-mail με ένα κενό ή αδικαιολόγητα σύντομο σώμα.",
     "resetpass-recycled": "Παρακαλούμε επαναφέρετε τον κωδικό πρόσβασής σας σε κάτι διαφορετικό από τον τρέχοντα κωδικό πρόσβασης.",
     "resetpass-temp-password": "Προσωρινός κωδικός:",
     "resetpass-abort-generic": "Η αλλαγή του κωδικού έχει απορριφθεί από μια προέκταση.",
+    "resetpass-expired": "Τον κωδικό πρόσβασής σας έχει λήξει. Ορίστε ένα νέο κωδικό πρόσβασης για να συνδεθείτε.",
+    "resetpass-validity-soft": "Τον κωδικό πρόσβασής σας δεν είναι έγκυρος: $1 \nΠαρακαλώ επιλέξτε ένα νέο κωδικό πρόσβασης τώρα, ή κάντε κλικ στο κουμπί \"{{int:resetpass-submit-cancel}}\" για να το επαναφέρετε αργότερα.",
     "passwordreset": "Κωδικός επαναφοράς",
     "passwordreset-text-one": "Συμπληρώστε την παρακάτω φόρμα για να επαναφέρετε τον κωδικό πρόσβασής σας.",
     "passwordreset-text-many": "{{PLURAL:$1|Συμπληρώστε ένα από τα πεδία για να λάβετε προσωρινό κωδικό πρόσβαση μέσω ηλεκτρονικού ταχυδρομείου.}}",
     "revdelete-no-file": "Το αρχείο που καθορίσατε δεν υπάρχει.",
     "revdelete-show-file-confirm": "Είστε σίγουροι ότι θέλετε να δείτε μία διεγραμμένη αναθεώρηση του αρχείου \"<nowiki>$1</nowiki>\" από τις $2 στις $3;",
     "revdelete-show-file-submit": "Ναι",
+    "revdelete-selected-text": "'''{{PLURAL:$2|Επιλεγμένη έκδοση|Επιλεγμένες εκδόσεις}} της [[:$1]]:'''",
     "logdelete-selected": "{{PLURAL:$1|Επιλεγμένο γεγονός αρχείου καταγραφής|Επιλεγμένα γεγονότα αρχείου καταγραφής}}:",
     "revdelete-confirm": "Παρακαλούμε επιβεβαιώστε ότι σκοπεύετε να το κάνετε αυτό, ότι αντιλαμβάνεσθε τις συνέπειες, και ότι το κάνετε σύμφωνα με την [[{{MediaWiki:Policy-url}}|πολιτική]].",
     "revdelete-suppress-text": "Η καταστολή μπορεί να χρησιμοποιηθεί <strong> μόνο </strong> για τις ακόλουθες περιπτώσεις:\n* Ενδεχόμενη συκοφαντική δυσφήμιση\n* Ακατάλληλες προσωπικές πληροφορίες\n*: <em>διευθύνσεις κατοικίας και αριθμοί τηλεφώνου, αριθμοί ταυτότητας, κλπ. </em>",
     "prefs-skin": "Οπτική οργάνωση (skin)",
     "skin-preview": "Προεπισκόπηση",
     "datedefault": "Χωρίς προτίμηση",
-    "prefs-beta": "Λειτουργίες της Beta",
     "prefs-datetime": "Ημερομηνία και ώρα",
     "prefs-labs": "Λειτουργίες των Labs",
     "prefs-user-pages": "Σελίδες του χρήστη",
     "right-editmyusercss": "Επεξεργασία των ιδιωτικών αρχείων CSS χρήστη",
     "right-editmyuserjs": "Επεξεργασία των ιδιωτικών αρχείων JavaScript χρήστη",
     "right-viewmywatchlist": "Προβολή της δικής σας λίστα παρακολούθησης",
+    "right-viewmyprivateinfo": "Δείτε τα προσωπικά σας δεδομένα (π.χ. διεύθυνση ηλεκτρονικού ταχυδρομείου, πραγματικό όνομα)",
+    "right-editmyprivateinfo": "Επεξεργαστείτε τα προσωπικά σας δεδομένα (π.χ. διεύθυνση ηλεκτρονικού ταχυδρομείου, πραγματικό όνομα)",
     "right-editmyoptions": "Επεξεργασία των προτιμήσεών σας",
     "right-rollback": "Γρήγορη αναστροφή των επεξεργασιών του τελευταίου χρήστη που επεξεργάστηκε μια σελίδα",
     "right-markbotedits": "Σήμανση επαναφερόμενων επεξεργασιών ως επεξεργασιών μποτ",
     "recentchanges-label-plusminus": "Μεταβολή του μεγέθους της σελίδας σε bytes",
     "recentchanges-legend-heading": "'''Υπόμνημα:'''",
     "recentchanges-legend-newpage": "(δείτε [[Special:NewPages|Νέες σελίδες]])",
-    "rcnotefrom": "Παρακάτω είναι οι αλλαγές από τις '''$2''' (εμφανίζονται μέχρι '''$1''').",
+    "rcnotefrom": "Παρακάτω είναι οι αλλαγές από τις <strong>$2</strong>  (εμφανίζονται μέχρι <strong>$1</strong> ).",
     "rclistfrom": "Εμφάνιση νέων αλλαγών αρχίζοντας από $1",
     "rcshowhideminor": "$1 μικροεπεξεργασιών",
     "rcshowhideminor-show": "Εμφάνιση",
     "rcshowhideminor-hide": "Απόκρυψη",
     "rcshowhidebots": "$1 ρομπότ",
+    "rcshowhidebots-show": "Εμφάνιση",
+    "rcshowhidebots-hide": "Απόκρυψη",
     "rcshowhideliu": "$1 εγγεγραμμένων χρηστών",
+    "rcshowhideliu-show": "Εμφάνιση",
+    "rcshowhideliu-hide": "Απόκρυψη",
     "rcshowhideanons": "$1 ανωνύμων χρηστών",
+    "rcshowhideanons-show": "Εμφάνιση",
+    "rcshowhideanons-hide": "Απόκρυψη",
     "rcshowhidepatr": "$1 ελεγμένων επεξεργασιών",
+    "rcshowhidepatr-show": "Εμφάνιση",
+    "rcshowhidepatr-hide": "Απόκρυψη",
     "rcshowhidemine": "$1 των επεξεργασιών μου",
+    "rcshowhidemine-show": "Εμφάνιση",
+    "rcshowhidemine-hide": "Απόκρυψη",
     "rclinks": "Εμφάνιση των τελευταίων $1 αλλαγών στο διάστημα των τελευταίων $2 ημερών<br />$3",
     "diff": "διαφορά",
     "hist": "ιστορικό",
     "uploaddisabledtext": "Η φόρτωση αρχείων είναι απενεργοποιημένη.",
     "php-uploaddisabledtext": "Οι επιφορτώσεις αρχείων ειναι απενεργοποιημένες στην PHP. Παρακαλούμε, ελέγξτε την ρύθμιση file_uploads.",
     "uploadscripted": "Αυτό το αρχείο περιέχει κώδικα HTML ή script που μπορεί να παρερμηνευθεί από μερικούς browser.",
+    "uploadinvalidxml": "Δεν ήταν δυνατή η ανάλυση του κώδικα XML στο αρχείο.",
     "uploadvirus": "Το αρχείο περιέχει ιό! Λεπτομέρειες: $1",
     "uploadjava": "Το αρχείο είναι αρχείο ZIP, το οποίο περιέχει ένα αρχείο .class της γλώσσας Java.\nΔεν επιτρέπεται η αποστολή αρχείων Java, επειδή μπορούν να προκαλέσουν παράκαμψη των περιορισμών ασφαλείας του συστήματος.",
     "upload-source": "Αρχείο πηγής",
     "download": "λήψη",
     "unwatchedpages": "Μη παρακολουθούμενες σελίδες",
     "listredirects": "Λίστα ανακατευθύνσεων",
+    "listduplicatedfiles": "Κατάλογος αρχείων με διπλότυπα",
     "unusedtemplates": "Αχρησιμοποίητα πρότυπα",
     "unusedtemplatestext": "Αυτή η σελίδα περιέχει όλες τις σελίδες στην περιοχή ονομάτος των {{ns:template}}, οι οποίες δεν περιλαμβάνονται σε άλλη σελίδα. Θυμηθείτε να ελέγξετε για άλλους συνδέσμους προς τα πρότυπα πριν τα διαγράψετε.",
     "unusedtemplateswlh": "άλλοι σύνδεσμοι",
     "ninterwikis": "$1 {{PLURAL:$1|σύνδεσμος|σύνδεσμοι}} interwiki",
     "nlinks": "$1 {{PLURAL:$1|σύνδεσμος|σύνδεσμοι}}",
     "nmembers": "$1 {{PLURAL:$1|μέλος|μέλη}}",
+    "nmemberschanged": "$1 → $2 {{PLURAL:$2|μέλος|μέλη}}",
     "nrevisions": "$1 {{PLURAL:$1|αναθεώρηση|αναθεωρήσεις}}",
     "nviews": "$1 {{PLURAL:$1|επίσκεψη|επισκέψεις}}",
     "nimagelinks": "Χρησιμοποιείται σε $1 {{PLURAL:$1|σελίδα|σελίδες}}",
     "protectedpages-page": "Σελίδα",
     "protectedpages-expiry": "Λήγει",
     "protectedpages-performer": "Προστασία χρήστη",
+    "protectedpages-reason": "Αιτία",
     "protectedpages-unknown-timestamp": "Άγνωστο",
     "protectedpages-unknown-performer": "Άγνωστος χρήστης",
     "protectedtitles": "Προστατευμένοι τίτλοι",
     "nowatchlist": "Δεν υπάρχουν εγγραφές στη λίστα παρακολούθησης.",
     "watchlistanontext": "Παρακαλώ $1 για να δείτε ή να επεξεργαστείτε στοιχεία στη λίστα παρακολούθησής σας.",
     "watchnologin": "Δεν έχετε συνδεθεί.",
-    "watchnologintext": "Για να κάνετε αλλαγές στη λίστα παρακολούθησης πρέπει να [[Special:UserLogin|συνδεθείτε]].",
     "addwatch": "Προσθήκη στη λίστα παρακολούθησης",
     "addedwatchtext": "Η σελίδα «[[:$1]]» έχει προστεθεί στη [[Special:Watchlist|λίστα παρακολούθησής σας]].\nΜελλοντικές αλλαγές σε αυτή τη σελίδα και στη συσχετισμένη σελίδα συζήτησής της θα εμφανίζονται εδώ.",
     "removewatch": "Αφαίρεση από τη λίστα παρακολούθησης",
     "allmessagesname": "Όνομα",
     "allmessagesdefault": "Προεπιλεγμένο κείμενο μηνύματος",
     "allmessagescurrent": "Παρόν κείμενο",
-    "allmessagestext": "Αυτή είναι μια λίστα με όλα τα μηνύματα συστήματος που βρίσκονται στην περιοχή MediaWiki.\nΠαρακαλούμε επισκεφθείτε τα [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] και [//translatewiki.net translatewiki.net] αν επιθυμείτε να συνεισφέρετε σε μια γενική μετάφραση του MediaWiki.",
+    "allmessagestext": "Αυτή είναι μια λίστα με όλα τα μηνύματα συστήματος που βρίσκονται στην περιοχή MediaWiki.\nΠαρακαλούμε επισκεφθείτε τα [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] και [//translatewiki.net translatewiki.net] αν επιθυμείτε να συνεισφέρετε σε μια γενική μετάφραση του MediaWiki.",
     "allmessagesnotsupportedDB": "Αυτή η σελίδα δεν υποστηρίζεται επειδή το ''wgUseDatabaseMessages'' είναι απενεργοποιημένο.",
     "allmessages-filter-legend": "Φίλτρο",
     "allmessages-filter": "Ταξινόμηση βάσει της δήλωσης προσαρμογής:",
index 4ca6300..b5110bd 100644 (file)
     "prefs-skin": "Skin",
     "skin-preview": "Preview",
     "datedefault": "No preference",
-    "prefs-beta": "Beta features",
     "prefs-datetime": "Date and time",
     "prefs-labs": "Labs features",
     "prefs-user-pages": "User pages",
     "nowatchlist": "You have no items on your watchlist.",
     "watchlistanontext": "Please $1 to view or edit items on your watchlist.",
     "watchnologin": "Not logged in",
-    "watchnologintext": "You must be [[Special:UserLogin|logged in]] to modify your watchlist.",
     "addwatch": "Add to watchlist",
     "addedwatchtext": "The page \"[[:$1]]\" has been added to your [[Special:Watchlist|watchlist]].\nFuture changes to this page and its associated talk page will be listed there.",
     "removewatch": "Remove from watchlist",
index 28c3434..9f0fec7 100644 (file)
     "gotaccountlink": "Ensaluti",
     "userlogin-resetlink": "Ĉu vi forgesis ensalutajn detalojn?",
     "userlogin-resetpassword-link": "Ĉu vi forgesis vian pasvorton?",
+    "userlogin-helplink2": "Helpo pri ensaluto",
     "userlogin-loggedin": "Vi jam estas ensalutita kiel {{GENDER:$1|$1}}.\nUzu la formularon suben por ensaluti kiel alia uzanto.",
     "userlogin-createanother": "Krei alian konton",
     "createacct-join": "Suben enigu informojn pri vi",
     "suspicious-userlogout": "Via peto por elsaluti estis malpermesita, ĉar verŝajne ĝi estis sendita de trompita retumilo aŭ kaŝiĝanta prokura servilo.",
     "createacct-another-realname-tip": "La vera nomo estas nenecesa.\nSe vi decidas indiki ĝin, ĝi estos uzata por montri atribuadon de viaj kontribuoj.",
     "pt-login": "Ensaluti",
+    "pt-login-button": "Ensaluti",
     "pt-createaccount": "Krei novan konton",
     "pt-userlogout": "Elsaluti",
     "php-mail-error-unknown": "Nekonata eraro en la funkcio mail() de PHP",
     "invalid-content-data": "Enhavo estas malvalida",
     "content-not-allowed-here": "Enhavo de $1 ne estas permesita en paĝo [[$2]]",
     "editwarning-warning": "Forlaso de ĉi tiu paĝo kaŭzos al vi perdi iun ajn ŝanĝojn kiujn vi faris.\nSe vi estas ensalutinta, vi povas malŝalti ĉi tiun averton en la sekcio \"{{int:prefs-editing}}\" de viaj preferoj.",
+    "editpage-notsupportedcontentformat-title": "Nesubtenata enhavoformo",
     "content-model-wikitext": "vikiteksto",
     "content-model-text": "ordinara teksto",
     "content-model-javascript": "JavaScript",
     "search-section": "(sekcio $1)",
     "search-suggest": "Ĉu vi intenciis: $1",
     "search-interwiki-caption": "Kunprojektoj",
-    "search-interwiki-default": "$1 rezultoj:",
+    "search-interwiki-default": "Rezultoj de $1:",
     "search-interwiki-more": "(plu)",
     "search-relatedarticle": "Relataj",
     "searcheverything-enable": "Traserĉi ĉiujn nomspacojn",
     "prefs-skin": "Etoso",
     "skin-preview": "Antaŭrigardo",
     "datedefault": "Nenia prefero",
-    "prefs-beta": "Ecoj de Beta",
     "prefs-datetime": "Dato kaj horo",
     "prefs-labs": "Ecoj el Laboratorio",
     "prefs-user-pages": "Uzantopaĝoj",
     "recentchanges-label-unpatrolled": "Ĉi tiu redakto ne jam estis patrolata.",
     "recentchanges-legend-heading": "'''Klarigo:'''",
     "recentchanges-legend-newpage": "(vidu ankaŭ [[Special:NewPages|liston de novaj paĝoj]])",
-    "rcnotefrom": "Jen la ŝanĝoj ekde '''$2''' (lastaj ĝis '''$1''').",
+    "rcnotefrom": "Sube estas ŝanĝoj ekde <strong>$2</strong> ({{PLURAL:$1|lasta|lastaj}} <strong>$1</strong>).",
     "rclistfrom": "Montri novajn ŝanĝojn ekde \"$1\"",
     "rcshowhideminor": "$1 redaktetojn",
     "rcshowhideminor-show": "Montri",
     "protectedpagesempty": "Neniuj paĝoj estas momente protektitaj kun ĉi tiuj parametroj.",
     "protectedpages-timestamp": "Tempindiko",
     "protectedpages-page": "Paĝo",
+    "protectedpages-performer": "Protektinto",
+    "protectedpages-params": "Ecoj de protekto",
     "protectedpages-reason": "Kialo",
     "protectedpages-unknown-timestamp": "Nekonata",
     "protectedpages-unknown-performer": "Nekonata uzanto",
     "listgrouprights-removegroup-self": "Povas forigi {{PLURAL:$2|grupon|grupojn}} de propra konto: $1",
     "listgrouprights-addgroup-self-all": "Povas aldoni ĉiujn grupojn al propra konto",
     "listgrouprights-removegroup-self-all": "Povas forigi ĉiujn grupojn de propra konto",
+    "trackingcategories-nodesc": "Neniu priskribo estas disponebla.",
+    "trackingcategories-disabled": "Kategorio estas malaktivigita",
     "mailnologin": "Neniu alsendota adreso",
     "mailnologintext": "Vi nepre estu [[Special:UserLogin|salutanta]] kaj havanta validan retpoŝtadreson en viaj [[Special:Preferences|preferoj]] por retpoŝti al aliaj uzantoj.",
     "emailuser": "Retpoŝti ĉi tiun uzanton",
     "nowatchlist": "Vi ne jam elektis priatenti iun ajn paĝon.",
     "watchlistanontext": "Bonvolu $1 por vidi aŭ redakti erojn en via atentaro.",
     "watchnologin": "Ne ensalutinta",
-    "watchnologintext": "Nepras [[Special:UserLogin|ensaluti]] por ŝanĝi vian atentaron.",
     "addwatch": "Aldoniĝi al atentaro",
     "addedwatchtext": "La paĝo \"[[:$1]]\" aldoniĝis al via [[Special:Watchlist|atentaro]]. Estontaj ŝanĝoj de tiu paĝo kaj de ĝia rilata diskutpaĝo aperos tie.",
     "removewatch": "Forigi el atentaro",
     "delete-edit-reasonlist": "Redakti kialojn de forigo",
     "delete-toobig": "Ĉi tiu paĝo havas grandan redakto-historion, pli ol $1 {{PLURAL:$1|version|versiojn}}. Forigo de ĉi tiaj paĝoj estis limigitaj por preventi akcidentan disrompigon de {{SITENAME}}.",
     "delete-warning-toobig": "Ĉi tiu paĝo havas grandan redakto-historion, pli ol $1 {{PLURAL:$1|version|versiojn}}. Forigo de ĝi povas disrompigi operacion de {{SITENAME}}; forigu singarde.",
+    "deleting-backlinks-warning": "'''Atentigo:'''\n[[Special:WhatLinksHere/{{FULLPAGENAME}}|Aliaj paĝoj]] ligas al aŭ transkludas tiun ĉi forigotan paĝon.",
     "rollback": "Restarigi antaŭan redakton",
     "rollback_short": "Malfari",
     "rollbacklink": "malfari",
     "protect-locked-blocked": "Vi ne povas ŝanĝi prokekto-nivelojn dum forbarita. Jen la nunaj ecoj de la paĝo '''$1''':",
     "protect-locked-dblock": "Ne povas ŝanĝi nivelojn de protekto pro aktiva datumbaza ŝlosado.\nJen la nunaj agordoj de la paĝo '''$1''':",
     "protect-locked-access": "Via konto ne havas rajton ŝanĝi protekto-nivelojn.\nJen la aktualaj valoroj por la paĝo '''$1''':",
-    "protect-cascadeon": "Ĉi paĝo estas nun protektita kontraŭ redaktado ĉar ĝi estas inkluzivita en {{PLURAL:$1|jena paĝo, kiu mem estas protektita|jenaj paĝoj, kiuj mem estas protektitaj}} per kaskada protekto.\nVi povas ŝanĝi ties protektnivelon, sed tio ne ŝanĝos la kaskadan protekton.",
+    "protect-cascadeon": "Ĉi paĝo estas nun protektita kontraŭ redaktado ĉar ĝi estas inkluzivita en {{PLURAL:$1|jena paĝo, kiu mem estas protektita|jenaj paĝoj, kiuj mem estas protektitaj}} per kaskada protekto.\nŜanĝoj de ĝia protektonivelo ne influos la kaskadan protekton.",
     "protect-default": "Permesigi ĉiujn uzantojn",
     "protect-fallback": "Permesi nur uzantojn kun la rajto  \"$1\"",
     "protect-level-autoconfirmed": "Permesi nur aŭtomate konfirmitajn uzantojn",
     "sp-contributions-newbies": "Montri nur kontribuojn de novaj kontoj",
     "sp-contributions-newbies-sub": "Kontribuoj de novaj uzantoj. Forigitaj paĝoj ne estas montritaj.",
     "sp-contributions-newbies-title": "Kontribuoj de novaj uzantoj",
-    "sp-contributions-blocklog": "Protokolo de forbaroj",
-    "sp-contributions-deleted": "forigitaj kontribuoj de uzantoj",
+    "sp-contributions-blocklog": "protokolo de forbaroj",
+    "sp-contributions-deleted": "forigitaj kontribuoj de uzanto",
     "sp-contributions-uploads": "alŝutoj",
     "sp-contributions-logs": "protokoloj",
     "sp-contributions-talk": "diskuto",
-    "sp-contributions-userrights": "administri rajtojn de uzantoj",
+    "sp-contributions-userrights": "administro de uzantorajtoj",
     "sp-contributions-blocked-notice": "La uzanto nune estas forbarita. Jen la lasta blokada listero en protokolo:",
     "sp-contributions-blocked-notice-anon": "Ĉi tiu IP-adreso estas nune forbarita.\nJen la lasta ero de la forbara protokolo:",
     "sp-contributions-search": "Serĉado de kontribuoj",
     "sp-contributions-username": "IP-adreso aŭ uzantonomo:",
     "sp-contributions-toponly": "Montru nur ŝanĝojn kiuj estas la plej lastaj revizioj",
+    "sp-contributions-newonly": "Montri nur redaktojn, kiuj kreis paĝon",
     "sp-contributions-submit": "Serĉi",
     "whatlinkshere": "Ligiloj ĉi tien",
     "whatlinkshere-title": "Paĝoj ligantaj al \"$1\"",
     "allmessagesname": "Nomo",
     "allmessagesdefault": "Defaŭlta teksto",
     "allmessagescurrent": "Nuna teksto",
-    "allmessagestext": "Ĉi tio estas listo de ĉiuj mesaĝoj haveblaj en la MediaWiki-nomspaco.\nBonvolu aliri [https://www.mediawiki.org/wiki/Localisation MediaWiki-Asimilado] kaj [//translatewiki.net translatewiki.net]\nse vi volus kontribui al la komuna MediaWiki-asimilado.",
+    "allmessagestext": "Ĉi tio estas listo de ĉiuj mesaĝoj haveblaj en la MediaWiki-nomspaco.\nBonvolu aliri [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki-Asimilado] kaj [//translatewiki.net translatewiki.net]\nse vi volus kontribui al la komuna MediaWiki-asimilado.",
     "allmessagesnotsupportedDB": "{{ns:special}}:Allmessages ne subtenata ĉar la variablo wgUseDatabaseMessages estas malkonektita.",
     "allmessages-filter-legend": "Filtri",
     "allmessages-filter": "Filtri laŭ ŝanĝada stato",
     "pageinfo-length": "Paĝgrandeco (en bajtoj)",
     "pageinfo-article-id": "Paĝa identigo",
     "pageinfo-language": "Lingvo de paĝa enhavo",
+    "pageinfo-content-model": "Modelo de paĝoenhavo",
     "pageinfo-robot-policy": "Indeksado per robotoj",
     "pageinfo-robot-index": "Permesata",
     "pageinfo-robot-noindex": "Malpermesata",
     "confirm-watch-top": "Ĉu aldoni tiun ĉi paĝon al via atentaro?",
     "confirm-unwatch-button": "Ek!",
     "confirm-unwatch-top": "Ĉu forigi tiun ĉi paĝon el via atentaro?",
+    "quotation-marks": "„$1“",
     "imgmultipageprev": "← antaŭa paĝo",
     "imgmultipagenext": "sekva paĝo →",
     "imgmultigo": "Ek!",
     "imgmultigoto": "Iri al paĝo $1",
     "img-lang-default": "(defaŭlta lingvo)",
+    "img-lang-info": "Bildigi tiun ĉi bildon en $1. $2",
     "img-lang-go": "Ek",
     "ascending_abbrev": "sprn",
     "descending_abbrev": "subn",
     "version-version": "($1)",
     "version-license": "Permesilo de MediaWiki",
     "version-ext-license": "Permesilo",
+    "version-ext-colheader-name": "Etendilo",
     "version-ext-colheader-version": "Versio",
     "version-ext-colheader-license": "Permesilo",
     "version-ext-colheader-description": "Priskribo",
     "version-ext-colheader-credits": "Aŭtoroj",
     "version-license-title": "Permesilo por $1",
+    "version-license-not-found": "Por tiu ĉi etendilo ne estis trovitaj pli detalaj permesilaj informoj.",
     "version-credits-title": "Agnosko por $1",
+    "version-credits-not-found": "Por tiu ĉi etendilo ne estis trovitaj pli detalaj informoj pri aŭtoroj.",
     "version-poweredby-credits": "Ĉi tiu vikio funkcias per '''[https://www.mediawiki.org/ MediaWiki]''', aŭtorrajto ©&thinsp;2001–$1 $2.",
     "version-poweredby-others": "aliaj",
     "version-poweredby-translators": "tradukantoj de translatewiki.net",
     "duration-centuries": "$1 {{PLURAL:$1|jarcento|jarcentoj}}",
     "duration-millennia": "$1 {{PLURAL:$1|jarmilo|jarmiloj}}",
     "rotate-comment": "Bildo pivotita $1 {{PLURAL:$1|gradon|gradojn}} dekstren",
+    "limitreport-title": "Profiladaj datumoj de sintaksa analizilo:",
     "limitreport-cputime": "Uzo de procesora tempo",
     "limitreport-cputime-value": "$1 {{PLURAL:$1|sekundo|sekundoj}}",
     "limitreport-walltime": "Uzo de reala tempo",
     "limitreport-ppvisitednodes": "Nombro da nodoj vizititaj de antaŭtraktilo",
     "limitreport-ppgeneratednodes": "Nombro da nodoj kreitaj de antaŭtraktilo",
     "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|bitoko|bitokoj}}",
+    "limitreport-templateargumentsize": "Grandeco de argumentoj de ŝablonoj",
     "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|bitoko|bitokoj}}",
+    "limitreport-expensivefunctioncount": "Nombro de kostaj sintaks-analizilaj funkcioj",
     "expandtemplates": "Ampleksigi ŝablonojn",
     "expand_templates_intro": "Ĉi tiu speciala paĝo traktas tekston kaj ampleksigas ĉiujn ŝablonojn en ĝi rekursie.\nĜi ankaŭ ampleksigas sintaksajn funkciojn kiel\n<code><nowiki>{{</nowiki>#language:…}}</code> kaj variablojn kiel\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>. Fakte preskaŭ iujn ajn en duoblaj krampoj.",
     "expand_templates_title": "Kunteksta titolo, por {{FULLPAGENAME}}, ktp.:",
index 4efaeac..4c5a3c8 100644 (file)
     "changeemail-cancel": "Cancelar",
     "changeemail-throttled": "Has intentado acceder demasiadas veces.\nEspera $1 antes de intentarlo de nuevo.",
     "resettokens": "Restablecer claves",
-    "resettokens-text": "Puede restablecer las claves que permiten el acceso a ciertos datos privados asociados a tu cuenta aquí.\n\nDeberías hacerlo si accidentalmente la has compartido con alguien o si su cuenta ha sido comprometida.",
+    "resettokens-text": "Aquí puedes restablecer las fichas que permiten el acceso a ciertos datos privados asociados con tu cuenta.\n\nDeberías hacerlo si accidentalmente los has compartido o si tu cuenta ha sido intervenida.",
     "resettokens-no-tokens": "No hay claves para restablecer.",
     "resettokens-legend": "Restablecer claves",
     "resettokens-tokens": "Claves:",
     "prefs-skin": "Apariencia",
     "skin-preview": "Previsualizar",
     "datedefault": "Sin preferencia",
-    "prefs-beta": "Funciones en pruebas",
     "prefs-datetime": "Fecha y hora",
     "prefs-labs": "Características de los laboratorios",
     "prefs-user-pages": "Páginas de usuario",
     "download": "descargar",
     "unwatchedpages": "Páginas no vigiladas",
     "listredirects": "Lista de redirecciones",
+    "listduplicatedfiles": "Lista de archivos con duplicados",
+    "listduplicatedfiles-entry": "[[:File:$1|$1]] tiene [[$3|{{PLURAL:$2|un duplicado|$2 duplicados}}]].",
     "unusedtemplates": "Plantillas sin uso",
     "unusedtemplatestext": "Aquí se enumeran todas las páginas en el espacio de nombres {{ns:template}} que no están incluidas en otras páginas. Recuerda mirar lo que enlaza a las plantillas antes de borrarlas.",
     "unusedtemplateswlh": "otros enlaces",
     "listgrouprights-removegroup-self": "Eliminar {{PLURAL:$2|grupo|grupos}} de tu propia cuenta: $1",
     "listgrouprights-addgroup-self-all": "Agregar todos los grupos a tu propia cuenta",
     "listgrouprights-removegroup-self-all": "Eliminar todos los grupos de tu propia cuenta",
+    "trackingcategories": "Categorías de seguimiento",
+    "trackingcategories-msg": "Categoría de seguimiento",
+    "trackingcategories-name": "Nombre del mensaje",
+    "trackingcategories-desc": "Criterios de inclusión de categoría",
+    "noindex-category-desc": "La página contiene la palabra mágica <nowiki>__NOINDEX__</nowiki> (y está en un espacio de nombres donde la función está activada); y por ello los robots no la indizan.",
+    "trackingcategories-nodesc": "No hay descripción disponible.",
+    "trackingcategories-disabled": "La categoría está desactivada",
     "mailnologin": "Ninguna dirección de envio",
     "mailnologintext": "Debes [[Special:UserLogin|iniciar sesión]] y tener una dirección electrónica válida en tus [[Special:Preferences|preferencias]] para enviar un correo electrónico a otros usuarios.",
     "emailuser": "Enviar un correo electrónico a {{GENDER:{{BASEPAGENAME}}|este usuario|esta usuaria}}",
     "nowatchlist": "No tienes ninguna página en tu lista de seguimiento.",
     "watchlistanontext": "Para ver o editar las entradas de tu lista de seguimiento es necesario $1.",
     "watchnologin": "No has iniciado sesión",
-    "watchnologintext": "Debes [[Special:UserLogin|iniciar sesión]] para modificar tu lista de seguimiento.",
     "addwatch": "Añadir a la lista de seguimiento",
     "addedwatchtext": "La página «[[:$1]]» ha sido añadida a tu [[Special:Watchlist|lista de seguimiento]]. Los cambios futuros en esta página y en su página de discusión asociada se indicarán ahí.",
     "removewatch": "Quitar de la lista de seguimiento",
     "sp-contributions-newbies-sub": "Para cuentas nuevas",
     "sp-contributions-newbies-title": "Contribuciones de usuarios nuevos",
     "sp-contributions-blocklog": "registro de bloqueos",
+    "sp-contributions-suppresslog": "Contribuciones borradas de usuario",
     "sp-contributions-deleted": "contribuciones de usuario borradas",
     "sp-contributions-uploads": "subidas",
     "sp-contributions-logs": "registros",
     "sp-contributions-blocked-notice": "Este usuario está actualmente bloqueado. La última entrada del registro de bloqueos es presentada debajo para mayor referencia:",
     "sp-contributions-blocked-notice-anon": "Esta dirección IP se encuentra actualmente bloqueada.\nA continuación se muestra la última entrada del registro de bloqueos para mayor referencia.",
     "sp-contributions-search": "Buscar contribuciones",
-    "sp-contributions-suppresslog": "Contribuciones borradas de usuario",
     "sp-contributions-username": "Dirección IP o nombre de usuario:",
     "sp-contributions-toponly": "Solo mostrar últimas ediciones de página",
     "sp-contributions-newonly": "Mostrar solo ediciones que son creaciones de páginas",
     "allmessagesname": "Nombre",
     "allmessagesdefault": "Texto predeterminado",
     "allmessagescurrent": "Texto actual",
-    "allmessagestext": "Esta es una lista de mensajes del sistema disponibles en el espacio de nombres MediaWiki:\nPor favor visita [https://www.mediawiki.org/wiki/Localisation Localización MediaWiki] y [//translatewiki.net translatewiki.net] si deseas contribuir con la localización genérica MediaWiki.",
+    "allmessagestext": "Esta es una lista de mensajes del sistema disponibles en el espacio de nombres MediaWiki:\nPor favor visita [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Localización MediaWiki] y [//translatewiki.net translatewiki.net] si deseas contribuir con la localización genérica MediaWiki.",
     "allmessagesnotsupportedDB": "Esta página no está disponible porque '''$wgUseDatabaseMessages''' está deshabilitado.",
     "allmessages-filter-legend": "Filtro",
     "allmessages-filter": "Filtrar por estado de personalización:",
     "version-entrypoints": "URL del punto de entrada",
     "version-entrypoints-header-entrypoint": "Punto de entrada",
     "version-entrypoints-header-url": "Dirección URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Ruta del artículo]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Ruta de la secuencia de comandos (script)]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Ruta del artículo]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Ruta de la secuencia de comandos (script)]",
     "redirect": "Redirigir por archivo, usuario, página o ID de revisión",
     "redirect-legend": "Redirigir a un archivo o página",
     "redirect-summary": "Esta página especial redirige a un fichero (dado un nombre de fichero), a una página (dado un identificador de revisión o de página) o a una página de usuario (dado un identificador numérico de usuario). Uso: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], o [[{{#Special:Redirect}}/user/101]].",
     "limitreport-expensivefunctioncount": "Cuenta de la funcion expansiva del analizador",
     "expandtemplates": "Expandir plantillas",
     "expand_templates_intro": "Esta página especial toma un texto wiki y expande todas sus plantillas recursivamente.\nTambién expande las funciones sintácticas como <code><nowiki>{{</nowiki>#language:…}}</code>, y variables como\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>. De hecho, expande casi cualquier cosa que esté entre llaves dobles.",
-    "expand_templates_title": "Título de la página, útil para expandir <nowiki>{{PAGENAME}}</nowiki> o similares",
+    "expand_templates_title": "Título de la página, útil para expandir {{PAGENAME}} o similares",
     "expand_templates_input": "Texto a expandir:",
     "expand_templates_output": "Resultado:",
     "expand_templates_xml_output": "Salida XML",
index ffc888a..cf097f7 100644 (file)
     "prefs-skin": "Kujundus",
     "skin-preview": "eelvaade",
     "datedefault": "Eelistus puudub",
-    "prefs-beta": "Beetafunktsioonid",
     "prefs-datetime": "Kuupäev ja kellaaeg",
     "prefs-labs": "Katsefunktsioonid",
     "prefs-user-pages": "Kasutajaleheküljed",
     "nowatchlist": "Sinu jälgimisloend on tühi.",
     "watchlistanontext": "Oma jälgimisloendi nägemiseks ja muutmiseks pead $1.",
     "watchnologin": "Ei ole sisse logitud",
-    "watchnologintext": "Jälgimisloendi muutmiseks pead [[Special:UserLogin|sisse logima]].",
     "addwatch": "Lisa jälgimisloendisse",
     "addedwatchtext": "Lehekülg \"[[:$1]]\" on lisatud sinu [[Special:Watchlist|jälgimisloendisse]].\nEdasised muudatused sellel leheküljel ja seotud aruteluleheküljel tuuakse ära jälgimisloendis.",
     "removewatch": "Eemalda jälgimisloendist",
     "sp-contributions-newbies-sub": "Uute kontode kaastöö",
     "sp-contributions-newbies-title": "Uute kasutajate kaastöö",
     "sp-contributions-blocklog": "blokeerimised",
+    "sp-contributions-suppresslog": "varjatud kaastöö",
     "sp-contributions-deleted": "kustutatud kaastöö",
     "sp-contributions-uploads": "üleslaadimised",
     "sp-contributions-logs": "logid",
     "sp-contributions-blocked-notice": "See kasutaja on parajasti blokeeritud. Allpool on toodud kõige hilisem blokeerimislogi sissekanne:",
     "sp-contributions-blocked-notice-anon": "See IP-aadress on parajasti blokeeritud.\nAllpool on toodud viimane blokeerimislogi sissekanne:",
     "sp-contributions-search": "Kaastöö otsimine",
-    "sp-contributions-suppresslog": "varjatud kaastöö",
     "sp-contributions-username": "IP-aadress või kasutajanimi:",
     "sp-contributions-toponly": "Ainult uusimad redaktsioonid",
     "sp-contributions-newonly": "Näita ainult uute lehekülgedega alustamist",
     "allmessagesname": "Nimi",
     "allmessagesdefault": "Vaiketekst",
     "allmessagescurrent": "Praegune tekst",
-    "allmessagestext": "See on loend kõikidest olemasolevatest süsteemisõnumitest MediaWiki nimeruumis.\nKui soovid MediaWiki tarkvara tõlkimises osaleda, siis vaata lehti [https://www.mediawiki.org/wiki/Localisation MediaWiki lokaliseerimine] ja [//translatewiki.net translatewiki.net].",
+    "allmessagestext": "See on loend kõikidest olemasolevatest süsteemisõnumitest MediaWiki nimeruumis.\nKui soovid MediaWiki tarkvara tõlkimises osaleda, siis vaata lehti [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki lokaliseerimine] ja [//translatewiki.net translatewiki.net].",
     "allmessagesnotsupportedDB": "Seda lehekülge ei saa kasutada, sest '''$wgUseDatabaseMessages''' ei tööta.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Muutmisoleku filter:",
index f4028ea..44611e3 100644 (file)
     "prefs-skin": "Itxura",
     "skin-preview": "Aurrebista",
     "datedefault": "Hobespenik ez",
-    "prefs-beta": "Beta ezaugarriak",
     "prefs-datetime": "Data eta ordua",
     "prefs-labs": "Labs ezaugarriak",
     "prefs-user-pages": "Erabiltzaile orriak",
     "nowatchlist": "Zure jarraipen zerrenda hutsik dago.",
     "watchlistanontext": "Mesedez $1 zure jarraipen zerrendako orrialdeak ikusi eta aldatu ahal izateko.",
     "watchnologin": "Saioa hasi gabe",
-    "watchnologintext": "[[Special:UserLogin|Saioa hasi]] behar duzu zure jarraipen zerrenda aldatzeko.",
     "addwatch": "Jarraipen zerrendara gehitu",
     "addedwatchtext": "«[[:$1]]» orria zure [[Special:Watchlist|jarraipen zerrendara]] erantsi da. \n\nOrri honetan aurrerantzean egindako aldaketak zerrenda horretan agertuko dira.",
     "removewatch": "Kendu zure jarraipen zerrendatik",
     "rollbacklinkcount-morethan": "desegin {{PLURAL:$1|edizio bat|$1 edizio}} baino gehiago",
     "rollbackfailed": "Desegiteak huts egin dud",
     "cantrollback": "Ezin da aldaketa desegin; erabiltzaile bakarrak hartu du parte.",
-    "alreadyrolled": "Ezin da [[User:$2|$2]](e)k ([[User talk:$2|Eztabaida]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) [[$1]](e)n egindako azken aldaketa desegin;\nbeste norbaitek editatu du edo jada desegin du.\n\n Azken aldaketa [[User:$3|$3]](e)k ([[User talk:$3|Eztabaida]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]) egin du.",
+    "alreadyrolled": "Ezin da [[User:$2|$2]] ([[User talk:$2|Eztabaida]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) wikilariak «[[$1]]» orrian egindako azken aldaketa desegin;\nbeste norbaitek editatu edo desegin du jadanik.\n\n Azken aldaketa [[User:$3|$3]] ([[User talk:$3|Eztabaida]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]) wikilariak egin du.",
     "editcomment": "Aldaketaren laburpena: \"''$1''\".",
     "revertpage": "[[Special:Contributions/$2|$2]] ([[User talk:$2|talk]]) wikilariaren aldaketak deseginda, edukia [[User:$1|$1]] wikilariaren azken bertsiora itzuli da.",
     "rollback-success": "$1 wikilariaren aldaketak deseginda,\nedukia $2 wikilariaren azken bertsiora itzuli da.",
     "allmessagesname": "Izena",
     "allmessagesdefault": "Testu lehenetsia",
     "allmessagescurrent": "Oraingo testua",
-    "allmessagestext": "MediaWikin erabiltzen diren mezu guztien zerrenda.\nMesedez bisitatu [https://www.mediawiki.org/wiki/Localisation MediaWiki] eta [//translatewiki.net translatewiki.net] orrialdeak MediaWikira ekarpenak egin badituzu.",
+    "allmessagestext": "MediaWikin erabiltzen diren mezu guztien zerrenda.\nMesedez bisitatu [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki] eta [//translatewiki.net translatewiki.net] orrialdeak MediaWikira ekarpenak egin badituzu.",
     "allmessagesnotsupportedDB": "Ezin da '''{{ns:special}}:Allmessages''' erabili '''$wgUseDatabaseMessages''' ezgaituta dagoelako.",
     "allmessages-filter-legend": "Iragazi",
     "allmessages-filter": "Aldaketa-egoeraren arabera iragazi:",
     "tooltip-recreate": "Orrialdea birsortu ezabatu egin den arren",
     "tooltip-upload": "Igoera hasi",
     "tooltip-rollback": "\"Desegin\" ekintzak orriaren azken egilearen ekarpena ezabatzen du klik batean",
-    "tooltip-undo": "\"Desegin\" botoiak egindako aldaketa ezeztatzen du eta aurreikuspen bista erakusten du.\nLaburpenean arrazoi bat gehitzea baimentzen du",
+    "tooltip-undo": "«Desegin» botoiak egindako aldaketa ezeztatzen du, eta aurreikuspen bista erakusten. Laburpenean arrazoi bat gehitzeko aukera ematen du.",
     "tooltip-preferences-save": "Hobespenak gorde",
     "tooltip-summary": "Laburpen labur bat sar ezazu",
     "common.css": "/** Hemen idatzitako CSS kodeak itxura guztietan izango du eragina */",
index a78feef..053cadf 100644 (file)
     "nowatchlist": "La tu lista e seguimientu está vacia.",
     "watchlistanontext": "Pa vel u eital las entrás ena tu lista e seguimientu es mestel $1.",
     "watchnologin": "Nu estás rustriu",
-    "watchnologintext": "Ebis [[Special:UserLogin|abril la tu cuenta]] pa puel hazel chambus ena tu lista e seguimientu.",
     "addedwatchtext": "S´á añiiu la páhina \"[[:$1]]\" a la tu [[Special:Watchlist|lista e seguimientu]].\nLos huturus chambus de la páhina i ena su caraba se muestrarán aquí,\ni el su entítulu apaicirá en '''negrina''' ena [[Special:RecentChanges|lista d´úrtimus chambus]].\n\nSi quieis ehal de vehilal la páhina, pursa sobri \"Ehal de vehilal\".",
     "removedwatchtext": "La página \"[[:$1]]\" á siu esborrá de la tu [[Special:Watchlist|lista de seguimientu]].",
     "watch": "Vegilal",
     "allmessagesname": "Nombri",
     "allmessagesdefault": "Testu pol defeutu",
     "allmessagescurrent": "Testu atual",
-    "allmessagestext": "Esta es una lista e mensahis del sistema disponibris nel espaciu e nombris MediaWiki:\nPol favol, vesita [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] i [//translatewiki.net translatewiki.net] si quieis colabutal.",
+    "allmessagestext": "Esta es una lista e mensahis del sistema disponibris nel espaciu e nombris MediaWiki:\nPol favol, vesita [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] i [//translatewiki.net translatewiki.net] si quieis colabutal.",
     "allmessagesnotsupportedDB": "Nu se puei gastal esta páhina polque '''$wgUseDatabaseMessages''' está desativau.",
     "thumbnail-more": "Agrandal",
     "filemissing": "Archivu escambulliu",
index 4806c7a..f969476 100644 (file)
@@ -1,6 +1,39 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "Alnokta",
+            "Americophile",
+            "Amire80",
+            "Armandaneshjoo",
+            "Armin1392",
+            "Calak",
+            "Dalba",
+            "Ebraminio",
+            "Fatemi127",
+            "Goudarz",
+            "Huji",
+            "Ladsgroup",
+            "Leyth",
+            "Mardetanha",
+            "Mehdi",
+            "Mehran",
+            "Meisam",
+            "Mjbmr",
+            "Omidh",
+            "Omnia",
+            "Reza1615",
+            "Rtemis",
+            "Sahim",
+            "Surena",
+            "Taha",
+            "Wayiran",
+            "Zack90",
+            "ZxxZxxZ",
+            "לערי ריינהארט",
+            "جواد",
+            "درفش کاویانی",
+            "محک"
+        ]
     },
     "tog-underline": "خط کشیدن زیر پیوندها:",
     "tog-hideminor": "تغییرات جزئی از فهرست تغییرات اخیر پنهان شوند",
     "prefs-skin": "پوسته",
     "skin-preview": "پیش‌نمایش",
     "datedefault": "بدون ترجیح",
-    "prefs-beta": "ویژگی‌های آزمایشی",
     "prefs-datetime": "تاریخ و زمان",
     "prefs-labs": "گزینه‌های آزمایشی",
     "prefs-user-pages": "صفحه‌های کاربری",
     "nowatchlist": "در فهرست پی‌گیری‌های شما هیچ موردی نیست.",
     "watchlistanontext": "برای مشاهده و ویرایش فهرست پی‌گیری‌های خود از $1 استفاده کنید.",
     "watchnologin": "به سامانه وارد نشده‌اید",
-    "watchnologintext": "برای تغییر فهرست پی‌گیری‌هایتان باید [[Special:UserLogin|به سامانه وارد شوید]].",
     "addwatch": "افزودن به فهرست پی‌گیری",
     "addedwatchtext": "صفحهٔ «[[:$1]]» به [[Special:Watchlist|فهرست پی‌گیری‌های]] شما اضافه شد.\nتغییرات این صفحه و صفحهٔ بحث متناظرش در آینده در اینجا فهرست خواهد شد.",
     "removewatch": "حذف از فهرست پی‌گیری",
     "sp-contributions-newbies-sub": "برای تازه‌کاران",
     "sp-contributions-newbies-title": "مشارکت‌های کاربری برای حساب‌های تازه‌کار",
     "sp-contributions-blocklog": "سیاههٔ بسته‌شدن‌ها",
+    "sp-contributions-suppresslog": "کمک‌های کاربر متوقف شده",
     "sp-contributions-deleted": "مشارکت‌های حذف‌شدهٔ کاربر",
     "sp-contributions-uploads": "بارگذاری‌ها",
     "sp-contributions-logs": "سیاهه‌ها",
     "sp-contributions-blocked-notice": "این کاربر در حال حاضر بسته شده‌است.\nآخرین سیاههٔ بسته شدن در زیر آمده‌است:",
     "sp-contributions-blocked-notice-anon": "این نشانی آی‌پی در حال حاضر بسته است.\nآخرین سیاههٔ بسته شدن در زیر آمده‌است:",
     "sp-contributions-search": "جستجوی مشارکت‌ها",
-    "sp-contributions-suppresslog": "کمک‌های کاربر متوقف شده",
     "sp-contributions-username": "نشانی آی‌پی یا نام کاربری:",
     "sp-contributions-toponly": "فقط ویرایش‌هایی که آخرین نسخه‌اند نمایش داده شود",
     "sp-contributions-newonly": "فقط نمایش ویرایش‌هایی که تولید‌های صفحه هستند",
     "allmessagesname": "نام",
     "allmessagesdefault": "متن پیش‌فرض پیغام",
     "allmessagescurrent": "متن کنونی پیغام",
-    "allmessagestext": "این فهرستی از پیغام‌های سامانه‌ای موجود در فضای نام مدیاویکی است.\nچنانچه مایل به مشارکت در محلی‌سازی مدیاویکی هستید لطفاً [https://www.mediawiki.org/wiki/Localisation محلی‌سازی مدیاویکی] و [//translatewiki.net translatewiki.net] را ببینید.",
+    "allmessagestext": "این فهرستی از پیغام‌های سامانه‌ای موجود در فضای نام مدیاویکی است.\nچنانچه مایل به مشارکت در محلی‌سازی مدیاویکی هستید لطفاً [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation محلی‌سازی مدیاویکی] و [//translatewiki.net translatewiki.net] را ببینید.",
     "allmessagesnotsupportedDB": "این صفحه نمی‌تواند استفاده شود به این دلیل که <bdi>'''$wgUseDatabaseMessages'''</bdi> غیرفعال شده‌است.",
     "allmessages-filter-legend": "پالایه",
     "allmessages-filter": "پالودن بر اساس وضعیت شخصی‌سازی:",
     "version-entrypoints": "نشانی اینترنتی محل ورود",
     "version-entrypoints-header-entrypoint": "نقطه ورود",
     "version-entrypoints-header-url": "نشانی اینترنتی",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath مسیر مقاله]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath مسیر اسکریپت]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath مسیر مقاله]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath مسیر اسکریپت]",
     "redirect": "تغییرمسیر توسط پرونده، کاربر، صفحه یا شناسهٔ نسخه",
     "redirect-legend": "تغییرمسیر به یک پرونده یا صفحه",
     "redirect-summary": "این صفحهٔ ویژه به پرونده (نام پرونده داده‌شده)، صفحه (شماره شناسهٔ صفحه یا شماره نسخهٔ داده‌شده) یا صفحهٔ کاربری (شناسهٔ عددی کاربری داده‌شده) تغییرمسیر می‌یابد. طرز استفاده: [[{{#Special:Redirect}}/file/Example.jpg]]، \n[[{{#Special:Redirect}}/page/64308]]، [[{{#Special:Redirect}}/revision/328429]] یا [[{{#Special:Redirect}}/user/101]].",
index 38dcb6c..914e2e6 100644 (file)
     "prefs-skin": "Ulkoasu",
     "skin-preview": "esikatselu",
     "datedefault": "Ei omaa määrittelyä",
-    "prefs-beta": "Beeta-ominaisuudet",
     "prefs-datetime": "Aika ja päiväys",
     "prefs-labs": "Testattavana olevat ominaisuudet",
     "prefs-user-pages": "Käyttäjäsivut",
     "download": "lataa",
     "unwatchedpages": "Tarkkailemattomat sivut",
     "listredirects": "Ohjaukset",
-    "listduplicatedfiles": "Luettelo tiedostoista, joista on kaksoiskappale.",
+    "listduplicatedfiles": "Luettelo tiedostoista, joista on kaksoiskappale",
     "listduplicatedfiles-summary": "Tämä on luettelo niistä tiedostoista, joiden uusin versio on kaksoiskappale eli täysin sama jonkun toisen tiedoston uusimman version kanssa. Vain paikallisesti tallennetut tiedostot tutkitaan.",
     "listduplicatedfiles-entry": "Tiedostosta [[:File:$1|$1]] on olemassa [[$3|{{PLURAL:$2|kaksoiskappale|$2 kaksoiskappaletta}}]].",
     "unusedtemplates": "Käyttämättömät mallineet",
     "listgrouprights-removegroup-self": "Voi poistaa itsensä {{PLURAL:$2|ryhmästä|ryhmistä}} $1",
     "listgrouprights-addgroup-self-all": "Voi lisätä itsensä kaikkiin ryhmiin",
     "listgrouprights-removegroup-self-all": "Voi poistaa itsensä kaikista ryhmistä",
+    "trackingcategories": "Tarkkailuluokat",
+    "trackingcategories-summary": "Tällä sivulla on luettelo sellaisista jälkiä seuraavista luokista (tarkkailuluokat), joiden sisällön synnyttää automaattisesti MediaWiki-ohjelmisto. Luokkien nimiä voi vaihtaa muuttamalla asianomaista järjestelmäviestiä nimiavaruudessa {{ns:8}}.",
+    "trackingcategories-msg": "Tarkkailuluokka",
+    "trackingcategories-name": "Viestin nimi",
+    "trackingcategories-desc": "Kriteerit luokkaan joutumiselle",
+    "post-expand-template-argument-category-desc": "Kun mallineen argumentti on laajennettu (argumentti on merkkijono kolmen kaarisulun sisällä kuten {{{Foo}}}), sivu on suurempi kuin $wgMaxArticleSize.",
+    "trackingcategories-nodesc": "Ei kuvausta olemassa.",
+    "trackingcategories-disabled": "Luokka on poistettu käytöstä",
     "mailnologin": "Lähettäjän osoite puuttuu",
     "mailnologintext": "Sinun pitää olla [[Special:UserLogin|kirjautuneena sisään]] ja [[Special:Preferences|asetuksissasi]] pitää olla toimiva ja <strong>varmennettu</strong> sähköpostiosoite, jotta voit lähettää sähköpostia muille käyttäjille.",
     "emailuser": "Lähetä sähköpostia tälle käyttäjälle",
     "nowatchlist": "Tarkkailulistallasi ei ole sivuja.",
     "watchlistanontext": "Sinun täytyy $1, jos haluat käyttää tarkkailulistaa.",
     "watchnologin": "Et ole kirjautunut sisään",
-    "watchnologintext": "Sinun pitää [[Special:UserLogin|kirjautua sisään]], jotta voisit käyttää tarkkailulistaasi.",
     "addwatch": "Lisää tarkkailulistalle",
     "addedwatchtext": "Sivu '''[[:$1]]''' on lisätty [[Special:Watchlist|tarkkailulistallesi]].\nTulevaisuudessa sivuun ja sen keskustelusivuun tehtävät muutokset listataan täällä.",
     "removewatch": "Poista tarkkailulistalta",
     "sp-contributions-newbies-sub": "Uusien käyttäjien muokkaukset",
     "sp-contributions-newbies-title": "Uusien käyttäjien muokkaukset",
     "sp-contributions-blocklog": "estoloki",
+    "sp-contributions-suppresslog": "häivytetyt käyttäjän muokkaukset",
     "sp-contributions-deleted": "poistetut muokkaukset",
     "sp-contributions-uploads": "tallennukset",
     "sp-contributions-logs": "lokit",
     "sp-contributions-blocked-notice": "Tämä käyttäjä on tällä hetkellä estetty. Alla on viimeisin estolokin tapahtuma:",
     "sp-contributions-blocked-notice-anon": "Tämä IP-osoite on tällä hetkellä estetty.\nAlla on viimeisin estolokin tapahtuma:",
     "sp-contributions-search": "Etsi muokkauksia",
-    "sp-contributions-suppresslog": "häivytetyt käyttäjän muokkaukset",
     "sp-contributions-username": "IP-osoite tai käyttäjätunnus",
     "sp-contributions-toponly": "Näytä vain muokkaukset, jotka ovat viimeisimpiä versioita",
     "sp-contributions-newonly": "Näytä vain muokkaukset, joilla on luotu sivu",
     "allmessagesname": "Nimi",
     "allmessagesdefault": "Oletusarvo",
     "allmessagescurrent": "Nykyinen arvo",
-    "allmessagestext": "Tämä on luettelo järjestelmäviesteistä, jotka ovat saatavilla MediaWiki-nimiavaruudessa.\nJos haluat muokata MediaWikin yleistä kotoistusta, käy [https://www.mediawiki.org/wiki/Localisation MediaWikin kotoistussivuilla] ja sivustolla [//translatewiki.net translatewiki.net].",
+    "allmessagestext": "Tämä on luettelo järjestelmäviesteistä, jotka ovat saatavilla MediaWiki-nimiavaruudessa.\nJos haluat muokata MediaWikin yleistä kotoistusta, käy [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWikin kotoistussivuilla] ja sivustolla [//translatewiki.net translatewiki.net].",
     "allmessagesnotsupportedDB": "Tämä sivu ei ole käytössä, koska <tt>$wgUseDatabaseMessages</tt>-asetus on pois päältä.",
     "allmessages-filter-legend": "Suodata",
     "allmessages-filter": "Suodata muutosten perusteella",
     "expand_templates_remove_nowiki": "Poista <nowiki>-tagit tulosteesta",
     "expand_templates_generate_xml": "Näytä XML-jäsennyspuu",
     "expand_templates_generate_rawhtml": "Näytä raaka HTML",
-    "expand_templates_preview": "Esikatselu",
-    "trackingcategories": "Tarkkailuluokat",
-    "trackingcategories-summary": "Tällä sivulla on luettelo sellaisista jälkiä seuraavista luokista (tarkkailuluokat), joiden sisällön synnyttää automaattisesti MediaWiki-ohjelmisto. Luokkien nimiä voi vaihtaa muuttamalla asianomaista järjestelmäviestiä nimiavaruudessa {{ns:8}}.",
-    "trackingcategories-msg": "Tarkkailuluokka",
-    "trackingcategories-name": "Viestin nimi",
-    "trackingcategories-desc": "Kriteerit luokkaan joutumiselle",
-    "trackingcategories-nodesc": "Ei kuvausta olemassa.",
-    "trackingcategories-disabled": "Luokka on poistettu käytöstä"
+    "expand_templates_preview": "Esikatselu"
 }
index ce7a865..bb14ba2 100644 (file)
     "prefs-skin": "Hamur",
     "skin-preview": "Forskoðan",
     "datedefault": "Ongi serlig ynskir",
-    "prefs-beta": "Betafunktiónir",
     "prefs-datetime": "Dato og tíð",
     "prefs-labs": "Testfunktiónir",
     "prefs-user-pages": "Brúkarasíður",
     "nowatchlist": "Tú hevur ongar lutir í eftirlitinum.",
     "watchlistanontext": "Vinarliga $1 fyri at síggja ella rætta lutir í tínum eftirlitslista.",
     "watchnologin": "Tú hevur ikki ritað inn",
-    "watchnologintext": "Tú mást vera [[Special:UserLogin|innritað/ur]] fyri at broyta tín eftirlitslista.",
     "addwatch": "Legg til eftirlitslista",
     "addedwatchtext": "Síðan  \"[[:$1]]\" er løgd undir [[Special:Watchlist|eftirlitslistan]] hjá tær.\nFramtíðar broytingar á hesi síðu og tilknýttu kjaksíðuni verða at síggja har.",
     "removewatch": "Tak burtur frá eftirlistslistanum",
     "allmessagesname": "Navn",
     "allmessagesdefault": "Enskur tekstur",
     "allmessagescurrent": "Verandi tekstur",
-    "allmessagestext": "Hetta er eitt yvirlit av tøkum kervisboðum í MediaWiki-navnarúmi.\nVinarliga vitja [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] og [//translatewiki.net translatewiki.net] um tú ynskir at geva títt íkast til ta generisku MediaWiki lokalisatiónina.",
+    "allmessagestext": "Hetta er eitt yvirlit av tøkum kervisboðum í MediaWiki-navnarúmi.\nVinarliga vitja [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] og [//translatewiki.net translatewiki.net] um tú ynskir at geva títt íkast til ta generisku MediaWiki lokalisatiónina.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:AllMessages''' er ikki stuðlað orsakað av at '''$wgUseDatabaseMessages''' er sløkt.",
     "allmessages-filter-legend": "Filtur",
     "allmessages-filter-unmodified": "Óbroytt",
index d66dbf7..fa91554 100644 (file)
     "pool-timeout": "Délai d'attente dépassé",
     "pool-queuefull": "La file d'attente est pleine",
     "pool-errorunknown": "Erreur inconnue",
+    "pool-servererror": "Le service de comptage de la réserve n’est pas disponible ($1).",
     "aboutsite": "À propos de {{SITENAME}}",
     "aboutpage": "Project:À propos",
     "copyright": "Le contenu est disponible sous licence $1 sauf mention contraire.",
     "prefs-skin": "Habillage",
     "skin-preview": "Prévisualiser",
     "datedefault": "Aucune préférence",
-    "prefs-beta": "Fonctionnalités bêta",
     "prefs-datetime": "Date et heure",
     "prefs-labs": "Fonctionnalités « labs »",
     "prefs-user-pages": "Pages utilisateur",
     "listgrouprights-removegroup-self": "Peut se retirer {{PLURAL:$2|le groupe|les groupes}} de son propre compte : $1",
     "listgrouprights-addgroup-self-all": "Peut s'ajouter tous les groupes à son propre compte",
     "listgrouprights-removegroup-self-all": "Peut se retirer tous les groupes de son propre compte",
+    "trackingcategories": "Catégories de suivi",
+    "trackingcategories-summary": "Cette page liste les catégories de suivi qui sont remplies automatiquement par le logiciel MédiaWiki. Leurs noms peuvent être changés en modifiant les messages systèmes correspondants dans l’espace de noms {{ns:8}}.",
+    "trackingcategories-msg": "Catégorie de suivi",
+    "trackingcategories-name": "Nom du message",
+    "trackingcategories-desc": "Critère d’inclusion de la catégorie",
+    "noindex-category-desc": "La page contient un mot magique <nowiki>__NOINDEX__</nowiki> (et est dans un espace de noms où ce marquage est autorisé), et donc ne sera pas indexée par les robots.",
+    "index-category-desc": "La page contient un <nowiki>__INDEX__</nowiki> (et est dans un espace de noms où ce marquage est autorisé), et sera donc indexée par les robots alors qu’elle ne l’aurait pas été normalement.",
+    "post-expand-template-inclusion-category-desc": "Après avoir développé tous les modèles, la taille de la page dépasse $wgMaxArticleSize ; certains modèles n’ont donc pas été développés.",
+    "post-expand-template-argument-category-desc": "Après avoir développé l’argument d’un modèle (quelque chose entre accolades triples, comme {{{Foo}}}), la page dépasse $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "Trop de fonctions coûteuses de l’analyseur (comme <code>#ifexist</code>) sont incluses dans une page. Voyez [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Catégorie ajoutée su la page contient un lien de fichier incorrect (un lien pour inclure un fichier alors que celui-ci n’existe pas).",
+    "hidden-category-category-desc": "C’est une catégorie contenant <nowiki>__HIDDENCAT__</nowiki>, qui empêche son affichage dans la zone des liens de catégorie sur les pages, par défaut.",
+    "trackingcategories-nodesc": "Aucune description disponible.",
+    "trackingcategories-disabled": "La catégorie est désactivée",
     "mailnologin": "Pas d'adresse d'expéditeur",
     "mailnologintext": "Vous devez être [[Special:UserLogin|identifié]] et avoir indiqué une adresse électronique valide dans vos [[Special:Preferences|préférences]] pour pouvoir envoyer des courriels à d'autres utilisateurs.",
     "emailuser": "Lui envoyer un courriel",
     "nowatchlist": "Votre liste de suivi ne référence aucune page.",
     "watchlistanontext": "Veuillez vous $1 pour visualiser ou modifier les éléments de votre liste de suivi.",
     "watchnologin": "Non connecté",
-    "watchnologintext": "Vous devez être [[Special:UserLogin|identifié]] pour modifier votre liste de suivi.",
     "addwatch": "Ajouter à la liste de suivi",
     "addedwatchtext": "La page « [[:$1]] » a été ajoutée à votre [[Special:Watchlist|liste de suivi]].\nLes prochaines modifications de cette page et de la page de discussion associée y seront répertoriées.",
     "removewatch": "Supprimer de la liste de suivi",
     "sp-contributions-newbies-sub": "Parmi les nouveaux comptes",
     "sp-contributions-newbies-title": "Contributions d'utilisateurs parmi les nouveaux comptes",
     "sp-contributions-blocklog": "journal des blocages",
+    "sp-contributions-suppresslog": "contributions masquées",
     "sp-contributions-deleted": "contributions supprimées",
     "sp-contributions-uploads": "imports",
     "sp-contributions-logs": "journaux",
     "sp-contributions-blocked-notice": "Cet utilisateur est actuellement bloqué. La dernière entrée du journal des blocages est indiquée ci-dessous à titre d'information :",
     "sp-contributions-blocked-notice-anon": "Cette adresse IP est actuellement bloquée.\nLa dernière entrée du journal des blocages est indiquée ci-dessous à titre d'information :",
     "sp-contributions-search": "Rechercher les contributions",
-    "sp-contributions-suppresslog": "contributions masquées",
     "sp-contributions-username": "Adresse IP ou nom d'utilisateur :",
     "sp-contributions-toponly": "Ne montrer que les contributions qui sont les dernières des articles",
     "sp-contributions-newonly": "Afficher uniquement les modifications qui sont des créations de page",
     "allmessagesname": "Nom du message",
     "allmessagesdefault": "Message par défaut",
     "allmessagescurrent": "Message actuel",
-    "allmessagestext": "Ceci est la liste des messages disponibles dans l’espace MediaWiki.\nVeuillez visiter la [https://www.mediawiki.org/wiki/Localisation Localisation de MediaWiki] et [//translatewiki.net/ translatewiki.net] si vous désirez contribuer à la localisation générique de MediaWiki.",
+    "allmessagestext": "Ceci est la liste des messages disponibles dans l’espace MediaWiki.\nVeuillez visiter la [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Localisation de MediaWiki] et [//translatewiki.net/ translatewiki.net] si vous désirez contribuer à la localisation générique de MediaWiki.",
     "allmessagesnotsupportedDB": "Cette page '''{{ns:special}}:Allmessages''' n'est pas utilisable car '''$wgUseDatabaseMessages''' a été désactivé.",
     "allmessages-filter-legend": "Filtrer",
     "allmessages-filter": "Filtrer par état de modification :",
     "version-entrypoints": "URL des points d'entrée",
     "version-entrypoints-header-entrypoint": "Point d'entrée",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Chemin d’article]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Chemin de script]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Chemin d’article]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Chemin de script]",
     "redirect": "Redirigé par fichier, utilisateur, page ou ID de révision",
     "redirect-legend": "Rediriger vers une page ou un fichier",
     "redirect-summary": "Cette page spéciale redirige vers un fichier (nom de fichier fourni), une page (ID de révision ou de page fourni) ou une page d’utilisateur (identifiant numérique de l’utilisateur fourni). Utilisation : [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], ou [[{{#Special:Redirect}}/user/101]].",
     "expand_templates_remove_nowiki": "Supprime les marqueurs <nowiki> dans le résultat",
     "expand_templates_generate_xml": "Voir l’arborescence d’analyse XML",
     "expand_templates_generate_rawhtml": "Afficher le HTML brut",
-    "expand_templates_preview": "Aperçu du rendu",
-    "trackingcategories": "Catégories de suivi",
-    "trackingcategories-summary": "Cette page liste les catégories de suivi qui sont remplies automatiquement par le logiciel MédiaWiki. Leurs noms peuvent être changés en modifiant les messages systèmes correspondants dans l’espace de noms {{ns:8}}.",
-    "trackingcategories-msg": "Catégorie de suivi",
-    "trackingcategories-name": "Nom du message",
-    "trackingcategories-desc": "Critère d’inclusion de la catégorie",
-    "noindex-category-desc": "La page contient un mot magique <nowiki>__NOINDEX__</nowiki> (et est dans un espace de noms où ce marquage est autorisé), et donc ne sera pas indexée par les robots.",
-    "index-category-desc": "La page contient un <nowiki>__INDEX__</nowiki> (et est dans un espace de noms où ce marquage est autorisé), et sera donc indexée par les robots alors qu’elle ne l’aurait pas été normalement.",
-    "post-expand-template-inclusion-category-desc": "Après avoir développé tous les modèles, la taille de la page dépasse $wgMaxArticleSize ; certains modèles n’ont donc pas été développés.",
-    "post-expand-template-argument-category-desc": "Après avoir développé l’argument d’un modèle (quelque chose entre accolades triples, comme {{{Foo}}}), la page dépasse $wgMaxArticleSize.",
-    "expensive-parserfunction-category-desc": "Trop de fonctions coûteuses de l’analyseur (comme #ifexists) sont incluses dans une page. Voyez [https://www.mediawiki.org/wiki/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-    "broken-file-category-desc": "Catégorie ajoutée su la page contient un lien de fichier incorrect (un lien pour inclure un fichier alors que celui-ci n’existe pas).",
-    "hidden-category-category-desc": "C’est une catégorie contenant <nowiki>__HIDDENCAT__</nowiki>, qui empêche son affichage dans la zone des liens de catégorie sur les pages, par défaut.",
-    "trackingcategories-nodesc": "Aucune description disponible.",
-    "trackingcategories-disabled": "La catégorie est désactivée"
+    "expand_templates_preview": "Aperçu du rendu"
 }
index a68bf33..8726b31 100644 (file)
     "prefs-skin": "Habelyâjo",
     "skin-preview": "Prèvêre",
     "datedefault": "Niona prèference",
-    "prefs-beta": "Fonccionalitâts « Bèta »",
     "prefs-datetime": "Dâta et hora",
     "prefs-labs": "Fonccionalitâts « Laboratiors »",
     "prefs-user-pages": "Pâges utilisator",
     "nowatchlist": "Vos éd gins de piéce dedens voutra lista de siuvu.",
     "watchlistanontext": "Se vos plét, vos vos dête $1 por povêr vêre ou ben changiér les piéces de voutra lista de siuvu.",
     "watchnologin": "Pas branchiê",
-    "watchnologintext": "Vos dête étre [[Special:UserLogin|branchiê(ye)]] por povêr changiér voutra lista de siuvu.",
     "addwatch": "Apondre a la lista de siuvu",
     "addedwatchtext": "La pâge « [[:$1]] » est étâye apondua a voutra [[Special:Watchlist|lista de siuvu]].\nLos changements que vegnont de ceta pâge et de la sina pâge de discussion y seront listâs.",
     "removewatch": "Enlevar de la lista de siuvu",
     "allmessagesname": "Nom du mèssâjo",
     "allmessagesdefault": "Mèssâjo per dèfôt",
     "allmessagescurrent": "Tèxto d’ora",
-    "allmessagestext": "O est la lista des mèssâjos sistèmo disponiblos dens l’èspâço MediaWiki.\nVolyéd visitar la [https://www.mediawiki.org/wiki/Localisation localisacion de MediaWiki] et pués [//translatewiki.net translatewiki.net] se vos voléd contribuar a la localisacion g·ènèrica de MediaWiki.",
+    "allmessagestext": "O est la lista des mèssâjos sistèmo disponiblos dens l’èspâço MediaWiki.\nVolyéd visitar la [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation localisacion de MediaWiki] et pués [//translatewiki.net translatewiki.net] se vos voléd contribuar a la localisacion g·ènèrica de MediaWiki.",
     "allmessagesnotsupportedDB": "Ceta pâge '''{{ns:special}}:Allmessages''' est inutilisâbla perce que '''$wgUseDatabaseMessages''' at étâ dèsactivâ.",
     "allmessages-filter-legend": "Filtro",
     "allmessages-filter": "Filtrar per ètat de changement :",
index 11159ce..2ed86fb 100644 (file)
     "pool-timeout": "Tidj uflepen bi't teewen üüb't sperang",
     "pool-queuefull": "Pool as auerläästet",
     "pool-errorunknown": "Ünbekäänd feeler",
+    "pool-servererror": "Di pooltäälersiinst werket ei ($1).",
     "aboutsite": "Auer {{SITENAME}}",
     "aboutpage": "Project:Auer",
     "copyright": "Det sidj as tu fun oner $1 , wan diar niks ööders stäänt.",
     "revdelete-no-file": "Son dateinööm as ei diar.",
     "revdelete-show-file-confirm": "Wel dü würelk det stregen werjuun faan det datei „<nowiki>$1</nowiki>“ faan di $2, am a klook $3 uunluke?",
     "revdelete-show-file-submit": "Ja",
+    "revdelete-selected-text": "'''{{PLURAL:$1|ütjsoocht werjuun|ütjsoocht werjuunen}} faan [[:$2]]:'''",
+    "revdelete-selected-file": "Ütjsoocht {{PLURAL:$1|dateiwerjuun|dateiwerjuunen}} faan [[:$2]]:",
     "logdelete-selected": "{{PLURAL:$1|Ütjsoocht logbukiindrach|Ütjsoocht logbukiindracher}}:",
     "revdelete-text-text": "Stregen werjuunen bliiw uun't werjuunshistoore, man dialen diarfaan san ei för arken tu sen.",
     "revdelete-text-file": "Stregen datei-werjuunen bliiw uun't werjuunshistoore, man dialen diarfaan san ei för arken tu sen.",
     "prefs-skin": "Skak",
     "skin-preview": "Föörskau",
     "datedefault": "Föör-iinstelang",
-    "prefs-beta": "Beta mögelkhaiden",
     "prefs-datetime": "Dai an klooktidj",
     "prefs-labs": "Alpha mögelkhaiden",
     "prefs-user-pages": "Brükersidjen",
     "listgrouprights-removegroup-self": "Aanj brükerkonto faan {{PLURAL:$2|detdiar skööl|jodiar sköölen}} wechnem: $1",
     "listgrouprights-addgroup-self-all": "Koon aal a sköölen tu't aanj brükerkonto tuwise",
     "listgrouprights-removegroup-self-all": "Koon aal a sköölen faan't aanj brükerkonto wechnem",
+    "trackingcategories": "Kategoriin ferfulge",
+    "trackingcategories-summary": "Üüb detdiar sidj stun ferfulagt kategoriin, diar faan't MediaWiki-software iindraanj wurden san. Hör nöömer kön feranert wurd, wan dü a süsteem-noorachten uun a {{ns:8}}-nöömrüm feranerst.",
+    "trackingcategories-msg": "Kategorii ferfulge",
+    "trackingcategories-name": "Nööm faan't bööd",
+    "trackingcategories-desc": "Kriteerien för't iinbinjen faan kategoriin.",
+    "noindex-category-desc": "Üüb detdiar sidj stäänt det maagisk wurd <nowiki>__NOINDEX__</nowiki> an as uun en nöömrüm, huar det tuläät as. Sodenang woort det faan a bots ei indisiaret.",
+    "index-category-desc": "Üüb detdiar sidj stäänt det maagisk wurd <nowiki>__INDEX__</nowiki> an as uun en nöömrüm, huar det ei tuläät as. Sodenang woort det faan a bots likes indisiaret.",
+    "post-expand-template-inclusion-category-desc": "Efter't ütjwidjin faan a föörlaagen as det sidj grater üs $wgMaxArticleSize, sodenang kön enkelt föörlaagen ei ütjwidjet wurd.",
+    "post-expand-template-argument-category-desc": "Efter't ütjwidjin faan en föörlaagenargument (det stäänt uun trebelt kläämen so üs {{{Foo}}}) as det sidj grater üs $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "Diar san tu föl parser-funktjuunen (so üs <code>#ifexist</code>) uun det sidj iinbünjen. Luke efter uun't [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit brüker-hoonbuk].",
+    "broken-file-category-desc": "Detdiar kategorii woort iinsaat, wan üüb det sidj en uunstaken ferwisang föörkomt. (Det as ferlicht en ferwisang üüb en datei, wat det goorei jaft.)",
+    "hidden-category-category-desc": "Det as en kategorii, huar <nowiki>__HIDDENCAT__</nowiki> üüb stäänt. Hat woort normoolerwiis ei bi a kategoriin uunwiset.",
+    "trackingcategories-nodesc": "Diar as nian beskriiwang.",
+    "trackingcategories-disabled": "Detdiar kategorii as ufsteld wurden",
     "mailnologin": "Bi't e-mail ferschüüren as wat skiaf gingen",
     "mailnologintext": "Dü skel [[Special:UserLogin|uunmeldet wees]] an en gudkäänd e-mail-adres uun din [[Special:Preferences|iinstelangen]] haa, am dat dü ööder brükern en e-mail schüür könst.",
     "emailuser": "E-mail tu didiar brüker",
     "nowatchlist": "Diar as nään iindrach, diar dü uun't uug behual wel.",
     "watchlistanontext": "Dü skel di $1, am iindracher tu leesen of tu bewerkin, diar dü uun't uug behual wel.",
     "watchnologin": "Ei uunmeldet",
-    "watchnologintext": "Dü skel [[Special:UserLogin|uunmeldet]] wees, am iindracher tu bewerkin, diar dü uun't uug behual wel.",
     "addwatch": "Uk uun't uug behual",
     "addedwatchtext": "Det sidj „[[:$1]]“ wel dü [[Special:Watchlist|uun't uug behual]].\nFeranrangen faan detdiar sidj wurd üüb detdiar list fäästhäälen.",
     "removewatch": "Ei muar uun't uug behual",
     "sp-contributions-newbies-sub": "Faan nei brükern",
     "sp-contributions-newbies-title": "Brükerbidracher faan nei brükern",
     "sp-contributions-blocklog": "Sper-logbuk",
+    "sp-contributions-suppresslog": "Ei uunwiset brüker-bidracher",
     "sp-contributions-deleted": "Stregen bidracher",
     "sp-contributions-uploads": "Huuchschüürd bilen",
     "sp-contributions-logs": "Logbuken",
     "sp-contributions-blocked-notice": "Didiar brüker as speret. Det stäänt uun't sperlogbuk:",
     "sp-contributions-blocked-notice-anon": "Detdiar IP-adres as speret. Det stäänt uun't sperlogbuk:",
     "sp-contributions-search": "Schük efter brükerbidracher",
-    "sp-contributions-suppresslog": "Ei uunwiset brüker-bidracher",
     "sp-contributions-username": "IP-adres of brükernööm:",
     "sp-contributions-toponly": "Bluas aktuel werjuunen wise",
     "sp-contributions-newonly": "Bluas nei maaget sidjen wise",
     "allmessagesname": "Nööm",
     "allmessagesdefault": "Standard tekst",
     "allmessagescurrent": "Aktuel tekst",
-    "allmessagestext": "Det as en list mä MediaWiki-süsteemteksten.\nWees so gud an beschük a sidjen [https://www.mediawiki.org/wiki/Localisation MediaWiki-auersaatang] an [//translatewiki.net translatewiki.net], wan dü bi't auersaaten mähalep meest.",
+    "allmessagestext": "Det as en list mä MediaWiki-süsteemteksten.\nWees so gud an beschük a sidjen [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki-auersaatang] an [//translatewiki.net translatewiki.net], wan dü bi't auersaaten mähalep meest.",
     "allmessagesnotsupportedDB": "Detdiar spezial-sidj koon ei brükt wurd, auer <tt>$wgUseDatabaseMessages</tt> ei aktiif as.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filter för di uunpaaset stant:",
index fdce5d8..8d0a4d6 100644 (file)
     "watchlistfor2": "Par $1 $2",
     "nowatchlist": "Nissun element al è tignût di voli.",
     "watchnologin": "No tu sês jentrât",
-    "watchnologintext": "Tu 'nd âs di [[Special:UserLogin|jentrâ]] par modificâ la liste des pagjinis tignudis di voli.",
     "addedwatchtext": "La pagjine \"<nowiki>$1</nowiki>\" e je stade zontade ae [[Special:Watchlist|liste di chês tignudis di voli]].\nTal futûr i cambiaments a cheste pagjine e ae pagjine di discussion relative a saran segnalâts ca,\ne la pagjine e sarà '''gruessute''' te [[Special:RecentChanges|liste dai ultins cambiaments]] cussì che tu puedis notâle daurman.\n\n<p>Se tu vuelis gjavâle de liste pi indevant, frache su \"No stâ tignî di voli\" te sbare in alt.",
     "removedwatchtext": "La pagjine \"[[:$1]]\" e je stade gjavade de [[Special:Watchlist|liste di chês tignudis di voli]].",
     "watch": "Ten di voli",
     "allmessagesname": "Non",
     "allmessagesdefault": "Test predeterminât",
     "allmessagescurrent": "Test curint",
-    "allmessagestext": "Cheste e je une liste dai messaçs di sisteme disponibii tal non dal spazi MediaWiki.\nPar plasê va su [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se tu vuelis contribuî ae traduzion gjeneriche di MediaWiki.",
+    "allmessagestext": "Cheste e je une liste dai messaçs di sisteme disponibii tal non dal spazi MediaWiki.\nPar plasê va su [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se tu vuelis contribuî ae traduzion gjeneriche di MediaWiki.",
     "allmessages-filter-all": "Ducj",
     "allmessages-language": "Lenghe:",
     "allmessages-filter-submit": "Va",
index bf4d458..eb41f36 100644 (file)
     "mywatchlist": "Folchlist",
     "nowatchlist": "Jo hawwe gjin siden op jo folchlist.",
     "watchnologin": "Net oanmeld yn",
-    "watchnologintext": "Jo moatte [[Special:UserLogin|oanmeld]] wêze om jo folchlist te feroarjen.",
     "addedwatchtext": "De side \"'''[[:$1]]'''\" is tafoege oan jo [[Special:Watchlist|folchlist]]. Bewurkings fan dizze side en oerlisside wurde yn de takomst op jo folchlist oanjûn. Hja wurde foar jo ek '''fet''' printe op [[Special:RecentChanges|Koartlyn feroare]].\n\nAt jo letter in side net mear folgje wolle, dan brûke jo op dy side de keppeling \"Ferjit dizze side.\" Jo [[Special:Watchlist|folchlist]] hat ek in keppeling \"Jo folchlist bewurkje,\" foar at jo mear as ien side \"ferjitte\" wolle.",
     "removedwatchtext": "De side \"[[:$1]]\" stiet net mear op jo folchlist.",
     "watch": "Folgje",
     "allmessagesname": "Namme",
     "allmessagesdefault": "Standerttekst",
     "allmessagescurrent": "Tekst yn de nijste ferzje",
-    "allmessagestext": "Dit is in list fan alle systeemberjochten beskikber yn de MediaWiki-nammeromte.\nSjoch: [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation], [//translatewiki.net translatewiki.net].",
+    "allmessagestext": "Dit is in list fan alle systeemberjochten beskikber yn de MediaWiki-nammeromte.\nSjoch: [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation], [//translatewiki.net translatewiki.net].",
     "thumbnail-more": "Fergrutsje",
     "filemissing": "Triem net fûn",
     "thumbnail_error": "Flater by it oanmeitsjen fan thumbnail: $1",
index 9b87b60..285c558 100644 (file)
     "nowatchlist": "Níl aon rud ar do liosta faire.",
     "watchlistanontext": "$1, le d'thoil, chun míreanna ar do liosta faire a fheiceáil ná a athrú.",
     "watchnologin": "Níl tú logáilte isteach",
-    "watchnologintext": "Tá ort a bheith [[Special:UserLogin|logáilte isteach]] chun do liosta faire a athrú.",
     "addedwatchtext": "Cuireadh an leathanach \"<nowiki>$1</nowiki>\" le do [[Special:Watchlist|liosta faire]].\nAmach anseo liostálfar athruithe don leathanach seo agus dá leathanach plé ansin,\nagus beidh '''cló trom''' ar a theideal san [[Special:RecentChanges|liosta de na hathruithe is déanaí]] sa chaoi go bhfeicfeá iad go héasca.",
     "removedwatchtext": "Baineadh an leathanach \"[[:$1]]\" as [[Special:Watchlist|do liosta faire]].",
     "watch": "Déan faire",
     "allmessagesname": "Ainm",
     "allmessagesdefault": "Téacs réamhshocraithe",
     "allmessagescurrent": "Téacs reatha",
-    "allmessagestext": "Is liosta é seo de theachtaireachtaí córais atá le fáil san ainmspás MediaWiki.\nTabhair cuairt ar [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] agus [//translatewiki.net translatewiki.net] le do thoil más mian leat cur leis an logánú ginearálta MediaWiki.",
+    "allmessagestext": "Is liosta é seo de theachtaireachtaí córais atá le fáil san ainmspás MediaWiki.\nTabhair cuairt ar [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] agus [//translatewiki.net translatewiki.net] le do thoil más mian leat cur leis an logánú ginearálta MediaWiki.",
     "allmessagesnotsupportedDB": "Ní féidir an leathanach seo a úsáid dá bharr gur díchumasaíodh '''$wgUseDatabaseMessages'''.",
     "allmessages-filter-all": "Uile",
     "allmessages-language": "Teanga:",
index 0af5c70..c315751 100644 (file)
     "nowatchlist": "倷𠮶监视列表什哩都冇有。",
     "watchlistanontext": "请$1眵吖或改吖倷𠮶监视列表。",
     "watchnologin": "冇登入",
-    "watchnologintext": "倷要[[Special:UserLogin|登入]]起才改得正倷𠮶监视列表。",
     "addedwatchtext": "页面\"[[:$1]]\" 加到嘞倷𠮶[[Special:Watchlist|监视列表]]。个页同佢𠮶讨论页𠮶全部改动以后都会列到许首,佢会用'''粗体''' 列到[[Special:RecentChanges|最近更改]]让倷更加容易识别。 倷以后要系拿佢到监视列表删卟佢𠮶话,就到导航条点吖“莫眏到”。",
     "removedwatchtext": "页面[[:$1]]到[[Special:Watchlist|倷𠮶监视列表]]删卟哩。",
     "watch": "眏到",
     "allmessagesname": "名字",
     "allmessagesdefault": "默认文字",
     "allmessagescurrent": "眼前𠮶文字",
-    "allmessagestext": "个首列到全部制定得正𠮶系统界面。\nPlease visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
+    "allmessagestext": "个首列到全部制定得正𠮶系统界面。\nPlease visit [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:系统界面功能'''关卟嘞('''$wgUseDatabaseMessages''')。",
     "thumbnail-more": "放大",
     "filemissing": "寻伓到档案",
index 9c8eb9d..aeb3d49 100644 (file)
     "nowatchlist": "倷嗰監視列表什哩都冇有。",
     "watchlistanontext": "請$1眵吖或改吖倷嗰監視列表。",
     "watchnologin": "冇登入",
-    "watchnologintext": "倷要[[Special:UserLogin|登入]]起才改得正倷嗰監視列表。",
     "addedwatchtext": "頁面「[[:$1]]」加到嘞倷嗰[[Special:Watchlist|監視列表]]。箇頁同佢嗰討論頁嗰全部改動以後都會列到許首,佢會用'''粗體''' 列到[[Special:RecentChanges|最近更改]]讓倷更加容易識別。 倷以後要係拿佢到監視列表刪卟佢嗰話,就到導航條點吖「莫眏到」。",
     "removedwatchtext": "頁面[[:$1]]到[[Special:Watchlist|倷嗰監視列表]]刪卟哩。",
     "watch": "眏到",
     "allmessagesname": "名字",
     "allmessagesdefault": "默認文字",
     "allmessagescurrent": "眼前嗰文字",
-    "allmessagestext": "箇首列到全部制定得正嗰系統界面。\nPlease visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
+    "allmessagestext": "箇首列到全部制定得正嗰系統界面。\nPlease visit [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:系統界面功能'''關卟嘞('''$wgUseDatabaseMessages''')。",
     "thumbnail-more": "放大",
     "filemissing": "尋伓到檔案",
index 9fa15ae..951a52c 100644 (file)
     "prefs-skin": "Bian",
     "skin-preview": "Ro-shealladh",
     "datedefault": "Gun roghainnean",
-    "prefs-beta": "Feartan Beta",
     "prefs-datetime": "Ceann-là is àm",
     "prefs-labs": "Feartan nan deuchainn-lannan",
     "prefs-user-pages": "Duilleagan a' chleachdaiche",
     "allmessages": "Teachdaireachdan an t-siostaim",
     "allmessagesname": "Ainm",
     "allmessagesdefault": "Teacsa bunaiteach na teachdaireachd",
-    "allmessagestext": "Seo liosta de theachdaireachdan an t-siostaim a tha ri làimh ann an namespace MediaWiki.\nTadhail air [https://www.mediawiki.org/wiki/Localisation Ionadaileadh MediaWiki] is [//translatewiki.net translatewiki.net] ma tha thu airson pàirt a ghabhail ann an ionadaileadh MediaWiki.",
+    "allmessagestext": "Seo liosta de theachdaireachdan an t-siostaim a tha ri làimh ann an namespace MediaWiki.\nTadhail air [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Ionadaileadh MediaWiki] is [//translatewiki.net translatewiki.net] ma tha thu airson pàirt a ghabhail ann an ionadaileadh MediaWiki.",
     "thumbnail-more": "Meudaich",
     "filemissing": "Faidhle a dhìth",
     "thumbnail_error": "Mearachd le cruthachadh na h-ìomhaigheige: $1",
index d2ecdc7..a6e7ffc 100644 (file)
@@ -13,7 +13,8 @@
             "Toliño",
             "Vivaelcelta",
             "Xosé",
-            "לערי ריינהארט"
+            "לערי ריינהארט",
+            "Fitoschido"
         ]
     },
     "tog-underline": "Subliñar as ligazóns:",
     "pool-timeout": "Tempo límite de espera para o peche",
     "pool-queuefull": "A cola está chea",
     "pool-errorunknown": "Erro descoñecido",
+    "pool-servererror": "O servidor de contador de recursos comúns non está dispoñible ($1).",
     "aboutsite": "Acerca de {{SITENAME}}",
     "aboutpage": "Project:Acerca de",
     "copyright": "Todo o contido está dispoñible baixo a licenza $1, agás que se indique o contrario.",
     "content-model-text": "texto simple",
     "content-model-javascript": "JavaScript",
     "content-model-css": "CSS",
-    "expensive-parserfunction-warning": "'''Aviso:''' Esta páxina contén demasiados analizadores de funcións de chamadas.\n\nDebe ter menos {{PLURAL:$2|dunha chamada|de $2 chamadas}}, e agora hai $1.",
-    "expensive-parserfunction-category": "Páxinas con moitos analizadores de funcións de chamadas moi caros",
+    "expensive-parserfunction-warning": "'''Aviso:''' Esta páxina contén demasiadas chamadas a funcións analíticas custosas.\n\nDebe ter menos {{PLURAL:$2|dunha chamada|de $2 chamadas}}, e agora hai $1.",
+    "expensive-parserfunction-category": "Páxinas con moitas chamadas a funcións analíticas custosas",
     "post-expand-template-inclusion-warning": "'''Aviso:''' O tamaño do modelo é moi grande.\nAlgúns modelos non se incluirán.",
     "post-expand-template-inclusion-category": "Páxinas nas que se excede o tamaño dos modelos",
     "post-expand-template-argument-warning": "'''Aviso:''' Esta páxina contén, polo menos, un argumento de modelo que ten un tamaño e expansión moi grande.\nEstes argumentos foron omitidos.",
     "prefs-skin": "Aparencia",
     "skin-preview": "Vista previa",
     "datedefault": "Ningunha preferencia",
-    "prefs-beta": "Características en probas",
     "prefs-datetime": "Data e hora",
     "prefs-labs": "Características experimentais",
     "prefs-user-pages": "Páxinas de usuario",
     "listgrouprights-removegroup-self": "Pode eliminar {{PLURAL:$2|un grupo|grupos}} pola súa propia conta: $1",
     "listgrouprights-addgroup-self-all": "Pode engadir todos os grupos pola súa propia conta",
     "listgrouprights-removegroup-self-all": "Pode eliminar todos os grupos pola súa propia conta",
+    "trackingcategories": "Categorías de seguimento",
+    "trackingcategories-summary": "Esta páxina lista as categorías de seguimento que o software de MediaWiki enche automaticamente. Pódense alterar os seus nomes modificando as correspondentes mensaxes do sistema no espazo de nomes \"{{ns:8}}\".",
+    "trackingcategories-msg": "Categoría de seguimento",
+    "trackingcategories-name": "Nome da mensaxe",
+    "trackingcategories-desc": "Criterio de inclusión da categoría",
+    "noindex-category-desc": "A páxina contén a palabra máxica <nowiki>__NOINDEX__</nowiki> (e está nun espazo de nomes no que esa marca está permitida) e, polo tanto, non será indexada polos bots.",
+    "index-category-desc": "A páxina contén a palabra máxica <nowiki>__INDEX__</nowiki> (e está nun espazo de nomes no que esa marca está permitida) e, polo tanto, será indexada polos bots cando non debera selo normalmente.",
+    "post-expand-template-inclusion-category-desc": "Despois de expandir todos os modelos, o tamaño da páxina é maior que $wgMaxArticleSize; algúns modelos non se expandiron.",
+    "post-expand-template-argument-category-desc": "Despois de expandir o argumento dun modelo (algo entre chaves triples, como {{{Proba}}}), a páxina é maior que $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "Hai demasiadas funcións analíticas custosas (como <code>#ifexist</code>) incluídas nunha páxina. Consulte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Categoría engadida se a páxina contén unha ligazón de ficheiro rota (unha ligazón para incorporar un ficheiro cando o ficheiro non existe).",
+    "hidden-category-category-desc": "Esta é unha categoría coa palabra máxica <nowiki>__HIDDENCAT__</nowiki>, que impide que se mostre por defecto na caixa de categorías das páxinas.",
+    "trackingcategories-nodesc": "Non hai ningunha descrición dispoñible.",
+    "trackingcategories-disabled": "A categoría está desactivada",
     "mailnologin": "Non existe enderezo para o envío",
     "mailnologintext": "Debe [[Special:UserLogin|acceder ao sistema]] e ter rexistrado un enderezo de correo electrónico válido nas súas [[Special:Preferences|preferencias]] para enviar correos electrónicos a outros usuarios.",
     "emailuser": "Enviar un correo electrónico a {{GENDER:{{BASEPAGENAME}}|este usuario|esta usuaria}}",
     "nowatchlist": "Non ten elementos na súa lista de vixilancia.",
     "watchlistanontext": "Debe $1 para ver ou editar os elementos da súa lista de vixilancia.",
     "watchnologin": "Non accedeu ao sistema",
-    "watchnologintext": "Debe [[Special:UserLogin|acceder ao sistema]] para modificar a súa lista de vixilancia.",
     "addwatch": "Engadir á lista vixilancia",
     "addedwatchtext": "A páxina \"[[:$1]]\" foi engadida á súa [[Special:Watchlist|lista de vixilancia]].\nOs cambios futuros nesta páxina e na súa páxina de conversa asociada serán listados alí.",
     "removewatch": "Eliminar da lista de vixilancia",
     "sp-contributions-newbies-sub": "Contribucións dos usuarios novos",
     "sp-contributions-newbies-title": "Contribucións dos usuarios novos",
     "sp-contributions-blocklog": "rexistro de bloqueos",
+    "sp-contributions-suppresslog": "contribucións borradas do usuario",
     "sp-contributions-deleted": "contribucións borradas do usuario",
     "sp-contributions-uploads": "cargas",
     "sp-contributions-logs": "rexistros",
     "sp-contributions-blocked-notice": "Este usuario está bloqueado. Velaquí está a última entrada do rexistro de bloqueos, por se quere consultala:",
     "sp-contributions-blocked-notice-anon": "Este enderezo IP está bloqueado.\nVelaquí está a última entrada do rexistro de bloqueos, por se quere consultala:",
     "sp-contributions-search": "Busca de contribucións",
-    "sp-contributions-suppresslog": "contribucións borradas do usuario",
     "sp-contributions-username": "Enderezo IP ou nome de usuario:",
     "sp-contributions-toponly": "Mostrar só as últimas revisións",
     "sp-contributions-newonly": "Mostrar só as edicións que crearon páxinas",
     "allmessagesname": "Nome",
     "allmessagesdefault": "Texto predeterminado",
     "allmessagescurrent": "Texto actual",
-    "allmessagestext": "Esta é unha lista de todas as mensaxes dispoñibles no espazo de nomes MediaWiki.\nPor favor, visite a páxina de [https://www.mediawiki.org/wiki/Localisation localización de MediaWiki] e [//translatewiki.net translatewiki.net] se quere contribuír á localización xenérica de MediaWiki.",
+    "allmessagestext": "Esta é unha lista de todas as mensaxes dispoñibles no espazo de nomes MediaWiki.\nPor favor, visite a páxina de [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation localización de MediaWiki] e [//translatewiki.net translatewiki.net] se quere contribuír á localización xenérica de MediaWiki.",
     "allmessagesnotsupportedDB": "Esta páxina non está dispoñible porque '''$wgUseDatabaseMessages''' está desactivado.",
     "allmessages-filter-legend": "Filtrar",
     "allmessages-filter": "Filtrar por estado de personalización:",
     "version-entrypoints": "Enderezos URL de punto de entrada",
     "version-entrypoints-header-entrypoint": "Punto de entrada",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Ruta dos artigos]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Ruta das escrituras]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Ruta dos artigos]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Ruta das escrituras]",
     "redirect": "Redirixir por nome de ficheiro, ID de usuario, ID de páxina ou ID de revisión",
     "redirect-legend": "Redirixir a un ficheiro ou unha páxina",
     "redirect-summary": "Esta páxina especial redirixe cara a un ficheiro (dado o nome), unha páxina (dado o ID da páxina ou o dunha revisión) ou unha páxina de usuario (dado o ID dun usuario). Utilización: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] ou [[{{#Special:Redirect}}/user/101]].",
     "redirect-submit": "Continuar",
     "redirect-lookup": "Procurar:",
     "redirect-value": "Valor:",
-    "redirect-user": "ID de usuario",
+    "redirect-user": "Id. do usuario",
     "redirect-page": "ID de páxina",
     "redirect-revision": "Revisión de páxina",
     "redirect-file": "Nome de ficheiro",
     "limitreport-templateargumentsize": "Tamaño dos argumentos do modelo",
     "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|byte|bytes}}",
     "limitreport-expansiondepth": "Máxima profundidade de expansión",
-    "limitreport-expensivefunctioncount": "Número de funcións de análise custosas",
+    "limitreport-expensivefunctioncount": "Número de funcións analíticas custosas",
     "expandtemplates": "Expandir os modelos",
     "expand_templates_intro": "Esta páxina especial toma texto e expande todos os modelos dentro del recursivamente.\nTamén expande as funcións de análise como\n<code><nowiki>{{</nowiki>#language:…}}</code> e variables como\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nDe feito, expande case calquera cousa entre dúas chaves.",
     "expand_templates_title": "Título do contexto, para {{FULLPAGENAME}} etc.:",
index b0a5147..2b58fbc 100644 (file)
     "loginlanguagelabel": "Sproch: $1",
     "suspicious-userlogout": "Dyy Versuech di abzmälde isch abbroche wore, wel s uusgsäh het, wie wänn s vun eme bschedigte Browser oder eme Cacheproxy uus gsändet woren isch.",
     "createacct-another-realname-tip": "Dr richtig Name isch optional.\nWänn Du ne aagiisch, wird er bruucht fir d Zueornig vu dr Byytreg.",
+    "pt-login": "Aamälde",
+    "pt-login-button": "Aamälde",
+    "pt-userlogout": "Abmälde",
     "php-mail-error-unknown": "Nit bekannte Fähler mit dr Funktion mail() vu PHP",
     "user-mail-no-addy": "Es isch versuecht worde e E-Mail ohni Angab vunere E-Mail-Adräss z verschigge.",
     "user-mail-no-body": "S isch versuecht wore, ne E-Mail mit eme lääre oder z churze Tekscht z verschicke.",
     "prefs-skin": "Benutzeroberflechi",
     "skin-preview": "Vorschou",
     "datedefault": "kei Aagab",
-    "prefs-beta": "Betafunktione",
     "prefs-datetime": "Datum un Zyt",
     "prefs-labs": "Alphafunktione",
     "prefs-user-pages": "Benutzersyte",
     "nowatchlist": "Du hesch ke Yträg uf dyre Beobachtigslischte.",
     "watchlistanontext": "Du muesch Di $1 go Dyyni Beobachtungslischt z säh oder go Yytreg uf ere bearbeite.",
     "watchnologin": "Du bisch nit aagmäldet",
-    "watchnologintext": "Du muesch [[Special:UserLogin|aagmäldet]] syy, zum Dyyni Beobachtigssyte z bearbeite.",
     "addwatch": "zue de Beobachtigslischte derzue tue",
     "addedwatchtext": "D Syte \"[[:$1]]\" stoht jetz uf Dyyre [[Special:Watchlist|Beobachtigslischt]].\nNeji Änderige an dr Syte oder dr Diskussionssyte drvo chasch jetz dert säh.",
     "removewatch": "Us der Beobachtigsliste usegnuu",
     "allmessagesname": "Name",
     "allmessagesdefault": "Standardtext",
     "allmessagescurrent": "jetzige Tekscht",
-    "allmessagestext": "Des isch e Lischt vu allene meglige Syschtemnochrichte us em MediaWiki Namensruum.\nLueg au uf [https://www.mediawiki.org/wiki/Localisation MediaWiki Lokalisierig] un [//translatewiki.net translatewiki.net], wänn Du zue dr MediaWiki-Lokalisierig wit byytrage.",
+    "allmessagestext": "Des isch e Lischt vu allene meglige Syschtemnochrichte us em MediaWiki Namensruum.\nLueg au uf [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Lokalisierig] un [//translatewiki.net translatewiki.net], wänn Du zue dr MediaWiki-Lokalisierig wit byytrage.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:Allmessages''' cha nit bruucht wärde will '''$wgUseDatabaseMessages''' abgschalte isch.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filter fir dr aapasst Zuestand:",
index fad6812..e96592a 100644 (file)
     "prefs-skin": "ફલક",
     "skin-preview": "ફેરફાર બતાવો",
     "datedefault": "મારી પસંદ",
-    "prefs-beta": "બીટા લક્ષણો",
     "prefs-datetime": "તારીખ અને સમય",
     "prefs-labs": "પ્રયોગશાળા લક્ષણો",
     "prefs-user-pages": "સભ્ય પાનાંઓ",
     "rcshowhidebots": "બૉટો $1",
     "rcshowhidebots-show": "બતાવો",
     "rcshowhidebots-hide": "છુપાવો",
-    "rcshowhideliu": "$1 નોંધણી કરેલ સભ્યો",
+    "rcshowhideliu": "નોંધણી કરેલા સભ્યો $1",
     "rcshowhideliu-show": "બતાવો",
     "rcshowhideliu-hide": "છુપાવો",
     "rcshowhideanons": "અનામી સભ્યો $1",
     "nowatchlist": "તમારી ધ્યાન સૂચિ ખાલી છે",
     "watchlistanontext": "તમારી ધ્યાનસૂચિની વસ્તુઓ જોવા અને ફેરફાર કરવા $1 કરો",
     "watchnologin": "પ્રવેશ કરેલ નથી",
-    "watchnologintext": "ધ્યાનસૂચિમાં ફેરફારાકરવા તમે પ્રવેશ [[Special:UserLogin|logged in]] કરેલો હોવો જરૂરી છે.",
     "addwatch": "ધ્યાનસૂચિ માં ઉમેરો",
     "addedwatchtext": "પાનું \"[[:$1]]\" તમારી [[Special:Watchlist|ધ્યાનસૂચિ]]માં ઉમેરાઈ ગયું છે.\nભવિષ્યમાં આ પાના અને તેનાં સંલગ્ન ચર્ચાનાં પાનામાં થનારા ફેરફારોની યાદી ત્યાં આપવામાં આવશે.",
     "removewatch": "ધ્યાનસૂચિમાંથી કાઢી નાખો",
     "allmessagesname": "નામ",
     "allmessagesdefault": "મૂળ સંદેશ",
     "allmessagescurrent": "વર્તમાન દસ્તાવેજ",
-    "allmessagestext": "આ મિડિયાવિકિ નામસ્થળમાં આવેલ પ્રણાલીજનિત સંદેશાની યાદી આ મુજબ છે.\nજો તમે મિડિયાયાવિકિના સ્થાનીયકરણમાં મદદરૂપ થવા ઇચ્છતા હોવ તો કૃપયા [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] અને [//translatewiki.net translatewiki.net]ની મુલાકાત લો.",
+    "allmessagestext": "આ મિડિયાવિકિ નામસ્થળમાં આવેલ પ્રણાલીજનિત સંદેશાની યાદી આ મુજબ છે.\nજો તમે મિડિયાયાવિકિના સ્થાનીયકરણમાં મદદરૂપ થવા ઇચ્છતા હોવ તો કૃપયા [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] અને [//translatewiki.net translatewiki.net]ની મુલાકાત લો.",
     "allmessagesnotsupportedDB": "આ પાનું ન વાપરી શકાશે કેમકે '''$wgUseDatabaseMessages'''  નિષ્ક્રીય કરાયું છે",
     "allmessages-filter-legend": "ચાળણી",
     "allmessages-filter": "સ્થાનીયકરણ સ્થિતિ દ્વારા ચાળો",
index d1e997f..b0f78c7 100644 (file)
     "nowatchlist": "汝嘅監視列表係空嘅。",
     "watchlistanontext": "請$1來查看或編寫汝嘅監視列表。",
     "watchnologin": "還吂登入",
-    "watchnologintext": "汝必須先[[Special:UserLogin|登入]],正做得更改汝嘅監視列表。",
     "addedwatchtext": "Hong-mien \"[[:$1]]\" yí-kîn pûn kâ-ngi̍p to ngì-ke [[Special:Watchlist|Kam-sṳ chhîn-tân]] chûng. Chiông-lòi yû-kôan chhṳ́ hong-mien khi̍p khì-thâ thó-lun-hong ke ngim-hò siû-cháng chiông-voi chhai hong-mien lie̍t-chhut, song-chhiá hàn-voi chhai [[Special:RecentChanges|Chui-khiûn ke kiên-kói]] chûng ke '''chhû-thí''' hìn-sṳt lie̍t-chhut. Kó-yèn  ngì heu-lòi sióng chhiùng hong-mien kam-sṳ chhîn-tân chûng chhîn-chhù, hí-khó tiám-kit thô-hòng thiàu-chûng \"thìn-chṳ́ kam-sṳ\" ke lièn-kiet。",
     "removedwatchtext": "Vùn-chông \"[[:$1]]\" yí-kîn chhiùng Ngì kekam-sṳ lie̍t-péu mien-chûng yì-chhù.",
     "watch": "監視",
     "allmessagesname": "名",
     "allmessagesdefault": "默認信息文字",
     "allmessagescurrent": "Tông-chhièn ke vùn-sṳ",
-    "allmessagestext": "Liá-piên lie̍t-chhut só-yû hí-khó thin-chṳ ke ne-thúng kie-mien.\nPlease visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
+    "allmessagestext": "Liá-piên lie̍t-chhut só-yû hí-khó thin-chṳ ke ne-thúng kie-mien.\nPlease visit [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
     "allmessagesnotsupportedDB": "Ne-thúng kie-mien kûng-yung chhu-yî kôan-pit chong-thai (wgUseDatabaseMessages)。",
     "thumbnail-more": "放大",
     "filemissing": "Mò-fap cháu-to tóng-on",
index ba8997b..8092add 100644 (file)
     "october-date": "$1 ʻOkakopa",
     "november-date": "$1 Nowemapa",
     "december-date": "$1 Kēkēmapa",
-    "pagecategories": "{{PLURAL:$1|Mahele| mau Māhele}}",
+    "pagecategories": "{{PLURAL:$1|Mahele|Māhele}}",
     "category_header": "Nā ʻaoʻao i loko o ka mahele \"$1\"",
     "subcategories": "Nā Māhele kūloko",
     "category-media-header": "Nā Pāpaho i loko o ka mahele \"$1\"",
     "hidden-categories": "{{PLURAL:$1|mahele hūnā|mau māhele hūnā}}",
     "hidden-category-category": "Nā māhele hūnā",
     "category-subcat-count": "{{PLURAL:$2|Hoʻokahi mahele kūloko wale nō o kēia mahele.|Aia {{PLURAL:$1|i kēia mahele kūloko|$1 mau māhele kūloko}} i loko o kēia mahele, $2 ka huina.}}",
+    "category-subcat-count-limited": "Loaʻa i kēia mahele {{PLURAL:$1|hoʻokahi mahele kūloko|$1 mau māhele}}.",
     "category-article-count": "{{PLURAL:$2|Hoʻokahi ʻaoʻao wale nō o kēia mahele.|Aia {{PLURAL:$1|i kēia ʻaoʻao|$1 mau ʻaoʻao}} i loko o kēia mahele, $2 ka huina.}}",
+    "category-article-count-limited": "Aia {{PLURAL:$1|kēia ʻaoʻao|$1 mau ʻaoʻao}} ma ka mahele okamanawa.",
     "category-file-count": "{{PLURAL:$2|Hoʻokahi waihona wale nō o kēia mahele.|Aia {{PLURAL:$1|i kēia waihona|$1 mau waihona}} i loko o kēia mahele, $2 ka huina.}}",
+    "category-file-count-limited": "Aia {{PLURAL:$1|kēia waihona|$1 mau waihona}} ma ka mahele okamanawa.",
     "listingcontinuesabbrev": "(homaʻia)",
+    "index-category": "ʻAoʻao i hoʻopapakuhikuhi kikoʻī ʻia",
     "noindex-category": "Nā ʻAoʻao i hoʻopapakuhikuhi kikoʻī ʻia",
+    "broken-file-category": "ʻAoʻao me nā loulou waihona haki",
     "about": "No ia",
     "article": "ʻAoʻao mealoko",
     "newwindow": "(wehe ʻia i loko o kekahi pukaaniani hou)",
     "jumptonavigation": "kelena",
     "jumptosearch": "huli",
     "view-pool-error": "E kala mai, ua hoʻoili nui ʻino nā pūnaewele i kēia manawa. Hoʻāʻo nā mea hoʻohana nui kā e ʻike i kēia ʻaoʻao. E ʻoluʻolu, e kali no kekahi mau minuke a hana hou. \n\n$1",
+    "pool-timeout": "Hele a ʻole ka hola no ke kali ʻana o ka laka",
+    "pool-queuefull": "Piha ke kiʻo kiū",
     "pool-errorunknown": "Hewa ʻikeʻole",
     "aboutsite": "No {{SITENAME}}",
     "aboutpage": "Project:No translatewiki.net",
+    "copyright": "Aia nā mealoko ma lalo o ka laikini $1 inā noka ʻole ia.",
     "copyrightpage": "{{ns:project}}:Kūleana kope",
     "currentevents": "Nūhou",
     "currentevents-url": "Project:Nūhou",
     "privacy": "Kulekele pilikino",
     "privacypage": "Project:Kulekele pilikino",
     "badaccess": "Hewa ‘aena",
+    "badaccess-group0": "ʻAe ʻole ʻoe ke hana i ka mea āu i noi ʻia.",
     "versionrequired": "Noi ʻia ka mana $1 o MekiaWiki",
     "versionrequiredtext": "Noi ʻia ka mana $1 o MekiaWiki no ka hoʻohana ʻana o kēia ʻaoʻao.\nʻIke i ka [[Special:Version|ʻaoʻao mana]].",
     "ok": "Hiki nō",
     "viewdeleted": "Nānā iā $1?",
     "restorelink": "{{PLURAL:$1|kekahi loli holoi|$1 mau loli holoi}}",
     "feedlinks": "Hānaīke:",
+    "feed-invalid": "Hewa ka hulu hānaīke kiaʻi.",
+    "feed-unavailable": "Loaʻa ʻole i nā hānaīke sinidiketiona",
     "site-rss-feed": "Hānaīke RSS o $1",
     "site-atom-feed": "Hānaīke Atom o $1",
     "page-rss-feed": "Hānaīke RSS o \"$1\"",
     "nstab-help": "Kōkua",
     "nstab-category": "Mahele",
     "nosuchaction": "ʻAʻohe hana",
+    "nosuchactiontext": "Hewa ka hana a ka URL.\nUa kikokiko hewa paha ʻoe i ka URL, aiʻole hāhai ʻia kekahi loulou hewa.\nHōʻike paha nō hoʻi kēia i kekahi mū ma loko o ka lako polokalamu e hana ʻia e {{SITENAME}}.",
     "nosuchspecialpage": "ʻAʻohe ʻaoʻao kūikawā",
+    "nospecialpagetext": "<strong>Ua noi ʻoe i kekahi ʻaoʻao kūikawā hewa.</strong>\n\nAia kekahi papahelu pololei o nā ʻaoʻao kūikawā ma [[Special:SpecialPages|{{int:specialpages}}]].",
     "error": "Hewa",
     "databaseerror": "Hewa hōkeo ʻikepili",
+    "databaseerror-text": "Ua loaʻa kekahi hewa nīnau hōkeo ʻikepili.\nHōʻike paha kēīa i kekahi mū ma ka lako polokalamu.",
+    "databaseerror-textcl": "Ua loaʻa kekahi hewa nīnau hōkeo ʻikepili.",
     "databaseerror-query": "Nīnau: $1",
     "databaseerror-function": "Hana: $1",
     "databaseerror-error": "Hewa: $1",
     "laggedslavemode": "<strong>E akahele:</strong> ʻAʻole loaʻa paha i ka ʻaoʻao na hoʻouka hou hou.",
     "readonly": "Laka ‘ia ka hōkeo ‘ikepili",
+    "enterlockreason": "E kikokiko i kekahi kumu no ka laka, a hoʻokomo pū i ka pau ana o kēlā laka",
+    "readonlytext": "Ke laka nei ka hōkeo ʻikepili i kēia manawa no nā hana hou a me nā kāloli ʻē aʻe no kekahi mālama hōkeo ʻikepili hōʻoia hou a hou paha a e hele a maʻamau i ka pau ana.\n\nUa hāʻawi ke kahu i laka i kēia kumu: $1",
     "missing-article": "Loaʻa ʻole i ka hōkeo ʻikepili ke kikokikona o ka ʻaoʻao i pono e loaʻa ʻia i kapa ʻia ʻo \"$1\" $2.\n\nHana ʻia kēia pilikia e ka hāhai ʻana o kekahi ʻokoʻa kahiko aiʻole i kekahi loulou mōʻaukala i kekahi ʻaoʻao i holoi ʻia.\n\nInā ʻaʻole ka hana, ua loaʻa paha iā ʻoe i kekahi mū i loko o ka lako pōlamu.\nE ʻoluʻolu, e lono  kēia pilikia i kekahi [[Special:ListUsers/sysop|kahu]], mai poina i ka URL.",
     "missingarticle-rev": "(kāmua#: $1)",
     "missingarticle-diff": "(ʻOkoʻa: $1, $2)",
+    "readonly_lag": "Ua hikalaka ka hōkeo ʻikepili i ka hele nei ʻana o nā hōkeo ʻikepili kauā i ka haku",
     "internalerror": "Hewa koloko",
     "internalerror_info": "Hewa koloko:$1",
     "fileappenderrorread": "ʻAʻole hiki ke heluhelu iā \"$1\" ma loko o ka pākuʻi ʻana.",
     "directorycreateerror": "ʻAʻole hiki ke haku ka papakuhi waihona \"$1\"",
     "filenotfound": "‘A‘ole hiki ke loa‘a ka waihona \"$1\".",
     "fileexistserror": "ʻAʻole hiki ke kākau i ka waihona \"$1\": Aia no ia.",
+    "unexpected": "Helu mahuʻi ʻole: \"$1\"=\"$2\".",
+    "formerror": "Hewa: Hiki ʻole ke waiho i ke kahua.",
+    "badarticleerror": "Hiki ʻole i kēia hana ke hana ʻia ma kēia ʻaoʻao.",
+    "cannotdelete": "Hiki ʻole i ka ʻaoʻao aiʻole ka waihona \"$1\" ke holoi ʻia.\nUa holoi ʻia paha ia e kekahi mea ʻē aʻe.",
     "cannotdelete-title": "Hiki ʻole ke holoi iā \"$1\"",
+    "delete-hook-aborted": "Ua ʻoʻu ʻia ka holoi ʻana e ka hūka.\nʻAʻohe kumu āna.",
+    "no-null-revision": "Hiki ʻole ke haku i kekahi hōʻole kāmua hou no ka ʻaoʻao \"$1\"",
     "badtitle": "Inoa ʻohe",
     "badtitletext": "ʻAʻohe paha, hakahaka paha aiʻole loulou hewa paha ka poʻoinoa ʻaoʻao.\nLoaʻa paha nā hua kikokikona e hiki ʻole ke hana i nā poʻoinoa.",
     "viewsource": "Nānā i ke kumu",
     "createacct-imgcaptcha-ph": "E kikokiko i ke kikokikona  i luna",
     "createacct-submit": "Kāinoa",
     "createacct-another-submit": "Kāinoa hou",
+    "createacct-benefit-heading": "Hana ʻia ʻo {{SITENAME}} e nā kanaka e like me ʻoe.",
+    "createacct-benefit-body1": "{{PLURAL:$1|hoʻololi|mau hoʻololi}}",
+    "createacct-benefit-body2": "{{PLURAL:$1|ʻaoʻao|mau ʻaoʻao}}",
+    "createacct-benefit-body3": "{{PLURAL:$1|mea haʻawina|mau mea haʻawina}} hou",
     "badretype": "ʻAʻole like nā ʻōlelo hūnā āu i hoʻokomo ai",
     "userexists": "Ua kāinoa ʻia ka inoa mea ho‘ohana.\nE koho i kekahi inoa ʻē aʻe, ke ‘olu‘olu.",
     "loginerror": "Hewa ʻeʻe",
     "createacct-error": "Hewa kāinoa",
     "createaccounterror": "ʻAʻole hiki ke kāinoa: $1",
+    "nocookiesnew": "Ua haku ʻia ka moʻokāki mea hoʻohana, akā ʻaʻole ʻoe e ʻeʻe nei i kēia manawa.\nHana ʻo {{SITENAME}} i nā makana no ke ʻeʻe ʻana i nā mea hoʻohana.\nUa hoʻā ʻole ʻoe i nā makana.\nE ʻoluʻolu, e hoʻā i nā makana, a laila e ʻeʻe me kāu inoa mea hoʻohana hou a me ka ʻōlelo hūnā hou.",
+    "nocookieslogin": "Hana ʻo {{SITENAME}} i nā makana no ke ʻeʻe ʻana i nā mea hoʻohana.\nUa hoʻā ʻole ʻoe i nā makana.\nE ʻoluʻolu, e hoʻā i nā makana, a hana hou.",
     "loginsuccesstitle": "ʻEʻe kūleʻa",
     "loginsuccess": "<strong>Ua ʻeʻe ʻo \"$1\" iā {{SITENAME}}.</strong>",
     "nouserspecified": "Pono ʻoe e kāhuakomo i ka inoa mea hoʻohana.",
     "wrongpasswordempty": "Hakahaka ka ʻōlelo hūnā.\nE ʻoluʻolu, e hana hou.",
     "mailmypassword": "Kāinoa hou i ka ʻōlelo hūnā",
     "passwordremindertitle": "He 'ōlelo hūnā kūikawā no {{SITENAME}}",
+    "mailerror": "He hewa me ka hoʻouna leka ana: $1",
     "emailauthenticated": "Ua hō‘oia ‘ia kāu wahinoho lekauila ma ka lā $2 i ka hola $3.",
     "emailnotauthenticated": "ʻAʻole hōʻoia ʻia kāu wahinoho lekauila.\nHoʻouna ʻole i kekahi lekauila no kēia mau helena.",
     "emailconfirmlink": "E hō‘oia i kāu wahinoho lekauila",
+    "emaildisabled": "ʻAʻole hiki i kēia kahua ke hoʻouna i nā lekauila.",
     "accountcreated": "Ua kāinoa",
     "accountcreatedtext": "Ua kāinoa ka moʻokāki no [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|walaʻau]])",
     "createaccount-title": "Kāinoa moʻokāki no {{SITENAME}}",
     "retypenew": "E kikokiko hou i ka ʻōlelo hūnā hou:",
     "resetpass_submit": "Kau i ka ʻōlelo hūnā a ʻeʻe",
     "changepassword-success": "Ua hoʻololi ‘ia kāu hua‘ōlelo huna!",
+    "resetpass-submit-loggedin": "Hoʻololi i ka ʻōlelo hūnā",
     "resetpass-submit-cancel": "Hoʻōki",
     "resetpass-temp-password": "ʻŌlelo hūnā kūikawā:",
     "passwordreset": "Kāinoa hou i ka ʻōlelo hūnā",
     "changeemail-password": "Kāu ʻōlelo hūnā {{SITENAME}}:",
     "changeemail-submit": "Loli i kāu lekauila",
     "changeemail-cancel": "Hoʻōki",
+    "resettokens-token-label": "$1 (helu okamanawa: $2)",
     "bold_sample": "Ho‘okā‘ele",
     "bold_tip": "Ho‘okā‘ele",
     "italic_sample": "Ho‘ohiō",
     "showlivepreview": "Nāmua ʻānō",
     "showdiff": "E hō'ike i nā loli",
     "anoneditwarning": "<strong>E akahele:</strong> ʻAʻole ʻoe ʻeʻe nei.\nE hoʻopaʻa ʻia ana kāu IP ma ko kēia ʻaoʻao mōʻaukala hoʻololi.",
+    "summary-preview": "Nāmua hōʻuluʻulu manaʻo:",
     "blockedtitle": "Ua pale ‘ia ka mea ho‘ohana",
     "blockednoreason": "‘a‘ohe kumu",
     "loginreqtitle": "Noi i ka ʻeʻe ʻana",
     "search-section": "(pauku $1)",
     "search-suggest": "ʻO kēia paha kou manaʻo: $1",
     "search-interwiki-caption": "Nā pāhana ʻē aʻe",
+    "search-interwiki-default": "Nā hualoaʻa mai $1:",
     "search-interwiki-more": "(hou aʻe)",
     "search-relatedarticle": "Nā Mea ʻālike",
+    "searcheverything-enable": "Huli i nā lewainoa apau",
     "searchrelated": "na mea ʻālike",
     "searchall": "nā mea apau",
     "showingresultsheader": "{{PLURAL:$5|<strong>$1</strong> hualoaʻa o <strong>$3</strong> mau hualoaʻa|<strong$1-$2</strong> mau hualoaʻa o <strong>$3</strong> mau hualoaʻa}} no <strong>$4</strong>",
     "search-nonefound": "ʻAʻohe hualoaʻa no kēia huli.",
     "powersearch-legend": "Hulina kūlana kiʻekiʻe",
     "powersearch-ns": "Huli i loko o nā wahi inoa:",
+    "powersearch-redir": "Helu i nā kiahou",
     "powersearch-togglelabel": "Hōʻoia:",
     "powersearch-toggleall": "Nā mea apau",
     "powersearch-togglenone": "ʻAʻohe",
     "prefs-skin": "ʻIli",
     "skin-preview": "Nāmua",
     "datedefault": "ʻAʻohe makemake",
-    "prefs-beta": "Helena Beta",
     "prefs-datetime": "Ka lā a me ka hola",
+    "prefs-user-pages": "ʻAoʻao mea ho‘ohana",
     "prefs-personal": "ʻAoʻao mea hoʻohana",
     "prefs-rc": "Nā loli hou",
     "prefs-watchlist": "Papakiaʻi",
     "prefs-watchlist-days": "Nā lā e hōʻike i ka papakiaʻi:",
     "prefs-watchlist-days-max": "He palenanui o $1 {{PLURAL:$1|lā|mau lā}}",
+    "prefs-watchlist-edits-max": "Helu palena nui: 1000",
+    "prefs-resetpass": "Hoʻololi i ka ʻōlelo hūnā",
+    "prefs-changeemail": "Hoʻololi i ka wahinoho lekauila",
+    "prefs-setemail": "Hoʻopaʻa i kekahi wahinoho lekauila",
     "prefs-email": "Koho lekauila",
     "prefs-rendering": "Helena",
     "saveprefs": "Mālama",
     "prefs-help-email": "Koi ʻole i ka wahinoho lekauila, akā pono ia nō ke kāinoa ʻana o ka ʻōlelo hūnā inā poina ʻoe i kāu ʻōlelo hūnā.",
     "prefs-help-email-others": "Hiki iā ʻoe ke koho i ka ʻae ʻana i nā mea ʻē aʻe e hoʻokaʻaʻike iā ʻoe mao ka lekauila mao kekahi loulou ma kāu ʻaoʻao mea hoʻohana aiʻole kāu ʻaoʻao walaʻau.\nʻAʻole hōʻike ʻia kāu wahinoho lekauila i nā mea ʻē aʻe e hoʻokaʻaʻike iā ʻoe.",
     "prefs-help-email-required": "Koi i ka lekauila.",
+    "prefs-info": "ʻIke nōhie",
+    "prefs-i18n": "ʻŌlelo",
     "prefs-signature": "Pūlima",
+    "prefs-dateformat": "Hulu lā",
+    "prefs-timeoffset": "Hulu hola",
     "prefs-advancedediting": "Koho paʻamau",
     "prefs-editor": "Luna Hoʻoponopono:",
     "prefs-preview": "Nāmua",
     "prefs-displayrc": "Koho nānā",
     "prefs-displaysearchoptions": "Koho nānā",
     "prefs-displaywatchlist": "Koho nānā",
+    "prefs-tokenwatchlist": "Tokene",
     "prefs-diffs": "ʻOkoʻa",
+    "prefs-help-prefershttps": "E hana ana kēia makemake i ka ʻeʻe hou ana.",
     "userrights": "Ho‘oponopono ‘ana o nā kuleana",
     "userrights-groupsmember": "He lālā o:",
     "userrights-reason": "Kumu:",
     "fileuploadsummary": "Hōʻuluʻulu manaʻo:",
     "filesource": "Kumu:",
     "uploadedfiles": "Waihona hoʻouka ʻia",
+    "uploadwarning": "Akahele hoʻouka",
     "savefile": "Waihona mālama",
     "uploadedimage": "ua hoʻouka iā \"[[$1]]\"",
     "upload-source": "Waihona kūmole",
     "sourcefilename": "Inoa waihona kūmole:",
     "sourceurl": "URL kūmole:",
+    "upload-maxfilesize": "Nui palena nui waihona: $1",
+    "upload-description": "Hōʻike ʻano waihona",
+    "upload-options": "Koho hoʻouka",
+    "watchthisupload": "E kiaʻi i kēia waihona",
+    "upload-warning-subj": "Akahele hoʻouka",
+    "upload-file-error": "Hewa kūloko",
+    "upload-unknown-size": "Nui ʻikeʻole",
+    "upload-http-error": "Ua loaʻa kekahi hewa HTTP: $1",
     "license": "Laikini:",
     "license-header": "Laikini",
     "imgfile": "waihona",
     "filedelete-reason-otherlist": "Nā kumu ʻē aʻe",
     "download": "hoʻoili",
     "randompage": "ʻAtikala Kaulele",
+    "randomincategory-selectcategory-submit": "Huli",
     "statistics": "ʻIkepilihelu",
+    "statistics-header-pages": "ʻIkepilihelu ʻaoʻao",
+    "statistics-header-edits": "ʻIkepilihelu hoʻololi",
+    "statistics-header-views": "ʻIkepilihelu nānā",
+    "statistics-header-users": "ʻIkepilihelu mea hoʻohana",
+    "statistics-header-hooks": "ʻIkepilihelu ʻē aʻe",
+    "statistics-articles": "ʻAoʻao mealoko",
+    "statistics-pages": "‘Ao‘ao",
+    "statistics-files": "Waihona i hoʻouka ʻia",
     "brokenredirects-edit": "ho‘ololi",
     "brokenredirects-delete": "holoi",
     "withoutinterwiki-submit": "Hō‘ike",
     "prefixindex": "Nā ʻAoʻao apau me ka pākuʻina kau mua",
     "shortpages": "Nā ʻaoʻao pōkole",
     "longpages": "Nā ʻaoʻao lōʻihi",
+    "protectedpages-page": "ʻAoʻao",
+    "protectedpages-reason": "Kumu",
+    "protectedpages-unknown-timestamp": "ʻIkeʻole",
+    "protectedpages-unknown-performer": "Mea hoʻohana ʻikeʻole",
     "usercreated": "{{GENDER:$3|Haku ʻia}} i ka lā $1 ma ka hola $2",
     "newpages": "Nā ‘Ao‘ao hou",
     "newpages-username": "Inoa mea ho'ohana:",
     "allmessagescurrent": "Kikokikona i kēia manawa",
     "thumbnail-more": "Ho‘onui",
     "thumbnail_error": "Loaʻa i ka hewa ka haku ʻana o ke kiʻiliʻi: $1",
+    "import-interwiki-submit": "Kākomo",
+    "import-upload-filename": "Inoawaihona:",
+    "import-comment": "Kaumanaʻo:",
+    "importstart": "Ke kākomo nei i nā ʻaoʻao...",
+    "import-revision-count": "$1 {{PLURAL:$1|loihape|mau loihape}}",
+    "importnopages": "ʻAʻohe ʻaoʻao no ke kākomo ʻana.",
     "tooltip-pt-userpage": "Kāu ʻaoʻao mea hoʻohana",
     "tooltip-pt-mytalk": "Kāu walaʻau",
     "tooltip-pt-preferences": "Kāu makemake",
     "tooltip-n-help": "Kahi e aʻo mai",
     "tooltip-t-whatlinkshere": "He papahelu o nā ʻaoʻao wiki apau e loulou i ʻaneʻi",
     "tooltip-t-recentchangeslinked": "Nā loli hou i nā ʻaoʻao i loulou ʻia mai kēia ʻaoʻao",
+    "tooltip-feed-rss": "Hānaīke RSS no kēia ʻaoʻao",
     "tooltip-feed-atom": "Hānaīke Atom no kēia ʻaoʻao",
     "tooltip-t-contributions": "He papahelu o nā hāʻawina o ka mea hoʻohana",
     "tooltip-t-emailuser": "Leka uila i kēia mea hoʻohana",
     "tooltip-t-permalink": "Loulou paʻa no kēia kāmua o ka ʻaoʻao",
     "tooltip-ca-nstab-main": "Nānā i ka ʻaoʻao mealoko",
     "tooltip-ca-nstab-user": "Nānā i ka ʻaoʻao mea hoʻohana",
+    "tooltip-ca-nstab-media": "Nānā i ka ʻaoʻao pāpaho",
     "tooltip-ca-nstab-special": "He ʻaoʻao kūikawā kēia; ʻaʻole hiki iā ʻoe ke hoʻololi",
     "tooltip-ca-nstab-project": "Nānā i ka ‘ao‘ao papahana",
     "tooltip-ca-nstab-image": "Nānā i ka ʻaoʻao waihona",
+    "tooltip-ca-nstab-mediawiki": "Nānā i ka pūlono ʻōnaehana",
     "tooltip-ca-nstab-template": "Nānā i ke anakuhi",
     "tooltip-ca-nstab-help": "Nānaina i ka ʻaoʻao kōkua",
     "tooltip-ca-nstab-category": "Nānā i ka ‘ao‘ao mahele",
     "tooltip-diff": "Hōʻike i nā loli āu i hana ai i kēia kikokikona",
     "tooltip-compareselectedversions": "E ʻike i na ʻokoʻa ma waena o nā kāmua ʻelua i koho ʻia o kēia ʻaoʻao",
     "tooltip-watch": "Hoʻohui i kāu papakiʻai",
+    "tooltip-watchlistedit-normal-submit": "Holoi poʻoinoa",
+    "tooltip-watchlistedit-raw-submit": "Hoʻopuka hou i ka papakiaʻi",
+    "tooltip-upload": "Hoʻomaka i ka hoʻouka ʻana",
     "tooltip-rollback": "Hoʻihoʻi ʻo \"Hoʻihoʻi\" i nā hoʻololi i kēia ʻaoʻao o ka mea hāʻawi hopeloa i hoʻokahi kāomi",
     "tooltip-undo": "Hoʻihoʻi ʻo \"Hōʻole\" i kēia hoʻololi a wehe ia i ka ʻaoʻao hoʻololi i ke ʻano nāmua. ʻAe ia i ka hoʻohui ʻana i kekahi kumu i loko o ka hōʻuluʻulu manaʻo.",
+    "tooltip-preferences-save": "Mālama i nā makemake",
     "tooltip-summary": "Kikokiko i kekahi hōʻuluʻulu manaʻo pōkole",
+    "siteuser": "$1, he mea hoʻohana o {{SITENAME}}",
+    "anonuser": "$1, he mea hoʻohana inoa ʻole o {{SITENAME}}",
+    "lastmodifiedatby": "Ua kāloli ʻia kēia ʻaoʻao ma ka hola $2 o $1 na $3.",
+    "othercontribs": "Hakuloli ʻia i ke kumuhana na $1.",
+    "others": "mea ʻē aʻe",
+    "siteusers": "{{PLURAL:$2|ka mea hoʻohana|nā mea hoʻohana}} {{SITENAME}} $1",
+    "anonusers": "{{PLURAL:$2|ka mea hoʻohana|nā mea hoʻohana}} inoa ʻole {{SITENAME}} $1",
+    "creditspage": "Pailaha ʻaoʻao",
+    "nocredits": "ʻAʻohe ʻike pailaha a kēia ʻaoʻao.",
+    "pageinfo-title": "ʻIke no \"$1\"",
+    "pageinfo-header-basic": "ʻIke nōhie",
+    "pageinfo-header-edits": "Hoʻololi i ka mōʻaukala",
+    "pageinfo-article-id": "ID ʻaoʻao",
+    "pageinfo-language": "ʻŌlelo mealoko ʻaoʻao",
+    "pageinfo-robot-index": "ʻAe",
+    "pageinfo-robot-noindex": "ʻAʻole",
+    "pageinfo-views": "Helu o nā nānā",
+    "pageinfo-watchers": "Helu o nā mea nānā ʻaoʻao",
+    "pageinfo-redirects-name": "Helu o nā kiahou i kēia ʻaoʻao",
+    "pageinfo-subpages-name": "Helu o nā ʻaoʻao kūloko o kēia ʻaoʻao",
+    "pageinfo-toolboxlink": "ʻIke ʻaoʻao",
+    "pageinfo-redirectsto": "Kiahou iā",
+    "pageinfo-redirectsto-info": "ʻike",
+    "pageinfo-contentpage-yes": "ʻAe",
+    "pageinfo-protect-cascading-yes": "ʻAe",
+    "pageinfo-category-info": "ʻIke māhele",
+    "pageinfo-category-pages": "Helu o nā ʻaoʻao",
+    "pageinfo-category-subcats": "Helu o nā ʻaoʻao kūloko",
+    "pageinfo-category-files": "Helu o nā waihona",
     "previousdiff": "← Hoʻololi aku nei",
     "nextdiff": "Hoʻololi hou aʻe →",
-    "file-info-size": "$1 x $2 kiʻiʻuku, nui waihona: $3, ʻano MIME: $4",
+    "thumbsize": "Nui kiʻiliʻi:",
+    "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|ʻaoʻao|mau ʻaoʻao}}",
+    "file-info": "nui waihona: $1, kaila MIME: $2",
+    "file-info-size": "$1 x $2 pikela, nui waihona: $3, ʻano MIME: $4",
+    "file-info-size-pages": "$1 × $2 mau pikela, nui waihona: $3, kaila MIME: $4, $5 {{PLURAL:$5|ʻaoʻao|mau ʻaoʻao}}",
     "file-nohires": "Loaʻa ʻole ka miomio aʻe.",
     "svg-long-desc": "Waihona SVG, $1 x $2 mau pikela, nui waihona: $3",
+    "svg-long-error": "Hewa ka waihona SVG: $1",
     "show-big-image": "Waihona kumu",
+    "show-big-image-preview": "Ka nui o kēia nāmua: $1.",
+    "show-big-image-size": "$1 × $2 mau pikela",
+    "newimages-legend": "Kānana",
+    "showhidebots": "($1 mau lopako)",
+    "noimages": "ʻAʻohe mea.",
     "ilsubmit": "Huli",
+    "bydate": "e ka lā",
+    "sp-newimages-showfrom": "Hōʻike i nā waihona hou mai ka hola $2, $1",
+    "seconds": "{{PLURAL:$1|$1 kekona|$1 mau kekona}}",
+    "minutes": "{{PLURAL:$1|$1 minuke|$1 mau minuke}}",
+    "hours": "{{PLURAL:$1|$1 hola|$1 mau hola}}",
+    "days": "{{PLURAL:$1|$1 lā|$1 mau lā}}",
+    "weeks": "{{PLURAL:$1|$1 pule|$1 mau pule}}",
+    "months": "{{PLURAL:$1|$1 mahina|$1 mau mahina}}",
+    "years": "{{PLURAL:$1|$1 makahiki|$1 mau makahiki}}",
+    "ago": "$1 ma mua",
+    "just-now": "i kēia manawa ʻānō",
+    "hours-ago": "$1 {{PLURAL:$1|hola|mau hola}} ma mua",
+    "minutes-ago": "$1 {{PLURAL:$1|minuke|mau minuke}} ma mua",
+    "seconds-ago": "$1 {{PLURAL:$1|kekona|mau kekona}} ma mua",
+    "monday-at": "Poʻākahi ma $1",
+    "tuesday-at": "Poʻālua ma $1",
+    "wednesday-at": "Poʻākolu ma $1",
+    "thursday-at": "Poʻāhā ma $1",
+    "friday-at": "Poʻālima ma $1",
+    "saturday-at": "Poʻāono ma $1",
+    "sunday-at": "Lāpule ma $1",
+    "yesterday-at": "I nehinei ma $1",
     "bad_image_list": "ʻO kēia ka hulu:\n\nNoʻonoʻo pono wale no i nā ʻikamu papahelu (nā laina e hoʻomaka ʻia me *).\nPono ka loulou mua loa ma kekahi laina e loulou i kekahi waihona ʻino.\nNoʻonoʻo ʻia nā loulou heleiho ma kēlā laina like i nā kūʻē lula, he laʻana kēia, nā ʻaoʻao e loaʻa i ka waihona i loko o ka laina.",
     "metadata": "ʻIkepiliMeta",
     "metadata-help": "Loaʻa i kēia waihona nā ʻike ʻē aʻe i hoʻohui ʻia paha mai kekahi pahupaʻakiʻi aiʻole kekahi mīkinikopekiʻi i hana ʻia no ka haku ʻana aiʻole ka hoʻokamepiuila ʻana o ia.\nInā ua kāloli ʻia ka waihona mai kona ʻano kumu, hōʻike piha ʻole i kekahi o nā kikoʻī o ka waihona i kāloli ʻia.",
     "metadata-fields": "E hoʻokomo ʻia ana nā kula ʻikepiliMeta kiʻi i loko o kēia pūlono ma ka hōʻike ʻaoʻao kiʻi oiai ka hoʻoliʻi ʻana o ke pākaukau ʻikepiliMeta.\nHoʻohuna paʻamau i nā mea ʻē aʻe\n* kahana lōkō\n* kaʻano\n* kalāholakumu\n* holahuʻena\n* heluf\n* kūlanawikiiso\n* loaaniani\n* meahana\n* kūleanakope\n* hōʻikeʻanokiʻi\n* lakikūgps\n* lonikūgps\n* kiʻekiʻegps",
+    "exif-languagecode": "ʻŌlelo",
+    "exif-iimversion": "Mana IIM",
+    "exif-iimcategory": "Mahele",
+    "exif-label": "Lepili",
+    "exif-meteringmode-0": "ʻIkeʻole",
+    "exif-gpsspeed-n": "Mile loa",
+    "exif-gpsdestdistance-k": "Kilomika",
+    "exif-gpsdestdistance-m": "Mile",
+    "exif-gpsdestdistance-n": "Mile moana",
+    "exif-objectcycle-a": "Lā wale nō",
+    "exif-objectcycle-p": "Pō wale nō",
+    "exif-objectcycle-b": "Ka lā a me ka pō pākahi nō",
+    "exif-dc-date": "Lā",
+    "exif-dc-source": "Pāpaho kūmole",
+    "exif-dc-type": "Kaila pāpaho",
+    "exif-iimcategory-edu": "Hoʻonaʻauao",
+    "exif-iimcategory-evn": "ʻĀina",
+    "exif-iimcategory-hth": "Olakino",
+    "exif-iimcategory-wea": "Anianilā",
     "watchlistall2": "nā mea apau",
     "namespacesall": "nā mea apau",
     "monthsall": "nā mea apau",
     "confirm_purge_button": "Hiki nō",
+    "confirm-watch-button": "Hiki nō",
+    "confirm-watch-top": "Hoʻohui i kēia ʻaoʻao i kāu papakiaʻi?",
+    "confirm-unwatch-button": "Hiki nō",
+    "confirm-unwatch-top": "Holoi i kēia ʻaoʻao mai kāu papakiaʻi?",
     "imgmultipageprev": "← ʻaoʻao aku nei",
     "imgmultipagenext": "ʻaoʻao hou aʻe →",
+    "imgmultigo": "Kele!",
+    "imgmultigoto": "Kele i ka ʻaoʻao $1",
+    "img-lang-default": "(ʻōlelo paʻamau)",
+    "img-lang-info": "Hana i kēia kiʻi ma ka $1. $2",
+    "img-lang-go": "Kele",
+    "ascending_abbrev": "Pilu",
+    "descending_abbrev": "Pila",
     "table_pager_next": "ʻAoʻao hou aʻe",
     "table_pager_prev": "ʻAoʻao aku nei",
+    "table_pager_first": "ʻAoʻao mua",
+    "table_pager_last": "ʻAoʻao hope",
+    "table_pager_limit": "Hōike i $1 mau ʻikamu no kekahi ʻaoʻao",
+    "table_pager_limit_label": "ʻIkamu no kekahi ʻaoʻao:",
+    "table_pager_limit_submit": "Kele",
+    "table_pager_empty": "ʻAʻohe hualoaʻa",
     "autosumm-replace": "Ke pani nei i ka mealoko me '$1'",
     "autoredircomment": "Kiahou i ka ʻaoʻao iā [[$1]]",
     "autosumm-new": "Ua hoʻokumu ʻia kekahi ʻaoʻao me '$1'",
     "watchlisttools-raw": "Hoʻololi i ka papakiaʻi maka",
     "duplicate-defaultsort": "<strong>E akahele:</strong> Mauʻaʻe ke kī kaʻalike paʻamau \"$2\" i ke kī kaʻalike paʻamau \"$1\" mai ka wā mua.",
     "version-specialpages": "Nā ‘Ao‘ao kūikawā",
+    "version-poweredby-translators": "Mea unuhi translatewiki.net",
+    "version-software-version": "Mana",
+    "redirect": "Kiahou e ka waihona, ka mea hoʻohana, ka ʻaoʻao aiʻole ka ID loihape",
+    "redirect-legend": "Kiahou i kekahi waihona aiʻole kekahi ʻaoʻao",
+    "redirect-summary": "Kiahou kēia ʻaoʻao kūikawā i kekahi waihona (inā hāʻawi ʻia kekahi inoa waihona), kekahi ʻaoʻao (inā hāʻawi ʻia kekahi ID loihape aiʻole ID ʻaoʻao) aiʻole kekahi ʻaoʻao mea hoʻohana (inā hāʻawi ʻia ka ID mea hoʻohana helu). Ka hana ʻana: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], aiʻole [[{{#Special:Redirect}}/user/101]].",
+    "redirect-submit": "Huli",
+    "redirect-lookup": "Huli no:",
+    "redirect-value": "Helu:",
+    "redirect-user": "ID mea hoʻohana",
+    "redirect-page": "ID ʻaoʻao",
+    "redirect-revision": "Loihape ʻaoʻao",
+    "redirect-file": "Inoa waihona",
+    "fileduplicatesearch-filename": "Inoawaihona:",
     "fileduplicatesearch-submit": "Huli",
     "specialpages": "Nā ‘Ao‘ao kūikawā",
+    "blankpage": "ʻAoʻao hakahaka",
     "external_image_whitelist": " #Waiho i kēia laina<pre>\n#Kau i nā hapa haʻi maʻamau (nā hapa e kau ʻia ma waena o nā //) i lalo\n#Hoʻohālikelike ia mea me nā URL o nā kiʻi kūwaho (loulouhūnāloko)\n#Hōʻike ʻia ia mea e hoʻohālikelike me he mau kiʻi, inā ʻaʻole pēlā e hōʻike wale me he loulou no ke kiʻi wale nō\n#Mālama ʻia nā laina e hoʻomaka me ka # e like me nā kaumanaʻo\n#Kākau wale, mai hopohopo e pili ana nā ʻaui\n\n#Kau i nā hapa ligaka apau ma luna o kēia laina. Wahiho i kēia laina</pre>",
     "tag-filter": "Kānana [[Special:Tags|lepili]]:",
+    "tag-filter-submit": "Kānana",
+    "tags-title": "Lepili",
+    "tags-tag": "Inoa lepili",
+    "tags-active-yes": "ʻAe",
+    "tags-active-no": "ʻAʻole",
     "tags-edit": "hoʻololi",
+    "tags-hitcount": "$1 {{PLURAL:$1|loli|mau loli}}",
+    "compare-page1": "ʻAoʻao 1",
+    "compare-page2": "ʻAoʻao 2",
+    "compare-rev1": "Loihape 1",
+    "compare-rev2": "Loihape 2",
+    "htmlform-submit": "Waiho",
+    "htmlform-reset": "Hanaʻole i nā loli",
+    "htmlform-selectorother-other": "Mea ʻē aʻe",
+    "htmlform-no": "ʻAʻole",
+    "htmlform-yes": "ʻAe",
+    "htmlform-chosen-placeholder": "Koho i kekahi koho",
+    "rightsnone": "(ʻaʻohe)",
+    "feedback-subject": "Kumunui:",
+    "feedback-message": "Pūlono:",
+    "feedback-cancel": "Hoʻōki",
+    "feedback-submit": "Hoʻouna i nā Manaʻo",
+    "feedback-adding": "Ke hoʻohui nei i ka manaʻo i ka ʻaoʻao...",
+    "feedback-close": "Ua pau",
+    "searchsuggest-search": "Huli",
+    "api-error-unknown-code": "Hewa ʻikeʻole: \"$1\".",
+    "api-error-unknown-warning": "Akahele ʻikeʻole: \"$1\".",
+    "api-error-unknownerror": "Hewa ʻikeʻole: \"$1\".",
+    "duration-seconds": "$1 {{PLURAL:$1|kekona|mau kekona}}",
+    "duration-minutes": "$1 {{PLURAL:$1|minuke|mau minuke}}",
+    "duration-hours": "$1 {{PLURAL:$1|hola|mau hola}}",
+    "duration-days": "$1 {{PLURAL:$1|lā|mau lā}}",
+    "duration-weeks": "$1 {{PLURAL:$1|pule|mau pule}}",
+    "duration-years": "$1 {{PLURAL:$1|makahiki|mau makahiki}}",
+    "duration-decades": "$1 {{PLURAL:$1|kekeke|mau kekeke}}",
+    "duration-centuries": "$1 {{PLURAL:$1|kenekulia|mau kenekulia}}",
+    "duration-millennia": "$1 {{PLURAL:$1|melenio|mau melenio}}",
+    "expand_templates_output": "Hualoaʻa",
     "expand_templates_ok": "Hiki nō",
+    "expand_templates_remove_comments": "Holoi i nā kaumanaʻo",
     "expand_templates_preview": "Nāmua"
 }
index e6461b9..e127a35 100644 (file)
     "pool-timeout": "זמן ההמתנה לסיום הנעילה עבר",
     "pool-queuefull": "התור מלא",
     "pool-errorunknown": "שגיאה בלתי ידועה",
+    "pool-servererror": "שירות המנייה אינו זמין ($1).",
     "aboutsite": "אודות {{SITENAME}}",
     "aboutpage": "Project:אודות",
     "copyright": "התוכן זמין לפי תנאי $1 אלא אם נאמר אחרת.",
     "prefs-skin": "עיצוב",
     "skin-preview": "תצוגה מקדימה",
     "datedefault": "ברירת המחדל",
-    "prefs-beta": "אפשרויות בטא",
     "prefs-datetime": "תאריך ושעה",
     "prefs-labs": "אפשרויות מעבדה",
     "prefs-user-pages": "דפי משתמש",
     "listgrouprights-removegroup-self": "הסרת {{PLURAL:$2|הקבוצה|הקבוצות}} מהחשבון האישי: $1",
     "listgrouprights-addgroup-self-all": "הוספת כל הקבוצות לחשבון האישי",
     "listgrouprights-removegroup-self-all": "הסרת כל הקבוצות מהחשבון האישי",
+    "trackingcategories": "קטגוריות מעקב",
+    "trackingcategories-summary": "דף זה כולל רשימה של קטגוריות מעקב, שנוצרות אוטומטית על־ידי תוכנת מדיה‏‏֫־ויקי. ניתן לשנות את שמותיהן על‏‏֫־ידי שינוי הודעות המערכת הרלוונטיות במרחב השם \"{{ns:8}}\".",
+    "trackingcategories-msg": "קטגוריית מעקב",
+    "trackingcategories-name": "שם ההודעה",
+    "trackingcategories-desc": "הקריטריון להכללה בקטגוריה",
+    "noindex-category-desc": "הדף כולל את מילת הקסם <nowiki>__לא_לחיפוש__</nowiki> (והוא במרחב שם שבו דגל כזה מותר לשימוש), ולכן אינו מאונדקס על‏‏֫־ידי רובוטים.",
+    "index-category-desc": "הדף כולל את מילת הקסם <nowiki>__לחיפוש__</nowiki> (והוא במרחב שם שבו דגל כזה מותר לשימוש), ולכן הוא מאונדקס על‏‏֫־ידי רובוטים אף שכברירת מחדל הוא לא היה מאונדקס על ידם.",
+    "post-expand-template-inclusion-category-desc": "לאחר הרחבת כל התבניות, גודל הדף גדול מ‏‏֫־$wgMaxArticleSize, ולכן מספר תבניות אינן מורחבות.",
+    "post-expand-template-argument-category-desc": "לאחר הרחבת ארגומנט של תבנית (משהו בסוגריים משולשים, כגון {{{Foo}}}), הדף גדול מ‏‏֫‏‏֫־$wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "יותר מדי פונקציות מפענח יקרות לשימוש (כגון #קיים) מוכללות בדף. ראו [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "הקטגוריה נוספת אם הדף כולל קישור שבור לקובץ (קישור להטמעת קובץ כאשר הקובץ אינו קיים).",
+    "hidden-category-category-desc": "קטגוריה זו כוללת את מילת הקסם <nowiki>__קטגוריה_מוסתרת__</nowiki>, שגורמת לה לא להופיע בתיבת קישורי הקטגוריות בדפים כברירת מחדל.",
+    "trackingcategories-nodesc": "התיאור אינו זמין.",
+    "trackingcategories-disabled": "הקטגוריה מבוטלת",
     "mailnologin": "אין כתובת לשליחה",
     "mailnologintext": "עליכם [[Special:UserLogin|להיכנס לחשבון]] ולהגדיר לעצמכם כתובת דואר אלקטרוני תקינה ב[[Special:Preferences|העדפות המשתמש]] שלכם כדי לשלוח דואר למשתמש אחר.",
     "emailuser": "שליחת דואר אלקטרוני למשתמש זה",
     "nowatchlist": "אין דפים ברשימת המעקב.",
     "watchlistanontext": "עליכם $1 כדי לצפות או לערוך פריטים ברשימת המעקב.",
     "watchnologin": "לא נכנסת לחשבון",
-    "watchnologintext": "עליכם [[Special:UserLogin|להיכנס לחשבון]] כדי לערוך את רשימת המעקב.",
     "addwatch": "הוספה לרשימת המעקב",
     "addedwatchtext": "הדף [[:$1]] נוסף ל[[Special:Watchlist|רשימת המעקב]].\nשינויים שייערכו בעתיד בדף זה ובדף השיחה שלו, יוצגו ברשימת המעקב.",
     "removewatch": "הסרה מרשימת המעקב",
     "sp-contributions-newbies-sub": "עבור משתמשים חדשים",
     "sp-contributions-newbies-title": "תרומות של משתמשים חדשים",
     "sp-contributions-blocklog": "יומן חסימות",
+    "sp-contributions-suppresslog": "תרומות משתמש מוסתרות",
     "sp-contributions-deleted": "תרומות משתמש מחוקות",
     "sp-contributions-uploads": "העלאות",
     "sp-contributions-logs": "יומנים",
     "sp-contributions-blocked-notice": "{{GENDER:$1|המשתמש הזה חסום|המשתמשת הזו חסומה}} כרגע.\nהפעולה האחרונה ביומן החסימות מוצגת להלן:",
     "sp-contributions-blocked-notice-anon": "כתובת IP זו חסומה כרגע.\nהפעולה האחרונה ביומן החסימות מוצגת להלן:",
     "sp-contributions-search": "חיפוש תרומות",
-    "sp-contributions-suppresslog": "תרומות משתמש מוסתרות",
     "sp-contributions-username": "שם משתמש או כתובת IP:",
     "sp-contributions-toponly": "הצגת עריכות שהן הגרסאות האחרונות בלבד",
     "sp-contributions-newonly": "הצגת עריכות שהן יצירות של דפים בלבד",
     "allmessagesname": "שם",
     "allmessagesdefault": "טקסט ברירת המחדל של ההודעה",
     "allmessagescurrent": "הטקסט הנוכחי של ההודעה",
-    "allmessagestext": "זוהי רשימת כל הודעות המערכת שבמרחב השם {{ns:mediawiki}}, המשמשות את ממשק האתר.\n\nמפעילי המערכת יכולים לערוך את ההודעות בלחיצה על שם ההודעה.",
+    "allmessagestext": "זוהי רשימת כל הודעות המערכת שבמרחב השם {{ns:mediawiki}}.\nאנא בקרו בדף [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] וב‏‏֫אתר [//translatewiki.net translatewiki.net] אם ברצונכם לתרום לתרגום הכללי של מדיה‏‏֫־ויקי.",
     "allmessagesnotsupportedDB": "לא ניתן להשתמש בדף זה כיוון ש־wgUseDatabseMessages מבוטל.",
     "allmessages-filter-legend": "מסנן",
     "allmessages-filter": "סינון לפי מצב ההודעה:",
     "expand_templates_remove_nowiki": "הסרת תגי <nowiki> בתוצאה",
     "expand_templates_generate_xml": "הצגת עץ הפענוח של XML",
     "expand_templates_generate_rawhtml": "הצגת HTML גולמי",
-    "expand_templates_preview": "תצוגה מקדימה",
-    "trackingcategories": "קטגוריות מעקב",
-    "trackingcategories-summary": "דף זה כולל רשימה של קטגוריות מעקב, שנוצרות אוטומטית על ידי תוכנת מדיה‏‏֫־ויקי. ניתן לשנות את שמותיהן על‏‏֫־ידי שינוי הודעות המערכת הרלוונטיות במרחב השם \"{{ns:8}}\".",
-    "trackingcategories-msg": "קטגוריית מעקב",
-    "trackingcategories-name": "שם ההודעה",
-    "trackingcategories-desc": "הקריטריון להכללה בקטגוריה",
-    "noindex-category-desc": "הדף כולל את מילת הקסם <nowiki>__לא_לחיפוש__</nowiki> (והוא במרחב שם שבו דגל כזה מותר לשימוש), ולכן אינו מאונדקס על‏‏֫־ידי רובוטים.",
-    "index-category-desc": "הדף כולל את מילת הקסם <nowiki>__לחיפוש__</nowiki> (והוא במרחב שם שבו דגל כזה מותר לשימוש), ולכן הוא מאונדקס על‏‏֫־ידי רובוטים אף שכברירת מחדל הוא לא היה מאונדקס על ידם.",
-    "post-expand-template-inclusion-category-desc": "לאחר הרחבת כל התבניות, גודל הדף גדול מ‏‏֫־$wgMaxArticleSize, ולכן מספר תבניות אינן מורחבות.",
-    "post-expand-template-argument-category-desc": "לאחר הרחבת ארגומנט של תבנית (משהו בסוגריים משולשים, כגון {{{Foo}}}), הדף גדול מ‏‏֫‏‏֫־$wgMaxArticleSize.",
-    "expensive-parserfunction-category-desc": "יותר מדי פונקציות מפענח יקרות לשימוש (כגון #קיים) מוכללות בדף. ראו [https://www.mediawiki.org/wiki/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-    "broken-file-category-desc": "הקטגוריה נוספת אם הדף כולל קישור שבור לקובץ (קישור להטמעת קובץ כאשר הקובץ אינו קיים).",
-    "hidden-category-category-desc": "קטגוריה זו כוללת את מילת הקסם <nowiki>__קטגוריה_מוסתרת__</nowiki>, שגורמת לה לא להופיע בתיבת קישורי הקטגוריות בדפים כברירת מחדל.",
-    "trackingcategories-nodesc": "התיאור אינו זמין.",
-    "trackingcategories-disabled": "הקטגוריה מבוטלת"
+    "expand_templates_preview": "תצוגה מקדימה"
 }
index 4c5d915..cc674d7 100644 (file)
     "pool-timeout": "तालाबन्दी के लिए प्रतीक्षा समय समाप्त",
     "pool-queuefull": "पूल पंक्ति भरी हुई है",
     "pool-errorunknown": "अज्ञात त्रुटि",
+    "pool-servererror": "पूल काउंटर सेवा उपलब्ध नहीं है ($1)।",
     "aboutsite": "{{SITENAME}} के बारे में",
     "aboutpage": "Project:परिचय",
     "copyright": "उपलब्ध सामग्री $1 के अधीन है जब तक अलग से उल्लेख ना किया गया हो।",
     "prefs-skin": "त्वचा",
     "skin-preview": "झलक",
     "datedefault": "खा़स पसंद नहीं",
-    "prefs-beta": "बीटा सुविधाएँ",
     "prefs-datetime": "दिनांक तथा समय",
     "prefs-labs": "लैब विशेषताएँ",
     "prefs-user-pages": "सदस्य पृष्ठ",
     "listgrouprights-removegroup-self": " अपने  खाते से {{PLURAL:$2|समूह}} हटाएँ: $1",
     "listgrouprights-addgroup-self-all": "अपने खाते में सभी समूह शामिल करें",
     "listgrouprights-removegroup-self-all": "अपने खाते से सभी समूह हटाएँ",
+    "trackingcategories-nodesc": "कोई वर्णन उपलब्ध नहीं।",
     "mailnologin": "पाने वाले का एड्रेस दिया नहीं",
     "mailnologintext": "अन्य सदस्यों को इ-मेल भेजने के लिये [[Special:UserLogin|लॉग इन]] करना आवश्यक है और आपकी [[Special:Preferences|वरीयताओं]] में वैध ई-मेल पता होना आवश्यक है।",
     "emailuser": "इस सदस्य को ई-मेल भेजें",
     "nowatchlist": "आपकी ध्यानसूची में कोई भी पृष्ठ नहीं हैं।",
     "watchlistanontext": "अपनी ध्यानसूची में मौजूद पृष्ठ देखने या फिर संपादित करने के लिये कॄपया $1 करें।",
     "watchnologin": "लॉग इन नहीं किया है",
-    "watchnologintext": "ध्यानसूची में बदलाव के लिये [[Special:UserLogin|लॉग इन]] करना आवश्यक है।",
     "addwatch": "ध्यानसूची में जोड़ें",
     "addedwatchtext": "आपकी [[Special:Watchlist|ध्यानसूची]] में \"[[:$1]]\" पृष्ठ जोड़ दिया गया है।\nभविष्य में इस पृष्ठ तथा इसके वार्ता पृष्ठ में होने वाले बदलाव आपकी ध्यानसूची में दिखेंगे।",
     "removewatch": "ध्यानसूची से हटाएँ",
     "sp-contributions-search": "योगदान के लिये खोज",
     "sp-contributions-username": "आईपी एड्रेस या सदस्यनाम:",
     "sp-contributions-toponly": "केवल उन सम्पादनों को दिखाएँ जो नवीनतम संशोधन हैं",
+    "sp-contributions-newonly": "केवल वे सम्पादन दिखाएँ जिनसे पृष्ठ निर्मित हुए हों",
     "sp-contributions-submit": "खोजें",
     "whatlinkshere": "यहाँ के हवाले कहाँ कहाँ हैं",
     "whatlinkshere-title": "$1 से जुड़े हुए पृष्ठ",
     "allmessagesname": "नाम",
     "allmessagesdefault": "डिफॉल्ट पाठ",
     "allmessagescurrent": "वर्तमान पाठ",
-    "allmessagestext": "ये मीडियाविकि नामस्थान में उपलब्ध प्रणाली संदेशों की एक सूची है। यदि आप सामान्य मीडियाविकि क्षेत्रीयकरण में योगदान देना चाहें तो कृपया [https://www.mediawiki.org/wiki/Localisation मीडियाविकि क्षेत्रीयकरण] व [//translatewiki.net translatewiki.net] को देखें।",
+    "allmessagestext": "ये मीडियाविकि नामस्थान में उपलब्ध प्रणाली संदेशों की एक सूची है। यदि आप सामान्य मीडियाविकि क्षेत्रीयकरण में योगदान देना चाहें तो कृपया [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation मीडियाविकि क्षेत्रीयकरण] व [//translatewiki.net translatewiki.net] को देखें।",
     "allmessagesnotsupportedDB": "इस पृष्ठ का इस्तेमाल नहीं कर सकते क्योंकी '''$wgUseDatabaseMessages''' बंद हैं।",
     "allmessages-filter-legend": "छानें",
     "allmessages-filter": "अनुकूलन स्थिति के आधार पर छानें:",
     "expand_templates_remove_comments": "टिप्पणी हटायें",
     "expand_templates_remove_nowiki": "परिणाम में <nowiki> टैग हटाएँ",
     "expand_templates_generate_xml": "XML का पार्स (parse) वृक्ष दर्शायें",
-    "expand_templates_preview": "झलक",
-    "trackingcategories-nodesc": "कोई वर्णन उपलब्ध नहीं।"
+    "expand_templates_preview": "झलक"
 }
index c0f7487..e21b4f3 100644 (file)
     "prefs-skin": "Skin",
     "skin-preview": "Jhalak",
     "datedefault": "Koi pasand nai",
-    "prefs-beta": "Nawaa features",
     "prefs-datetime": "Tarik aur time",
     "prefs-labs": "Try kare waala features",
     "prefs-user-pages": "Sadasya ke panna",
     "nowatchlist": "Aap ke dhyan suchi me koi chij nai hai.",
     "watchlistanontext": "Aapan dhyan suchi me ke dekhe nai to badle ke khatir meharbani kar ke $1 karo.",
     "watchnologin": "Logged in nai hai",
-    "watchnologintext": "Aapan dhyan suchi ke badle ke khatir aap ke [[Special:UserLogin|logged in]] rahe ke chaahi.",
     "addwatch": "Dhyan suchi me jorro",
     "addedwatchtext": "Panna \"[[:$1]]\" ke aap ke [[Special:Watchlist|watchlist]] me jorr dewa gais hae.\nIi panna ke aage ke badlao aur usse jurra baat waala panna ki suchi hian pe hae.",
     "removewatch": "Dhyan suchi me se hatao",
     "allmessagesname": "Naam",
     "allmessagesdefault": "Default text",
     "allmessagescurrent": "Abhi ke text",
-    "allmessagestext": "Ii ek system sandes ke suchi hai jon ki MediaWiki namespace me pawa jaae sake hai.\nAgar aap generic MediaWiki localisation ke yogdaan de mangtaa hai tab meharbani kar ke [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] aur [//translatewiki.net translatewiki.net]  pe jao.",
+    "allmessagestext": "Ii ek system sandes ke suchi hai jon ki MediaWiki namespace me pawa jaae sake hai.\nAgar aap generic MediaWiki localisation ke yogdaan de mangtaa hai tab meharbani kar ke [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] aur [//translatewiki.net translatewiki.net]  pe jao.",
     "allmessagesnotsupportedDB": "Ii panna ke kaam me nai lawa jaae sake hai kahe ki '''$wgUseDatabaseMessages''' ke band kar dewa gais hai.",
     "allmessages-filter-legend": "Chaalo",
     "allmessages-filter": "Customisation state se chhaano",
index 81c1635..19e360f 100644 (file)
     "unprotectthispage": "Promijeni zaštitu ove stranice",
     "newpage": "Nova stranica",
     "talkpage": "Razgovor o ovoj stranici",
-    "talkpagelinktext": "Razgovor",
+    "talkpagelinktext": "razgovor",
     "specialpage": "Posebna stranica",
     "personaltools": "Osobni alati",
     "postcomment": "Novi odlomak",
     "undo-success": "Izmjena je uklonjena (tekst u okviru ispod ne sadrži posljednju izmjenu). Molim sačuvajte stranicu (provjerite sažetak).",
     "undo-failure": "Ova izmjena ne može biti uklonjena zbog postojanja međuinačica.",
     "undo-norev": "Izmjena nije mogla biti uklonjena jer ne postoji ili je obrisana.",
-    "undo-summary": "Uklanjanje izmjene $1 što ju je unio/unijela [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]])",
+    "undo-summary": "uklanjanje izmjene $1 {{GENDER:$2|suradnika|suradnice}} [[Posebno:Doprinosi/$2|$2]] ([[Razgovor sa suradnikom:$2|razgovor]])",
     "cantcreateaccounttitle": "Nije moguće stvoriti suradnički račun",
     "cantcreateaccount-text": "Otvaranje suradničkog računa ove IP adrese ('''$1''') blokirao/la je [[User:$3|$3]].\n\nRazlog koji je dao/la $3 je ''$2''",
     "viewpagelogs": "Vidi evidencije za ovu stranicu",
     "prefs-skin": "Izgled",
     "skin-preview": "Pregled",
     "datedefault": "Nemoj postaviti",
-    "prefs-beta": "Beta mogućnosti",
     "prefs-datetime": "Datum i vrijeme",
     "prefs-labs": "Labs mogućnosti",
     "prefs-user-pages": "Suradničke stranice",
     "userrights-unchangeable-col": "Skupine koje ne možete promijeniti",
     "group": "Skupina:",
     "group-user": "Suradnici",
-    "group-autoconfirmed": "Automatski potvrđeni suradnici",
+    "group-autoconfirmed": "automatski potvrđeni suradnici",
     "group-bot": "Botovi",
     "group-sysop": "Administratori",
     "group-bureaucrat": "Birokrati",
     "group-bureaucrat-member": "{{GENDER:$1|birokrat|birokratica}}",
     "group-suppress-member": "{{GENDER:$1|nadzornik|nadzornica}}",
     "grouppage-user": "{{ns:project}}:Suradnici",
-    "grouppage-autoconfirmed": "{{ns:project}}:Automatski potvrđeni suradnici",
+    "grouppage-autoconfirmed": "{{ns:project}}:automatski potvrđeni suradnici",
     "grouppage-bot": "{{ns:project}}:Botovi",
     "grouppage-sysop": "{{ns:project}}:Administratori",
     "grouppage-bureaucrat": "{{ns:project}}:Birokrati",
     "nowatchlist": "Na Vašem popisu praćenja nema nijednog članka.",
     "watchlistanontext": "Molimo Vas $1 kako biste mogli vidjeti ili uređivati Vaš popis praćenih stranica.",
     "watchnologin": "Niste prijavljeni",
-    "watchnologintext": "Morate biti [[Special:UserLogin|prijavljeni]]\nza promjene u popisu praćenja.",
     "addwatch": "Dodaj u popis praćenja",
     "addedwatchtext": "Stranica \"[[:$1]]\" je dodana na Vaš [[Special:Watchlist|popis praćenja]].\nPromjene na toj stranici i njenoj stranici za razgovor bit će prikazane na popisu praćenja.",
     "removewatch": "Ukloni s popisa praćenja",
     "cantrollback": "Ne mogu ukloniti posljednju promjenu, postoji samo jedna promjena.",
     "alreadyrolled": "Ne mogu ukloniti posljednju promjenu članka [[:$1]] koju je napravio  [[User:$2|$2]] ([[User talk:$2|Razgovor]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]); netko je već promijenio stranicu ili uklonio promjenu.\n\nPosljednju promjenu napravio je [[User:$3|$3]] ([[User talk:$3|Razgovor]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
     "editcomment": "Sažetak promjene je bio: \"''$1''\".",
-    "revertpage": "Uklonjena promjena suradnika [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]]), vraćeno na posljednju inačicu suradnika [[User:$1|$1]]",
+    "revertpage": "uklonjena promjena {{GENDER:$2|suradnika|suradnice}} [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]]), vraćeno na posljednju inačicu {{GENDER:$1|suradnika|suradnice}} [[User:$1|$1]]",
     "revertpage-nouser": "Vraćene izmjene suradnika (suradničko ime uklonjeno) na posljednju inačicu suradnika [[User:$1|$1]]",
-    "rollback-success": "Uklonjeno uređivanje {{GENDER:$1|suradnika|suradnice}} $1\nvraćeno na posljednju inačicu {{GENDER:$2|suradnika|suradnice}} $2.",
+    "rollback-success": "uklonjeno uređivanje {{GENDER:$1|suradnika|suradnice}} $1\nvraćeno na posljednju inačicu {{GENDER:$2|suradnika|suradnice}} $2.",
     "sessionfailure-title": "Prekid sesije",
     "sessionfailure": "Uočili smo problem s Vašom prijavom. Zadnja naredba nije izvršena kako bi se izbjegla zloupotreba. Molimo Vas da se u pregledniku vratite natrag na prethodnu stranicu, ponovno je učitate i zatim pokušate opet.",
     "protectlogpage": "Evidencija zaštićivanja",
     "allmessagesname": "Ime",
     "allmessagesdefault": "Prvotni tekst",
     "allmessagescurrent": "Trenutačni tekst",
-    "allmessagestext": "Ovo je popis svih sistemskih poruka u imenskom prostoru MediaWiki. Molimo posjetite [https://www.mediawiki.org/wiki/Localisation lokalizaciju MediaWikija] i [//translatewiki.net translatewiki.net] ako želite doprinijeti lokalizaciji MediaWiki softvera.",
+    "allmessagestext": "Ovo je popis svih sistemskih poruka u imenskom prostoru MediaWiki. Molimo posjetite [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation lokalizaciju MediaWikija] i [//translatewiki.net translatewiki.net] ako želite doprinijeti lokalizaciji MediaWiki softvera.",
     "allmessagesnotsupportedDB": "Ova stranica ne može biti korištena jer je isključen parametar '''$wgUseDatabaseMessages'''.",
     "allmessages-filter-legend": "Filtriraj",
     "allmessages-filter": "Filtriraj prema prilagođenom obliku:",
index 74bfd2f..6dddd29 100644 (file)
     "prefs-skin": "Drasta",
     "skin-preview": "Přehlad",
     "datedefault": "Žane nastajenje",
-    "prefs-beta": "Betafunkcije",
     "prefs-datetime": "Datum a čas",
     "prefs-labs": "Laborowe funkcije",
     "prefs-user-pages": "Wužiwarske strony",
     "nowatchlist": "Nimaš žane strony w swojich wobkedźbowankach.",
     "watchlistanontext": "Dyrbiš so $1, zo by swoje wobkedźbowanki wobhladać abo wobdźěłać móhł.",
     "watchnologin": "Njejsy přizjewjeny.",
-    "watchnologintext": "Dyrbiš [[Special:UserLogin|přizjewjeny]] być, zo by swoje wobkedźbowanki změnić móhł.",
     "addwatch": "K wobkedźbowankam přidać",
     "addedwatchtext": "Strona [[:$1]] bu k twojim [[Special:Watchlist|wobkedźbowankam]] přidata.\nPřichodne změny tuteje strony a přisłušneje diskusijneje strony budu so tam nalistować.",
     "removewatch": "Z wobkedźbowankow wotstronić",
     "sp-contributions-newbies-sub": "Za nowačkow",
     "sp-contributions-newbies-title": "Wužiwarske přinoški za nowe konta",
     "sp-contributions-blocklog": "protokol zablokowanjow",
+    "sp-contributions-suppresslog": "potłóčene wužiwarske přinoški",
     "sp-contributions-deleted": "wušmórnjene wužiwarske přinoški",
     "sp-contributions-uploads": "nahraća",
     "sp-contributions-logs": "protokole",
     "sp-contributions-blocked-notice": "Tutón wužiwar je tuchwilu zablokowany. Najnowši protokolowy zapisk so deleka jako referenca podawa:",
     "sp-contributions-blocked-notice-anon": "Tuta IP-adresa je tuchwilu zablokowana.\nNajnowši zapisk w protokolu blokowanjow so deleka jako referenca podawa:",
     "sp-contributions-search": "Přinoški pytać",
-    "sp-contributions-suppresslog": "potłóčene wužiwarske přinoški",
     "sp-contributions-username": "IP-adresa abo wužiwarske mjeno:",
     "sp-contributions-toponly": "Jenož wyše wersije pokazać",
     "sp-contributions-newonly": "Jenož změny pokazać, kotrež su wutworjenja stronow",
     "allmessagesname": "Mjeno",
     "allmessagesdefault": "Standardny tekst",
     "allmessagescurrent": "Aktualny tekst",
-    "allmessagestext": "To je lisćina systemowych zdźělenkow, kotrež w mjenowym rumje MediaWiki k dispoziciji steja. Prošu wopytaj [https://www.mediawiki.org/wiki/Localisation lokalizaciju MediaWiki] a [//translatewiki.net translatewiki.net], jeli chceš k powšitkownej lokalizaciji MediaWiki přinošować.",
+    "allmessagestext": "To je lisćina systemowych zdźělenkow, kotrež w mjenowym rumje MediaWiki k dispoziciji steja. Prošu wopytaj [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation lokalizaciju MediaWiki] a [//translatewiki.net translatewiki.net], jeli chceš k powšitkownej lokalizaciji MediaWiki přinošować.",
     "allmessagesnotsupportedDB": "Tuta strona njeda so wužiwać, dokelž '''$wgUseDatabaseMessages''' bu znjemóžnjeny.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Po přiměrjenskim stawje filtrować:",
index ec50e26..2882461 100644 (file)
     "prefs-skin": "Felület",
     "skin-preview": "előnézet",
     "datedefault": "Nincs beállítás",
-    "prefs-beta": "Béta funkciók",
     "prefs-datetime": "Dátum és idő",
     "prefs-labs": "Kísérleti funkciók",
     "prefs-user-pages": "Felhasználói lapok",
     "nowatchlist": "Nincs lap a figyelőlistádon.",
     "watchlistanontext": "A figyelőlistád megtekintéséhez és szerkesztéséhez $1.",
     "watchnologin": "Nem vagy bejelentkezve",
-    "watchnologintext": "Ahhoz, hogy figyelőlistád lehessen, [[Special:UserLogin|be kell lépned]].",
     "addwatch": "Hozzáadás a figyelőlistához",
     "addedwatchtext": "A(z) „[[:$1]]” lapot hozzáadtam a [[Special:Watchlist|figyelőlistádhoz]].\nEzután minden, a lapon vagy annak vitalapján történő változást ott fogsz látni.",
     "removewatch": "Eltávolítás a figyelőlistáról",
     "allmessagesname": "Név",
     "allmessagesdefault": "Alapértelmezett szöveg",
     "allmessagescurrent": "Jelenlegi szöveg",
-    "allmessagestext": "Ezen a lapon a MediaWiki-névtérben elérhető rendszerüzenetek listája látható.\nHa részt szeretnél venni a MediaWiki fordításában, látogass el a [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation], valamint a [//translatewiki.net translatewiki.net] oldalra.",
+    "allmessagestext": "Ezen a lapon a MediaWiki-névtérben elérhető rendszerüzenetek listája látható.\nHa részt szeretnél venni a MediaWiki fordításában, látogass el a [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation], valamint a [//translatewiki.net translatewiki.net] oldalra.",
     "allmessagesnotsupportedDB": "A '''''{{ns:special}}:Allmessages''''' lap nem használható, mert a '''$wgUseDatabaseMessages''' ki van kapcsolva.",
     "allmessages-filter-legend": "Elemek szűrése",
     "allmessages-filter": "Módosítás állapota:",
index 833a4bb..762a51c 100644 (file)
     "prefs-skin": "Տեսք",
     "skin-preview": "նախադիտել",
     "datedefault": "Առանց նախընտրության",
-    "prefs-beta": "Փորձնական հնարավորություններ",
     "prefs-datetime": "Օր ու ժամ",
     "prefs-personal": "Անձնական",
     "prefs-rc": "Վերջին փոփոխություններ",
     "nowatchlist": "Ձեր հսկողության ցանկը դատարկ է։",
     "watchlistanontext": "Անհրաժեշտ է $1՝ հսկացանկը դիտելու կամ խմբագրելու համար։",
     "watchnologin": "Չեք մտել համակարգ",
-    "watchnologintext": "Անհրաժեշտ է [[Special:UserLogin|մտնել համակարգ]]՝ հսկացանկը փոփոխելու համար։",
     "addwatch": "Ավելացնել հսկացանկին",
     "addedwatchtext": "«[[:$1]]» էջը ավելացված է ձեր [[Special:Watchlist|հսկացանկին]]։ Այս էջի և նրան կապված քննարկումների էջի հետագա փոփոխությունները կգրանցվեն այդտեղ, և կցուցադրվեն թավատառով [[Special:RecentChanges|վերջին փոփոխությունների]] ցանկում։\n\nՀետագայում հսկացանկից էջը հեռացնելու ցանկության դեպքում մատնահարեք էջի վերնամասի ընտրացանկում գտնվող «հանել հսկումից» կոճակին։",
     "removewatch": "Հեռացնել հսկացանկից",
     "allmessagesname": "Անուն",
     "allmessagesdefault": "Ուղերձի լռելյայն տեքստ",
     "allmessagescurrent": "Ընթացիկ տեքստ",
-    "allmessagestext": "Ստորև բերված է «MediaWiki» անվանատարածքի բոլոր համակարգային ուղերձների ցանկը։\nPlease visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
+    "allmessagestext": "Ստորև բերված է «MediaWiki» անվանատարածքի բոլոր համակարգային ուղերձների ցանկը։\nPlease visit [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
     "allmessagesnotsupportedDB": "Այս էջը չի գործում, քանի որ '''$wgUseDatabaseMessages''' հատկանիշը անջատված է։",
     "allmessages-filter-all": "Բոլորը",
     "allmessages-language": "Լեզու",
index 419637c..27ca669 100644 (file)
     "prefs-skin": "Apparentia",
     "skin-preview": "Previsualisation",
     "datedefault": "Nulle preferentia",
-    "prefs-beta": "Functiones beta",
     "prefs-datetime": "Data e hora",
     "prefs-labs": "Functiones experimental",
     "prefs-user-pages": "Paginas de usator",
     "nowatchlist": "Tu non ha paginas sub observation.",
     "watchlistanontext": "Tu debe $1 pro poter vider o modificar entratas in tu observatorio.",
     "watchnologin": "Tu non ha aperite un session",
-    "watchnologintext": "Tu debe [[Special:UserLogin|aperir un session]] pro modificar tu observatorio.",
     "addwatch": "Adder al observatorio",
     "addedwatchtext": "Le pagina \"[[:$1]]\" ha essite addite a tu [[Special:Watchlist|observatorio]].\nLe modificationes futur in iste pagina e in le pagina de discussion associate essera listate in illo.",
     "removewatch": "Remover del observatorio",
     "sp-contributions-newbies-sub": "Pro nove contos",
     "sp-contributions-newbies-title": "Contributiones de nove contos de usator",
     "sp-contributions-blocklog": "Registro de blocadas",
+    "sp-contributions-suppresslog": "contributiones supprimite de usatores",
     "sp-contributions-deleted": "contributiones delite de usatores",
     "sp-contributions-uploads": "incargamentos",
     "sp-contributions-logs": "registros",
     "sp-contributions-blocked-notice": "Iste usator es actualmente blocate. Le ultime entrata del registro de blocadas es reproducite ci infra pro information:",
     "sp-contributions-blocked-notice-anon": "Iste adresse IP es actualmente blocate.\nLe ultime entrata del registro de blocadas es reproducite hic infra pro information:",
     "sp-contributions-search": "Cercar contributiones",
-    "sp-contributions-suppresslog": "contributiones supprimite de usatores",
     "sp-contributions-username": "Adresse IP o nomine de usator:",
     "sp-contributions-toponly": "Monstrar solmente le versiones recente",
     "sp-contributions-newonly": "Monstrar solmente le modificationes que es creationes de pagina",
     "allmessagesname": "Nomine",
     "allmessagesdefault": "Texto predefinite",
     "allmessagescurrent": "Texto actual",
-    "allmessagestext": "Isto es un lista de messages de systema disponibile in le spatio de nomines MediaWiki.\nPer favor visita [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] si tu desira contribuer al localisation general de MediaWiki.",
+    "allmessagestext": "Isto es un lista de messages de systema disponibile in le spatio de nomines MediaWiki.\nPer favor visita [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] si tu desira contribuer al localisation general de MediaWiki.",
     "allmessagesnotsupportedDB": "Iste pagina non pote esser usate proque '''$wgUseDatabaseMessages''' ha essite disactivate.",
     "allmessages-filter-legend": "Filtro",
     "allmessages-filter": "Filtrar per stato de personalisation:",
     "version-entrypoints": "URL del puncto de entrata",
     "version-entrypoints-header-entrypoint": "Puncto de entrata",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Cammino al articulo]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Cammino al script]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Cammino al articulo]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Cammino al script]",
     "redirect": "Rediriger per nomine de file, ID de usator, ID de pagina o ID de version",
     "redirect-legend": "Rediriger a un file o pagina",
     "redirect-summary": "Iste pagina special redirige a un file (si es date le nomine de un file), a un pagina (si es date un ID de version o ID de pagina) o a un pagina de usator (si es date un ID de usator numeric). Usage: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] o [[{{#Special:Redirect}}/user/101]].",
index 3a1d7b1..a19abdd 100644 (file)
     "gotaccountlink": "Masuk log",
     "userlogin-resetlink": "Lupa detail info masuk Anda?",
     "userlogin-resetpassword-link": "Lupa kata sandi?",
+    "userlogin-helplink2": "Bantuan masuk log",
     "userlogin-loggedin": "Andan telah masuk log sebagai $1.\nGunakan formulir di bawah untuk masuk log sebagai pengguna lain.",
     "userlogin-createanother": "Buat akun lain",
     "createacct-join": "Masukkan informasi Anda di bawah ini.",
     "loginlanguagelabel": "Bahasa: $1",
     "suspicious-userlogout": "Permintaan Anda untuk keluar log ditolak karena tampaknya dikirim oleh penjelajah yang rusak atau proksi penyinggah.",
     "createacct-another-realname-tip": "Nama asli bersifat opsional.\nJika Anda memberikannya, nama asli Anda akan digunakan untuk memberi pengenalan atas hasil kerja Anda.",
+    "pt-login": "Masuk log",
+    "pt-login-button": "Masuk log",
+    "pt-createaccount": "Buat akun baru",
+    "pt-userlogout": "Keluar log",
     "php-mail-error-unknown": "Kesalahan yang tidak dikenal dalam fungsi mail() PHP",
     "user-mail-no-addy": "Mencoba mengirimkan surel tanpa alamat surel.",
     "user-mail-no-body": "Mencoba untuk mengirim surel kosong atau terlalu pendek.",
     "changepassword": "Ganti kata sandi",
-    "resetpass_announce": "Anda telah masuk log dengan kode sementara yang dikirim melalui surel. Untuk melanjutkan, Anda harus memasukkan kata sandi baru di sini:",
+    "resetpass_announce": "Untuk menyelesaikan masuk log, Anda harus memasukkan kata sandi baru.",
     "resetpass_text": "<!-- Tambahkan teks di sini -->",
     "resetpass_header": "Ganti kata sandi akun",
     "oldpassword": "Kata sandi lama:",
     "resetpass-submit-loggedin": "Ganti kata sandi",
     "resetpass-submit-cancel": "Batalkan",
     "resetpass-wrong-oldpass": "Kata sandi tidak sah.\nAnda mungkin telah berhasil mengganti kata sandi Anda atau telah meminta kata sandi sementara yang baru.",
+    "resetpass-recycled": "Mohon menyetel ulang kata sandi Anda.",
+    "resetpass-temp-emailed": "Anda masuk log dengan kode sementara yang disurel.\nUntuk menyelesaikan masuk log, Anda harus mengatur sandi baru di sini:",
     "resetpass-temp-password": "Kata sandi sementara:",
     "resetpass-abort-generic": "Perubahan kata sandi telah dibatalkan oleh ekstensi.",
+    "resetpass-expired": "Kata sandi Anda telah kedaluarsa. Silakan atur kata sandi baru untuk masuk log.",
+    "resetpass-expired-soft": "Kata sandi Anda telah kedaluarsa dan perlu disetel ulang. Silakan memilih kata sandi baru, atau klik \"{{int:resetpass-submit-cancel}}\" untuk menyetel ulang pada waktu lain.",
+    "resetpass-validity-soft": "Kata sandi tidak valid: $1\n\nSilakan pilih kata sandi baru sekarang, atau klik \"{{int:resetpass-submit-cancel}}\" untuk menyetel ulang pada waktu lain.",
     "passwordreset": "Setel ulang kata sandi",
     "passwordreset-text-one": "Lengkapi formulir ini untuk menyetel ulang kata sandi.",
     "passwordreset-text-many": "{{PLURAL:$1|Isi salah satu kotak di bawah ini untuk mendapatkan kata sandi sementara melalui surel.}}",
     "changeemail-password": "Sandi {{SITENAME}} Anda:",
     "changeemail-submit": "Ubah surel",
     "changeemail-cancel": "Batalkan",
+    "changeemail-throttled": "Anda sudah terlalu banyak mencoba masuk log.\nSilakan menunggu $1 sebelum mencoba lagi.",
     "resettokens": "Reset token",
     "resettokens-text": "Anda dapat me-reset Token yang memungkinkan akses ke data pribadi tertentu yang terkait dengan akun Anda di sini.\n\nAnda harus melakukannya jika Anda secara tidak sengaja berbagi dengan seseorang atau jika akun Anda telah disusupi.",
     "resettokens-no-tokens": "Tidak ada token untuk di-reset.",
     "undo-summary-username-hidden": "Batalkan revisi $1 oleh seorang pengguna tersembunyi",
     "cantcreateaccounttitle": "Akun tak dapat dibuat",
     "cantcreateaccount-text": "Pembuatan akun dari alamat IP ini (<strong>$1</strong>) telah diblokir oleh [[User:$3|$3]].\n\nAlasan yang diberikan oleh $3 adalah ''$2''",
-    "cantcreateaccount-range-text": "Pembuatan akun dari alamat IP dalam rentang '''$1''', yang mencakup alamat IP anda ('''$4'''), telah diblokir oleh [[Pengguna:$3|$3]].\n\nAlasan yang diberikan oleh  $3  adalah ''$2''",
+    "cantcreateaccount-range-text": "Pembuatan akun dari alamat IP dalam rentang '''$1''', yang mencakup alamat IP anda ('''$4'''), telah diblokir oleh [[User:$3|$3]].\n\nAlasan yang diberikan oleh  $3  adalah ''$2''",
     "viewpagelogs": "Lihat log halaman ini",
     "nohistory": "Tidak ada sejarah penyuntingan untuk halaman ini",
     "currentrev": "Revisi terkini",
     "revdelete-no-file": "Berkas yang dituju tidak ditemukan.",
     "revdelete-show-file-confirm": "Apakah Anda yakin ingin melihat revisi yang telah dihapus dari berkas \"<nowiki>$1</nowiki>\" per $3, $2?",
     "revdelete-show-file-submit": "Ya",
+    "revdelete-selected-text": "{{PLURAL:$1|Revisi terpilih|Revisi terpilih}} dari [[:$2]]:",
+    "revdelete-selected-file": "{{PLURAL:$1|Versi berkas terpilih|Versi berkas terpilih}} dari [[:$2]]:",
     "logdelete-selected": "{{PLURAL:$1|Log|Log-log}} pilihan untuk:",
     "revdelete-confirm": "Tolong konfirmasi bahwa Anda memang bermaksud melakukan ini, memahami konsekuensinya, dan bahwa Anda melakukannya sesuai dengan [[{{MediaWiki:Policy-url}}|kebijakan]].",
     "revdelete-suppress-text": "Penyembunyian revisi '''hanya''' boleh digunakan untuk kasus-kasus berikut:\n* Informasi yang berpotensi memfitnah\n* Informasi pribadi yang tak sepantasnya\n*: ''alamat rumah dan nomor telepon, nomor kartu identitas, dan lain-lain.''",
     "search-file-match": "(cocok dengan isi berkas)",
     "search-suggest": "Mungkin maksud Anda adalah: $1",
     "search-interwiki-caption": "Proyek lain",
-    "search-interwiki-default": "Hasil $1:",
+    "search-interwiki-default": "Hasil dari $1:",
     "search-interwiki-more": "(selanjutnya)",
     "search-relatedarticle": "Berkaitan",
     "searcheverything-enable": "Cari di semua ruang nama",
     "prefs-skin": "Kulit",
     "skin-preview": "Pratayang",
     "datedefault": "Tak ada preferensi",
-    "prefs-beta": "Fitur Beta",
     "prefs-datetime": "Tanggal dan waktu",
     "prefs-labs": "Fitur Labs",
     "prefs-user-pages": "Halaman pengguna",
     "rcnotefrom": "Di bawah ini adalah perubahan sejak <strong>$2</strong> (ditampilkan sampai <strong>$1</strong> perubahan).",
     "rclistfrom": "Perlihatkan perubahan terbaru sejak $1",
     "rcshowhideminor": "$1 suntingan kecil",
+    "rcshowhideminor-show": "Tampilkan",
+    "rcshowhideminor-hide": "Sembunyikan",
     "rcshowhidebots": "$1 bot",
+    "rcshowhidebots-show": "Tampilkan",
+    "rcshowhidebots-hide": "Sembunyikan",
     "rcshowhideliu": "$1 pengguna-pengguna terdaftar",
+    "rcshowhideliu-show": "Tampilkan",
+    "rcshowhideliu-hide": "Sembunyikan",
     "rcshowhideanons": "$1 pengguna anon",
+    "rcshowhideanons-show": "Tampilkan",
+    "rcshowhideanons-hide": "Sembunyikan",
     "rcshowhidepatr": "$1 suntingan terpatroli",
+    "rcshowhidepatr-show": "Tampilkan",
+    "rcshowhidepatr-hide": "Sembunyikan",
     "rcshowhidemine": "$1 suntingan saya",
+    "rcshowhidemine-show": "Tampilkan",
+    "rcshowhidemine-hide": "Sembunyikan",
     "rclinks": "Perlihatkan $1 perubahan terbaru dalam $2 hari terakhir<br />$3",
     "diff": "beda",
     "hist": "versi",
     "uploaddisabledtext": "Pemuatan berkas tidak diizinkan.",
     "php-uploaddisabledtext": "Pemuatan berkas dimatikan di PHP. Silakan cek pengaturan file_uploads.",
     "uploadscripted": "Berkas ini mengandung HTML atau kode yang dapat diinterpretasikan dengan keliru oleh penjelajah web.",
+    "uploadscriptednamespace": "Berkas SVG ini memuat ruang nama ilegal \"$1\"",
     "uploadinvalidxml": "XML dalam berkas yang diunggah tidak bisa diuraikan.",
     "uploadvirus": "Berkas tersebut mengandung virus! Rincian: $1",
     "uploadjava": "Berkas ini adalah berkas ZIP yang mengnadung berkas .class Java.\nPenggunggahan berkas Java tidak diperbolehkan karena dapat menyebabkan pengabaian batasan keamanan.",
     "download": "unduh",
     "unwatchedpages": "Halaman yang tak dipantau",
     "listredirects": "Daftar pengalihan",
+    "listduplicatedfiles": "Daftar berkas yang berduplikat",
     "unusedtemplates": "Templat yang tak digunakan",
     "unusedtemplatestext": "Daftar berikut adalah semua halaman pada ruang nama {{ns:template}} yang tidak dipakai di halaman mana pun.\nCek dahulu pranala lain ke templat tersebut sebelum menghapusnya.",
     "unusedtemplateswlh": "pranala lain",
     "listgrouprights-removegroup-self": "Menghapus {{PLURAL:$2|kelompok|kelompok}} dari akun sendiri: $1",
     "listgrouprights-addgroup-self-all": "Dapat menambahkan semua grup ke akun sendiri",
     "listgrouprights-removegroup-self-all": "Menghapus semua kelompok dari akun sendiri",
+    "trackingcategories-disabled": "Kategori dinonaktifkan",
     "mailnologin": "Tidak ada alamat surel",
     "mailnologintext": "Anda harus [[Special:UserLogin|masuk log]] dan mempunyai alamat surel yang sah di dalam [[Special:Preferences|preferensi]] untuk mengirimkan surel kepada pengguna lain.",
     "emailuser": "Surel pengguna",
     "nowatchlist": "Daftar pantauan Anda kosong.",
     "watchlistanontext": "Silakan $1 untuk melihat atau menyunting daftar pantauan Anda.",
     "watchnologin": "Belum masuk log",
-    "watchnologintext": "Anda harus [[Special:UserLogin|masuk log]] untuk mengubah daftar pantauan Anda.",
     "addwatch": "Tambahkan ke daftar pantauan",
     "addedwatchtext": "Halaman \"[[:$1]]\" telah ditambahkan ke [[Special:Watchlist|daftar pantauan]] Anda.\nPerubahan-perubahan berikutnya pada halaman tersebut dan halaman pembicaraan terkaitnya akan tercantum di sini.",
     "removewatch": "Hapus dari daftar pantauan",
     "allmessagesname": "Nama",
     "allmessagesdefault": "Teks baku",
     "allmessagescurrent": "Teks sekarang",
-    "allmessagestext": "Ini adalah daftar semua pesan sistem yang tersedia dalam ruang nama MediaWiki.\nSilakan kunjungi [https://www.mediawiki.org/wiki/Localisation Pelokalan MediaWiki] dan [//translatewiki.net translatewiki.net] jika Anda ingin berkontribusi untuk pelokalan generik MediaWiki.",
+    "allmessagestext": "Ini adalah daftar semua pesan sistem yang tersedia dalam ruang nama MediaWiki.\nSilakan kunjungi [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Pelokalan MediaWiki] dan [//translatewiki.net translatewiki.net] jika Anda ingin berkontribusi untuk pelokalan generik MediaWiki.",
     "allmessagesnotsupportedDB": "Halaman ini tidak dapat digunakan karena '''$wgUseDatabaseMessages''' telah dimatikan.",
     "allmessages-filter-legend": "Penyaring",
     "allmessages-filter": "Saring dengan keadaan kustomisasi:",
     "version-entrypoints": "URL titik entri",
     "version-entrypoints-header-entrypoint": "Titik entri",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Artikel path]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Skrip path]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Artikel path]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Skrip path]",
     "redirect": "Pengalihan berdasarkan ID berkas, pengguna, halaman atau revisi",
     "redirect-legend": "Pengalihan ke sebuah berkas atau halaman",
     "redirect-summary": "Halaman istimewa ini beralih ke berkas (sesuai nama berkasnya), halaman (sesuai ID revisinya), atau halaman pengguna (sesuai ID numerik penggunanya). Penggunaan: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], atau [[{{#Special:Redirect}}/user/101]].",
index fbe83db..f4ffe1f 100644 (file)
     "prefs-skin": "Kudil",
     "skin-preview": "Ipadas",
     "datedefault": "Awan ti kakaykayatan",
-    "prefs-beta": "Dagiti beta a langa",
     "prefs-datetime": "Petsa ken oras",
     "prefs-labs": "Dagiti subokan a langa",
     "prefs-user-pages": "Dagiti panid ti agar-aramat",
     "nowatchlist": "Awan ti banag iti listaan dagiti bambantayam.",
     "watchlistanontext": "Pangngaasim ti $1 tapno makitam dagiti inurnosmo dita bambantayam.",
     "watchnologin": "Saan a nakastrek",
-    "watchnologintext": "Masapul a [[Special:UserLogin|nakastrekka]] tapno mabaliwam dagiti bambantayam a panid.",
     "addwatch": "Inayon iti bambantayan",
     "addedwatchtext": "Ti panid iti \"[[:$1]]\" ket nainayonen idiay [[Special:Watchlist|listaan ti bambantayam]].\nDagiti masakbayan a panagsukat iti daytoy a panid ken dagiti mainaig a tungtunganna a panid ket mailistanto idiay.",
     "removewatch": "Ikkaten dita bambantayan",
     "sp-contributions-newbies-sub": "Para kadagiti kabarbaro a pakabilangan",
     "sp-contributions-newbies-title": "Dagiti inar-aramid ti agar-aramat iti baro a pakabilangan",
     "sp-contributions-blocklog": "listaan ti naserraan",
+    "sp-contributions-suppresslog": "pasardengen dagiti kontribusion ti agar-aramat",
     "sp-contributions-deleted": "dagiti naikkat nga inar-aramid ti agar-aramat",
     "sp-contributions-uploads": "dagiti pang-ipan",
     "sp-contributions-logs": "listaan",
     "sp-contributions-blocked-notice": "Naserraan tatta daytoy nga agar-aramat.\nTi naudi a listaan ti pannakaserra ket adda dita baba tapno mausar a reperensia:",
     "sp-contributions-blocked-notice-anon": "Daytoy nga IP a pagtaengan ket naserraan.\nTi naudi a listaan ti pannakaserra ket adda dita baba tapno mausar a reperensia:",
     "sp-contributions-search": "Agsapul para kadagiti naar-aramid",
-    "sp-contributions-suppresslog": "pasardengen dagiti kontribusion ti agar-aramat",
     "sp-contributions-username": "IP a pagtaengan wenno nagan ti agar-aramat:",
     "sp-contributions-toponly": "Ipakita laeng dagiti inurnos a kinaudian a panagbaliw",
     "sp-contributions-newonly": "Ipakita laeng dagiti inurnos a pannakapartuat ti pampanid",
     "allmessagesname": "Nagan",
     "allmessagesdefault": "Kasisigud a testo ti mensahe",
     "allmessagescurrent": "Agdama a testo ti mensahe",
-    "allmessagestext": "Daytoy ti listaan dagiti mensahe ti sistema a magun-od idiay MediaWiki a nagan ti espasio.\nPangngaasi a bisitaen ti [https://www.mediawiki.org/wiki/Localisation Lokalisasion ti MediaWiki] ken [//translatewiki.net translatewiki.net] no kayatmo ti agparawad kadagiti sapasap a panagipatarus ti MediaWiki.",
+    "allmessagestext": "Daytoy ti listaan dagiti mensahe ti sistema a magun-od idiay MediaWiki a nagan ti espasio.\nPangngaasi a bisitaen ti [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Lokalisasion ti MediaWiki] ken [//translatewiki.net translatewiki.net] no kayatmo ti agparawad kadagiti sapasap a panagipatarus ti MediaWiki.",
     "allmessagesnotsupportedDB": "Saan a mausar daytoy a panid ngamin ket ti '''$wgUseDatabaseMessages''' ket nabaldado.",
     "allmessages-filter-legend": "Sagat",
     "allmessages-filter": "Sagaten babaen ti naipaduma a kasasaad:",
index 110dfad..1b895dc 100644 (file)
     "mywatchlist": "Surveyaji",
     "nowatchlist": "Vu ne havas objekti en vua listo di surveyaji.",
     "watchnologin": "Vu ne startis sesiono",
-    "watchnologintext": "Vu mustas [[Special:UserLogin|enirir]] por modifikar vua surveyaji.",
     "addedwatchtext": "La pagino \"<nowiki>$1</nowiki>\" atachesis a vua [[Special:Watchlist|listo de surveyaji]]. Futura chanji di ica pagino ed olua relatanta debato-pagini montresos ibe, ed la pagino aparos per '''dika literi''' en la [[Special:RecentChanges|listo de recenta chanji]] por faciligar sua trovebleso.\n\n<p> Se vu volas efacar la pagino de vua listo de surveyaji pose, presez \"Ne plus surveyar\" en la selektaro.",
     "removedwatchtext": "La pagino \"[[:$1]]\" forigesis de [[Special:Watchlist|vua surveyado]].",
     "watch": "Surveyar",
     "export-addcat": "Adjuntar",
     "allmessages": "Omna sistemo-mesaji",
     "allmessagesname": "Nomo",
-    "allmessagestext": "Ico esas listo di omna sistemo-mesaji disponebla en la MediaWiki nomaro.\nVoluntez vizitar [https://www.mediawiki.org/wiki/Localisation MediaWiki Lokizado] e [//translatewiki.net translatewiki.net] se vu volus kontributar ad generala MediaWiki lokizado.",
+    "allmessagestext": "Ico esas listo di omna sistemo-mesaji disponebla en la MediaWiki nomaro.\nVoluntez vizitar [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Lokizado] e [//translatewiki.net translatewiki.net] se vu volus kontributar ad generala MediaWiki lokizado.",
     "allmessages-language": "Linguo:",
     "thumbnail-more": "Grandigar",
     "thumbnail_error": "Ne sucesas krear imajeto: $1",
index 3415cd9..3ae472d 100644 (file)
     "suspicious-userlogout": "Beiðni um útskráningu hafnað því hún var líklegast send frá biluðum vafra eða vefseli sem hefur vistað vefsíðuna í flýtiminni.",
     "createacct-another-realname-tip": "Alvöru nafn er valfrjálst. Ef þú kýst að gefa það upp, verður það notað til að gefa þér heiður af verkum þínum.",
     "pt-createaccount": "Stofna aðgang",
+    "pt-userlogout": "Útskrá",
     "php-mail-error-unknown": "Óþekkt villa í PHP mail() aðgerð.",
     "user-mail-no-addy": "Gat ekki sent tölvupóst því ekkert tölvupóstfang fannst.",
     "user-mail-no-body": "Reyndi að senda tölvupóst með engu eða verulega stuttu meginmáli.",
     "changepassword": "Breyta lykilorði",
-    "resetpass_announce": "Þú skráðir þig inn með tímabundnum netfangskóða.\nTil að klára að skrá þig inn, verður þú að endurstilla lykilorðið hér:",
+    "resetpass_announce": "Til að klára að skrá þig inn, verður þú að velja nýtt lykilorð.",
     "resetpass_text": "<!-- Setja texta hér -->",
     "resetpass_header": "Breyta lykilorði",
     "oldpassword": "Gamla lykilorðið",
     "undo-success": "Breytingin hefur verið tekin tilbaka. Vinsamlegast staðfestu og vistaðu svo.",
     "undo-failure": "Breytinguna var ekki hægt að taka tilbaka vegna breytinga í millitíðinni.",
     "undo-norev": "Ekki var hægt að taka breytinguna aftr því að hún er ekki til eða henni var eytt.",
+    "undo-nochange": "Breytingin virðist þegar hafa verið tekin til baka.",
     "undo-summary": "Tek aftur breytingu $1 frá [[Special:Contributions/$2|$2]] ([[User talk:$2|spjall]])",
     "undo-summary-username-hidden": "Afturkalla breytingu $1 eftir faldan notanda",
     "cantcreateaccounttitle": "Ekki hægt að búa til aðgang",
     "cantcreateaccount-text": "Aðgangsgerð fyrir þetta vistfang ('''$1''') hefur verið bannað af [[User:$3|$3]].\n\nÁstæðan sem $3 gaf fyrir því er ''$2''",
+    "cantcreateaccount-range-text": "Aðgangsgerð frá visföngunum „$1”, sem innihalda vistfang þitt („$4”) hefur verið bönnuð af [[User:$3|$3]].\n\nÁstæðan sem $3 gaf fyrir því er „$2”",
     "viewpagelogs": "Sýna aðgerðir varðandi þessa síðu",
     "nohistory": "Þessi síða hefur enga breytingaskrá.",
     "currentrev": "Núverandi útgáfa",
     "showhideselectedversions": "Sýna/fela valdar breytingar",
     "editundo": "Taka aftur þessa breytingu",
     "diff-empty": "(Enginn munur)",
+    "diff-multi-sameuser": "($1 {{PLURAL:$1|millibreyting ekki sýnd|millibreytingar ekki sýndar}} frá sama notandanum)",
     "diff-multi-manyusers": "($1 {{PLURAL:$1|millibreyting ekki sýnd|millibreytingar ekki sýndar}} frá fleiri en $2 {{PLURAL:$2|notanda|notendum}}.)",
     "difference-missing-revision": "$2 {{PLURAL:$2|útgáfa|útgáfur}} samanburðarins ($1) {{PLURAL:$2|fannst|fundust}} ekki.\n\nÞetta gerist oftast þegar úreldur samanburðartengill tengir á síðu sem hefur verið eytt.\nFrekari upplýsingar eru í [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} eyðingarskránni].",
     "searchresults": "Leitarniðurstöður",
     "search-result-score": "Gildi: $1%",
     "search-redirect": "(tilvísun $1)",
     "search-section": "(hluti $1)",
+    "search-file-match": "(passar við innihald skráa)",
     "search-suggest": "Varstu að leita að: $1",
     "search-interwiki-caption": "Systurverkefni",
     "search-interwiki-default": "$1 útkomur:",
     "prefs-skin": "Þema",
     "skin-preview": "Forskoða",
     "datedefault": "Sjálfgefið",
-    "prefs-beta": "Stillingar á prufustigi",
     "prefs-datetime": "Tímasnið og tímabelti",
     "prefs-labs": "Stillingar á tilraunastigi",
     "prefs-user-pages": "Notendasíður",
     "recentchanges-label-bot": "Þessi breyting var gerð af vélmenni",
     "recentchanges-label-unpatrolled": "Þessi breyting hefur ekki verið yfirfarin",
     "recentchanges-legend-newpage": "(sjá einng [[Special:NewPages|lista yfir nýjar síður]])",
-    "rcnotefrom": "Að neðan eru breytingar síðan '''$2''' (allt að '''$1''' sýndar).",
+    "rcnotefrom": "Að neðan eru breytingar síðan <strong>$2<strong> (allt að <strong>$1<strong> sýndar).",
     "rclistfrom": "Sýna breytingar frá og með $1",
     "rcshowhideminor": "$1 minniháttar breytingar",
     "rcshowhideminor-show": "Sýna",
     "nowatchlist": "Vaktlistinn er tómur.",
     "watchlistanontext": "Vinsamlegast $1ðu þig til að skoða eða breyta vaktlistanum þínum.",
     "watchnologin": "Óinnskráð(ur)",
-    "watchnologintext": "Þú verður að vera [[Special:UserLogin|innskáð(ur)]] til að geta breytt vaktlistanum.",
     "addwatch": "Bæta á vaktlistann",
     "addedwatchtext": "Síðunni „[[:$1]]“ hefur verið bætt á [[Special:Watchlist|vaktlistann]] þinn.\nFrekari breytingar á henni eða spjallsíðu hennar munu verða sýndar þar.",
     "removewatch": "Fjarlægja af vaktlistanum",
     "change-blocklink": "breyta bönnun",
     "contribslink": "framlög",
     "emaillink": "senda tölvupóst",
-    "autoblocker": "Vistfang þitt er bannað vegna þess að það hefur nýlega verið notað af „[[User:$1|$1]]“.\nÁstæðan fyrir því að $1 var bannaður er: „$2“",
+    "autoblocker": "Vistfang þitt var sjálfkrafa bannað vegna þess að það var nýlega notað af „[[User:$1|$1]]“.\nÁstæðan fyrir því að $1 var bannaður er: „$2“",
     "blocklogpage": "Bönnunarskrá",
     "blocklog-showlog": "Notandinn hefur verið bannaður áður.\nSíðasta færsla notandans úr bönnunarskrá er sýnd hér fyrir neðan til skýringar:",
     "blocklog-showsuppresslog": "Notandinn hefur verið bældur niður áður.\nSíðasta færsla notandans úr bælingarskrá er sýnd hér fyrir neðan til skýringar:",
     "range_block_disabled": "Möppudýr geta ekki fjöldabannað vistföng á þessum wiki.",
     "ipb_expiry_invalid": "Tími ógildur.",
     "ipb_expiry_temp": "Bönn faldra notenda verða að vera varanleg.",
-    "ipb_hide_invalid": "Mistókst að bæla niður þennan aðgang; mögulega hefur hann of margar breytingar.",
+    "ipb_hide_invalid": "Mistókst að bæla niður þennan aðgang; hann hefur meira en $1 {{PLURAL:$1|breytingu|breytingar}}.",
     "ipb_already_blocked": "„$1“ er nú þegar í banni",
     "ipb-needreblock": "$1 er þegar bannaður. Vilt þú breyta banninu?",
     "ipb-otherblocks-header": "{{PLURAL:$1|Annað bann|Önnur bönn}}",
     "allmessagesname": "Titill",
     "allmessagesdefault": "Sjálfgefinn skilaboða texti",
     "allmessagescurrent": "Núverandi texti",
-    "allmessagestext": "Þetta er listi yfir kerfismeldingar í Melding-nafnrýminu.\nVinsamlegast heimsæktu [https://www.mediawiki.org/wiki/Localisation MediaWiki-staðfæringuna] og [//translatewiki.net translatewiki.net] ef þú vilt taka þátt í almennri MediaWiki-staðfæringu.",
+    "allmessagestext": "Þetta er listi yfir kerfismeldingar í Melding-nafnrýminu.\nVinsamlegast heimsæktu [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki-staðfæringuna] og [//translatewiki.net translatewiki.net] ef þú vilt taka þátt í almennri MediaWiki-staðfæringu.",
     "allmessagesnotsupportedDB": "Það er ekki hægt að nota '''{{ns:special}}:Allmessages''' því '''$wgUseDatabaseMessages''' hefur verið gerð óvirk.",
     "allmessages-filter-legend": "Sía",
     "allmessages-filter": "Sía með breytingarstöðu:",
     "importuploaderrortemp": "Upphlöðun skráarinnar mistókst.\nTímabundin mappa fannst ekki.",
     "import-parse-failure": "Þáttunarvilla við innflutning XML skjals",
     "import-noarticle": "Engin síða til innflutnings!",
-    "import-nonewrevisions": "Allar breytingar voru fluttar inn.",
+    "import-nonewrevisions": "Engar breytingar voru fluttar inn (þær voru allar annaðhvort þegar til eða sleppt vegna villna).",
     "xml-error-string": "$1 í línu $2, dálki $3 ($4 bæt): $5",
     "import-upload": "Hlaða inn XML-gögnum",
     "import-token-mismatch": "Týnd setu gögn.\nVinsamlegast reyndu aftur.",
     "version-parser-extensiontags": "Þáttuð smáforrita tög",
     "version-hook-subscribedby": "Í áskrift af",
     "version-version": "(Útgáfa $1)",
-    "version-license": "Leyfi",
+    "version-license": "MediaWiki leyfi",
     "version-poweredby-credits": "Þessi wiki er knúin af '''[https://www.mediawiki.org/ MediaWiki]''', höfundaréttur © 2001-$1 $2.",
     "version-poweredby-others": "aðrir",
     "version-license-info": "MediaWiki er frjáls hugbúnaður; þú mátt endurútgefa hann og/eða breyta honum undir GNU General Public leyfi eins og það er gefið út af Free Software stofnuninni, annaðhvort útgáfu 2 eða (að þínu mati) hvaða nýrri útgáfa sem er.\n\nMediaWiki er útgefin í þeirri von að hann sé gagnlegur, en ÁN ALLRAR ÁBYRGÐAR; þar meðtalið er undanskilin ábyrgð við MARKAÐSETNINGU og að hugbúnaðurinn VIRKI Í ÁKVEÐNUM TILGANGI. Sjá GNU General Public leyfið fyrir frekari upplýsingar.\n\nÞú ættir að hafa fengið [{{SERVER}}{{SCRIPTPATH}}/COPYING afrit af  GNU General Public leyfinu] með þessum hugbúnaði, en ef ekki, skrifaðu til Free Software stofnunarinnar, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, Bandaríkjunum eða [//www.gnu.org/licenses/old-licenses/gpl-2.0.html lestu það á netinu]",
index 8605bbc..79831af 100644 (file)
     "pool-timeout": "Timeout durante l'attesa dello sblocco",
     "pool-queuefull": "La coda del pool è piena",
     "pool-errorunknown": "Errore sconosciuto",
+    "pool-servererror": "Il servizio contatore dei pool non è disponibile ($1).",
     "aboutsite": "Informazioni su {{SITENAME}}",
     "aboutpage": "Project:Informazioni",
     "copyright": "Il contenuto è disponibile in base alla licenza $1, se non diversamente specificato.",
     "resettokens-token-label": "$1 (valore attuale: $2)",
     "resettokens-watchlist-token": "Token per il feed web (Atom/RSS) delle [[Special:Watchlist|modifiche alle pagine nei tuoi osservati speciali]]",
     "resettokens-done": "Token reimpostati.",
-    "resettokens-resetbutton": "Reset token selezionati",
+    "resettokens-resetbutton": "Reimposta token selezionati",
     "bold_sample": "Grassetto",
     "bold_tip": "Grassetto",
     "italic_sample": "Corsivo",
     "prefs-skin": "Aspetto grafico (skin)",
     "skin-preview": "Anteprima",
     "datedefault": "Nessuna preferenza",
-    "prefs-beta": "Funzionalità beta",
     "prefs-datetime": "Data e ora",
     "prefs-labs": "Funzionalità sperimentali",
     "prefs-user-pages": "Pagine utente",
     "listgrouprights-removegroup-self": "Può rimuoversi {{PLURAL:$2|dal gruppo|dai gruppi}}: $1",
     "listgrouprights-addgroup-self-all": "Può aggiungersi a tutti i gruppi",
     "listgrouprights-removegroup-self-all": "Può rimuoversi da tutti i gruppi",
+    "trackingcategories-name": "Nome del messaggio",
+    "trackingcategories-desc": "Criteri per l'inclusione nella categoria",
+    "noindex-category-desc": "La pagina contiene la parola magica <nowiki>__NOINDEX__</nowiki> (e si trova in un namespace dove tale flag è consentito) e quindi non è indicizzata dai robot.",
+    "index-category-desc": "La pagina contiene <nowiki>__INDEX__</nowiki> (e si trova in un namespace dove tale flag è consentito) e quindi è indicizzata dai robot, anche se normalmente non lo sarebbe.",
+    "post-expand-template-inclusion-category-desc": "Dopo aver espanso tutti i template, la dimensione della pagina sarà più grande di $wgMaxArticleSize, e dunque alcuni non si espanderanno.",
+    "post-expand-template-argument-category-desc": "Dopo aver espanso il parametro di un template (qualcosa tra parentesi graffe, come {{{Foo}}}), la pagina sarà più grande di $wgMaxArticleSize.",
+    "trackingcategories-nodesc": "Nessuna descrizione disponibile.",
+    "trackingcategories-disabled": "La categoria è disabilitata",
     "mailnologin": "Nessun indirizzo cui inviare il messaggio",
     "mailnologintext": "Per inviare messaggi e-mail ad altri utenti è necessario [[Special:UserLogin|accedere al sito]] e aver registrato un indirizzo valido nelle proprie [[Special:Preferences|preferenze]].",
     "emailuser": "Scrivi all'utente",
     "nowatchlist": "La lista degli osservati speciali è vuota.",
     "watchlistanontext": "Per visualizzare e modificare l'elenco degli osservati speciali è necessario $1.",
     "watchnologin": "Accesso non effettuato",
-    "watchnologintext": "Per modificare la lista degli osservati speciali è necessario prima eseguire l'[[Special:UserLogin|accesso al sito]].",
     "addwatch": "Aggiungi agli osservati speciali",
     "addedwatchtext": "La pagina \"[[:$1]]\" è stata aggiunta alla propria [[Special:Watchlist|lista degli osservati speciali]].\nD'ora in poi, le modifiche apportate alla pagina e alla sua discussione verranno elencate in quella sede.",
     "removewatch": "Rimuovi dagli osservati speciali",
     "sp-contributions-newbies-sub": "Per i nuovi utenti",
     "sp-contributions-newbies-title": "Contributi dei nuovi utenti",
     "sp-contributions-blocklog": "blocchi",
+    "sp-contributions-suppresslog": "contributi utente soppressi",
     "sp-contributions-deleted": "contributi utente cancellati",
     "sp-contributions-uploads": "file caricati",
     "sp-contributions-logs": "registri",
     "sp-contributions-blocked-notice": "Questo utente è attualmente bloccato. L'ultimo elemento del registro dei blocchi è riportato di seguito per informazione:",
     "sp-contributions-blocked-notice-anon": "Questo indirizzo IP è attualmente bloccato. Di seguito è riportato l'ultimo elemento del registro dei blocchi:",
     "sp-contributions-search": "Ricerca contributi",
-    "sp-contributions-suppresslog": "contributi utente soppressi",
     "sp-contributions-username": "Indirizzo IP o nome utente:",
     "sp-contributions-toponly": "Mostra solo i contributi che sono le ultime revisioni per la pagina",
     "sp-contributions-newonly": "Visualizza solo le modifiche che sono creazioni di pagina",
     "allmessagesname": "Nome",
     "allmessagesdefault": "Testo predefinito",
     "allmessagescurrent": "Testo attuale",
-    "allmessagestext": "Questa è la lista di tutti i messaggi di sistema disponibili nel namespace MediaWiki.\nVisitare [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se si desidera contribuire alla localizzazione generica di MediaWiki.",
+    "allmessagestext": "Questa è la lista di tutti i messaggi di sistema disponibili nel namespace MediaWiki.\nVisitare [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se si desidera contribuire alla localizzazione generica di MediaWiki.",
     "allmessagesnotsupportedDB": "Non è possibile utilizzare questa pagina perché il flag '''$wgUseDatabaseMessages''' non è attivo.",
     "allmessages-filter-legend": "Filtro",
     "allmessages-filter": "Filtra per stato di modifica:",
     "version-entrypoints": "URL di accesso",
     "version-entrypoints-header-entrypoint": "Punti di accesso",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Percorso voci]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Percorso script]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Percorso voci]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Percorso script]",
     "redirect": "Reindirizzamento da file, utente, pagina o versione",
     "redirect-legend": "Reindirizza a un file o una pagina",
     "redirect-summary": "Questa pagina speciale reindirizza a un file (specificando il nome del file), a una pagina (specificando un ID di versione o un ID pagina) o a un utente (specificando un ID utente numerico).\nEsempi: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].",
index 95b3b7f..7e33afb 100644 (file)
     "pool-timeout": "ロック待ちタイムアウト",
     "pool-queuefull": "プールキューがいっぱいです",
     "pool-errorunknown": "不明なエラー",
+    "pool-servererror": "プール カウンター サービスは利用できません ($1)。",
     "aboutsite": "{{SITENAME}}について",
     "aboutpage": "Project:{{SITENAME}}について",
     "copyright": "特に記載がない限り、内容は$1のライセンスで利用できます。",
     "prefs-skin": "外装",
     "skin-preview": "プレビュー",
     "datedefault": "選択なし",
-    "prefs-beta": "ベータ版機能",
     "prefs-datetime": "日付と時刻",
     "prefs-labs": "ラボの機能",
     "prefs-user-pages": "利用者ページ",
     "listgrouprights-removegroup-self": "自身のアカウントから{{PLURAL:$2|グループ}}を除去: $1",
     "listgrouprights-addgroup-self-all": "自身のアカウントに全グループを追加可能",
     "listgrouprights-removegroup-self-all": "自身のアカウントから全グループを除去可能",
+    "trackingcategories": "追跡用カテゴリ",
+    "trackingcategories-summary": "このページでは、MediaWiki ソフトウェアが自動的に追加した追跡用カテゴリを列挙します。これらの名前は、{{ns:8}} 名前空間内の対応するシステム メッセージを修正することで変更できます。",
+    "trackingcategories-msg": "追跡用カテゴリ",
+    "trackingcategories-name": "メッセージ名",
+    "trackingcategories-nodesc": "説明はありません。",
     "mailnologin": "送信アドレスがありません",
     "mailnologintext": "他の利用者宛にメールを送信するためには、[[Special:UserLogin|ログイン]]し、[[Special:Preferences|個人設定]]で有効なメールアドレスを設定する必要があります。",
     "emailuser": "この利用者にメールを送信",
     "nowatchlist": "ウォッチリストには何も項目がありません。",
     "watchlistanontext": "ウォッチリストにある項目を閲覧または編集するには、$1してください。",
     "watchnologin": "ログインしていません",
-    "watchnologintext": "ウォッチリストを変更するためには、[[Special:UserLogin|ログイン]]している必要があります。",
     "addwatch": "ウォッチリストに追加",
     "addedwatchtext": "ページ「[[:$1]]」を[[Special:Watchlist|ウォッチリスト]]に追加しました。\nこのページまたはそのトークページが変更されると、ウォッチリストに表示されます。",
     "removewatch": "ウォッチリストから除去",
     "sp-contributions-newbies-sub": "新規利用者のみ",
     "sp-contributions-newbies-title": "新規利用者の投稿記録",
     "sp-contributions-blocklog": "ブロック記録",
+    "sp-contributions-suppresslog": "利用者の秘匿された投稿",
     "sp-contributions-deleted": "削除された投稿の一覧",
     "sp-contributions-uploads": "アップロード",
     "sp-contributions-logs": "記録",
     "sp-contributions-blocked-notice": "この利用者は現在ブロックされています。\n参考のために最新のブロック記録項目を以下に表示します:",
     "sp-contributions-blocked-notice-anon": "このIPアドレスは現在ブロックされています。\n参考のために最近のブロック記録項目を以下に表示します:",
     "sp-contributions-search": "投稿の検索",
-    "sp-contributions-suppresslog": "利用者の秘匿された投稿",
     "sp-contributions-username": "IPアドレスまたは利用者名:",
     "sp-contributions-toponly": "最新版の編集のみを表示",
     "sp-contributions-newonly": "ページ作成を伴う編集のみを表示",
     "allmessagesname": "名前",
     "allmessagesdefault": "既定のメッセージ文",
     "allmessagescurrent": "現在のメッセージ文",
-    "allmessagestext": "これは MediaWiki 名前空間で利用できるシステム メッセージの一覧です。\nMediaWiki 全般のローカライズ (地域化) に貢献したい場合は、[https://www.mediawiki.org/wiki/Localisation/ja MediaWiki のローカライズ]や [//translatewiki.net?setlang=ja translatewiki.net] をご覧ください。",
+    "allmessagestext": "これは MediaWiki 名前空間で利用できるシステム メッセージの一覧です。\nMediaWiki 全般のローカライズ (地域化) に貢献したい場合は、[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki のローカライズ]や [//translatewiki.net?setlang=ja translatewiki.net] をご覧ください。",
     "allmessagesnotsupportedDB": "<strong>$wgUseDatabaseMessages</strong>が無効のため、このページを使用できません。",
     "allmessages-filter-legend": "絞り込み",
     "allmessages-filter": "変更状態により絞り込む:",
     "version-entrypoints": "エントリーポイントの URL",
     "version-entrypoints-header-entrypoint": "エントリーポイント",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath/ja 記事のパス]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath/ja スクリプトパス]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath 記事のパス]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath スクリプトパス]",
     "redirect": "ファイル名、利用者ID、ページID、版IDでの転送",
     "redirect-legend": "ファイルまたはページヘの転送",
     "redirect-summary": "この特別ページは、ファイル (ファイル名を指定)、ページ (版 ID またはページ ID を指定)、利用者ページ (利用者 ID を整数で指定) に転送されます。使用例: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]]",
     "expand_templates_remove_nowiki": "結果に含まれる <nowiki> タグを表示しない",
     "expand_templates_generate_xml": "XML 構文解析ツリーを表示",
     "expand_templates_generate_rawhtml": "HTML ソースを表示",
-    "expand_templates_preview": "プレビュー",
-    "trackingcategories": "追跡用カテゴリ",
-    "trackingcategories-summary": "このページでは、MediaWiki ソフトウェアが自動的に追加した追跡用カテゴリを列挙します。これらの名前は、{{ns:8}} 名前空間内の対応するシステム メッセージを修正することで変更できます。",
-    "trackingcategories-msg": "追跡用カテゴリ",
-    "trackingcategories-name": "メッセージ名",
-    "trackingcategories-nodesc": "説明はありません。"
+    "expand_templates_preview": "プレビュー"
 }
index 6d5183d..ae3a0bb 100644 (file)
     "prefs-skin": "Kulit",
     "skin-preview": "Pratilik",
     "datedefault": "Ora ana préferènsi",
-    "prefs-beta": "Piranti béta",
     "prefs-datetime": "Tanggal lan wektu",
     "prefs-labs": "Piranti lab",
     "prefs-user-pages": "Kaca panganggo",
     "nowatchlist": "Daftar pangawasan panjenengan kosong.",
     "watchlistanontext": "Mangga $1 kanggo mirsani utawa nyunting daftar pangawasan panjenengan.",
     "watchnologin": "Durung mlebu log",
-    "watchnologintext": "Panjenengan kudu [[Special:UserLogin|mlebu log]] kanggo ngowahi daftar artikel pilihan.",
     "addwatch": "Tambah nèng daptar pangawasan",
     "addedwatchtext": "Kaca \"[[:$1]]\" wis ditambahaké menyang [[Special:Watchlist|daftar pangawasan]].\nOwah-owahan sing dumadi ing tembé ing kaca iku lan kaca dhiskusi sing kagandhèng, bakal dipacak ing kéné.",
     "removewatch": "Singkiraké saka daptar pangawasan",
     "allmessagesname": "Asma (jeneng)",
     "allmessagesdefault": "Tèks baku",
     "allmessagescurrent": "Tèks saiki",
-    "allmessagestext": "Iki dhaptar kabèh pesen saka sistem sing ana ing bilik jeneng MediaWiki.\nMangga pirsani [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] lan [//translatewiki.net translatewiki.net] yèn panjenengan arep kontribusi ing lokalisasi generik MediaWiki.",
+    "allmessagestext": "Iki dhaptar kabèh pesen saka sistem sing ana ing bilik jeneng MediaWiki.\nMangga pirsani [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] lan [//translatewiki.net translatewiki.net] yèn panjenengan arep kontribusi ing lokalisasi generik MediaWiki.",
     "allmessagesnotsupportedDB": "Kaca iki ora bisa dienggo amerga '''$wgUseDatabaseMessages''' dipatèni.",
     "allmessages-filter-legend": "Penyaring",
     "allmessages-filter": "Saring nganggo kahanan kustomisasi:",
index 03331b1..271cf74 100644 (file)
     "showhideselectedversions": "ჩვენება/დამალვა არჩეული ვერსიებისა",
     "editundo": "გაუქმება",
     "diff-empty": "(განსხვავება არ არის)",
+    "diff-multi-sameuser": "({{PLURAL:$1|ერთი შუალედური ცვლილება|$1 შუალედური ცვლილებები}} იმავე მომხმარებლის მიერ არ არის ნაჩვენები)",
     "diff-multi-manyusers": "({{PLURAL:$2|ერთი მომხმარებლის|$2 მომხმარებლების}} {{PLURAL:$1|ერთი შუალედური ვერსია|$1 შუალედური ვერსიები}}, რომლებიც არ არის ნაჩვენები.)",
     "difference-missing-revision": "{{PLURAL:$2|$2 ვერსია}} ამ შედარებისათვის ($1) {{PLURAL:$2|ვერ მოიძებნა}}.\n\nეს ჩვეულებრივ ხდება მაშინ, თუ ვერსიების შედარების მოძველებული ბმულით გადადიხართ გვერდზე, რომელიც წაიშალა.\nდეტალური ინფორმაცია შესაძლებელია იყოს [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} წაშლების ჟურნალში].",
     "searchresults": "ძიების შედეგები",
     "prefs-skin": "გარეკანი",
     "skin-preview": "წინასწარი გადახედვა",
     "datedefault": "წყარო მითითებული არაა",
-    "prefs-beta": "ბეტა შესაძლებლობები",
     "prefs-datetime": "თარიღი და დრო",
     "prefs-labs": "ექსპერიმენტალური ფუნქციები",
     "prefs-user-pages": "მომხმარებლის გვერდები",
     "nowatchlist": "თქვენი კონტროლის სია ცარიელია.",
     "watchlistanontext": "$1\n\nიხილეთ ან რედაქტირება გაუკეთეთ თქვენი კონტროლის სიაში შეტანილ ერთეულებს.",
     "watchnologin": "რეგისტრაცია ვერ შესრულდა",
-    "watchnologintext": "თქვენ უნდა მოახდინოთ [[Special:UserLogin|რეგისტრაცია]] თქვენი კონტროლის სიის მოდიფიცირებისათვის.",
     "addwatch": "კონტროლის სიაში დამატება",
     "addedwatchtext": "გვერდი „[[:$1]]“ დაემატა თქვენს [[Special:Watchlist|კონტროლის სიას]].\nამ და მასთან დაკავშირებული განხილვის გვერდის შემდგომი ცვლილებები აისახება იქ.",
     "removewatch": "კონტროლის სიიდან წაშლა",
     "allmessagesname": "დასახელება",
     "allmessagesdefault": "სტანდარტული ტექსტი",
     "allmessagescurrent": "მიმდინარე ტექსტი",
-    "allmessagestext": "ეს არის სისემურ შეტყობინებათა სია «MediaWiki» სახელთა სივრცეში.\nგთხოვთ ეწვიოთ  [https://www.mediawiki.org/wiki/Localisation ლოკალიზაციის აღმწერ] გვერდს [//translatewiki.net translatewiki.net] პროექტს, თუ გსურთ MediaWiki ლოკალიზაციაში წვლილის შეტანა.",
+    "allmessagestext": "ეს არის სისემურ შეტყობინებათა სია «MediaWiki» სახელთა სივრცეში.\nგთხოვთ ეწვიოთ  [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation ლოკალიზაციის აღმწერ] გვერდს [//translatewiki.net translatewiki.net] პროექტს, თუ გსურთ MediaWiki ლოკალიზაციაში წვლილის შეტანა.",
     "allmessagesnotsupportedDB": "{{ns:special}}:AllMessages-ის უზრუნველყოფა არ ხდება, ვინაიდან wgUseDatabaseMessages გამორთულია.",
     "allmessages-filter-legend": "ფილტრი",
     "allmessages-filter": "ფილტრი ცვლილებების სტატუსით:",
     "version-entrypoints": "შესვლის წერტილის URL-ები",
     "version-entrypoints-header-entrypoint": "შესვლის წერტილი",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath გზა სტატიისაკენ]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath გზა სკრიპტისაკენ]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath გზა სტატიისაკენ]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath გზა სკრიპტისაკენ]",
     "redirect": "გადამისამართება ფაილიდან, მომხმარებლიდან, გვერდიდან ან ვერსიის იდენტიფიკატორიდან",
     "redirect-legend": "გადამისამართება ფაილზე ან გვერდზე",
     "redirect-submit": "მიდი",
index f8329e0..87691d7 100644 (file)
     "nowatchlist": "Baqlaw dizimin'iz bos.",
     "watchlistanontext": "Baqlaw dizimin'izdegilerdi qaraw yamasa o'zgertiw ushın $1 kerek.",
     "watchnologin": "Kirilmegen",
-    "watchnologintext": "Baqlaw dizimin'izdi o'zgertiw ushın [[Special:UserLogin|kiriwin'iz]] kerek.",
     "addedwatchtext": "\"[[:$1]]\" beti [[Special:Watchlist|baqlaw dizimin'izge]] qosıldı.\nUsı ha'm og'an baylanıslı bolg'an sa'wbet betlerinde bolatug'ın keleshektegi o'zgerisler usı dizimde ko'rsetiledi ha'mde betti tabıwdı an'satlastırıw ushın [[Special:RecentChanges|taza o'zgerisler diziminde]] '''juwan ha'ripte''' ko'rsetiledi.\nEger siz bul betti baqlaw dizimin'izden o'shirmekshi bolsan'ız bettin' joqarg'ı on' jag'ındag'ı \"Baqlamaw\" jazıwın basın'.",
     "removedwatchtext": "\"[[:$1]]\" beti [[Special:Watchlist|sizin' baqlaw dizimin'izden]] o'shirildi.",
     "watch": "Baqlaw",
     "allmessagesname": "Atama",
     "allmessagesdefault": "Defolt tekst",
     "allmessagescurrent": "Ha'zirgi tekst",
-    "allmessagestext": "Bul {{ns:mediawiki}} isimler ko'pligindegi bar bolg'an sistema xabarları dizimi.\nPlease visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
+    "allmessagestext": "Bul {{ns:mediawiki}} isimler ko'pligindegi bar bolg'an sistema xabarları dizimi.\nPlease visit [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
     "thumbnail-more": "U'lkeytiw",
     "filemissing": "Fayl tabılmadı",
     "thumbnail_error": "Miniatyura jaratıw qa'teligi: $1",
index b6aa9d5..75dde14 100644 (file)
     "prefs-skin": "Aglim",
     "skin-preview": "Pre-timeẓriwt",
     "datedefault": "Ur sɛiɣ ara asemyifi",
-    "prefs-beta": "Tiseɣnin bêta",
     "prefs-datetime": "Azemz d ukud",
     "prefs-labs": "Tiseɣnin « labs »",
     "prefs-user-pages": "Isebtar n useqdac",
     "nowatchlist": "Umuɣ n uɛessi inek d ilem.",
     "watchlistanontext": "G leɛnaya-k $1 iwakken ad twalaḍ neɣ tbeddleḍ iferdas deg wumuɣ n uɛessi inek.",
     "watchnologin": "Ur tekcimeḍ ara",
-    "watchnologintext": "Yessefk ad [[Special:UserLogin|tkecmeḍ]] iwakken ad tbeddleḍ umuɣ n uɛessi inek.",
     "addwatch": "Rnu i umuɣ n uɛassi",
     "addedwatchtext": "Asebter \"[[:$1]]\" yettwarnu deg [[Special:Watchlist|wumuɣ n uḍfar]] inek/inem.\nIbeddlen id-yetteddun deg usebter-agi neɣ deg usbtar umyennan ines, ad banen dagi.",
     "removewatch": "Ekkes seg umuɣ n uɛassi",
     "allmessagesname": "Isem",
     "allmessagesdefault": "Aḍris ameslugen",
     "allmessagescurrent": "Aḍris n tura",
-    "allmessagestext": "Wagi d-umuɣ n inzan yestufan deg tallunt MediaWiki.\nẒeṛ [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] dɣa [//translatewiki.net translatewiki.net] ma tebɣiḍ ad ɛiweneḍ i usideg imcettel n MediaWiki.",
+    "allmessagestext": "Wagi d-umuɣ n inzan yestufan deg tallunt MediaWiki.\nẒeṛ [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] dɣa [//translatewiki.net translatewiki.net] ma tebɣiḍ ad ɛiweneḍ i usideg imcettel n MediaWiki.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:Allmessages''' ut yezmir ara ad yettuseqdac axaṭer '''$wgUseDatabaseMessages''' yettwakkes.",
     "allmessages-filter-legend": "Tastayt",
     "allmessages-filter": "Ṣeffi s addad n ubeddil :",
index 822fd90..42b4448 100644 (file)
@@ -1,6 +1,9 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "GaiJin",
+            "Kaztrans"
+        ]
     },
     "tog-underline": "سىلتەمەنىڭ استىن سىز:",
     "tog-hideminor": "جۋىقتاعى وزگەرىستەردەن شاعىن وڭدەمەلەردى جاسىر",
     "nowatchlist": "باقىلاۋ تىزىمىڭىزدە ەش دانا جوق",
     "watchlistanontext": "باقىلاۋ تىزىمىڭىزدەگى دانالاردى قاراۋ, نە وڭدەۋ ٴۇشىن $1 كەرەك.",
     "watchnologin": "كىرمەگەنسىز",
-    "watchnologintext": "باقىلاۋ ٴتىزىمىڭىزدى وزگەرتۋ ٴۇشىن [[Special:UserLogin|كىرۋىڭىز]] ٴجون.",
     "addedwatchtext": "«[[:$1]]» بەتى [[{{#special:Watchlist}}|باقىلاۋ تىزىمىڭىزگە]] ۇستەلدى.\nبۇل بەتتىڭ جانە بايلانىستى تالقىلاۋ بەتىنىڭ كەلەشەكتەگى وزگەرىستەرى مىندا تىزىمدەلىنەدى دە, جانە بەتتىڭ اتاۋى جەڭىل تابىلۋ ٴۇشىن [[{{#special:Recentchanges}}|جۋىقتاعى وزگەرىستەر تىزىمىندە]] '''جۋان ارپىمەن''' كورسەتىلەدى.",
     "removedwatchtext": "«[[:$1]]» بەتى باقىلاۋ تىزىمىڭىزدەن الاستالدى.",
     "watch": "باقىلاۋ",
     "allmessagesname": "اتاۋى",
     "allmessagesdefault": "ادەپكى ٴماتىنى",
     "allmessagescurrent": "اعىمدىق ٴماتىنى",
-    "allmessagestext": "مىندا {{ns:mediawiki}} ەسىم اياسىندا جەتىمدى جۇيە حابار ٴتىزىمى بەرىلەدى.\nەگەر امبەباپ MediaWiki جەرسىندىرۋگە ۇلەس قوسقىڭىز كەلسە [https://www.mediawiki.org/wiki/Localisation MediaWiki جەرسىندىرۋ بەتىنە] جانە [//translatewiki.net translatewiki.net جوباسىنا] بارىپ شىعىڭىز.",
+    "allmessagestext": "مىندا {{ns:mediawiki}} ەسىم اياسىندا جەتىمدى جۇيە حابار ٴتىزىمى بەرىلەدى.\nەگەر امبەباپ MediaWiki جەرسىندىرۋگە ۇلەس قوسقىڭىز كەلسە [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki جەرسىندىرۋ بەتىنە] جانە [//translatewiki.net translatewiki.net جوباسىنا] بارىپ شىعىڭىز.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' وشىرىلگەن سەبەبىنەن '''{{ns:special}}:AllMessages''' بەتى قولدانىلمايدى.",
     "thumbnail-more": "ۇلكەيتۋ",
     "filemissing": "جوعالعان فايل",
index 262c153..0d9431d 100644 (file)
@@ -1,6 +1,14 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "Alibek Kisybay",
+            "Amangeldy",
+            "Arystanbek",
+            "Bakytgul Salykhova",
+            "Daniyar",
+            "GaiJin",
+            "Kaztrans"
+        ]
     },
     "tog-underline": "Сілтеменің астын сызу:",
     "tog-hideminor": "Жуықтағы өзгерістерден шағын өңдемелерді жасыру",
@@ -25,7 +33,7 @@
     "tog-enotifminoredits": "Шағын өңдеме туралы да маған хат жібер",
     "tog-enotifrevealaddr": "Е-поштамның мекенжайын ескерту хаттарда аш",
     "tog-shownumberswatching": "Бақылап тұрған қатысушылардың санын көрсет",
-    "tog-oldsig": "Ағымдағы қолтаңбаңыз:",
+    "tog-oldsig": "Қазіргі уақыттағы қолтаңбаңыз:",
     "tog-fancysig": "Қолтаңбаны уикимәтін ретінде қарастыру (автоматты сілтеме қойылмайды)",
     "tog-uselivepreview": "Тура қарап шығуды қолдану (сынақтық)",
     "tog-forceeditsummary": "Өңдеменің қысқаша мазмұндамасы бос қалғанда маған ескерт",
     "showhideselectedversions": "Бөлектенген нұсқаларды көрсет/жасыр",
     "editundo": "жоққа шығару",
     "diff-empty": "(айырмашылығы жоқ)",
-    "diff-multi-sameuser": "(Ð\96оғарыда көрсетілген қатысушының (бір ғана қатысушының) арадағы {{PLURAL:$1|бір түзетуі|$1 түзетуі}} көрсетілмеген)",
+    "diff-multi-sameuser": "(Ð\9eÒ£ Ð¶Ð°Ò\9b Ð¶оғарыда көрсетілген қатысушының (бір ғана қатысушының) арадағы {{PLURAL:$1|бір түзетуі|$1 түзетуі}} көрсетілмеген)",
     "diff-multi-otherusers": "({{PLURAL:$2|басқа бір қатысуышының|$2 қатысушының}} арадағы {{PLURAL:$1|бір түзетуі|$1 түзетуі}} көрсетілмеген)",
     "diff-multi-manyusers": "($2-(ден<sup>4</sup>) көп {{PLURAL:$2|қатысуышының|қатысушының}} арадағы {{PLURAL:$1|бір түзетуі|$1 түзетуі}} көрсетілмеген)",
     "difference-missing-revision": "Бұл ($1) {{PLURAL:$2|нұсқа|$2 нұсқалар}} айырмашылығы табылмады.\n\n\nБұл әлте жойылған беттің нұсқалар айырмашылығының сілтемесі.\nЕгжей-тегжейін [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} жою журналынан] таба аласыз.",
     "search-error": "Іздеген кезде қате кездесті: $1",
     "preferences": "Баптаулар",
     "mypreferences": "Баптаулар",
-    "prefs-edits": "Өңдеме саны:",
+    "prefs-edits": "Өңдеме саныңыз:",
     "prefsnologintext2": "Баптауларыңызды өзгерту үшін $1.",
     "prefs-skin": "Мәнерлер",
     "skin-preview": "Қарап шығу",
     "datedefault": "Еш қалаусыз",
-    "prefs-beta": "Beta мүмкіндік",
     "prefs-datetime": "Уақыт",
     "prefs-labs": "Тәжірибелік мүмкіндіктер",
     "prefs-user-pages": "Қатысушы беттері",
     "prefs-common-css-js": "Барлық skin-дер үшін CSS/JavaScript бөлісілді:",
     "prefs-emailconfirm-label": "Е-поштаның расталуы:",
     "youremail": "Е-поштаңыз:",
-    "username": "{{GENDER:$1|Қатысушы аты}}:",
+    "username": "{{GENDER:$1|Қатысушы атыңыз}}:",
     "uid": "{{GENDER:$1|Қатысушы}} теңдестіргішіңіз (ID):",
     "prefs-memberingroups": "{{GENDER:$2|Мүше}}  {{PLURAL:$1|тобыңыз|топтарыңыз}}:",
-    "prefs-registration": "Тіркелу уақыты:",
+    "prefs-registration": "Тіркелген уақытыңыз:",
     "yourrealname": "Нақты атыңыз:",
     "yourlanguage": "Тіліңіз:",
     "yourvariant": "Жазба тілінің нұсқалары:",
     "prefs-help-gender": "Бұл баптауды орнату міндетті емес.\nБағдарламалық жасақтама жынысыңызға сәйкес хабарларды көрсетуге қолданылады.\nБұл мағлұмат баршаға мәлім болады.",
     "email": "Е-поштаңыз",
     "prefs-help-realname": "Нақты атыңыз міндетті емес.\nЕгер бұны жетістіруді таңдасаңыз, бұл түзетуіңіздің ауторлығын анықтау үшін қолданылады.",
-    "prefs-help-email": "Электронды поштаңыздың мекенжайын көрсету міндетті емес, бірақ құпия сөзіңізді ұмытқан жағдайда керек болады.",
-    "prefs-help-email-others": "Кейде қатысушы немесе талқылау бетіңізге е-пошта мекенжайы сілтемесін көрсету арқылы басқалармен байланыса аласыз.\nЕ-пошта мекенжайыныңыз басқа қатысушылар сізбен байланысқан кезде көрсетілмейді",
+    "prefs-help-email": "Электронды поштаңыздың мекенжайын көрсету міндетті емес, бірақ құпия сөзіңізді ұмытқан жағдайда құпия сөзді қалпына келтіру үшін керек болады.",
+    "prefs-help-email-others": "Кейде қатысушы немесе талқылау бетіңізге е-пошта мекенжайы сілтемесін көрсету арқылы басқалармен байланыса аласыз.\nЕ-пошта мекенжайыныңыз басқа қатысушылар сізбен байланысқан кезде көрсетілмейді.",
     "prefs-help-email-required": "Е-пошта мекенжайы керек.",
     "prefs-info": "Негізгі мәлімет",
     "prefs-i18n": "Тіл туралы мәлімет",
     "rcshowhidemine-show": "көрсету",
     "rcshowhidemine-hide": "жасыру",
     "rclinks": "Соңғы $2 күнде болған, соңғы $1 өзгерісті көрсет<br />$3",
-    "diff": "айырм.",
+    "diff": "айырм",
     "hist": "тарихы",
     "hide": "жасыру",
     "show": "көрсету",
     "nviews": "$1 {{PLURAL:$1|қаралу|қаралу}}",
     "nimagelinks": "$1 {{PLURAL:$1|бетінде|беттерінде}} қолданылады",
     "ntransclusions": "$1 {{PLURAL:$1|бетінде|беттерінде}} қолданылады",
-    "specialpage-empty": "Бұл баянатқа еш нәтиже жоқ.",
+    "specialpage-empty": "Бұл сұраныс бойынша нәтиже жоқ.",
     "lonelypages": "Еш беттен сілтелмеген беттер",
     "lonelypagestext": "Келесі беттерге {{SITENAME}} жобасындағы басқа беттерінің ішіндегі кірікбеттер сілтемейді.",
     "uncategorizedpages": "Санатсыз беттер",
     "nowatchlist": "Бақылау тізіміңізде еш дана жоқ",
     "watchlistanontext": "Бақылау тізіміңіздегі даналарды қарау не өңдеу үшін $1.",
     "watchnologin": "Кірмегенсіз",
-    "watchnologintext": "Бақылау тізіміңізді өзгерту үшін [[Special:UserLogin|кіріңіз]].",
     "addwatch": "Бақылау тізіміңізге қосу",
     "addedwatchtext": "«[[:$1]]» беті [[Special:Watchlist|бақылау тізіміңізге]] қосылды.\nБұл беттің және байланысты талқылау бетінің келешектегі өзгерістері мында тізімделінеді де, және беттің атауы жеңіл табылу үшін [[{{#special:Recentchanges}}|жуықтағы өзгерістер тізімінде]] '''жуан әрпімен''' көрсетіледі.",
     "removewatch": "Бақылау тізіміңізден аластату",
     "sp-contributions-newbies": "Тек жаңа тіркелгіден жасаған үлестерді көрсет",
     "sp-contributions-newbies-sub": "Жаңа тіркелгендер үшін",
     "sp-contributions-newbies-title": "Жаңа тіркелгендер үшін қатысушы үлестері",
-    "sp-contributions-blocklog": "Ð\91Ò±Ò\93аÑ\82Ñ\82ау журналы",
-    "sp-contributions-deleted": "Қатысушының жойылған үлестері",
+    "sp-contributions-blocklog": "бұÒ\93аÑ\82Ñ\82алу журналы",
+    "sp-contributions-deleted": "жойылған үлесі",
     "sp-contributions-uploads": "жүктеулері",
     "sp-contributions-logs": "журналдары",
     "sp-contributions-talk": "талқылауы",
     "ipblocklist-no-results": "Сұратылған IP мекенжай не қатысушы аты бұғатталған емес.",
     "blocklink": "бұғаттау",
     "unblocklink": "бұғаттамау",
-    "change-blocklink": "Ð\91ұғаттауын өзгерту",
+    "change-blocklink": "бұғаттауын өзгерту",
     "contribslink": "үлесі",
     "emaillink": "хат жіберу",
     "autoblocker": "IP мекенжайыңызды жуықта \"[[User:$1|$1]]\" пайдаланған, сондықтан өздігінен бұғатталған.\n$1 бұғаттауы үшін келтірілген себебі: «''$2''».",
     "movepagetext": "Бетті бүкіл тарихымен қоса жаңа атауға жылжытқалы жатырсыз.\nБеттің бұрыңғы атауы жаңа бетке айдағыш сілтеме ретінде қалады.\nҚаласаңыз, бұрыңғы атауды мегзейтін сілтемелердің автоматты түрде жаңартылуын таңдай аласыз. Бұны таңдамаған жағдайда, [[Special:DoubleRedirects|екі мәрте айдағыш]] не [[Special:BrokenRedirects|сынық айдағыш]] сілтемелер қалып қоймауына көз жеткізіңіз.\nЖылжытудан кейін әр сілтеме өзіне тиісті бетке мегзейтініне жауапты боласыз.\n\nЕгер жылжытайын деп жатқан жаңа атау басқа бетке әлдеқашан берілген болса, жылжыту '''орындалмайды'''. Бұл шара әлдеқашан бар беттің қайта жазылуынан сақтайды. Алайда, егер бет —   бос бет, не өткен тарихы жоқ [[Special:ListRedirects|айдағыш бет]] болса, жылжыту орындалады. Бұл жаңылыс жылжытылған бетті бұрыңғы атауына қайтаруды мүмкін ету үшін жасалған.\n\n\n'''Ескерту!'''\nБұл көп қаралатын бетке тиісті өзгеріс болуы мүмкін;\nілгері басудан бұрын әрекетіңіздің салдарын есепке алуыңызды сұраймыз.",
     "movepagetext-noredirectfixer": "Бетті бүкіл тарихымен қоса жаңа атауға жылжытқалы жатырсыз.\nБеттің бұрыңғы атауы жаңа бетке айдағыш сілтеме ретінде қалады.\n[[Special:DoubleRedirects|Екі мәрте айдағыш]] не [[Special:BrokenRedirects|сынық айдағыш]] сілтемелер қалып қоймауына көз жеткізіңіз.\nЖылжытудан кейін әр сілтеме өзіне тиісті бетке мегзейтініне жауапты боласыз.\n\nЕгер жылжытайын деп жатқан жаңа атау басқа бетке әлдеқашан берілген болса, жылжыту '''орындалмайды'''. Бұл шара әлдеқашан бар беттің қайта жазылуынан сақтайды. Алайда, егер бет —   бос бет, не өткен тарихы жоқ [[Special:ListRedirects|айдағыш бет]] болса, жылжыту орындалады. Бұл жаңылыс жылжытылған бетті бұрыңғы атауына қайтаруды мүмкін ету үшін жасалған.\n\n\n'''Ескерту!'''\nБұл көп қаралатын бетке тиісті өзгеріс болуы мүмкін;\nілгері басудан бұрын әрекетіңіздің салдарын есепке алуыңызды сұраймыз.",
     "movepagetalktext": "Келесі жағдай орын алса, қатысты талқылау беті '''жылжытылмайды''':\n*жаңа атаумен аталатын беттің талқылау беті әлдеқашан бар болған кезде (бұл жағдайда талқылауын қолмен көшіруге болады, бірақ түйіндемесіне қай беттен көшірілгендігін міндетті түрде жазыңыз)\n*төмендегі қорапшадан құсбелгі алынып тасталғанда.\n\nАл мақаланың атауын өзгертем деп мағлұматын қолмен көшіруге болмайды, себебі беттің түзету тарихын өшіреді.",
-    "movearticle": "Ð\90Ò\93Ñ\8bмдаÒ\93Ñ\8b Ð±ÐµÑ\82 Ð°Ñ\82аÑ\83Ñ\8b:",
+    "movearticle": "Ð\91еÑ\82Ñ\82Ñ\96 Ð¶Ñ\8bлжÑ\8bÑ\82Ñ\83:",
     "moveuserpage-warning": "<strong>Ескерту:</strong> Сіз қатысушы бетін жылжытпақшысыз. Назар аударыңыз, қатысушы беті ғана жылжытылуы мүмкін және қатысушы аты <em>өзгертілмейді</em>.",
     "movenologintext": "Бетті жылжыту үшін тіркелген болуыңыз және [[{{#special:UserLogin}}|кіруіңіз]] жөн.",
     "movenotallowed": "{{SITENAME}} жобасында беттерді жылжытуға рұқсатыңыз жоқ.",
     "allmessagesname": "Атауы",
     "allmessagesdefault": "Әдепкі мәтіні",
     "allmessagescurrent": "Ағымдық мәтіні",
-    "allmessagestext": "Мында {{ns:mediawiki}} есім аясында жетімді жүйе хабар тізімі беріледі.\nЕгер әмбебап MediaWiki жерсіндіруге үлес қосқыңыз келсе [https://www.mediawiki.org/wiki/Localisation MediaWiki жерсіндіру бетіне] және [//translatewiki.net translatewiki.net жобасына] барып шығыңыз.",
+    "allmessagestext": "Мында {{ns:mediawiki}} есім аясында жетімді жүйе хабар тізімі беріледі.\nЕгер әмбебап MediaWiki жерсіндіруге үлес қосқыңыз келсе [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki жерсіндіру бетіне] және [//translatewiki.net translatewiki.net жобасына] барып шығыңыз.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' өшірілген себебінен '''{{#special:AllMessages}}''' беті қолданылмайды.",
     "allmessages-filter-legend": "Сүзгі",
     "allmessages-filter-unmodified": "Өзгертілмегендер",
index 44bf836..fb64486 100644 (file)
@@ -1,6 +1,10 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "Atabek",
+            "GaiJin",
+            "Kaztrans"
+        ]
     },
     "tog-underline": "Siltemeniñ astın sız:",
     "tog-hideminor": "Jwıqtağı özgeristerden şağın öñdemelerdi jasır",
     "nowatchlist": "Baqılaw tizimiñizde eş dana joq",
     "watchlistanontext": "Baqılaw tizimiñizdegi danalardı qaraw, ne öñdew üşin $1 kerek.",
     "watchnologin": "Kirmegensiz",
-    "watchnologintext": "Baqılaw tizimiñizdi özgertw üşin [[Special:UserLogin|kirwiñiz]] jön.",
     "addedwatchtext": "«[[:$1]]» beti [[{{#special:Watchlist}}|baqılaw tizimiñizge]] üsteldi.\nBul bettiñ jäne baýlanıstı talqılaw betiniñ keleşektegi özgeristeri mında tizimdelinedi de, jäne bettiñ atawı jeñil tabılw üşin [[{{#special:Recentchanges}}|jwıqtağı özgerister tiziminde]] '''jwan ärpimen''' körsetiledi.",
     "removedwatchtext": "«[[:$1]]» beti baqılaw tizimiñizden alastaldı.",
     "watch": "Baqılaw",
     "allmessagesname": "Atawı",
     "allmessagesdefault": "Ädepki mätini",
     "allmessagescurrent": "Ağımdıq mätini",
-    "allmessagestext": "Mında {{ns:mediawiki}} esim ayasında jetimdi jüýe xabar tizimi beriledi.\nEger ämbebap MediaWiki jersindirwge üles qosqıñız kelse [https://www.mediawiki.org/wiki/Localisation MediaWiki jersindirw betine] jäne [//translatewiki.net translatewiki.net jobasına] barıp şığıñız.",
+    "allmessagestext": "Mında {{ns:mediawiki}} esim ayasında jetimdi jüýe xabar tizimi beriledi.\nEger ämbebap MediaWiki jersindirwge üles qosqıñız kelse [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki jersindirw betine] jäne [//translatewiki.net translatewiki.net jobasına] barıp şığıñız.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' öşirilgen sebebinen '''{{ns:special}}:AllMessages''' beti qoldanılmaýdı.",
     "thumbnail-more": "Ülkeýtw",
     "filemissing": "Joğalğan faýl",
index 9e9d026..bb0f1ab 100644 (file)
     "faqpage": "Project:FAQ",
     "vector-action-addsection": "새 주제",
     "vector-action-delete": "삭제",
-    "vector-action-move": "ì\9d´ë\8f\99",
+    "vector-action-move": "ì\98®ê¸°ê¸°",
     "vector-action-protect": "보호",
     "vector-action-undelete": "되살리기",
     "vector-action-unprotect": "보호 설정 바꾸기",
     "vector-view-create": "만들기",
     "vector-view-edit": "편집",
-    "vector-view-history": "역사",
+    "vector-view-history": "역사 보기",
     "vector-view-view": "읽기",
     "vector-view-viewsource": "원본 보기",
     "actions": "행위",
     "prefs-skin": "스킨",
     "skin-preview": "미리 보기",
     "datedefault": "기본 값",
-    "prefs-beta": "베타 기능",
     "prefs-datetime": "날짜와 시각",
     "prefs-labs": "실험 중인 기능",
     "prefs-user-pages": "사용자 문서",
     "right-createtalk": "토론 문서 만들기",
     "right-createaccount": "새 계정 만들기",
     "right-minoredit": "사소한 편집으로 표시",
-    "right-move": "문ì\84\9c ì\9d´ë\8f\99",
-    "right-move-subpages": "문ì\84\9cì\99\80 í\95\98ì\9c\84 ë¬¸ì\84\9c ì\9d´ë\8f\99í\95\98기",
-    "right-move-rootuserpages": "ìµ\9cì\83\81ì\9c\84 ì\82¬ì\9a©ì\9e\90 ë¬¸ì\84\9c ì\9d´ë\8f\99",
+    "right-move": "문ì\84\9c ì\98®ê¸°ê¸°",
+    "right-move-subpages": "문ì\84\9cì\99\80 í\95\98ì\9c\84 ë¬¸ì\84\9c ì\98®ê¸°기",
+    "right-move-rootuserpages": "ìµ\9cì\83\81ì\9c\84 ì\82¬ì\9a©ì\9e\90 ë¬¸ì\84\9c ì\98®ê¸°ê¸°",
     "right-movefile": "파일 옮기기",
     "right-suppressredirect": "문서을 옮길 때 원래 문서 이름으로 된 넘겨주기를 만들지 않기",
     "right-upload": "파일 올리기",
     "uploadlogpage": "올리기 기록",
     "uploadlogpagetext": "최근 올라온 파일 목록입니다.\n갤러리 형식으로 확인하고 싶으시다면 [[Special:NewFiles|새 파일 목록]]을 보세요.",
     "filename": "파일 이름",
-    "filedesc": "파일의 설명",
+    "filedesc": "요약",
     "fileuploadsummary": "요약:",
     "filereuploadsummary": "파일의 바뀜:",
     "filestatus": "저작권 상태:",
     "sourceurl": "출처 URL:",
     "destfilename": "파일의 새 이름:",
     "upload-maxfilesize": "파일의 최대 크기: $1",
-    "upload-description": "파일 설명",
+    "upload-description": "파일 설명",
     "upload-options": "올리기 설정",
     "watchthisupload": "이 파일 주시하기",
     "filewasdeleted": "같은 이름을 가진 파일이 올라온 적이 있었고 그 후에 삭제되었습니다.\n올리기 전에 $1을 확인해 주시기 바랍니다.",
     "newpages": "새 문서 목록",
     "newpages-username": "사용자 이름:",
     "ancientpages": "오래된 문서 목록",
-    "move": "ì\9d´ë\8f\99",
-    "movethispage": "문서 이동하기",
+    "move": "ì\98®ê¸°ê¸°",
+    "movethispage": "이 문서 옮기기",
     "unusedimagestext": "다음은 어떠한 문서도 사용하지 않는 파일의 목록입니다.\n다른 사이트에서 URL 접근을 통해 파일을 사용할 수 있기 때문에, 아래 목록에 있는 파일도 실제로 사용 중일 가능성이 있다는 점을 주의해주세요.",
     "unusedcategoriestext": "사용하지 않는 분류 문서의 목록입니다.",
     "notargettitle": "해당하는 문서 없음",
     "nowatchlist": "주시하는 문서가 아직 없습니다.",
     "watchlistanontext": "주시문서 목록을 보거나 고치려면 $1 하세요.",
     "watchnologin": "로그인하지 않음",
-    "watchnologintext": "주시문서 목록을 고치려면 [[Special:UserLogin|로그인]]해야 합니다.",
     "addwatch": "주시문서 목록에 추가",
     "addedwatchtext": "\"[[:$1]]\" 문서를 [[Special:Watchlist|주시문서 목록]]에 추가했습니다.\n앞으로 이 문서나 관련된 토론 문서가 바뀌면 보일 것입니다.",
     "removewatch": "주시문서 목록에서 제거",
     "maximum-size": "최대 크기:",
     "pagesize": "(바이트)",
     "restriction-edit": "편집",
-    "restriction-move": "ì\9d´ë\8f\99",
+    "restriction-move": "ì\98®ê¸°ê¸°",
     "restriction-create": "만들기",
     "restriction-upload": "올리기",
     "restriction-level-sysop": "보호됨",
     "sp-contributions-newbies-sub": "새 사용자의 기여",
     "sp-contributions-newbies-title": "새 사용자의 기여",
     "sp-contributions-blocklog": "차단 기록",
+    "sp-contributions-suppresslog": "삭제된 사용자 기여",
     "sp-contributions-deleted": "삭제된 기여 목록",
     "sp-contributions-uploads": "올린 파일",
     "sp-contributions-logs": "기록",
     "sp-contributions-blocked-notice": "이 사용자는 현재 차단되어 있습니다.\n해당 사용자의 차단 기록은 다음과 같습니다:",
     "sp-contributions-blocked-notice-anon": "이 IP 주소는 현재 차단되어 있습니다.\n차단 기록은 다음과 같습니다:",
     "sp-contributions-search": "기여 검색",
-    "sp-contributions-suppresslog": "삭제된 사용자 기여",
     "sp-contributions-username": "IP 주소 또는 사용자 이름:",
     "sp-contributions-toponly": "최신판만 보기",
     "sp-contributions-newonly": "새 글인 기여만 보기",
     "lockfilenotwritable": "데이터베이스 잠금 파일에 쓰기 권한이 없습니다.\n데이터베이스를 잠그거나 잠금 해제하려면, 웹 서버에서 이 파일의 쓰기 권한을 설정해야 합니다.",
     "databasenotlocked": "데이터베이스가 잠겨 있지 않습니다.",
     "lockedbyandtime": "({{GENDER:$1|$1}} 사용자가 $2 $3에 잠금)",
-    "move-page": "$1 ì\9d´ë\8f\99",
-    "move-page-legend": "문ì\84\9c ì\9d´ë\8f\99í\95\98기",
+    "move-page": "$1 ì\98®ê¸°ê¸°",
+    "move-page-legend": "문ì\84\9c ì\98®ê¸°기",
     "movepagetext": "아래 양식을 채워 문서의 이름을 바꾸고 모든 역사를 새 이름으로 된 문서로 옮길 수 있습니다.\n원래의 문서는 새 문서로 넘겨주는 링크로만 남게 되고,\n원래 이름을 가리키는 넘겨주기는 자동으로 갱신됩니다.\n만약 이 설정을 선택하지 않았다면 [[Special:DoubleRedirects|이중 넘겨주기]]와 [[Special:BrokenRedirects|끊긴 넘겨주기]]를 확인해주세요.\n당신은 링크와 가리키는 대상이 서로 일치하도록 해야 하는 책임을 집니다.\n\n만약 이미 있는 문서의 이름을 새 이름으로 입력했을 때는 그 문서가 넘겨주기 문서이고 문서 역사가 없어야만 이동이 됩니다. 그렇지 않을 경우에는 이동되지 '''않습니다'''.\n이것은 실수로 이동한 문서를 되돌릴 수는 있지만, 이미 존재하는 문서 위에 덮어씌울 수는 없다는 것을 의미합니다.\n\n'''주의!'''\n자주 사용하는 문서를 이동하면 해결하기 어려운 문제를 일으킬 수도 있습니다.\n이동하기 전에 반드시 이 문서를 이동해도 문제가 없는지 확인해주세요.",
     "movepagetext-noredirectfixer": "아래 양식을 채워 문서의 이름을 바꾸고 모든 역사를 새 이름으로 된 문서로 옮길 수 있습니다.\n원래의 문서는 새 문서로 넘겨주는 링크로만 남게 됩니다.\n[[Special:DoubleRedirects|이중 넘겨주기]]와 [[Special:BrokenRedirects|끊긴 넘겨주기]]를 확인해주세요.\n당신은 링크와 가리키는 대상이 서로 일치하도록 해야 하는 책임을 집니다.\n\n만약 이미 있는 문서의 이름을 새 이름으로 입력했을 때는 그 문서가 넘겨주기 문서이고 문서 역사가 없어야만 이동이 됩니다. 그렇지 않을 경우에는 이동되지 '''않습니다'''.\n이것은 실수로 이동한 문서를 되돌릴 수는 있지만, 이미 존재하는 문서 위에 덮어씌울 수는 없다는 것을 의미합니다.\n\n'''주의!'''\n자주 사용하는 문서를 이동하면 해결하기 어려운 문제를 일으킬 수도 있습니다.\n이동하기 전에 반드시 이 문서를 이동해도 문제가 없는지 확인해주세요.",
     "movepagetalktext": "딸린 토론 문서도 자동으로 이동합니다. 하지만 다음의 경우는 '''이동하지 않습니다''':\n* 이동할 이름으로 된 문서가 이미 있는 경우\n* 아래의 선택을 해제하는 경우\n\n이 경우에는 문서를 직접 이동하거나 두 문서를 합쳐야 합니다.",
-    "movearticle": "문ì\84\9c ì\9d´ë\8f\99í\95\98기",
+    "movearticle": "문ì\84\9c ì\98®ê¸°ê¸°:",
     "moveuserpage-warning": "'''경고:''' 사용자 문서를 옮기려 하고 있습니다. 사용자 문서만 이동되며 사용자 이름이 바뀌지 '''않는다'''는 점을 참고하세요.",
     "movenologintext": "문서를 이동하려면 [[Special:UserLogin|로그인]]해야 합니다.",
     "movenotallowed": "문서를 옮길 권한이 없습니다.",
     "movenotallowedfile": "파일을 옮길 권한이 없습니다.",
     "cant-move-user-page": "사용자 문서를 옮길 권한이 없습니다(하위 문서는 예외).",
     "cant-move-to-user-page": "문서를 사용자 문서로 옮길 권한이 없습니다(하위 문서는 예외).",
-    "newtitle": "새 문서 이름",
-    "move-watch": "ì\9b\90본 문서와 대상 문서를 주시하기",
-    "movepagebtn": "이동",
+    "newtitle": "새 제목:",
+    "move-watch": "ì\9b\90ë\9e\98 문서와 대상 문서를 주시하기",
+    "movepagebtn": "문서 옮기기",
     "pagemovedsub": "옮기기 성공",
     "movepage-moved": "'''\"$1\" 문서를 \"$2\" 문서로 옮겼습니다.'''",
     "movepage-moved-redirect": "넘겨주기 문서를 만들었습니다.",
     "movepage-moved-noredirect": "넘겨주기 문서를 남기지 않았습니다.",
     "articleexists": "문서가 이미 존재하거나 이름이 올바르지 않습니다.\n다른 이름을 선택하세요.",
     "cantmove-titleprotected": "새로운 제목으로 문서를 만드는 것이 금지되어 있어 문서를 옮길 수 없습니다",
-    "movetalk": "딸린 토론도 함께 이동합니다.",
-    "move-subpages": "하위 문서도 함께 ($1개 이하) 이동합니다.",
-    "move-talk-subpages": "토론 문서의 하위 문서도 ($1개까지) 함께 이동합니다.",
+    "movetalk": "딸린 토론 문서도 옮기기",
+    "move-subpages": "하위 문서도 옮기기 ($1개까지)",
+    "move-talk-subpages": "토론 문서의 하위 문서도 옮기기 ($1개까지)",
     "movepage-page-exists": "$1 문서가 이미 존재하므로 자동으로 덮어쓸 수 없습니다.",
     "movepage-page-moved": "\"$1\" 문서를 \"$2\" 문서로 옮겼습니다.",
     "movepage-page-unmoved": "$1 문서를 $2 문서로 옮길 수 없습니다.",
     "movepage-max-pages": "{{PLURAL:$1|문서}}를 최대 $1개 옮겼으며 나머지 문서는 자동으로 옮기지 않습니다.",
-    "movelogpage": "ì\9d´ë\8f\99 기록",
-    "movelogpagetext": "ì\95\84ë\9e\98ë\8a\94 ì\9d´ë\8f\99í\95\9c 문서의 목록입니다.",
+    "movelogpage": "ì\98®ê¸°ê¸° 기록",
+    "movelogpagetext": "ì\95\84ë\9e\98ë\8a\94 ì\98®ê²¨ì§\84 ëª¨ë\93  문서의 목록입니다.",
     "movesubpage": "{{PLURAL:$1|하위 문서}}",
     "movesubpagetext": "이 문서에는 다음 {{PLURAL:$1|하위 문서}} $1개가 있습니다.",
     "movenosubpage": "이 문서에는 하위 문서가 존재하지 않습니다.",
     "movereason": "이유:",
     "revertmove": "되돌리기",
-    "delete_and_move": "ì\82­ì \9cí\95\98ê³  ì\9d´ë\8f\99",
+    "delete_and_move": "ì\82­ì \9cí\95\98ê³  ì\98®ê¸°ê¸°",
     "delete_and_move_text": "== 삭제 필요 ==\n이동하려는 제목으로 된 \"[[:$1]]\" 문서가 이미 존재합니다.\n삭제하고 이동할까요?",
     "delete_and_move_confirm": "네. 문서를 삭제합니다",
     "delete_and_move_reason": "\"[[$1]]\"에서 문서를 이동하기 위해 삭제함",
     "nonfile-cannot-move-to-file": "파일이 아닌 문서를 파일 이름공간으로 옮길 수 없습니다.",
     "imagetypemismatch": "새 파일의 확장자가 원래의 확장자와 일치하지 않습니다.",
     "imageinvalidfilename": "새 파일 이름이 잘못되었습니다.",
-    "fix-double-redirects": "기존 이름을 가리키는 넘겨주기를 새로 고침",
-    "move-leave-redirect": "ì\9d´ë\8f\99 í\9b\84 넘겨주기를 남기기",
+    "fix-double-redirects": "원래 제목을 가리키는 넘겨주기를 새로 고침",
+    "move-leave-redirect": "ì\98®ê¸´ ë\92¤ 넘겨주기를 남기기",
     "protectedpagemovewarning": "'''경고:''' 이 문서는 관리자만이 이동할 수 있도록 잠겨 있습니다.\n최근의 기록을 참고용으로 제공합니다:",
     "semiprotectedpagemovewarning": "'''참고:''' 이 문서는 등록된 사용자만이 이동할 수 있도록 잠겨 있습니다.\n최근 기록 내용을 참고용로 제공합니다:",
     "move-over-sharedrepo": "== 파일이 존재함 ==\n[[:$1]] 파일이 공용 저장소에 있습니다. 이 이름으로 파일을 옮기면 공용의 파일을 덮어쓰게 될 것입니다.",
     "allmessagesname": "이름",
     "allmessagesdefault": "기본 메시지 글",
     "allmessagescurrent": "현재 문자열",
-    "allmessagestext": "미디어위키 이름공간에 있는 모든 시스템 메시지의 목록입니다.\n미디어위키의 번역 작업에 관심이 있으면 [https://www.mediawiki.org/wiki/Localisation 미디어위키 지역화]나 [//translatewiki.net translatewiki.net]에 참가해주세요.",
+    "allmessagestext": "미디어위키 이름공간에 있는 모든 시스템 메시지의 목록입니다.\n미디어위키의 번역 작업에 관심이 있으면 [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation 미디어위키 지역화]나 [//translatewiki.net translatewiki.net]에 참가해주세요.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages'''가 비활성화되어 있어서 이 문서를 사용할 수 없습니다.",
     "allmessages-filter-legend": "필터",
     "allmessages-filter": "수정 상태로 거르기:",
     "tooltip-ca-unprotect": "이 문서의 보호 설정을 바꾸기",
     "tooltip-ca-delete": "문서 삭제하기",
     "tooltip-ca-undelete": "삭제되기 전에 이 문서의 완료한 편집 되살리기",
-    "tooltip-ca-move": "문서 이동하기",
+    "tooltip-ca-move": "이 문서 옮기기",
     "tooltip-ca-watch": "이 문서를 주시문서 목록에 추가",
     "tooltip-ca-unwatch": "이 문서를 주시문서 목록에서 제거",
     "tooltip-search": "{{SITENAME}} 검색",
     "quotation-marks": "“$1”",
     "imgmultipageprev": "← 이전 페이지",
     "imgmultipagenext": "다음 페이지 →",
-    "imgmultigo": "이동!",
+    "imgmultigo": "가기!",
     "imgmultigoto": "$1 페이지로 가기",
     "img-lang-default": "(기본 언어)",
     "img-lang-info": "이 그림을 $1로 렌더합니다. $2",
     "version-entrypoints": "URL 진입점",
     "version-entrypoints-header-entrypoint": "진입점",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath 문서 경로]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath 스크립트 경로]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath 문서 경로]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath 스크립트 경로]",
     "redirect": "파일, 사용자, 문서나 판 ID로 넘겨주기",
     "redirect-legend": "파일이나 문서로 넘겨주기",
     "redirect-summary": "이 특수 문서는 파일(파일 이름이 주어짐), 문서(판 ID나 문서 ID가 주어짐)나 사용자 문서(숫자로 표시된 사용자 ID가 주어짐)로 넘겨줍니다. 사용법: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], 또는 [[{{#Special:Redirect}}/user/101]].",
index 419fa02..577a4a7 100644 (file)
@@ -34,7 +34,7 @@
     "tog-shownumberswatching": "Бетни, кёзде тургъан тизмелерине къошханланы санын кёргюз",
     "tog-oldsig": "Бусагъатдагъы къол салыннган:",
     "tog-fancysig": "Къол салыуну энчи вики-тексти (автомат джибериусюз)",
-    "tog-uselivepreview": "Терк ал къарауну хайырландыр (JavaScript, экспериментал халда)",
+    "tog-uselivepreview": "Терк ал къарауну хайырландыр (экспериментал халда)",
     "tog-forceeditsummary": "Тюрлендириуню ачыкълау тизгини бош къалса, билдир",
     "tog-watchlisthideown": "Кёзюмде тургъан бетден мени тюрлендириулерими джашыр",
     "tog-watchlisthidebots": "Кёзюмде тургъан бетден ботланы тюрлендириулерин джашыр",
     "category-subcat-count": "{{PLURAL:$2|Бу категориягъа къуру баргъан тюбкатегория киреди.|$2 тюбкатегориядан $1 киреди бу категориягъа.}}",
     "category-subcat-count-limited": "Бу категорияда {{PLURAL:$1|тюбкатегория|$1 тюбкатегория}} барды.",
     "category-article-count": "{{PLURAL:$2|Бу категорияда къуру бир бет барды.|Бу категориядагъы $2 бетден {{PLURAL:$1|бет|$1 бет}} кёргюзюлгенди.}}",
-    "category-article-count-limited": "Бу категорияда {{PLURAL:$1|$1 бет}} барды.",
+    "category-article-count-limited": "Бу категорияда {{PLURAL:$1|$1 бет|1=джангыз бир бет}} барды.",
     "category-file-count": "{{PLURAL:$2|Бу категорияда къуру бир файл барды.|Категориядагъы $2 файлдан {{PLURAL:$1|бир файл|$1 файлы}} кёргюзюлгенди.}}",
-    "category-file-count-limited": "Бу категория да {{PLURAL:$1|$1 файл}} барды.",
+    "category-file-count-limited": "Бу категорияда {{PLURAL:$1|$1 файл|1=джангыз бир файл}} барды.",
     "listingcontinuesabbrev": "(баргъаны)",
     "index-category": "Индексленнген бетле",
     "noindex-category": "Индексленмеген бетле",
     "newwindow": "(джангы терезеде ачылады)",
     "cancel": "Ызына алыу",
     "moredotdotdot": "Баргъаны…",
-    "morenotlisted": "Энди Ð´Ð¶Ñ\83кÑ\8a Ð´Ð¶Ð¾ÐºÑ\8aдÑ\83...",
+    "morenotlisted": "Ð\91Ñ\83 Ñ\82изме Ñ\82олÑ\83 Ñ\82Ñ\8eлдÑ\8e.",
     "mypage": "Бет",
     "mytalk": "Сюзюу",
     "anontalk": "Бу IP-адресге сюзюу бет",
     "privacypage": "Project:Джашыргъанлыкъ политика",
     "badaccess": "Кириуню халаты",
     "badaccess-group0": "Сизни соргъан амалны этерге эркинлигигиз джокъду.",
-    "badaccess-groups": "Сиз соргъан амалны къуру $1 {{PLURAL:$2|1=группаны|группаланы}} къошулуучуларыны этерге мадарлары барды.",
+    "badaccess-groups": "Сиз соргъан амалны къуру {{PLURAL:$2|бу группаны|бу группаланы}} къошулуучуларыны этерге мадарлары барды: $1.",
     "versionrequired": "MediaWiki-ни $1 версиясы керекди",
     "versionrequiredtext": "Бу бетде ишлер ючюн MediaWiki-ни $1 версиясы керекди.  [[Special:Version|Хайырладырылгъан программаны версияларыны юсюнден информациягъа]] къара.",
     "ok": "ОК",
     "retrievedfrom": "Чыкъгъаны — «$1»",
     "youhavenewmessages": "Сизге $1 келдиле ($2).",
-    "youhavenewmessagesfromusers": "{{PLURAL:$3|1=Башха бир къошулуучудан|$3 къошулуучудан}} сеннге $1 келди ($2).",
+    "youhavenewmessagesfromusers": "{{PLURAL:$3|Башха бир къошулуучудан|$3 къошулуучудан}} {{PLURAL:$4|сеннге}} $1 келди ($2).",
     "youhavenewmessagesmanyusers": "Талай къошулуучудан $1 барды. ($2)",
-    "newmessageslinkplural": "{{PLURAL:$1|1=джангы билдириу|джангы билдириуле}}",
-    "newmessagesdifflinkplural": "ахыр {{PLURAL:$1|тюрлениу}}",
+    "newmessageslinkplural": "{{PLURAL:$1|джангы билдириу|999=джангы билдириуле}}",
+    "newmessagesdifflinkplural": "ахыр {{PLURAL:$1|тюрлениу|999=тюрлениу}}",
     "youhavenewmessagesmulti": "$1 бетде джангы билдириуле бардыла.",
     "editsection": "тюрлендир",
     "editold": "тюрлендир",
     "collapsible-expand": "кёргюз",
     "thisisdeleted": "$1 къараргъа неда къайтарыргъа (тургъузтургъа)?",
     "viewdeleted": "$1 къараймыса?",
-    "restorelink": "кетерилген {{PLURAL:$1|1=1|$1}} тюрлендириу",
+    "restorelink": "{{PLURAL:$1|джангыз бир кетерилген тюрлендириу|$1 кетерилген тюрлендириу}}",
     "feedlinks": "Бу кёрюмде:",
     "feed-invalid": "Джазылыу каналны типи терсди.",
     "feed-unavailable": "Синдикация лентала табылынмайла бусагъатда",
     "badtitle": "Джарамагъан ат",
     "badtitletext": "Сорулгъан бетни аты терсди, бошду, неда интервики аты терс джазылгъанды. Келишмеген (хайырланыргъа болмагъан) символла хайырланыргъада боллукъдула атында.",
     "perfcached": "Бу информация кэшден алыннганды, ахыр тюрлениулени кёргюзмезге боллукъду. Кэшде максимум {{PLURAL:$1|джазыу}} сакъланады.",
-    "perfcachedts": "Бу кэшден алыннган информацияды, ахыр кере ол $1 джангыртылыннганды. Кэшде эм кёбю бла  {{PLURAL:$4|1=джазыу|джазыу}} сакъланады.",
+    "perfcachedts": "Бу кэшден алыннган информацияды, ахыр кере ол $1 джангыртылыннганды. Кэшде эм кёбю бла   {{PLURAL:$4|бир джазыу|$4 джазыу}} сакъланады.",
     "querypage-no-updates": "Бу бетни бусагъатда джангыртыргъа болмайды.\nМында келтирилген информация къабыл этилинник тюйюлдю.",
     "viewsource": "Къарау",
     "viewsource-title": "$1 бетни чыкъгъан текстине къарау",
     "viewyourtext": "Бу бетде '''кесигизни тюрлендириулеригизни''' къайнакъ текстине къараргъа эм копия этерге боллукъсуз:",
     "protectedinterface": "Бу бетде программаны интерфейс билдириую барды.\nБютеу викиледе да бу билдириуню кёчюрмесин къошар неда тюрлендирир ючюн MediaWiki-ни локализациясыны сайты [//translatewiki.net/ translatewiki.net]-ни хайырландырыгъыз.",
     "editinginterface": "'''Эс бёл:''' Сен системаны интерфейс бетин тюрлендире тураса. Бу, викини башха къошулуучуларына да тиерик затды. Кёчюрюр ючюн неда кёчюрмелени тюрлендирир ючюн, MediaWiki-ни локализация этиу проекти [//translatewiki.net/ translatewiki.net]-ни хайырландырыгъыз.",
-    "cascadeprotected": "Бу бет тюрлениуледен джакъланыбды, ол каскадлы джакълау къабыл этилиннген  {{PLURAL:$1|1=бетге|бетлеге}} киргени ючюндю:\n$2",
+    "cascadeprotected": "Бу бет тюрлениуледен джакъланыбды, ол каскадлы джакълау къабыл этилиннген {{PLURAL:$1|бетге|бетлеге}} киргени ючюндю:\n$2",
     "namespaceprotected": "«$1» ат аламда бетлени тюрлендирирге эркинлигигиз джокъду.",
     "customcssprotected": "Бу CSS-бетни тюрлендирирге эркинлигигиз джокъду, бу бетде башха къошулуучуну энчи джарашдырыулары барды.",
     "customjsprotected": "Бу JavaScript-бетни тюрлендирирге эркинлигигиз джокъду, бу бетде башха къошулуучуну энчи джарашдырыулары барды.",
     "invalidtitle-knownnamespace": "«$2» ат аламы бла эм «$3» тексти бла джарамагъан башлыкъ.",
     "invalidtitle-unknownnamespace": "$1 белгили болмагъан алам номери бла эм «$2» тексти бла джарамагъан башлыкъ",
     "exception-nologin": "Авторизацияны ётмегенсиз",
-    "exception-nologin-text": "Бу бетге къарар ючюн неда сорулгъан ишни этер ючюн авторизацияны ётерге керекди.",
+    "exception-nologin-text": "Бу бетге къарар ючюн неда сорулгъан ишни этер ючюн [[Special:Userlogin|авторизацияны ётерге]] керекди.",
     "virus-badscanner": "Джарашдырыуну хатасы. Белгисиз вирус сканер: ''$1''",
     "virus-scanfailed": "скан этиуню хатасы (код $1)",
     "virus-unknownscanner": "белгисиз антивирус:",
-    "logouttext": "'''Аккаунтугъуздан чыкъдыгъыз.'''\n\nСиз {{SITENAME}} сайтда аноним халда къалыргъа боллкъсуз. неда <span class='plainlinks'>[$1 джангыдан кирирге]</span>.\nТалай бетле сиз тергеу джазыу (аккаунт) бла киргенча кёрюнюрге боллукъдула, аны кетерир ючюн кэшни джангыртыгъыз.",
+    "logouttext": "<strong>Аккаунтугъуздан чыкъдыгъыз.</strong>\n\nБир-бир бетле, сиз тергеу джазыу (аккаунт) бла киргенча кёрюнюрге боллукъдула. Аны кетерир ючюн браузеригизни кэшин джангыртыгъыз.",
     "welcomeuser": "Сау кел, $1!",
     "welcomecreation-msg": "Сизни тергеу джазыуугъуз (аккаунтугъуз) къуралды.\n{{SITENAME}} сайтда [[Special:Preferences|джарашдырыуларыгъызны]] тюрлендирирге унутмагъыз.",
     "yourname": "Къошулуучуну аты",
     "gotaccount": "Тергеу джазыуугъуз (аккаунтугъуз) энди бармыды? $1.",
     "gotaccountlink": "Системагъа кир",
     "userlogin-resetlink": "Кирир ючюн билгилеригизни унутхан этгенмисиз?",
-    "userlogin-resetpassword-link": "Паролну джибериу",
+    "userlogin-resetpassword-link": "Паролунгу унутдунгму?",
     "userlogin-helplink2": "Кириуде болушлукъ",
     "userlogin-createanother": "Башха аккаунт къурау",
     "createacct-join": "Билгилеринги тюбюрекде джаз.",
     "createacct-emailrequired": "Электрон почтаны адреси",
     "createacct-emailoptional": "Электрон почтаны адреси (амалсыз тюлдю)",
     "createacct-email-ph": "Электрон почта адресигизни джазыгъыз",
-    "createaccountmail": "Эсде болмагъанлай генерация этилген болджаллы паролну хайырландыр эм тюбюрекде берилген электрон почта адресге ий:",
+    "createaccountmail": "Эсде болмагъанлай генерация этилген болджаллы паролну хайырландырыу эмда берилген электрон почта адресге ийиу",
     "createacct-realname": "Керти атыгъыз (ажымсыз керек тюлдю)",
     "createaccountreason": "Чурум:",
     "createacct-reason": "Чурум",
     "createacct-submit": "Тергеу джазыуну къура",
     "createacct-another-submit": "Энтда бир аккаунт къурау",
     "createacct-benefit-heading": "{{SITENAME}} сизнича адамла бла къуралгъанды.",
-    "createacct-benefit-body1": "{{PLURAL:$1|тюрлениу}}",
-    "createacct-benefit-body2": "{{PLURAL:$1|бет}}",
-    "createacct-benefit-body3": "арт заманда {{PLURAL:$1|къошум этген}}",
+    "createacct-benefit-body1": "{{PLURAL:$1|тюрлениу|тюрлениу}}",
+    "createacct-benefit-body2": "{{PLURAL:$1|бет|бет}}",
+    "createacct-benefit-body3": "арт заманда {{PLURAL:$1|къошум этген|къошум этген}}",
     "badretype": "Джазгъан паролларыгъыз бир-бирине келишмейдиле.",
     "userexists": "Джазылгъан ат хайырландырылады.\nБашха ат сайлагъыз.",
     "loginerror": "Кириуде халат",
     "login-userblocked": "Бу къошулуучу блокга салыннганды. Кирирге мадары джокъду.",
     "wrongpassword": "Сиз джазгъан пароль терсди. Джангыдан кёрюгюз.",
     "wrongpasswordempty": "Пароль джазылмай къалгъанды. Джангыдан кёрюгюз.",
-    "passwordtooshort": "$1 {{PLURAL:$1|символдан}} аз болмазгъа керекди пароль.",
+    "passwordtooshort": "Пароль, {{PLURAL:$1|1 символдан|$1 символдан}} аз болмазгъа керекди.",
     "password-name-match": "Пароль къошулуучу атдан башха тюрлю болургъа керекди.",
     "password-login-forbidden": "Бу къошулуучу ат бла паролну хайырландыргъан джарамайды.",
     "mailmypassword": "Паролну джибер",
     "passwordremindertitle": "{{SITENAME}}  къошулуучугъа джангы болджаллы пароль",
-    "passwordremindertext": "Ким эседа (сиз болургъа боллукъсуз, IP-адрес: $1) {{SITENAME}} ($4) къошулуучугъа джангы пароль къураргъа соргъанды. $2 къошулуучугъа джангы пароль: $3. Сорууну джиберген сиз болгъан эсегиз, системагъа кирирге эм паролну алышдырыргъа тыйычлыды. Джангы паролну $5 {{PLURAL:$5|кюнню}} ичинде амалы боллукъду.\n\nПаролну алышдырыргъа сорууну сиз джибермеген эсегиз, неда эсигизге тюшген эсе паролюгъуз, бу билдириуге эс бёлмегизда къоюгъуз, эски паролюгъузну хайырландырыгъыз.",
+    "passwordremindertext": "Ким эсе да (сиз болургъа боллукъсуз, IP-адрес: $1) {{grammar:genitive|{{SITENAME}}}} ($4) къошулуучугъа джангы пароль къураргъа соргъанды. \n$2\nдеген къошулуучугъа джангы пароль къуралды: $3. Сорууну джиберген сиз болгъан эсегиз, системагъа кирирге эм джангы пароль сайларгъа тыйыншлыды. Болджаллы паролугъузну {{PLURAL:$5|1 кюнню|$5 кюнню}} ичинде амалы боллукъду.\n\nПаролну алмашдырыргъа сорууну сиз джибермеген эсегиз, неда эсигизге тюшген эсе паролугъуз,\nбу билдириуге эс бёлмегиз да къоюгъуз,\nэски паролугъузну хайырландырыгъыз.",
     "noemail": "$1 аты бла къошулуучугъа e-mail адрес джазылмагъанды.",
     "noemailcreate": "Сизге тюз e-mail адресни джазаргъа керекди",
     "passwordsent": "Джангы пароль $1 къошулуучуну электрон почтасына джиберилди.\n\nПаролну алгъандан сора, джангыдан киригиз системагъа.",
     "blocked-mailpassword": "Сизни IP-адресигиз блокланыб турады, аны бла паролну къайтарыу функцияда.",
-    "eauthentsent": "Ð\94жазÑ\8bлгÑ\8aан Ñ\8dлекÑ\82Ñ\80он Ð¿Ð¾Ñ\87Ñ\82агÑ\8aа Ð°Ð´Ñ\80еÑ\81ни Ñ\82Ñ\8eÑ\80лениÑ\83Ñ\8eн Ð±ÐµÐ³Ð¸Ñ\82иÑ\80ге Ñ\81оÑ\80Ñ\83Ñ\83 Ð´Ð¶Ð¸Ð±ÐµÑ\80илгенди. Ð\9fиÑ\81Ñ\8cмода Ð±Ñ\83 Ñ\81изни Ñ\8dлекÑ\82Ñ\80он Ð¿Ð¾Ñ\87Ñ\82агÑ\8aÑ\8bзнÑ\8b Ð°Ð´Ñ\80еÑ\81и Ð±Ð¾Ð»Ð³Ñ\8aанÑ\8bн Ð±ÐµÐ³Ð¸Ñ\82иÑ\80 Ñ\8eÑ\87Ñ\8eн Ð½Ðµ Ñ\8dÑ\82еÑ\80ге ÐºÐµÑ\80ек Ð±Ð¾Ð»Ð³Ñ\8aанÑ\8b Ð´Ð° чертилгенди.",
+    "eauthentsent": "Ð\94жазÑ\8bлгÑ\8aан Ñ\8dлекÑ\82Ñ\80он Ð¿Ð¾Ñ\87Ñ\82агÑ\8aа Ð±Ð¸Ð»Ð´Ð¸Ñ\80иÑ\83 Ð´Ð¶Ð¸Ð±ÐµÑ\80илди. Ð\91илдиÑ\80иÑ\83де Ð±Ñ\83 Ñ\81изни Ñ\8dлекÑ\82Ñ\80он Ð¿Ð¾Ñ\87Ñ\82агÑ\8aÑ\8bзнÑ\8b Ð°Ð´Ñ\80еÑ\81и Ð±Ð¾Ð»Ð³Ñ\8aанÑ\8bн Ð±ÐµÐ³Ð¸Ñ\82иÑ\80 Ñ\8eÑ\87Ñ\8eн Ð½Ðµ Ñ\8dÑ\82еÑ\80ге ÐºÐµÑ\80ек Ð±Ð¾Ð»Ð³Ñ\8aанÑ\8b чертилгенди.",
     "throttled-mailpassword": "Паролну билдириу амал {{PLURAL:$1|1=ахыр $1 сагъатны}} ичинде бир кере хайырланылгъанды.\nДжорукъдан чыгъыудан сакъланыр ючюн $1 {{PLURAL:$1|сагъатны}} ичинде къуру бир билдириу алыргъа болады.",
     "mailerror": "Почта джибериу хата: $1",
     "acct_creation_throttle_hit": "Кюн бла кечеге сизни IP-адресигизден {{PLURAL:$1|$1 тергеу джазыу (аккаунт)}} къуралгъанды. Бу амал энди бусагъатда джабыкъды.",
     "loginlanguagelabel": "Тил: $1",
     "suspicious-userlogout": "Терс браузер неда кэш этиучу прокси берген соруугъа ушагъаны ючюн, Сизни чыгъаргъа сорууугъуз алынмагъанды.",
     "pt-login": "Кириу",
+    "pt-login-button": "Кириу",
     "pt-createaccount": "Аккаунт къурау",
     "pt-userlogout": "Чыгъыу",
     "php-mail-error-unknown": "PHP's mail() функцияда белгили болмагъан халат",
     "revdelete-no-file": "Белгиленнген файл джокъду.",
     "revdelete-show-file-confirm": "«<nowiki>$1</nowiki>» файлны $2 $3 датада кетерилген версиясына къараргъа излегенигизге ишексизмисиз?",
     "revdelete-show-file-submit": "Хоу",
-    "logdelete-selected": "Журналны {{PLURAL:$1|1=Сайланнган джазыу|сайланнган джазыулары}}:",
+    "logdelete-selected": "Журналны {{PLURAL:$1|сайланнган джазыуу|сайланнган джазыулары}}:",
     "revdelete-confirm": "Тилейбиз, буну этерге излегенигизни, эсеблерин ангылагъаныгъызны, эм буну [[{{MediaWiki:Policy-url}}|джорукълагъа]] кёре этгенигизни билдиригиз.",
     "revdelete-suppress-text": "Джашырыу '''джангыз''' бу турумлада этиледи:\n* Келишмеген энчи информация\n*: ''юй адресле эм телефон номерле, паспорт номер эмда башхала''",
     "revdelete-legend": "Чеклеуле сал:",
-    "revdelete-hide-text": "Ð\91еÑ\82ни Ð±Ñ\83 Ð²ÐµÑ\80Ñ\81иÑ\8fÑ\81Ñ\8bнÑ\8b Ñ\82екÑ\81Ñ\82ин Ð´Ð¶Ð°Ñ\88Ñ\8bÑ\80",
+    "revdelete-hide-text": "ТÑ\8eÑ\80лендиÑ\80иÑ\83нÑ\8e Ñ\82екÑ\81Ñ\82и",
     "revdelete-hide-image": "Файлны ичин джашыр",
     "revdelete-hide-name": "Ишлеу бла аны объектин джашыр",
-    "revdelete-hide-comment": "Тюрлениулени ангылатыуларын джашыр",
-    "revdelete-hide-user": "Авторну атын/IP адресин джашыр",
+    "revdelete-hide-comment": "Тюрлениулени ачыкълау",
+    "revdelete-hide-user": "Авторну аты/IP адреси",
     "revdelete-hide-restricted": "Администраторладан да джашыр билгилени",
     "revdelete-radio-same": "(тюрлендирмей къой)",
-    "revdelete-radio-set": "ХоÑ\83",
-    "revdelete-radio-unset": "Ð\9eгÑ\8aай",
+    "revdelete-radio-set": "Ð\94жаÑ\88Ñ\8bÑ\80Ñ\8bлгÑ\8aан",
+    "revdelete-radio-unset": "Ð\9aÑ\91Ñ\80Ñ\8eннген",
     "revdelete-suppress": "Администраторладан да джашыра тур билгилени",
     "revdelete-unsuppress": "Ызына къайтарылгъан версияладан тыйгъычланы кетер",
     "revdelete-log": "Чурум:",
-    "revdelete-submit": "{{PLURAL:$1|1=Сайланнган версия|Сайланнган версиялада}} хайырлан",
+    "revdelete-submit": "{{PLURAL:$1|Сайланнган версияда|Сайланнган версиялада}} хайырлан",
     "revdelete-success": "'''Версияны кёрюнюую джетишимли тюрлендирилгенди'''",
     "revdelete-failure": "'''Версияны кёрюнюую тюрленеллик тюлдю'''\n$1",
     "logdelete-success": "'''Болууланы кёрюнюую тюрленнгенди.'''",
     "mergehistory-go": "Бирлешиннген тюрлендириулени кёргюз",
     "mergehistory-submit": "Тюрлениулени бирлештир",
     "mergehistory-empty": "Бирлешдирир ючюн тюрлениуле табылмагъандыла",
-    "mergehistory-success": "[[:$1]] бетни $3 {{PLURAL:$3|1=тюрлендириую|тюрлендириую}} тыйыншлы [[:$2]] ичинде бирлешдирилди.",
+    "mergehistory-success": "[[:$1]] бетни $3 {{PLURAL:$3|тюрлендириую}} тыйыншлы [[:$2]] ичинде бирлешдирилди.",
     "mergehistory-fail": "Бетлине тарихлери бирлешемеди, тилейбиз бетни эмда заманны параметрлерин джангыдан сынагъыз.",
     "mergehistory-no-source": "$1 тамал бет джокъду",
     "mergehistory-no-destination": "$1 нюзюр бет джокъду",
     "compareselectedversions": "Сайланнган версияланы тенглешдириу",
     "showhideselectedversions": "Сайланнган версияланы кёргюз/джашыр",
     "editundo": "ызына алыу",
-    "diff-multi-manyusers": "($2 къошулуучудан кёб {{PLURAL:$2|1=Бир къошулуучу|къошулуучу}} этген {{PLURAL:$1|1=бир аралыкъ тюрлениу|$1 аралыкъ тюрлениу}} кёргюзюлмегенди)",
-    "difference-missing-revision": "Бу тенглешдириу ($1) ючюн {{PLURAL:$2|1=$2 версия}} {{PLURAL:$2|табылмады}}.\n\n\nБу, эскирген джибериу бла кетерилген бетни версияларын тенглешдириуге кёчген сагъатда кёбюсюне болады.\nТолуракъ информация [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} кетериулени журналында] болургъа боллукъду.",
+    "diff-multi-manyusers": "($2 {{PLURAL:$2|къошулуучудан}} кёб этген {{PLURAL:$1|бир аралыкъ тюрлениу|$1 аралыкъ тюрлениу}} кёргюзюлмегенди)",
+    "difference-missing-revision": "Бу тенглешдириу ($1) ючюн {{PLURAL:$2|бир версия|$2 версия}} {{PLURAL:$2|табылмады}}.\n\n\nБу, эскирген джибериу бла кетерилген бетни версияларын тенглешдириуге кёчген сагъатда кёбюсюне болады.\nТолуракъ информация [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} кетериулени журналында] болургъа боллукъду.",
     "searchresults": "Излеуню эсеби",
     "searchresults-title": "«$1» ючюн излеуню эсеблери",
     "toomanymatches": "Асыры кёб бирчалыкъ барды, джангыдан соруу джиберирге кюрешигиз",
     "prevn": "алдагъы {{PLURAL:$1|$1}}",
     "nextn": "эндиги {{PLURAL:$1|$1}}",
     "prevn-title": "Алдагъы $1 {{PLURAL:$1|эсеб|эсеб}}",
-    "nextn-title": "Эндиги $1 {{PLURAL:$1|эсеб|эсеб}}",
+    "nextn-title": "Эндиги $1 {{PLURAL:$1|эсеб}}",
     "shown-title": "Бетде $1 {{PLURAL:$1|джазыуну}} кёргюз",
     "viewprevnext": "Къара: ($1 {{int:pipe-separator}} $2) ($3)",
     "searchmenu-exists": "'''Бу викиде «[[:$1]]» бет барды'''",
     "prefs-skin": "Джасауу",
     "skin-preview": "Ал къарау",
     "datedefault": "Сайлау джокъду",
-    "prefs-beta": "Бета-амалла",
     "prefs-datetime": "Дата бла сагъат",
     "prefs-labs": "Эксперимент амалла",
     "prefs-user-pages": "Къошулуучуну бетлери",
     "badsiglength": "Къол салыуугъуз бек узунду.\n$1 {{PLURAL:$1|1=символдан|символладан}} кеб болургъа болмайды.",
     "yourgender": "Эркиши/Тиширыу:",
     "gender-unknown": "Белгиленмегенди",
-    "gender-male": "эркиши",
-    "gender-female": "тиширыу",
+    "gender-male": "Викини бетлерин эркиши тюрлендиреди",
+    "gender-female": "Викини бетлерин тиширыу тюрлендиреди",
     "prefs-help-gender": "Излеуге байламлы: джазылым джанындан къошулуучуну ырхызына кёре хайырланады.\nБу билги хар кимгеда ачыкъды.",
     "email": "Электрон почта",
     "prefs-help-realname": "Керти ат (излеуге байламлы).\nАны кёргюзюрге излесегиз, сиз тюрлендирген бетлеригизни,сиз тюрлендиргенигизи белгили боллукъду.",
     "rcshowhideminor-show": "кёргюз",
     "rcshowhideminor-hide": "джашыр",
     "rcshowhidebots": "ботланыкъыланы $1",
+    "rcshowhidebots-show": "кёргюз",
+    "rcshowhidebots-hide": "джашыр",
     "rcshowhideliu": "системагъа киргенленикилени $1",
+    "rcshowhideliu-show": "кёргюз",
+    "rcshowhideliu-hide": "джашыр",
     "rcshowhideanons": "анонимленикилени $1",
-    "rcshowhidepatr": "$1 патруль этилиннген тюрлендириуле",
+    "rcshowhideanons-show": "кёргюз",
+    "rcshowhideanons-hide": "джашыр",
+    "rcshowhidepatr": "тинтилгенлени $1",
+    "rcshowhidepatr-show": "кёргюз",
+    "rcshowhidepatr-hide": "джашыр",
     "rcshowhidemine": "кесими тюрлендириулерими $1",
+    "rcshowhidemine-show": "кёргюз",
+    "rcshowhidemine-hide": "джашыр",
     "rclinks": "Ахыр $2 кюнню ичинде этилиннген $1 тюрлениуню кёргюз;<br /> $3",
     "diff": "башх.",
     "hist": "тарих",
     "withoutinterwiki-legend": "Префикс",
     "withoutinterwiki-submit": "Кёргюз",
     "fewestrevisions": "Эм аз версиясы болгъан бетле",
-    "nbytes": "$1 {{PLURAL:$1|байт|байт}}",
-    "ncategories": "$1 {{PLURAL:$1|1=категория|категорияла}}",
-    "nlinks": "$1 {{PLURAL:$1|1=джибериу|джибериу}}",
-    "nmembers": "$1 {{PLURAL:$1|объект|объект}}",
-    "nrevisions": "$1 {{PLURAL:$1|1=версия|версия}}",
-    "nviews": "$1 {{PLURAL:$1|1=къарау|къарау}}",
-    "nimagelinks": "$1 {{PLURAL:$1|1=бетде|бетде}} хайырланады",
-    "ntransclusions": "$1 {{PLURAL:$1|1=бетде|бетде}} хайырланады",
+    "nbytes": "$1 {{PLURAL:$1|байт}}",
+    "ncategories": "$1 {{PLURAL:$1|категория}}",
+    "nlinks": "$1 {{PLURAL:$1|джибериу}}",
+    "nmembers": "$1 {{PLURAL:$1|объект}}",
+    "nrevisions": "$1 {{PLURAL:$1|версия}}",
+    "nviews": "$1 {{PLURAL:$1|къарау}}",
+    "nimagelinks": "$1 {{PLURAL:$1|бетде}} хайырланады",
+    "ntransclusions": "$1 {{PLURAL:$1|бетде}} хайырланады",
     "specialpage-empty": "Сорма эсеб келтирмеди.",
     "lonelypages": "Ёксюз бетле",
     "lonelypagestext": "Тюбюндеги бетлеге {{SITENAME}} сайтдагъы башха бетледен джибериу берилмегенди неда ала башха бетлеге къошулмагъандыла.",
     "listusers": "Къошулуучуланы тизмеси",
     "listusers-editsonly": "Къуру тюрлендириу этген къошлуучуланы кёргюз",
     "listusers-creationsort": "Къуралгъан заманына кёре сафла",
-    "usereditcount": "$1 {{PLURAL:$1|1=тюрлендириу|тюрлендириу}}",
+    "usereditcount": "$1 {{PLURAL:$1|тюрлендириу}}",
     "usercreated": "$1 $2 заманда {{GENDER:$3|регистрацияны ётгенди}}",
     "newpages": "Джангы бетле",
     "newpages-username": "Къошулуучуну аты:",
     "nowatchlist": "Кёзюгюзде тургъан тизмегиз бошду.",
     "watchlistanontext": "Кёзюгюзде тургъан тизмегизни статьяларын кёрюр неда тюрлендирир ючюн бери ётюгюз: $1.",
     "watchnologin": "Системагъа кирирге керекди.",
-    "watchnologintext": "Кёзюгюзде тургъан тизмегизни тюрлендирир ючюн [[Special:UserLogin|системагъа кирирге керексиз]].",
     "addwatch": "Кёзде тургъан тизмеге къош",
     "addedwatchtext": "«[[:$1]]» бет [[Special:Watchlist|кёзюгюзде тургъан тизмегизге]] къошулду.\nБу бетни эмда муну бла байламлы сюзюу бетни тюрлениулери ол тизмеде белгиленникдиле, [[Special:RecentChanges|джангы тюрлениулени тизмесини]] бетинде уа къалын шрифт бла чертилинникдиле, кёрюрге тынчыракъ болурча.",
     "removewatch": "Кёзде тургъан тизмеден кетер",
     "notanarticle": "Статья тюлдю",
     "notvisiblerev": "Версия кетерилгенди",
     "watchlist-details": "Кёздеги тизмегизде сюзюу бетлери саналмай {{PLURAL:$1|бет|бет}} барды.",
-    "wlheader-enotif": "Эл. почта бла хапар бериу джандырылыбды.",
+    "wlheader-enotif": "E-mail бла хапар бериу джандырылыбды.",
     "wlheader-showupdated": "Ахыр кириуюгюзден сора бетни тюрлениулери '''къалын''' джазыу бла кёргюзюлгенди.",
     "watchmethod-recent": "кёзде тургъан бетледе этилген ахыр тюрлениуле кёрюу",
     "watchmethod-list": "кёзде тургъан бетледе этилген ахыр тюрлениуле кёрюу",
     "protect-locked-blocked": "Тергеу джазыуугъуз джасакъ болса, бетни къоруулауну дараджасын тюрлендиреллик тюлсюз.\n'''$1''' бетдеги бусагъатдагъы параметрле:",
     "protect-locked-dblock": "Актив билги базаны киритленнгени себебли, коъруулау параметрлени тюрлендиреллик тюлсюз.\n'''$1''' бет ючюн бусагъатдагъы параметрле:",
     "protect-locked-access": "Сизге хакъ джетмейди бетни джакълау дараджасын тюрлендирирге. '''$1''' бетни бусагъатдагъы джакълау джарашдырыулары:",
-    "protect-cascadeon": "Бу бет {{PLURAL:$1|1=тюбюнде белгиленнген бетге|тюбюнде белгиленнген бетлеге}} къошулгъаны ючюн джакъланыбды. Ол {{PLURAL:$1|1=бетде|бетледе}} каскадлы джакълау салыныб турады. Сиз бу бетни джакълау дараджасын тюрлендирирге боллукъсуз, алай а ол каскад джакълауну тюрледирлик тюлдю.",
+    "protect-cascadeon": "Бу бет, {{PLURAL:$1|тюбюнде белгиленнген бетге|тюбюнде белгиленнген бетлеге}} къошулгъаны ючюн джакъланыбды. Ол {{PLURAL:$1|бетде|бетледе}} каскадлы джакълау салыныб турады.\nСиз бу бетни джакълау дараджасын тюрлендирирге боллукъсуз, алай а ол каскад джакълауну тюрледирлик тюлдю.",
     "protect-default": "Джакълаусуз",
     "protect-fallback": "«$1» эркинлик керекди",
     "protect-level-autoconfirmed": "Джангы эм регистрация этмеген къошулуучуладан джакъла",
     "allmessagesname": "Ат",
     "allmessagesdefault": "Оригинал текст",
     "allmessagescurrent": "Хайырлана тургъан текст",
-    "allmessagestext": "Бу тизме MediaWiki ат аламында бар болгъан система билдириулени тизмесиди.\nMediaWiki локализациясына юлюш къошаргъа излей эсегиз, [https://www.mediawiki.org/wiki/Localisation MediaWiki локализация] бла [//translatewiki.net translatewiki.net] сайтлагъа киригиз.",
+    "allmessagestext": "Бу тизме MediaWiki ат аламында бар болгъан система билдириулени тизмесиди.\nMediaWiki локализациясына юлюш къошаргъа излей эсегиз, [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki локализация] бла [//translatewiki.net translatewiki.net] сайтлагъа киригиз.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' джабыкъ болгъаны ючюн '''{{ns:special}}:Allmessages''' хайырланыугъа ачыкъ тюлдю.",
     "allmessages-filter-legend": "Фильтр",
     "allmessages-filter": "Тюрлендириуюне кёре фильтрлендир:",
     "pageinfo-article-id": "Бетни идентификатору",
     "pageinfo-language": "Бетни ичиндегисини тили",
     "pageinfo-robot-policy": "Излеу къуллукъла бла индексация",
-    "pageinfo-robot-index": "Ð\98ндекÑ\81аÑ\86иÑ\8f Ñ\8dÑ\82иледи",
-    "pageinfo-robot-noindex": "Ð\98ндекÑ\81аÑ\86иÑ\8f Ñ\8dÑ\82илмейди",
+    "pageinfo-robot-index": "ЭÑ\80кинлик Ð±ÐµÑ\80илгенди",
+    "pageinfo-robot-noindex": "ЭÑ\80кинлик Ð±ÐµÑ\80илмегенди",
     "pageinfo-views": "Къарауланы саны",
     "pageinfo-watchers": "Бетни кёзде тутханланы саны",
-    "pageinfo-redirects-name": "Бу бетге редиректле",
+    "pageinfo-redirects-name": "Бу бетге редиректлени саны",
     "pageinfo-firstuser": "Бетле къураучу",
     "pageinfo-lastuser": "Ахыр редактор",
     "pageinfo-edits": "Бютеу тюрлендириулени саны",
     "imagemaxsize": "Суратны ёлчемини чеги:<br />''(файлны ангылытыу бетле ючюн)''",
     "thumbsize": "Гитче ёлчем:",
     "widthheight": "$1 × $2",
-    "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|1=бет|бет}}",
+    "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|бет}}",
     "file-info": "файлны ёлчеми: $1, MIME типи: $2",
     "file-info-size": "$1 × $2 пиксель, файлны ёлчеми: $3, MIME типи: $4",
     "file-nohires": "Мындан ары ачыкъланнган версиясы джокъду",
     "show-big-image-preview": "Ал къарауда уллулугъу: $1.",
     "show-big-image-size": "$1 × $2 пиксель",
     "file-info-gif-looped": "тогъайланнганды",
-    "file-info-gif-frames": "$1 {{PLURAL:$1|1=фрейм|фрейм}}",
+    "file-info-gif-frames": "$1 {{PLURAL:$1|фрейм}}",
     "file-info-png-looped": "тогъайланнганды",
-    "file-info-png-repeat": "$1 {{PLURAL:$1|1=кере|кере}} ойнатылды",
-    "file-info-png-frames": "$1 {{PLURAL:$1|1=фрейм|фрейм}}",
+    "file-info-png-repeat": "$1 {{PLURAL:$1|кере}} ойнатылды",
+    "file-info-png-frames": "$1 {{PLURAL:$1|фрейм}}",
     "newimages": "Джангы файлланы галереясы",
-    "imagelisttext": "Тюбюрекде $2 кёре тизилген '''$1''' {{PLURAL:$1|1=файл|файл}} кёрюнеди.",
+    "imagelisttext": "Тюбюрекде $2 кёре тизилген <strong>$1</strong> {{PLURAL:$1|файл}} кёрюнеди.",
     "newimages-summary": "Бу къуллукъ бет, кёб болмай джюкленнген файлланы кёргюзеди.",
     "newimages-legend": "Фильтр",
     "newimages-label": "Файлны аты (неда кесеги):",
     "ilsubmit": "Таб",
     "bydate": "Хронологиягъа кёре",
     "sp-newimages-showfrom": "$1, $2 замандан башлаб джангы файлланы кёргюз",
-    "seconds": "{{PLURAL:$1|1=$1 секунд|$1 секунд}}",
-    "minutes": "{{PLURAL:$1|1=$1 минут|$1 минут}}",
-    "hours": "{{PLURAL:$1|1=$1 сагъат|$1 сагъат}}",
-    "days": "{{PLURAL:$1|1=$1 кюн|$1 кюн}}",
+    "seconds": "{{PLURAL:$1|$1 секунд}}",
+    "minutes": "{{PLURAL:$1|$1 минут}}",
+    "hours": "{{PLURAL:$1|$1 сагъат}}",
+    "days": "{{PLURAL:$1|$1 кюн}}",
     "weeks": "{{PLURAL:$1|ыйыкъ}}",
     "months": "{{PLURAL:$1|ай}}",
     "years": "{{PLURAL:$1|джыл}}",
     "exif-compression-3": "CCITT Group 3, факс кодлау",
     "exif-compression-4": "CCITT Group 4, факс кодлау",
     "exif-copyrighted-true": "Автор хакъла бла джакъланыбды",
-    "exif-copyrighted-false": "Ð\94жамагÑ\8aаÑ\82 Ð¼Ñ\8eлк",
+    "exif-copyrighted-false": "Ð\90вÑ\82оÑ\80 Ð¾Ð½Ð³Ð½Ñ\83 Ñ\81Ñ\82аÑ\82Ñ\83Ñ\81Ñ\83 Ð±ÐµÑ\80илмегенди",
     "exif-unknowndate": "Билинмеген заман",
     "exif-orientation-1": "Нормал",
     "exif-orientation-2": "Горизонтал бла кёргюзюлгенди",
     "exif-gpslatitude-s": "Къыбыла кенглик",
     "exif-gpslongitude-e": "Кюнчыгъыш узунлукъ",
     "exif-gpslongitude-w": "Кюнбатыш узунлукъ",
-    "exif-gpsaltitude-above-sealevel": "$1 {{PLURAL:$1|1=метрге|метрге}} тенгизден мийик",
-    "exif-gpsaltitude-below-sealevel": "$1 {{PLURAL:$1|1=метрге|метрге}} тенгизден алаша",
+    "exif-gpsaltitude-above-sealevel": "$1 {{PLURAL:$1|метрге}} тенгизден мийик",
+    "exif-gpsaltitude-below-sealevel": "$1 {{PLURAL:$1|метрге}} тенгизден алаша",
     "exif-gpsstatus-a": "Ёлчелеу бошалмагъанды",
     "exif-gpsstatus-v": "Ёлчелеу бошалгъанды",
     "exif-gpsmeasuremode-2": "2-ли координатланы ёлчелеу",
     "livepreview-ready": "Джюклениу... Хазырды!",
     "livepreview-failed": "Джанлы ал къарау джетишимсиз! Нормал ал къарауну сынагъыз.",
     "livepreview-error": "Байланыу этиленмеди: $1 \"$2\".\nНормал ал къарауну хайырланыгъыз.",
-    "lag-warn-normal": "$1 {{PLURAL:$1|1=секундан|секундан}} джангы тюрлендириуле бу тизмеде кёрюнмезге боллукъдула.",
-    "lag-warn-high": "Билги базаны сервериндеги бек кечигиу себебли, $1 {{PLURAL:$1|1=секундан|секундан}} джангы тюрлендириуле бу тизмеде кёрюнмей къалыргъа болур.",
-    "watchlistedit-numitems": "Кёзде тургъан тизмеде {{PLURAL:$1|1=1 джазылгъан|$1 джазылгъан}} барды, сюзюу бетлени тышында.",
+    "lag-warn-normal": "$1 {{PLURAL:$1|секундан}} джангы тюрлендириуле бу тизмеде кёрюнмезге боллукъдула.",
+    "lag-warn-high": "Билги базаны сервериндеги бек кечигиу себебли, $1 {{PLURAL:$1|секундан}} джангы тюрлендириуле бу тизмеде кёрюнмей къалыргъа болур.",
+    "watchlistedit-numitems": "Кёзде тургъан тизмеде {{PLURAL:$1|1 джазылгъан|$1 джазылгъан}} барды, сюзюу бетлени тышында.",
     "watchlistedit-noitems": "Кёзюгюзде тургъан тизмегизде бир джазылгъан да джокъду.",
     "watchlistedit-normal-title": "Чынчыкълау спизокню тюрлендир",
     "watchlistedit-normal-legend": "Кёзюгюзде тургъан тизмегизден джазылгъанланы кетериу",
     "watchlistedit-normal-explain": "Кёзде тургъан тизмедеги бетле тюбюрекде кёргюзюлгендиле.\nДжазылгъанланы кетерир ючюн, къатындагъы тёртгюлчюкде белгилеб, «{{int:Watchlistedit-normal-submit}}» тиекден басыгъыз.\nСиз дагъыда [[Special:EditWatchlist/raw|тизмени текст кибик тюрлендирирге]] боллукъсуз.",
     "watchlistedit-normal-submit": "Башлыкъланы кетер",
-    "watchlistedit-normal-done": "{{PLURAL:$1|1=1 джазылгъан|$1 джазылгъан}}, кёзюгюзде тургъан тизмегизден кетерилди:",
+    "watchlistedit-normal-done": "{{PLURAL:$1|1 джазылгъан|$1 джазылгъан}}, кёзюгюзде тургъан тизмегизден кетерилди:",
     "watchlistedit-raw-title": "Кёзде тургъан «чий» тизмени тюрлендир",
     "watchlistedit-raw-legend": "Кёзде тургъан «чий» тизмени тюрлендир",
     "watchlistedit-raw-explain": "Кёзюгюзде тургъан тизмегиздеги бетле тюбюнде кёрюнедиле. Хар тизгинде бир башлыкъ болады, бетлени къошуб неда кетериб тизмени тюрлендирирге боллукъсуз.\nБошалса, «{{int:Watchlistedit-raw-submit}}» деген тиекден басыгъыз.\n[[Special:EditWatchlist|Стандарт тюрлендириу]] бла да хайырланаллыкъсыз.",
     "watchlistedit-raw-titles": "Башлыкъла:",
     "watchlistedit-raw-submit": "Кёзде тургъан тизмени сакъла",
     "watchlistedit-raw-done": "Кёзюгюзде тургъан тизмегиз сакъланнганды.",
-    "watchlistedit-raw-added": "{{PLURAL:$1|1=1 башлыкъ|$1 башлыкъ}} къошулду:",
-    "watchlistedit-raw-removed": "{{PLURAL:$1|1=1 башлыкъ|$1 башлыкъ}} кетерилди:",
+    "watchlistedit-raw-added": "{{PLURAL:$1|1 башлыкъ|$1 башлыкъ}} къошулду:",
+    "watchlistedit-raw-removed": "{{PLURAL:$1|1 башлыкъ|$1 башлыкъ}} кетерилди:",
     "watchlisttools-view": "Тизмеден бетледе тюрлениуле",
     "watchlisttools-edit": "Тизмеге къарау эм тюрлендириу",
     "watchlisttools-raw": "Текстча тюрлендириу",
     "version-hook-name": "Тутуучуну аты",
     "version-hook-subscribedby": "Абонент болгъан",
     "version-version": "(Версия $1)",
-    "version-license": "Лицензия",
+    "version-license": "MediaWiki'ни лицензиясы",
     "version-poweredby-credits": "Бу вики '''[https://www.mediawiki.org/ MediaWiki]''' программа бла ишлейди, copyright © 2001-$1 $2.",
     "version-poweredby-others": "башхала",
     "version-license-info": "MediaWiki эркин программа джазыуду, сиз аны GNU General Public License лицензияны (эркин программа джазыуланы фонду чыгъаргъан; экинчи версиясы неда андан кеч къайсысы да) шартларына кёре джаяргъа эмда/неда тюрлендирирге боллукъсуз.\n\nMediaWiki хайырлы боллукъду деген умут бла джайылады, алай а БИР ТЮРЛЮ БИР ГАРАНТИЯСЫЗДЫ, КОММЕРЦИЯЛЫКЪ неда ЭНЧИ БИР НЮЗЮРГЕ ДЖАРАРЫКЪ гаратияласыз огъунады. Толуракъ билгиле кёрюр ючюн GNU General Public License лицензиягъа къарагъыз.\n\nБу программа бла бирге  [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU General Public License лицензияны копиясы] болургъа керекди, джокъ эсе Free Software Foundation, Inc. комапиягъа джазыгъыз (адреси: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA) неда [//www.gnu.org/licenses/old-licenses/gpl-2.0.html лицензияны онлайн окъугъуз].",
     "fileduplicatesearch-submit": "Таб",
     "fileduplicatesearch-info": "$1 × $2 пиксель<br />Файлны ёлчеми: $3<br />MIME-тип: $4",
     "fileduplicatesearch-result-1": "«$1» файлны келишген дубликаты джокъду",
-    "fileduplicatesearch-result-n": "«$1» файлны {{PLURAL:$2|1=1 келишген дубликатыi|$2 келишген дубликаты}} барды.",
+    "fileduplicatesearch-result-n": "«$1» файлны {{PLURAL:$2|1 келишген дубликаты|$2 келишген дубликаты}} барды.",
     "fileduplicatesearch-noresults": "«$1» деген файл табылмады.",
     "specialpages": "Къуллукъ бетле",
-    "specialpages-note": "* Тюз къуллукъчу бетле.\n* <span class=\"mw-specialpagerestricted\">Кирирге эркинлик чекленнген къуллукъчу бетле.</span>\n* <span class=\"mw-specialpagecached\">Кэш этилген къуллукъчу бетле (эски болургъа боллукъдула).</span>",
+    "specialpages-note": "* Тюз къуллукъ бетле.\n* <span class=\"mw-specialpagerestricted\">Кирирге эркинлик чекленнген къуллукъ бетле.</span>",
     "specialpages-group-maintenance": "Техника баджарыуну отчетлары",
     "specialpages-group-other": "Башха къуллукъчу бетле",
     "specialpages-group-login": "Системагъа кириу / Аккаунт къурау",
     "tags-description-header": "Магъананы толу ангылтыуу",
     "tags-hitcount-header": "Белгиленнген тюрлендириуле",
     "tags-edit": "тюрлендир",
-    "tags-hitcount": "$1 {{PLURAL:$1|1=тюрлениу|тюрлениу}}",
+    "tags-hitcount": "$1 {{PLURAL:$1|тюрлениу}}",
     "comparepages": "Бетлени тенглешдир",
     "compare-page1": "Биринчи бет",
     "compare-page2": "Экинчи бет",
     "revdelete-uname-unhid": "къошулуучуну аты ачылды",
     "revdelete-restricted": "администраторла ючюн этилген чеклениуле",
     "revdelete-unrestricted": "администратолра ючюн этилген чеклениуле къоратылгъандыла",
-    "logentry-move-move": "$1, $3 бетни атын $4 деб тюрлендирди",
+    "logentry-move-move": "$1, $3 бетни атын $4 деб {{GENDER:$2|тюрлендирди}}",
     "logentry-move-move-noredirect": "$1, $3 бетни атын $4 деб {{GENDER:$2|тюрлендирди}} (редирект къоймагъанлай)",
     "logentry-move-move_redir": "$1, $3 бетни атын $4 деб {{GENDER:$2|тюрлендирди}} (редиректни башы бла)",
     "logentry-move-move_redir-noredirect": "$1, $3 бетни атын $4 деб {{GENDER:$2|тюрлендирди}} (редиректни башы бла эм редирект къурамай)",
-    "logentry-patrol-patrol": "$1, $3 бетни $4 версияын партруль этиб чыкъды",
-    "logentry-patrol-patrol-auto": "$1, $3 бетни $4 версиясын автомат халда тинтиб чыкъды",
+    "logentry-patrol-patrol": "$1, $3 бетни $4 версияын партруль этиб {{GENDER:$2|чыкъды}}",
+    "logentry-patrol-patrol-auto": "$1, $3 бетни $4 версиясын автомат халда тинтиб {{GENDER:$2|чыкъды}}",
     "logentry-newusers-newusers": "$1 тергеу джазыу (аккаунт) {{GENDER:$2|къуралды}}",
-    "logentry-newusers-create": "$1 тергеу джазыу (аккаунт) къуралды",
-    "logentry-newusers-create2": "$1, $3 тергеу джазыуну къурады",
-    "logentry-newusers-autocreate": "$1 тергеу джазыу автомат халда къуралды",
+    "logentry-newusers-create": "$1 тергеу джазыу (аккаунт) {{GENDER:$2|къуралды}}",
+    "logentry-newusers-create2": "$1, $3 тергеу джазыуну {{GENDER:$2|къурады}}",
+    "logentry-newusers-autocreate": "$1 тергеу джазыу автомат халда {{GENDER:$2|къуралды}}",
     "logentry-rights-rights": "$1 къошулуучу, $3 къошулуучуну членлигин $4 къауумдан $5 къауумгъа {{GENDER:$2|кёчюрдю}}",
-    "logentry-rights-rights-legacy": "$1 къошулуучу, $3 къушулуучуну къауумлада членлигин тюрлендирди",
+    "logentry-rights-rights-legacy": "$1 къошулуучу, $3 къушулуучуну къауумлада членлигин {{GENDER:$2|тюрлендирди}}",
     "logentry-rights-autopromote": "$1 къошулуучу, $4 къауумдан автомат халда $5 къауумгъа {{GENDER:$2|кёчюрюлдю}}",
     "rightsnone": "(джокъ)",
     "feedback-subject": "Тема:",
     "searchsuggest-search": "Излеу",
     "searchsuggest-containing": "ичиндегиси…",
     "api-error-badtoken": "Ич халат: терс токен.",
-    "api-error-duplicate-popup-title": " {{PLURAL:$1|1=Файлны|Файлны}} дубликаты",
+    "api-error-duplicate-popup-title": "Дубликат {{PLURAL:$1|файл|файлла}}",
     "api-error-empty-file": "Сиз ийген файлны ичи бошду.",
     "api-error-emptypage": "Ичи бош болгъан джангы бетле къураргъа болмайды.",
     "api-error-file-too-large": "Сиз ийген файл асыры уллуду.",
     "api-error-filename-tooshort": "Файлны аты асыры къысхады.",
     "api-error-filetype-banned": "Быллай типли файлла джасакъланыбдыла.",
-    "api-error-filetype-banned-type": "$1 — {{PLURAL:$4|1=джасакъланнган файл типди|джасакъланнган файл типледиле}}. {{PLURAL:$3|1=Эркинлик берилген файл тип —|Эркинлик берилген файл типле:}} $2.",
+    "api-error-filetype-banned-type": "$1 — {{PLURAL:$4|джасакъланнган файл типди|джасакъланнган файл типледиле}}. {{PLURAL:$3|Эркинлик берилген файл тип —|Эркинлик берилген файл типле:}} $2.",
     "api-error-filetype-missing": "Файлны кенгериую джокъду.",
     "api-error-hookaborted": "Сиз теджеген тюрлендириуню кенгертиуню сюзюучю джасакълагъанды.",
     "api-error-illegal-filename": "Джарамагъан файл ат.",
index 9880e24..d2c81e3 100644 (file)
@@ -1,6 +1,13 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "Geitost",
+            "Matma Rex",
+            "Purodha",
+            "Reedy",
+            "Rentenirer",
+            "לערי ריינהארט"
+        ]
     },
     "tog-underline": "Dun de Links ungerstriche:",
     "tog-hideminor": "Dun de klein Mini-Änderunge (<strong>M</strong>) en de Liss  met „{{int:Recentchanges}}“ <strong>nit</strong> aanzeije",
     "prefs-skin": "Et Ussinn",
     "skin-preview": "Vör-Ansich",
     "datedefault": "Ejaal - kein Vörliebe",
-    "prefs-beta": "Saache zum Ußprobeere, di schun en Zick lang erproob woode sin",
     "prefs-datetime": "Datum un Uhrzigge",
     "prefs-labs": "Neu Saache zom Ußprobeere, die künnte noch nit akeraat fluppe",
     "prefs-user-pages": "Metmaachersigge",
     "nowatchlist": "En Ding Oppassliss es nix dren.",
     "watchlistanontext": "Do muss $1, domet de en Ding Oppassliss erenluure kanns, oder jet dran ändere.",
     "watchnologin": "Nit enjelogg",
-    "watchnologintext": "Öm Ding Oppassliss ze ändere, mööts de ald [[Special:UserLogin|enjelogg]] sin.",
     "addwatch": "En de Oppassliss don",
     "addedwatchtext": "Die Sigg „[[:$1]]“ es jetz en Dinge [[Special:Watchlist|Oppaßleß]].\nWann di Sigg udder ier Klaafsigg verändert weed, kütt dat af jäz heh en di Oppaßleß.",
     "removewatch": "Us de Oppassliss nämme",
     "sp-contributions-newbies-sub": "För neu Metmaacher",
     "sp-contributions-newbies-title": "Neu Metmaacher ier Beidräsch",
     "sp-contributions-blocklog": "Logboch met Metmaacher-Sperre",
+    "sp-contributions-suppresslog": "verschtoche Beidrääch",
     "sp-contributions-deleted": "Fottjeschmesse Beidrääsch",
     "sp-contributions-uploads": "huhjelaade Dateie",
     "sp-contributions-logs": "Logböcher",
     "sp-contributions-blocked-notice": "Heh dä Metmaacher es em Momang jespert, Dä letzte Enndraach em Logbooch doh drövver kütt jez als ene Henwiiß:",
     "sp-contributions-blocked-notice-anon": "Heh di <i lang=\"en\">IP</i>-Address es em Momang jesperrt.\nDe neuste Sperr ier Enndraach em Logbooch es:",
     "sp-contributions-search": "Söök noh Metmaacher ier Beidräg",
-    "sp-contributions-suppresslog": "verschtoche Beidrääch",
     "sp-contributions-username": "Metmaachername odder IP-Address:",
     "sp-contributions-toponly": "Bloß neuste Versione zeije",
     "sp-contributions-newonly": "Blohß neu aanjelaate Sigge zeije.",
     "allmessagesname": "Name",
     "allmessagesdefault": "Dä standaadmäßije Tex",
     "allmessagescurrent": "Esu es dä Tex jetz",
-    "allmessagestext": "Heh kütt en Liss met Texte, Texstöck, un Nohreechte em Appachtemeng „MediaWiki“ — Do draan Ändere löht et Wiki anders ußsin, dat darf dröm nit Jede maache.\nWenn De jenerell aan [https://www.mediawiki.org/wiki/Localisation MediaWiki singe Översezung] jet anders han wells, do jangk noh [//translatewiki.net translatewiki.net].",
+    "allmessagestext": "Heh kütt en Liss met Texte, Texstöck, un Nohreechte em Appachtemeng „MediaWiki“ — Do draan Ändere löht et Wiki anders ußsin, dat darf dröm nit Jede maache.\nWenn De jenerell aan [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki singe Översezung] jet anders han wells, do jangk noh [//translatewiki.net translatewiki.net].",
     "allmessagesnotsupportedDB": "<strong>Dat wor nix!</strong> Mer künne „{{#special:allmessages}}“ nit zeije, <code>$wgUseDatabaseMessages</code> es usjeschalt!",
     "allmessages-filter-legend": "Ußsöhke — wat för en Täxte o Nohreeshte aazeije?",
     "allmessages-filter": "Zohshtand:",
     "version-entrypoints": "<i lang=\"en\" xml:lang=\"en\">URL</i>s för enzeschteije",
     "version-entrypoints-header-entrypoint": "Enschteesch",
     "version-entrypoints-header-url": "<i lang=\"en\">URL</i>",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Der Pad noh de Atikele]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Der Pad noh de Skrepte]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Der Pad noh de Atikele]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Der Pad noh de Skrepte]",
     "redirect": "Ömleide op en Dattei, ene Metmaacher udder de Väsjohn vun ener Sigg",
     "redirect-legend": "Ömleide ob_en Dattei udder Sigg",
     "redirect-summary": "Heh di {{int:specialpage}} leidt öm ob_en Dattei — doh mößd_Er ene Nahme aanjävve, för e Beischpell:[[{{#Special:Redirect}}/file/Example.jpg]] — udder en Sigg — doh mößd_Er en Kännong för, udder en Väsjuhn aanjävve, för e Beischpell esu: [[{{#Special:Redirect}}/page/64308]] udder [[{{#Special:Redirect}}/revision/328429]] — udder en Metmaachersigg — doh mößd_Er enem Metmaacher sing Kännong aanjävve, för e Beischpell: [[{{#Special:Redirect}}/user/101]].",
index ffd0d7b..1efa02f 100644 (file)
     "revisiondelete": "Emendationem delere",
     "revdelete-nooldid-title": "Emendatio-scopus invalida",
     "revdelete-show-file-submit": "Sic",
+    "revdelete-selected-text": "{{PLURAL:$1|Emendatio selecta|Emendationes selectae}} paginae [[:$2]]:",
+    "revdelete-selected-file": "{{PLURAL:$1|Emendatio selecta|Emendationes selectae}} fasciculi [[:$2]]:",
     "revdelete-legend": "Modificare cohibitiones visibilitatis",
     "revdelete-hide-text": "Textus emendationis",
     "revdelete-hide-image": "Celare contentum fasciculi",
     "prefs-skin": "Aspectum",
     "skin-preview": "Praevisum",
     "datedefault": "Nullum praeferentiae",
-    "prefs-beta": "Facultates experimentales",
     "prefs-datetime": "Dies et tempus",
     "prefs-user-pages": "Paginae usoris",
     "prefs-personal": "Minutiae rationis",
     "nowatchlist": "Nullas paginas custodis.",
     "watchlistanontext": "Necesse est $1 ad indicem paginarum custoditarum inspiciendum vel recensendum.",
     "watchnologin": "Conventum non est apertum",
-    "watchnologintext": "[[Special:UserLogin|Conventum aperire]] debes ut indicem paginarum custoditarum mutes.",
     "addedwatchtext": "Pagina \"[[:$1]]\" in [[Special:Watchlist|paginas tuas custoditas]] addita est.\nMutationes posthac huic paginae et paginae disputationis ibi notabuntur.",
     "removedwatchtext": "Pagina \"[[:$1]]\" ex [[Special:Watchlist|indice paginarum custoditarum]] remota est.",
     "watch": "Custodire",
index 8efc1a3..921899c 100644 (file)
     "prefs-skin": "Skin",
     "skin-preview": "Kucken",
     "datedefault": "Egal (Standard)",
-    "prefs-beta": "Beta-Funktiounen",
     "prefs-datetime": "Datum an Auerzäit",
     "prefs-labs": "\"Labs\"-Funktiounen",
     "prefs-user-pages": "Benotzersäiten",
     "download": "eroflueden",
     "unwatchedpages": "Net iwwerwaacht Säiten",
     "listredirects": "Lëscht vun de Viruleedungen",
+    "listduplicatedfiles-entry": "[[:File:$1|$1]] huet [[$3|{{PLURAL:$2|een Doublon|$2 Doublonen}}]].",
     "unusedtemplates": "Net benotzt Schablounen",
     "unusedtemplatestext": "Op dëser Säit stinn all Säiten aus dem {{ns:template}} Nummraum, déi a kenger anerer Säit benotzt ginn. Vergiesst net nozekucken, ob et keng aner Linken op dës Schabloune gëtt, ier Dir eng Schabloun läscht.",
     "unusedtemplateswlh": "Aner Linken",
     "listgrouprights-removegroup-self": "Däerf {{PLURAL:$2|de Grupp|d'Gruppe}} vu sengem eegene Benotzerkont ewechhuelen: $1",
     "listgrouprights-addgroup-self-all": "däerf all Gruppe bei säin eegene Benotzerkont derbäisetzen",
     "listgrouprights-removegroup-self-all": "Däerf all Gruppe vu sengem eegene Benotzerkont ewechhuelen",
+    "trackingcategories-name": "Numm vum Message",
+    "trackingcategories-nodesc": "Keng Beschreiwung disponibel.",
+    "trackingcategories-disabled": "Kategorie ass desaktivéiert",
     "mailnologin": "Keng E-Mailadress",
     "mailnologintext": "Dir musst [[Special:UserLogin|ageloggt]] sinn an eng gëlteg E-Mail Adress an Ären [[Special:Preferences|Astellungen]] aginn hunn, fir engem anere Benotzer eng E-Mail ze schécken.",
     "emailuser": "Dësem Benotzer eng E-Mail schécken",
     "nowatchlist": "Är Iwwerwaachungslëscht ass eidel.",
     "watchlistanontext": "Dir musst $1 fir Säiten op ärer Iwwerwaachungslëscht ze gesinn oder z'änneren.",
     "watchnologin": "Net ageloggt",
-    "watchnologintext": "Dir musst [[Special:UserLogin|ugemellt]] sinn, fir Är Iwwerwaachungslëscht z'änneren.",
     "addwatch": "Op d'Iwwerwaachungslëscht derbäisetzen",
     "addedwatchtext": "D'Säit \"[[:$1]]\" gouf op är [[Special:Watchlist|Iwwerwaachungslëscht]] gesat.\nAll weider Ännerungen op dëser Säit an der associéierter Diskussiounssäit ginn hei opgelëscht.",
     "removewatch": "Vun der Iwwerwaachungslëscht erofhuelen",
     "allmessagesname": "Numm",
     "allmessagesdefault": "Standardtext",
     "allmessagescurrent": "Aktuellen Text",
-    "allmessagestext": "Dëst ass eng Lëscht vun alle '''Messagen am MediaWiki:Nummraum, déi vun der MediaWiki-Software benotzt ginn.\nBesicht w.e.g. [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisatioun] an [//translatewiki.net translatewiki.net] wann Dir wëllt bei de MediaWiki Iwwersetzunge matschaffen.",
+    "allmessagestext": "Dëst ass eng Lëscht vun alle '''Messagen am MediaWiki:Nummraum, déi vun der MediaWiki-Software benotzt ginn.\nBesicht w.e.g. [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisatioun] an [//translatewiki.net translatewiki.net] wann Dir wëllt bei de MediaWiki Iwwersetzunge matschaffen.",
     "allmessagesnotsupportedDB": "Dës Säit kann net benotzt gi well '''$wgUseDatabaseMessages''' ausgeschalt ass.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filter nom ugepassten Zoustand:",
index 333ce85..bb43de7 100644 (file)
     "prefs-skin": "Къайдадиз ттунин тема",
     "skin-preview": "Сифтедин килигун",
     "datedefault": "Туькlуьрмир",
-    "prefs-beta": "Бета-мумкинвилер",
     "prefs-datetime": "Нумра ва вахт",
     "prefs-labs": "Экспериментдин мумкинвилер",
     "prefs-personal": "Уртахдин профил",
index 554b32d..eda257a 100644 (file)
     "allmessagesname": "Erinnya",
     "allmessagesdefault": "Ebigambo ebya bulijjo",
     "allmessagescurrent": "Ebiriwo kakano",
-    "allmessagestext": "Luno lwe lukalala olw'obubaka obwa sisitemu obw'omu kkuŋŋaanizo erya MediaWiki.\n\nOb'oyagala okuyamba ku kuvvuunula eby'omu MediaWiki yonna, kebera ku [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] ne [//translatewiki.net translatewiki.net].",
+    "allmessagestext": "Luno lwe lukalala olw'obubaka obwa sisitemu obw'omu kkuŋŋaanizo erya MediaWiki.\n\nOb'oyagala okuyamba ku kuvvuunula eby'omu MediaWiki yonna, kebera ku [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] ne [//translatewiki.net translatewiki.net].",
     "allmessages-filter-legend": "Ensunsula",
     "allmessages-filter": "Londamu:",
     "allmessages-filter-unmodified": "Ebitannakyusibwamu",
index f5d90fd..d858e45 100644 (file)
     "prefs-skin": "{{SITENAME}}-uterlik",
     "skin-preview": "Veurbesjouwing",
     "datedefault": "Gein veurkäör",
-    "prefs-beta": "Bètadeil",
     "prefs-datetime": "Datum en tied",
     "prefs-labs": "Alfadeil",
     "prefs-user-pages": "Gebroekerpagina's",
     "nowatchlist": "D'r sjtit niks op dien volglies.",
     "watchlistanontext": "$1 is verplich om dien volglies in te zeen of te wiezige.",
     "watchnologin": "De bis neet aangemèld",
-    "watchnologintext": "De mós [[Special:UserLogin|aangemèld]] zeen veur 't verangere van dien volglies.",
     "addwatch": "Aan volglies toeveuge",
     "addedwatchtext": "De pagina \"[[:$1]]\" is aan dien [[Special:Watchlist|volglies]] toegeveug.\nToekomstige verangeringe aan dees pagina en de biebehurende euverlèkpagina weure dao vermeld en de pagina weurt '''vèt''' weergegaeve in de [[Special:RecentChanges|lies van recènte verangeringe]].",
     "removewatch": "Van volglies aafhoale",
     "allmessagesname": "Naam",
     "allmessagesdefault": "Obligaten teks",
     "allmessagescurrent": "Hujige teks",
-    "allmessagestext": "Dit is 'n lies van alle systeemberichte besjikbaar in de MediaWiki-naamruumde.\nBezeuk [https://www.mediawiki.org/wiki/Localisation MediaWiki-lokalisatie] en [//translatewiki.net translatewiki.net] es doe wils biedrage aon lokalisatie.",
+    "allmessagestext": "Dit is 'n lies van alle systeemberichte besjikbaar in de MediaWiki-naamruumde.\nBezeuk [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki-lokalisatie] en [//translatewiki.net translatewiki.net] es doe wils biedrage aon lokalisatie.",
     "allmessagesnotsupportedDB": "Deze pagina kan neet gebroek waere omdet '''$wgUseDatabaseMessages''' oet steit.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filter óp aangepas:",
index 65e48d8..c66fd53 100644 (file)
     "watchlist": "Zwa mukoloko di kentezi",
     "mywatchlist": "Zwa mukoloko di kentezi",
     "watchnologin": "A ni sa menuhile",
-    "watchnologintext": "A sa [[Special:UserLogin|menuhile]] di hloli ye ng'i zwa mukoloko di kentezi.",
     "addedwatchtext": "Petulo \"[[:$1]]\" sa vugisize di zwa [[Special:Watchlist|mukoloko di kentezi]].\nPetuhoni di bye petulo e sa bulelezi sa mukolokosize ta, e '''ombelu''' kwa [[Special:RecentChanges|petuho nca]] di kwazidisize akusize.\n\nA sa afi kulobala di zwa mukoloko di kentezi, tampi \"ngambu kentezi\".",
     "removedwatchtext": "Petulo \"[[:$1]]\" sa afi kulobala di zwa mukoloko di kentezi.",
     "watch": "Kentezi",
     "allmessagesname": "Sebu",
     "allmessagesdefault": "Selt orge",
     "allmessagescurrent": "Selt nca",
-    "allmessagestext": "Bye mukoloko sa mukoloko di mulumiwani di MediaWiki poo.\nPlease visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
+    "allmessagestext": "Bye mukoloko sa mukoloko di mulumiwani di MediaWiki poo.\nPlease visit [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
     "thumbnail-more": "Pusize",
     "thumbnail_error": "Bufosi hloli tumbneli: $1",
     "import": "Petulo import",
index eb2691a..c34fc7f 100644 (file)
     "prefs-skin": "Išvaizda",
     "skin-preview": "Peržiūra",
     "datedefault": "Jokio pasirinkimo",
-    "prefs-beta": "Beta funkcijos",
     "prefs-datetime": "Data ir laikas",
     "prefs-labs": "Bandomosios funkcijos",
     "prefs-user-pages": "Naudotojo puslapiai",
     "nowatchlist": "Neturite nei vieno stebimo puslapio.",
     "watchlistanontext": "Prašome $1, kad peržiūrėtumėte ar pakeistumėte elementus savo stebimųjų sąraše.",
     "watchnologin": "Neprisijungęs",
-    "watchnologintext": "Jums reikia būti [[Special:UserLogin|prisijungusiam]], kad pakeistumėte savo stebimųjų sąrašą.",
     "addwatch": "Pridėti į stebimųjų sąrašą",
     "addedwatchtext": "Puslapis „[[:$1]]“ pridėtas į [[Special:Watchlist|stebimųjų sąrašą]].\nBūsimi puslapio bei atitinkamo aptarimo puslapio pakeitimai bus rodomi stebimųjų puslapių sąraše,\ntaip pat bus '''paryškinti''' [[Special:RecentChanges|naujausių keitimų sąraše]], kad išsiskirtų iš kitų puslapių.",
     "removewatch": "Pašalinti iš stebimųjų sąrašo",
     "allmessagesname": "Pavadinimas",
     "allmessagesdefault": "Pradinis tekstas",
     "allmessagescurrent": "Dabartinis tekstas",
-    "allmessagestext": "Čia pateikiamas sisteminių pranešimų sąrašas, esančių MediaWiki vardų srityje.\nAplankykite [https://www.mediawiki.org/wiki/Localisation „MediaWiki“ lokaliziciją] ir [//translatewiki.net „translatewiki.net“], jei norite prisidėti prie bendrojo „MediaWiki“ lokalizavimo.",
+    "allmessagestext": "Čia pateikiamas sisteminių pranešimų sąrašas, esančių MediaWiki vardų srityje.\nAplankykite [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation „MediaWiki“ lokaliziciją] ir [//translatewiki.net „translatewiki.net“], jei norite prisidėti prie bendrojo „MediaWiki“ lokalizavimo.",
     "allmessagesnotsupportedDB": "Šis puslapis nepalaikomas, nes nuostata '''$wgUseDatabaseMessages''' yra išjungtas.",
     "allmessages-filter-legend": "Filtras",
     "allmessages-filter": "Filtruoti pagal būseną:",
index 3d59b9f..5810392 100644 (file)
@@ -1,6 +1,26 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "Admresdeserv.",
+            "Dark Eagle",
+            "Edgars2007",
+            "FnTmLV",
+            "Geimeris",
+            "Geitost",
+            "GreenZeb",
+            "Kaganer",
+            "Karlis",
+            "Kikos",
+            "Knakts",
+            "Marozols",
+            "Papuass",
+            "Reedy",
+            "Shirayuki",
+            "Srolanh",
+            "Xil",
+            "Yyy",
+            "לערי ריינהארט"
+        ]
     },
     "tog-underline": "Pasvītrot saites:",
     "tog-hideminor": "Paslēpt maznozīmīgus labojumus pēdējo izmaiņu lapā",
     "prefs-skin": "Apdare",
     "skin-preview": "Priekšskats",
     "datedefault": "Vienalga",
-    "prefs-beta": "Beta funkcijas",
     "prefs-datetime": "Datums un laiks",
     "prefs-labs": "Laboratorijas funkcijas",
     "prefs-user-pages": "Lietotāja lapas",
     "nowatchlist": "Tavā uzraugāmo rakstu sarakstā nav neviena raksta.",
     "watchlistanontext": "Lūdzu $1, lai apskatītu vai labotu savu uzraugāmo rakstu saraksta saturu.",
     "watchnologin": "Neesi iegājis",
-    "watchnologintext": "Tev ir [[Special:UserLogin|jāieiet]], lai mainītu uzraugāmo lapu sarakstu.",
     "addwatch": "Pievienot uzraugāmo lapu sarakstam",
     "addedwatchtext": "Lapa \"[[:$1]]\" ir pievienota [[Special:Watchlist|tevis uzraudzītajām lapām]], kur tiks parādītas izmaiņas, kas izdarītas šajā lapā vai šīs lapas diskusiju lapā, kā arī šī lapa tiks iezīmēta '''pustrekna''' [[Special:RecentChanges|pēdējo izmaiņu lapā]], lai to būtu vieglāk pamanīt.\n\nJa vēlāk pārdomāsi un nevēlēsies vairs uzraudzīt šo lapu, klikšķini uz saites '''neuzraudzīt''' rīku joslā.",
     "removewatch": "Izņemt no uzraugāmo lapu saraksta",
     "allmessagesname": "Nosaukums",
     "allmessagesdefault": "Noklusētais ziņojuma teksts",
     "allmessagescurrent": "Pašreizējais teksts",
-    "allmessagestext": "Šajā lapā ir visu \"'''MediaWiki:'''\" lapās atrodamo sistēmas paziņojumu uzskaitījums.\nŠos paziņojumus var izmainīt tikai admini. Izmainot tos šeit, tie tiks izmainīti tikai šajā mediawiki instalācijā. Lai tos izmainītu visām pārējām, apskatieties [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] un [//translatewiki.net translatewiki.net].",
+    "allmessagestext": "Šajā lapā ir visu \"'''MediaWiki:'''\" lapās atrodamo sistēmas paziņojumu uzskaitījums.\nŠos paziņojumus var izmainīt tikai admini. Izmainot tos šeit, tie tiks izmainīti tikai šajā mediawiki instalācijā. Lai tos izmainītu visām pārējām, apskatieties [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] un [//translatewiki.net translatewiki.net].",
     "allmessagesnotsupportedDB": "Šī lapa nedarbojas, tāpēc, ka '''wgUseDatabaseMessages''' nedarbojas.",
     "allmessages-filter-legend": "Filtrs",
     "allmessages-filter": "Filtrēt pēc izmainīšanas statusa:",
index 3c4d45a..f0710f0 100644 (file)
@@ -1,6 +1,17 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "C933103",
+            "Itsmine",
+            "Justincheng12345",
+            "Omnipaedista",
+            "Shinjiman",
+            "Simon Shek",
+            "StephDC",
+            "Super Wang",
+            "Xiaomingyan",
+            "Yanteng3"
+        ]
     },
     "tog-underline": "鏈墊線:",
     "tog-hideminor": "隱近校",
     "gotaccountlink": "登簿",
     "userlogin-resetlink": "君忘登簿所需爾?",
     "userlogin-resetpassword-link": "輸子符節",
+    "userlogin-helplink2": "助登簿",
     "createacct-emailrequired": "電郵",
     "createacct-emailoptional": "電郵 (可選)",
     "createaccountmail": "同郵",
     "login-abort-generic": "登簿未成——棄",
     "loginlanguagelabel": "語:$1",
     "suspicious-userlogout": "爾欲無離也,可由壞瀏覽器或快枝代理呈送之。",
+    "pt-login": "登簿",
+    "pt-login-button": "登簿",
+    "pt-createaccount": "增簿",
+    "pt-userlogout": "去簿",
     "php-mail-error-unknown": "於 PHP mail() 參數現錯",
     "user-mail-no-addy": "遣函豈能無址?",
     "user-mail-no-body": "試遞一空或過短郵",
     "newpassword": "新符節:",
     "retypenew": "重察新符節:",
     "resetpass_submit": "設符再登",
-    "changepassword-success": "爾之符節已改!\n現登簿中...",
+    "changepassword-success": "爾之符節已改!",
+    "changepassword-throttled": "爾多試於此簿登中。\n請候再試之。",
     "resetpass_forbidden": "無改符節",
     "resetpass-no-info": "爾須登簿後方進此頁。",
     "resetpass-submit-loggedin": "改符節",
     "yournick": "新署名︰",
     "prefs-help-signature": "論版以論事以「<nowiki>~~~~</nowiki>」署名之,換爾之署名與時辰也。",
     "badsig": "無效之自畫。\n查HTML籤之。",
-    "badsiglength": "署名宜簡。",
+    "badsiglength": "署名宜簡,勿逾$1字。",
     "yourgender": "性別︰",
     "gender-unknown": "未",
     "gender-male": "男",
     "rcnotefrom": "下為自'''$2'''至'''$1'''之易也。",
     "rclistfrom": "自$1起之易也",
     "rcshowhideminor": "$1校",
+    "rcshowhideminor-show": "示",
+    "rcshowhideminor-hide": "藏",
     "rcshowhidebots": "$1僕",
+    "rcshowhidebots-show": "示",
+    "rcshowhidebots-hide": "藏",
     "rcshowhideliu": "$1簿",
+    "rcshowhideliu-show": "示",
+    "rcshowhideliu-hide": "藏",
     "rcshowhideanons": "$1匿名",
+    "rcshowhideanons-show": "示",
+    "rcshowhideanons-hide": "藏",
     "rcshowhidepatr": "$1哨",
+    "rcshowhidepatr-show": "示",
+    "rcshowhidepatr-hide": "藏",
     "rcshowhidemine": "$1吾纂",
+    "rcshowhidemine-show": "示",
+    "rcshowhidemine-hide": "藏",
     "rclinks": "$2日內$1近易。<br />$3",
     "diff": "辨",
     "hist": "誌",
     "listfiles_size": "幅(位元組)",
     "listfiles_description": "述",
     "listfiles_count": "擇",
+    "listfiles-latestversion-yes": "是",
+    "listfiles-latestversion-no": "否",
     "file-anchor-link": "檔",
     "filehist": "檔史",
     "filehist-help": "揀日尋檔。",
     "filepage-nofile": "查無此檔。",
     "filepage-nofile-link": "查無此檔,爾可[$1 貢焉]。",
     "uploadnewversion-linktext": "更新此檔",
+    "shared-repo-from": "自$1",
     "shared-repo-name-wikimediacommons": "維基共享",
     "filerevert": "還$1",
     "filerevert-legend": "還檔",
     "nowatchlist": "無哨",
     "watchlistanontext": "$1以治哨",
     "watchnologin": "未登簿",
-    "watchnologintext": "[[Special:UserLogin|登簿]]以治哨。",
     "addedwatchtext": "\"[[:$1]]\"哨派矣。後有易、議者可見於[[Special:Watchlist|哨站]],且'''粗體'''列於[[Special:RecentChanges|近易]]。",
     "removedwatchtext": "\"[[:$1]]\"[[Special:Watchlist|哨]]撤矣。",
     "watch": "派哨",
     "allmessagesname": "話",
     "allmessagesdefault": "慣話文",
     "allmessagescurrent": "今話文",
-    "allmessagestext": "此列MediaWiki官話。\n如貢正宗MediaWiki本地化,[https://www.mediawiki.org/wiki/Localisation MediaWiki本地化]與[//translatewiki.net translatewiki.net]閱之。",
+    "allmessagestext": "此列MediaWiki官話。\n如貢正宗MediaWiki本地化,[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki本地化]與[//translatewiki.net translatewiki.net]閱之。",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages'''閉庫,'''無纂也。",
     "allmessages-filter-legend": "濾",
     "allmessages-filter": "以易濾:",
     "spambot_username": "MediaWiki清濫",
     "spam_reverting": "還新審之無鏈$1者。",
     "spam_blanking": "審皆鏈$1,遂令白頁。",
+    "pageinfo-toolboxlink": "文訊",
     "skinname-cologneblue": "馨藍",
     "skinname-monobook": "單書",
     "skinname-modern": "時髦",
index e052d4c..2ed1ce9 100644 (file)
     "prefs-skin": "रूप",
     "skin-preview": "पूर्वावलोकन",
     "datedefault": "कोनो मोनपसंद नै",
-    "prefs-beta": "द्वितीय-परीक्षा गुण सभ",
     "prefs-datetime": "दिन आ तिथि",
     "prefs-labs": "प्रायोगिक गुण सभ",
     "prefs-personal": "प्रयोक्ता परिचय",
     "nowatchlist": "अहाँक साकांक्ष-सूचीमे कोनो बौस्तु नै अछि।",
     "watchlistanontext": "कृपा कऽ $1 अहाँक साकांक्ष-सूचीकेँ देखबा वा सम्पादित करबा लेल।",
     "watchnologin": "सम्प्रवेशित नै",
-    "watchnologintext": "अहाँ [[Special:UserLogin|सम्प्रवेशित]] साकांक्ष-सूची संशोधित करबा लेल।",
     "addwatch": "साकांक्ष सूचीमे जोड़ू",
     "addedwatchtext": "पन्ना \"[[:$1]]\" अहाँक [[Special:Watchlist|साकांक्ष सूची]] मे जोड़ल गेल।\nऐ पन्नामे भविष्यक परिवर्तन आ एकर सम्बन्धित चौबटिया पन्ना एतए सूचीबद्ध रहत, आ पन्ना [[Special:RecentChanges|हालक परिवर्तन]]मे '''गाढ़''' देखाएत , जइसँ आसानीसँ एकरा चिन्हल जा सकत।",
     "removewatch": "साकांक्ष सूचीसँ हटाउ",
     "allmessagesname": "नाम",
     "allmessagesdefault": "पूर्वनिर्धारित संदेश पाठ",
     "allmessagescurrent": "अखुनका संदेश पाठ",
-    "allmessagestext": "ई मीडियाविकी नामस्थानमे उपलब्ध संस्थागत संदेशक सूची छी।\nकृपा कऽ देखू [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] आ [//translatewiki.net translatewiki.net] जँ अहाँ मीडियाविकीक स्थानिकीकरणक मूलक अनुवादमे योगदान करए चाहै छी।",
+    "allmessagestext": "ई मीडियाविकी नामस्थानमे उपलब्ध संस्थागत संदेशक सूची छी।\nकृपा कऽ देखू [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] आ [//translatewiki.net translatewiki.net] जँ अहाँ मीडियाविकीक स्थानिकीकरणक मूलक अनुवादमे योगदान करए चाहै छी।",
     "allmessagesnotsupportedDB": "ई पन्ना प्रयोगमे नै आनल जा सकैए कारण '''$wgUseDatabaseMessages''' अशक्त कएल अछि।",
     "allmessages-filter-legend": "चलनी",
     "allmessages-filter": "अपन हिसाबे अनुकूलित कऽ छाँटू:",
index d403c78..28ceac7 100644 (file)
     "nowatchlist": "Мезеге аш тонь мельгеваномасот.",
     "watchlistanontext": "$1 тонь ванома мельгеваномаста лопат ваноманкса эли петнеманкса.",
     "watchnologin": "Апак сувак",
-    "watchnologintext": "Тондейть эряви [[Special:UserLogin|сувамс]] тонь мельгеваномацень петнеманкса.",
     "addedwatchtext": "Лопась \"[[:$1]]\" сувафнезь тонь [[Special:Watchlist|Мельгеваномасот]].\nСяда тов тя лопать ди мархтонза сюлмаф Корхнема лопать полафнематне кармайхть тякшстафтовома   тя лувомас, сяда тёждяень няевомаснонды синь тага кармайхть сёрмадовома  [[Special:RecentChanges|мекольце полафнематнень лувомас]] '''эчке тяшксса'''.\n\nУлендяряй тонь мяльце тя лопать нардамс тонь мельгеваномастот, люпштак \"аф ваномс мельге\" лопань вярдень виде ужеса.",
     "removedwatchtext": "Лопась \"[[:$1]]\" нардафоль [[Special:Watchlist|тонь мельгеванома лувомастот]].",
     "watch": "Ватт мельге",
     "allmessagesname": "Лем",
     "allmessagesdefault": "Апак полафтт текст",
     "allmessagescurrent": "Тяниень текст",
-    "allmessagestext": "Тя MediaWiki-са васьфневи системонь пачфтематнень лувомась.\nЭняльттяма, сувак [https://www.mediawiki.org/wiki/Localisation MediaWiki Локализациес] ди [//translatewiki.net translatewiki.net-с] кда тонь мяльце тиемс эсь путксце марстонь MediaWiki локализациес.",
+    "allmessagestext": "Тя MediaWiki-са васьфневи системонь пачфтематнень лувомась.\nЭняльттяма, сувак [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Локализациес] ди [//translatewiki.net translatewiki.net-с] кда тонь мяльце тиемс эсь путксце марстонь MediaWiki локализациес.",
     "allmessagesnotsupportedDB": "Тя лопас аш кода кунцемс сяс мес '''$wgUseDatabaseMessages'''лоткафоль.",
     "allmessages-language": "Кяль:",
     "allmessages-filter-submit": "Ётамс",
index 7ebb8a4..4c05c6a 100644 (file)
     "prefs-skin": "Endrika",
     "skin-preview": "Tsipalotra",
     "datedefault": "Tsy misy safidy",
-    "prefs-beta": "Fitaovana beta",
     "prefs-datetime": "Daty sy ora",
     "prefs-labs": "Fitaovana  « labs »",
     "prefs-user-pages": "Pejim-pikambana",
     "nowatchlist": "Tsy manaraka pejy ianao.",
     "watchlistanontext": "Andana $1 hahafahanao mijery na manova zavatra ao amin'ny pejy arahanao.",
     "watchnologin": "Tsy niditra",
-    "watchnologintext": "Mila [[Special:UserLogin|miditra]] ianao vao afaka manova ny lisitry ny pejy arahanao.",
     "addwatch": "Ampiana ao amin'ny pejy arahana",
     "addedwatchtext": "Voalisitra ao amin'ny [[Special:Watchlist|pejy arahanao]] ilay pejy \"[[:$1]]\". Ny fanovana ho avy ao amin'ilay pejy ary ao amin'ilay pejin-dresaka dia ho voalisitra any.",
     "removewatch": "Alàna amin'ny pejy arahana",
     "allmessagesname": "Anarana",
     "allmessagesdefault": "Dikan-teny tany am-boalohany",
     "allmessagescurrent": "Dikan-teny miasa ankehitriny",
-    "allmessagestext": "Ity dia lisitry ny hafatra hita ao amin'ny anaran-tsehatra MediaWiki.\nAndana vangio ny [https://www.mediawiki.org/wiki/Localisation Fandikana an'i Mediawiki] ary [//translatewiki.net/ translatewiki.net] raha tia handray anjara amin'ny fandikana an'i Mediawiki amin'ny ankapobeny.",
+    "allmessagestext": "Ity dia lisitry ny hafatra hita ao amin'ny anaran-tsehatra MediaWiki.\nAndana vangio ny [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Fandikana an'i Mediawiki] ary [//translatewiki.net/ translatewiki.net] raha tia handray anjara amin'ny fandikana an'i Mediawiki amin'ny ankapobeny.",
     "allmessagesnotsupportedDB": "Tsy mbola mandeha ny '''{{ns:special}}:Allmessages''' satria tsy mandeha koa ny '''$wgUseDatabaseMessages'''.",
     "allmessages-filter-legend": "Tantavanina",
     "allmessages-filter": "Hanasivana araka ny satam-panovana :",
index 0afee3d..bba0e63 100644 (file)
     "prefs-skin": "Kulik",
     "skin-preview": "Caliak",
     "datedefault": "Indak usah diatua",
-    "prefs-beta": "Baru uji-cubo (Beta)",
     "prefs-datetime": "Tanggal jo wakatu",
     "prefs-labs": "Alaik uji",
     "prefs-user-pages": "Laman pangguno",
     "version-software-product": "Produk",
     "version-software-version": "Versi",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Artikel path]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Skrip path]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Artikel path]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Skrip path]",
     "fileduplicatesearch": "Pancarian berkas duplikat",
     "fileduplicatesearch-summary": "Pancarian berkas duplikat badasaran nilai hash-nyo.",
     "fileduplicatesearch-result-n": "Berkas \"$1\" ado {{PLURAL:$2|$2 duplikat nan samo}}.",
index 4b83e57..ba7e811 100644 (file)
     "pool-timeout": "Истече времето за чекање на заклучувањето",
     "pool-queuefull": "Редицата на барања е полна",
     "pool-errorunknown": "Непозната грешка",
+    "pool-servererror": "Службата на фондовскиот шалтер е недостапна ($1).",
     "aboutsite": "За {{SITENAME}}",
     "aboutpage": "Project:За {{SITENAME}}",
     "copyright": "Содржината е достапна под условите на $1 освен ако не е поинаку наведено.",
     "prefs-skin": "Руво",
     "skin-preview": "Преглед",
     "datedefault": "Небитно",
-    "prefs-beta": "Бета-можности",
     "prefs-datetime": "Датум и време",
     "prefs-labs": "Експериментални можности",
     "prefs-user-pages": "Кориснички страници",
     "listgrouprights-removegroup-self": "Може да брише {{PLURAL:$2|група|групи}} од сопствената корисничка сметка: $1",
     "listgrouprights-addgroup-self-all": "Може да ги додаде сите групи на сопствената корисничка сметка",
     "listgrouprights-removegroup-self-all": "Може да ги избрише сите групи од сопствената корисничка сметка",
+    "trackingcategories": "Следачки категории",
+    "trackingcategories-summary": "На страницава се наведени следачки категории што автоматски се пополнуваат од програмот на МедијаВики. Нивните називи можат да се сменат со измена на соодветните системски пораки во именскиот простор {{ns:8}}.",
+    "trackingcategories-msg": "Следачка категорија",
+    "trackingcategories-name": "Назив на пораката",
+    "trackingcategories-desc": "Критериуми за вклучување",
+    "noindex-category-desc": "Страницата содржи волшебен збор <nowiki>__NOINDEX__</nowiki> (и се наоѓа во именски простор кајшто е дозволен), па затоа не се индексира од роботи.",
+    "index-category-desc": "Страницата содржи <nowiki>__INDEX__</nowiki> (и се наоѓа во именски простор кајшто ова е дозволено), па затоа се индексира од роботи, што инаку не би било.",
+    "post-expand-template-inclusion-category-desc": "По проширувањето на сите шаблони, страницата е поголема од $wgMaxArticleSize, па затоа некои шаблони не се проширени.",
+    "post-expand-template-argument-category-desc": "По проширување на шаблонски аргумент (нешто во тројни кадрави загради, како на пр. {{{Foo}}}), страницата е поголема од $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "Во страницата има премногу оптоварувачки расчленувачки функции (како <code>#ifexist</code>). Погл. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Категорјата се става ако страницата содржи неисправна податотечка врска (врска за вметнување на податотека што не постои).",
+    "hidden-category-category-desc": "Ова е категорија што содржи <nowiki>__HIDDENCAT__</nowiki>, што значи дека по основно не се прикажува во страниците.",
+    "trackingcategories-nodesc": "Нема опис.",
+    "trackingcategories-disabled": "Категоријата е оневозможена",
     "mailnologin": "Нема адреса за праќање",
     "mailnologintext": "Мора да сте [[Special:UserLogin|најавени]] и да имате важечка е-поштенска адреса во вашите [[Special:Preferences|нагодувања]] за да може да праќате е-пошта до други корисници.",
     "emailuser": "Пиши е-пошта на корисникот",
     "nowatchlist": "Немате ништо во списокот на набљудувања.",
     "watchlistanontext": "Треба да сте $1 за да можете да го прегледувате и уредувате списокот на набљудувања.",
     "watchnologin": "Не сте најавени",
-    "watchnologintext": "Мора да сте [[Special:UserLogin|најавени]] за да го менувате списокот на набљудувања.",
     "addwatch": "Додај во списокот на набљудувања",
     "addedwatchtext": "Страницата „[[:$1]]“ е додадена во [[Special:Watchlist|списокот на набљудувања]].\nИдните промени на оваа страница и нејзината страница за разговор ќе се прикажуваат таму.",
     "removewatch": "Отстрани од списокот на набљудувања",
     "sp-contributions-newbies-sub": "За нови кориснички сметки",
     "sp-contributions-newbies-title": "Придонеси на нови корисници",
     "sp-contributions-blocklog": "Дневник на блокирања",
+    "sp-contributions-suppresslog": "притаени придонеси на корисникот",
     "sp-contributions-deleted": "избришани придонеси на корисникот",
     "sp-contributions-uploads": "подигања",
     "sp-contributions-logs": "дневници",
     "sp-contributions-blocked-notice": "Овој корисник е блокиран. Последните ставки во дневникот на блокирања, за ваша информација се дадени подолу:",
     "sp-contributions-blocked-notice-anon": "Оваа IP-адреса е моментално блокирана.\nПодолу е наведен најновиот дневнички запис на блокирање:",
     "sp-contributions-search": "Пребарување на придонеси",
-    "sp-contributions-suppresslog": "притаени придонеси на корисникот",
     "sp-contributions-username": "IP-адреса или корисничко име:",
     "sp-contributions-toponly": "Прикажувај само последни преработки",
     "sp-contributions-newonly": "Прикажувај само новосоздадени страници",
     "allmessagesname": "Име",
     "allmessagesdefault": "Текст по основно",
     "allmessagescurrent": "Сегашен текст",
-    "allmessagestext": "Ова е список на системските пораки расположиви за именскиот простор „МедијаВики“.\nОдете на [https://www.mediawiki.org/wiki/Localisation Локализација на МедијаВики] и [//translatewiki.net translatewiki.net] ако сакате да придонесете кон општата локализација на МедијаВики.",
+    "allmessagestext": "Ова е список на системските пораки расположиви за именскиот простор „МедијаВики“.\nОдете на [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Локализација на МедијаВики] и [//translatewiki.net translatewiki.net] ако сакате да придонесете кон општата локализација на МедијаВики.",
     "allmessagesnotsupportedDB": "Оваа страница не може да се користи бидејќи '''$wgUseDatabaseMessages''' е исклучено.",
     "allmessages-filter-legend": "Филтер",
     "allmessages-filter": "Филтрирај по состојба на прилагодувањето:",
     "version-entrypoints": "URL-а на влезните точки",
     "version-entrypoints-header-entrypoint": "Влезна точка",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath?uselang=mk Статија]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath?uselang=mk Скрипта]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath?uselang=mk Статија]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath?uselang=mk Скрипта]",
     "redirect": "Пренасочување по податотеки, корисник или назнака на преработка",
     "redirect-legend": "Пренасочување кон податотека или страница",
     "redirect-summary": "Оваа специјална страница пренасочува кон податотека (се задава името), страница (се задава назнаката на преработката или страницата) или корисничка странца (се задава бројчената назнака на корисникот). Употреба: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] или [[{{#Special:Redirect}}/user/101]].",
     "expand_templates_remove_nowiki": "Притаи <nowiki> ознаки во резултатот",
     "expand_templates_generate_xml": "Прикажи XML-дрво на расчленувањето",
     "expand_templates_generate_rawhtml": "Прикажувај сиров HTML",
-    "expand_templates_preview": "Преглед",
-    "trackingcategories": "Следачки категории",
-    "trackingcategories-summary": "На страницава се наведени следачки категории што автоматски се пополнуваат од програмот на МедијаВики. Нивните називи можат да се сменат со измена на соодветните системски пораки во именскиот простор {{ns:8}}.",
-    "trackingcategories-msg": "Следачка категорија",
-    "trackingcategories-name": "Назив на пораката",
-    "trackingcategories-desc": "Критериуми за вклучување",
-    "noindex-category-desc": "Страницата содржи волшебен збор <nowiki>__NOINDEX__</nowiki> (и се наоѓа во именски простор кајшто е дозволен), па затоа не се индексира од роботи.",
-    "index-category-desc": "Страницата содржи <nowiki>__INDEX__</nowiki> (и се наоѓа во именски простор кајшто ова е дозволено), па затоа се индексира од роботи, што инаку не би било.",
-    "post-expand-template-inclusion-category-desc": "По проширувањето на сите шаблони, страницата е поголема од $wgMaxArticleSize, па затоа некои шаблони не се проширени.",
-    "post-expand-template-argument-category-desc": "По проширување на шаблонски аргумент (нешто во тројни кадрави загради, како на пр. {{{Foo}}}), страницата е поголема од $wgMaxArticleSize.",
-    "expensive-parserfunction-category-desc": "Во страницата има премногу оптоварувачки расчленувачки функции (како #ifexists). Погл. [https://www.mediawiki.org/wiki/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
-    "broken-file-category-desc": "Категорјата се става ако страницата содржи неисправна податотечка врска (врска за вметнување на податотека што не постои).",
-    "hidden-category-category-desc": "Ова е категорија што содржи <nowiki>__HIDDENCAT__</nowiki>, што значи дека по основно не се прикажува во страниците.",
-    "trackingcategories-nodesc": "Нема опис.",
-    "trackingcategories-disabled": "Категоријата е оневозможена"
+    "expand_templates_preview": "Преглед"
 }
index 564934a..19361b1 100644 (file)
     "prefs-skin": "ദൃശ്യരൂപം",
     "skin-preview": "എങ്ങനെയുണ്ടെന്നു കാണുക",
     "datedefault": "ക്രമീകരണങ്ങൾ വേണ്ട",
-    "prefs-beta": "പരീക്ഷണാടിസ്ഥാനത്തിലുള്ള സൗകര്യങ്ങൾ",
     "prefs-datetime": "ദിവസവും സമയവും",
     "prefs-labs": "പരീക്ഷണശാലയിൽ തയ്യാറാകുന്ന സൗകര്യങ്ങൾ",
     "prefs-user-pages": "ഉപയോക്തൃതാളുകൾ",
     "listgrouprights-removegroup-self": "സ്വന്തം അംഗത്വത്തിൽ നിന്ന് {{PLURAL:$2|സംഘത്തെ|സംഘങ്ങളെ}} നീക്കം ചെയ്യുക: $1",
     "listgrouprights-addgroup-self-all": "എല്ലാ സംഘങ്ങളേയും സ്വന്തം അംഗത്വത്തിൽ ചേർക്കുക",
     "listgrouprights-removegroup-self-all": "സ്വന്തം അംഗത്വത്തിൽ നിന്ന് എല്ലാ സംഘങ്ങളേയും നീക്കംചെയ്യുക",
+    "trackingcategories": "പിന്തുടരൽ വർഗ്ഗങ്ങൾ",
+    "trackingcategories-summary": "ഈ താളിൽ മീഡിയവിക്കി സോഫ്റ്റ്‌വേർ സ്വതേ നിർമ്മിക്കുന്ന പിന്തുടരൽ വർഗ്ഗങ്ങളുടെ പട്ടിക കാണാം. അവയുടെ പേരുകൾ {{ns:8}} നാമമേഖലയിലെ ബന്ധപ്പെട്ട വ്യവസ്ഥാസന്ദേശങ്ങൾ തിരുത്തി മാറ്റാവുന്നതാണ്.",
+    "trackingcategories-msg": "പിന്തുടരൽ വർഗ്ഗം",
+    "trackingcategories-name": "സന്ദേശത്തിന്റെ പേര്",
+    "trackingcategories-desc": "വർഗ്ഗം ഉൾപ്പെടുത്തുന്നതിനുള്ള മാനദണ്ഡം",
+    "noindex-category-desc": "ഈ താളിൽ <nowiki>__NOINDEX__</nowiki> എന്ന മാന്ത്രികവാക്ക് ഉണ്ട് (അത് അനുവദിച്ചിട്ടുള്ള നാമമേഖലയിലും ആണ്), അതുകൊണ്ടിത് റോബോട്ടുകളാൽ സൂചികാവത്കരിക്കപ്പെടില്ല.",
+    "index-category-desc": "ഈ താളിൽ <nowiki>__INDEX__</nowiki> എന്ന മാന്ത്രികവാക്ക് ഉണ്ട് (അത് അനുവദിച്ചിട്ടുള്ള നാമമേഖലയിലും ആണ്), അതുകൊണ്ടിത്, സാധാരണഗതിയിൽ പാടില്ലാത്തതാണെങ്കിലും റോബോട്ടുകളാൽ സൂചികാവത്കരിക്കപ്പെടുന്നതാണ്.",
+    "post-expand-template-inclusion-category-desc": "എല്ലാ ഫലകങ്ങളും വികസിപ്പിച്ചു കഴിയുമ്പോൾ, താളിന്റെ വലിപ്പം $wgMaxArticleSize എന്നതിലും കൂടുതലാവുമെന്നതിനാൽ, ചില ഫലകങ്ങൾ വികസിപ്പിച്ചിരുന്നില്ല.",
+    "post-expand-template-argument-category-desc": "ഫലകത്തിലേയ്ക്കുള്ള ചരം വികസിപ്പിച്ച ശേഷം ({{{പന}}} പോലെയുള്ള മൂന്ന് കോഷ്ഠകങ്ങളിലെ എഴുത്ത്), താളിന്റെ വലിപ്പം $wgMaxArticleSize എന്നതിലും കൂടുതലായി.",
+    "expensive-parserfunction-category-desc": "നിരവധി വ്യയമേറിയ പാഴ്സർ ഫങ്ഷനുകൾ ( #എങ്കിൽ പോലെയുള്ളവ) താളിൽ ഉൾപ്പെടുത്തിയിരിക്കുന്നു. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit] കാണുക.",
+    "broken-file-category-desc": "താളിൽ നിലവിലില്ലാത്ത പ്രമാണത്തിലോട്ട് കണ്ണി ചേർത്തിട്ടുണ്ടെങ്കിൽ വർഗ്ഗം ചേർക്കപ്പെടും.",
+    "hidden-category-category-desc": "ഈ വർഗ്ഗത്തിൽ <nowiki>__HIDDENCAT__</nowiki> ഉള്ളതിനാൽ, താളുകളിലെ വർഗ്ഗങ്ങളുടെ കണ്ണികൾ കാണിക്കുന്ന പെട്ടിയിൽ സ്വതേ പ്രത്യക്ഷപ്പെടുന്നതല്ല.",
+    "trackingcategories-nodesc": "വിവരണം ലഭ്യമല്ല.",
+    "trackingcategories-disabled": "വർഗ്ഗം നിർജ്ജീവമാക്കിയിരിക്കുന്നു",
     "mailnologin": "അയയ്ക്കാനുള്ള വിലാസം ലഭ്യമല്ല",
     "mailnologintext": "മറ്റ് ഉപയോക്താക്കൾക്കു ഇമെയിലയക്കുവാൻ താങ്കൾ [[Special:UserLogin|ലോഗിൻ]] ചെയ്തിരിക്കുകയും, സാധുവായ ഒരു ഇമെയിൽ വിലാസം താങ്കളുടെ [[Special:Preferences|ക്രമീകരണങ്ങൾ]] താളിൽ സജ്ജീകരിച്ചിരിക്കുകയും വേണം.",
     "emailuser": "ഈ ഉപയോക്താവിനു ഇമെയിൽ അയക്കുക",
     "nowatchlist": "താങ്കൾ ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽ ഇനങ്ങളൊന്നുമില്ല.",
     "watchlistanontext": "താങ്കൾ ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടിക കാണുവാനോ തിരുത്തുവാനോ $1.",
     "watchnologin": "ലോഗിൻ ചെയ്തിട്ടില്ല",
-    "watchnologintext": "ശ്രദ്ധിക്കുന്ന താളിന്റെ പട്ടിക തിരുത്തുവാൻ താങ്കൾ [[Special:UserLogin|ലോഗിൻ]] ചെയ്തിരിക്കണം.",
     "addwatch": "ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിലേക്കു ചേർക്കുക",
     "addedwatchtext": "താങ്കൾ [[Special:Watchlist|ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിലേക്ക്]] \"[[:$1]]\" എന്ന ഈ താൾ ചേർത്തിരിക്കുന്നു. ഇനി മുതൽ ഈ താളിലും ബന്ധപ്പെട്ട സം‌വാദം താളിലും ഉണ്ടാകുന്ന മാറ്റങ്ങൾ ആ പട്ടികയിൽ ദൃശ്യമാവും.",
     "removewatch": "ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടികയിൽ നിന്നും ഒഴിവാക്കുക",
     "sp-contributions-newbies-sub": "പുതിയ ഉപയോക്താക്കൾ ചെയ്തവ",
     "sp-contributions-newbies-title": "പുതിയ അംഗത്വമെടുത്ത ഉപയോക്താക്കളുടെ സേവനങ്ങൾ",
     "sp-contributions-blocklog": "തടയൽ രേഖ",
+    "sp-contributions-suppresslog": "ഒതുക്കപ്പെട്ട ഉപയോക്തൃസംഭാവനകൾ",
     "sp-contributions-deleted": "മായ്ക്കപ്പെട്ട ഉപയോക്തൃസംഭാവനകൾ",
     "sp-contributions-uploads": "അപ്‌ലോഡുകൾ",
     "sp-contributions-logs": "പ്രവർത്തനരേഖകൾ",
     "sp-contributions-blocked-notice": "ഈ ഉപയോക്താവ് ഇപ്പോൾ തടയപ്പെട്ടിരിക്കുകയാണ്. അവലംബമായി തടയൽ രേഖയുടെ പുതിയ ഭാഗം താഴെ കൊടുത്തിരിക്കുന്നു:",
     "sp-contributions-blocked-notice-anon": "ഈ ഐ.പി. വിലാസം ഇപ്പോൾ തടയപ്പെട്ടിരിക്കുകയാണ്.\nഅവലംബമായി തടയൽ രേഖയുടെ പുതിയഭാഗം താഴെ കൊടുത്തിരിക്കുന്നു:",
     "sp-contributions-search": "ചെയ്ത സേവനങ്ങൾ",
-    "sp-contributions-suppresslog": "ഒതുക്കപ്പെട്ട ഉപയോക്തൃസംഭാവനകൾ",
     "sp-contributions-username": "ഐ.പി. വിലാസം അഥവാ ഉപയോക്തൃനാമം:",
     "sp-contributions-toponly": "ഒടുവിലത്തെ നാൾപ്പതിപ്പുകൾ മാത്രം പ്രദർശിപ്പിക്കുക",
     "sp-contributions-newonly": "താൾ സൃഷ്ടിക്കാനുള്ള തിരുത്തുകൾ മാത്രം പ്രദർശിപ്പിക്കുക",
     "allmessagesname": "പേര്‌",
     "allmessagesdefault": "സ്വതേയുള്ള ഉള്ളടക്കം",
     "allmessagescurrent": "നിലവിലുള്ള ഉള്ളടക്കം",
-    "allmessagestext": "ഇത് മീഡിയവിക്കി നാമമേഖലയിൽ ലഭ്യമായ വ്യവസ്ഥാസന്ദേശങ്ങളുടെ ഒരു പട്ടിക ആണ്‌.\nപ്രാമാണികമായ വിധത്തിൽ മീഡിയവിക്കിയുടെ പ്രാദേശീകരണം താങ്കൾ ഉദ്ദേശിക്കുന്നുവെങ്കിൽ ദയവായി [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation], [//translatewiki.net translatewiki.net] എന്നീ താളുകൾ സന്ദർശിക്കുക.",
+    "allmessagestext": "ഇത് മീഡിയവിക്കി നാമമേഖലയിൽ ലഭ്യമായ വ്യവസ്ഥാസന്ദേശങ്ങളുടെ ഒരു പട്ടിക ആണ്‌.\nപ്രാമാണികമായ വിധത്തിൽ മീഡിയവിക്കിയുടെ പ്രാദേശീകരണം താങ്കൾ ഉദ്ദേശിക്കുന്നുവെങ്കിൽ ദയവായി [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation മീഡിയവിക്കി പ്രാദേശീകരണം], [//translatewiki.net പരിഭാഷാവിക്കി] തുടങ്ങിയവ സന്ദർശിക്കുക.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' ബന്ധിച്ചിരിക്കുന്നതു കാരണം ഈ താൾ ഉപയോഗിക്കുവാൻ സാദ്ധ്യമല്ല.",
     "allmessages-filter-legend": "അരിപ്പ",
     "allmessages-filter": "പുനഃക്രമീകരിച്ച ക്രമത്തിൽ തിരഞ്ഞുവെയ്ക്കുക:",
     "version-entrypoints": "പ്രവേശനസ്ഥാന യു.ആർ.എല്ലുകൾ",
     "version-entrypoints-header-entrypoint": "പ്രവേശനസ്ഥാനം",
     "version-entrypoints-header-url": "യു.ആർ.എൽ.",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath ലേഖന പഥം]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath സ്ക്രിപ്റ്റ് പഥം]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath ലേഖനപഥം]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath സ്ക്രിപ്റ്റ് പഥം]",
     "redirect": "പ്രമാണത്താൽ, ഉപയോക്താവിനാൽ, താളിനാൽ അഥവാ നാൾപ്പതിപ്പ് ഐ.ഡി.യാൽ ചെയ്യുന്ന തിരിച്ചുവിടൽ",
     "redirect-legend": "ഒരു പ്രമാണത്തിലോട്ടോ താളിലോട്ടോ ഉള്ള തിരിച്ചുവിടൽ",
     "redirect-summary": "ഈ പ്രത്യേക താൾ ഒരു പ്രമാണത്തിലേയ്ക്കോ (പ്രമാണത്തിന്റെ പേര് തന്നിട്ടുണ്ട്), ഒരു താളിലേയ്ക്കോ (നാൾപ്പതിപ്പിന്റെ ഐ.ഡി. അല്ലെങ്കിൽ താൾ തന്നിട്ടുണ്ട്), അല്ലെങ്കിൽ ഒരു ഉപയോക്തൃതാളിലേയ്ക്കോ (ഉപയോക്താവിന്റെ സംഖ്യാ ഐ.ഡി. തന്നിട്ടുണ്ട്) തിരിച്ചുവിടുന്നു. ഉപയോഗം: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]],  [[{{#Special:Redirect}}/revision/328429]], അല്ലെങ്കിൽ [[{{#Special:Redirect}}/user/101]].",
index 8820bb8..6e75084 100644 (file)
     "prefs-skin": "Арьс",
     "skin-preview": "Урьдчилж харах",
     "datedefault": "Анхны байдал",
-    "prefs-beta": "Туршилтын бета хэрэгсүүрүүд",
     "prefs-datetime": "Огноо ба цаг",
     "prefs-labs": "Labs -ын функцүүд",
     "prefs-user-pages": "Хэрэглэгчийн хуудсууд",
     "nowatchlist": "Танд хянаж буй зүйл байхгүй.",
     "watchlistanontext": "Та өөрийн хянах листийг өөрчлөх буюу үзэхийг хүсвэл $1 хэрэгтэй.",
     "watchnologin": "Нэвтрээгүй байна.",
-    "watchnologintext": "Та өөрийн хянаж буй хуудаснуудын жагсаалтыг өөрчлөхийн тулд [[Special:UserLogin|нэвтэрсэн байх]] шаардлагатай.",
     "addwatch": "Хяналтын жагсаалтад нэмэх",
     "addedwatchtext": "\"[[:$1]]\" гэсэн хуудас таны [[Special:Watchlist|хянах жагсаалтанд]] нэмэгдлээ.\nЭнэ хуудас эсвэл түүний хэлэлцүүлгийн хуудас засварлагдахад тэдгээр нь [[Special:RecentChanges|сүүлийн засваруудын жагсаалтад]] '''тодруулалттай''' харагдах болно.",
     "removewatch": "Хяналтын жагсаалтаас хасах",
     "sp-contributions-newbies-sub": "Шинээр бүртгүүлсэн хэрэглэгчид",
     "sp-contributions-newbies-title": "Шинэ бүртгэлүүдийн хувь нэмэр",
     "sp-contributions-blocklog": "Түгжээний лог",
+    "sp-contributions-suppresslog": "Хориглосон хэрэглэгчийн оролцоо",
     "sp-contributions-deleted": "устгагдсан хэрэглэгчийн хувь нэмэр",
     "sp-contributions-uploads": "өгөгдөл дамжуулалт",
     "sp-contributions-logs": "логууд",
     "sp-contributions-blocked-notice": "Энэхүү хэрэглэгч одоогоор түгжигдсэн байна.\nЛавлагааны зориулалтаар түгжээний лог дээрх хамгийн сүүлийн нэмэлтийг доор оруулав:",
     "sp-contributions-blocked-notice-anon": "Энэхүү IP хаягыг одоогоор түгжигдсэн байна.\nЛавлагааны зориулалтаар түгжээний лог дээрх хамгийн сүүлийн нэмэлтийг доор оруулав:",
     "sp-contributions-search": "Хувь нэмрийг хайх",
-    "sp-contributions-suppresslog": "Хориглосон хэрэглэгчийн оролцоо",
     "sp-contributions-username": "IP хаяг эсвэл хэрэглэгчийн нэр:",
     "sp-contributions-toponly": "Хамгийн сүүлийн засваруудыг л үзүүлэх",
     "sp-contributions-submit": "Хайх",
     "allmessagesname": "Нэр",
     "allmessagesdefault": "Анхны",
     "allmessagescurrent": "Одоогийн",
-    "allmessagestext": "Энэ бол МедиаВики дахь системийн мэдэгдлүүдийн жагсаалт юм.\nМедиаВикиг орчуулах тухай мэдээллийг [https://www.mediawiki.org/wiki/Localisation МедиаВикигийн орчуулга], мөн [//translatewiki.net translatewiki.net]-с авна уу.",
+    "allmessagestext": "Энэ бол МедиаВики дахь системийн мэдэгдлүүдийн жагсаалт юм.\nМедиаВикиг орчуулах тухай мэдээллийг [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation МедиаВикигийн орчуулга], мөн [//translatewiki.net translatewiki.net]-с авна уу.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' нь унтарсан байгаа тул '''Special:Allmessages'''-г хэрэглэж болохгүй.",
     "allmessages-filter-legend": "Шүүлтүүр",
     "allmessages-filter": "Өөрийн болгосон байдлаар нь шүүх:",
index 103178b..4790f1d 100644 (file)
@@ -1,6 +1,23 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "Algazel-ms",
+            "Anakmalaysia",
+            "Aurora",
+            "Aviator",
+            "CoolCityCat",
+            "Diagramma Della Verita",
+            "Hydra",
+            "Izzudin",
+            "Kaganer",
+            "Kurniasan",
+            "Meno25",
+            "Putera Luqman Tunku Andre",
+            "SNN95",
+            "Yosri",
+            "Zamwan",
+            "לערי ריינהארט"
+        ]
     },
     "tog-underline": "Garis bawah pautan:",
     "tog-hideminor": "Sembunyikan suntingan kecil dalam laman perubahan terkini",
     "prefs-skin": "Rupa",
     "skin-preview": "Pralihat",
     "datedefault": "Tiada keutamaan",
-    "prefs-beta": "Ciri-ciri beta",
     "prefs-datetime": "Tarikh dan waktu",
     "prefs-labs": "Ciri-ciri makmal",
     "prefs-user-pages": "Laman pengguna",
     "nowatchlist": "Tiada item dalam senarai pantau anda.",
     "watchlistanontext": "Sila $1 terlebih dahulu untuk melihat atau menyunting senarai pantau anda.",
     "watchnologin": "Belum log masuk",
-    "watchnologintext": "Anda mesti [[Special:UserLogin|log masuk]] terlebih dahulu untuk mengubah senarai pantau.",
     "addwatch": "Tambahkan ke senarai pantau",
     "addedwatchtext": "Halaman \"[[:$1]]\" telah dimasukkan ke dalam [[Special:Watchlist|senarai pantau anda]].\nPerubahan-perubahan pada halaman ini dan halaman perbualannya pada masa akan datang akan tersenarai di dalam senarai itu.",
     "removewatch": "Buang dari senarai pantau",
     "allmessagesname": "Nama",
     "allmessagesdefault": "Teks mesej asal",
     "allmessagescurrent": "Teks pesanan semasa",
-    "allmessagestext": "Ini ialah senarai pesanan sistem yang terdapat dalam ruang nama MediaWiki.\nSila lawat [https://www.mediawiki.org/wiki/Localisation Penyetempatan MediaWiki] dan [//translatewiki.net translatewiki.net] sekiranya anda mahu menyumbang dalam menyetempatkan dan menterjemah perisian MediaWiki.",
+    "allmessagestext": "Ini ialah senarai pesanan sistem yang terdapat dalam ruang nama MediaWiki.\nSila lawat [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Penyetempatan MediaWiki] dan [//translatewiki.net translatewiki.net] sekiranya anda mahu menyumbang dalam menyetempatkan dan menterjemah perisian MediaWiki.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:Allmessages''' tidak boleh digunakan kerana '''$wgUseDatabaseMessages''' dipadamkan.",
     "allmessages-filter-legend": "Penapisan",
     "allmessages-filter": "Tapis berdasarkan keadaan penempahan:",
     "version-entrypoints": "URL titik permulaan",
     "version-entrypoints-header-entrypoint": "Titik permulaan",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Laluan rencana]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Laluan skrip]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Laluan rencana]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Laluan skrip]",
     "redirect": "Lencongkan mengikut ID fail, pengguna, halaman atau semakan",
     "redirect-legend": "Lencongkan ke fail atau halaman",
     "redirect-summary": "Halaman khas ini melencong kepada fail (dengan nama fail), halaman (dengan ID semakan atau ID halaman) atau halaman pengguna (dengan ID pengguna berangka). Penggunaan: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], atau [[{{#Special:Redirect}}/user/101]].",
index 8a4d359..22896db 100644 (file)
     "prefs-skin": "Aspett grafiku (skin)",
     "skin-preview": "dehra proviżorja",
     "datedefault": "L-ebda preferenza",
-    "prefs-beta": "Karatteristiċi tal-Beta",
     "prefs-datetime": "Data u ħin",
     "prefs-labs": "Karatteristiċi tal-laboratorji",
     "prefs-user-pages": "Paġni tal-utent",
     "nowatchlist": "Il-lista ta' osservazzjoni tiegħek hija vojta.",
     "watchlistanontext": "Sabiex tara u timmodifika l-lista ta' osservazzjoni tiegħek, hemm bżonn li $1.",
     "watchnologin": "Għadek ma dħaltx ġewwa",
-    "watchnologintext": "Biex tagħmel modifika fil-lista t'osservazzjoni speċjali huwa neċessarju li l-ewwel [[Special:UserLogin|tidħol]] fil-kont tiegħek.",
     "addwatch": "Żid mal-lista ta' osservazzjonijiet",
     "addedwatchtext": "Il-paġna \"[[:$1]]\" ġiet miżjuda mal-[[Special:Watchlist|lista ta' osservazzjonijiet]] tiegħek.\nKwalunkwe modifika li ssir fil-futur, kemm fuq din il-paġna u fil-paġna ta' diskussjoni tagħha, tiġi elenkata hemmhekk.",
     "removewatch": "Neħħi mil-lista ta' osservazzjonijiet",
index 0d4f821..f18f5ed 100644 (file)
     "pool-timeout": "Tidsavbudd mens man ventet på låsing",
     "pool-queuefull": "Prosesskøen er full",
     "pool-errorunknown": "Ukjent feil",
+    "pool-servererror": "Pool-teller tjenesten er ikke tilgjengelig ($1).",
     "aboutsite": "Om {{SITENAME}}",
     "aboutpage": "Project:Om",
     "copyright": "Innholdet er tilgjengelig under $1 med mindre annet er spesifikt angitt.",
     "gotaccountlink": "Logg inn",
     "userlogin-resetlink": "Har du glemt påloggingsdetaljene dine?",
     "userlogin-resetpassword-link": "Glemt passordet?",
+    "userlogin-helplink2": "Hjelp med innlogging",
     "userlogin-loggedin": "Du er allerede logget inn som {{GENDER:$1|$1}}.\nBruk skjemaet nedenfor for å logge inn som en annen bruker.",
     "userlogin-createanother": "Opprett ny konto",
     "createacct-join": "Skriv inn informasjonen din under.",
     "suspicious-userlogout": "Din forespørsel om å logge ut ble nektet fordi den så ut til å ha bli sendt av en ødelagt nettleser eller en mellomtjener.",
     "createacct-another-realname-tip": "Det er frivillig å oppgi ditt egentlige navn.\nHvis du velger å oppgi det, vil det blir anvendt for å gi deg som bruker anerkjennelse",
     "pt-login": "Logg inn",
+    "pt-login-button": "Logg inn",
     "pt-createaccount": "Opprett konto",
+    "pt-userlogout": "Logg ut",
     "php-mail-error-unknown": "Ukjent feil i PHPs mail()-funksjon",
     "user-mail-no-addy": "Forsøkte å sende e-post uten e-postadresse",
     "user-mail-no-body": "Prøvde å sende e-post med tom eller for kort brødtekst.",
     "resetpass-temp-password": "Midlertidig passord:",
     "resetpass-abort-generic": "Endring av passord har blitt avbrutt av en utvidelse.",
     "resetpass-expired": "Passordet ditt har utløpt. Vær vennlig å angi et nytt passord for å logge inn.",
-    "resetpass-expired-soft": "Passordet ditt har utløpt og må endres. Vær vennlig å angi et nytt passord, eller klikk avbryt for å endre det senere.",
+    "resetpass-expired-soft": "Passordet ditt har utløpt og må endres. Vær vennlig å angi et nytt passord, eller klikk \"{{int:resetpass-submit-cancel}}\" for å endre det senere.",
+    "resetpass-validity-soft": "Ditt passord er ikke gyldig: $1",
     "passwordreset": "Tilbakestilling av passord",
     "passwordreset-text-one": "Fyll ut skjemaet for å tilbakestille passordet",
     "passwordreset-text-many": "{{PLURAL:$1|Fyll inn ett av datafeltene for å tilbakestille passordet ditt via epost.}}",
     "revdelete-no-file": "Den spesifiserte filen finnes ikke.",
     "revdelete-show-file-confirm": "Er du sikker på at du ønsker å vise en slettet versjon av filen «<nowiki>$1</nowiki>» fra $2 kl. $3?",
     "revdelete-show-file-submit": "Ja",
+    "revdelete-selected-text": "{{PLURAL:$1|Valgt revisjon|Valgte revisjoner}} av [[:$2]]:",
+    "revdelete-selected-file": "{{PLURAL:$1|Valgt filversjon|Valgte filversjoner}} av [[:$2]]:",
     "logdelete-selected": "{{PLURAL:$1|Valgt loggoppføring|Valgte loggoppføringer}}:",
+    "revdelete-text-text": "Slettede revisjoner vil fortsatt finnes i sidens historikk, men deler av deres innhold vil være utilgjengelige for offentligheten.",
+    "revdelete-text-file": "Slettede filversjoner vil fortsatt finnes i filhistorikken, men deler av deres innhold vil være utilgjengelige for offentligheten.",
+    "logdelete-text": "Slettede hendelser i loggen vil fortsatt finnes i loggene, men deler av deres innhold vil være utilgjengelige for offentligheten.",
+    "revdelete-text-others": "Andre administratorer på {{SITENAME}} vil fortsatt ha tilgang til det skjulte innholdet og kan rulle det tilbake igjen via det samme grensesnittet, hvis ikke ytterligere begrensinger er satt.",
     "revdelete-confirm": "Bekreft at du ønsker å gjøre dette, at du forstår konsekvensene, og at du gjør det i samsvar med [[{{MediaWiki:Policy-url}}|retningslinjene]].",
     "revdelete-suppress-text": "Skjuling bør '''kun''' brukes i følgende tilfeller:\n* Mulig injurierende utsagn\n* Følsomme personlige opplysninger\n*: ''privatadresser og -telefonnumre, fødselsnumre og lignende''",
     "revdelete-legend": "Fastsett synlighetsbegrensninger",
     "search-file-match": "(matcher filinnhold)",
     "search-suggest": "Mente du: $1",
     "search-interwiki-caption": "Søsterprosjekter",
-    "search-interwiki-default": "$1-resultater:",
+    "search-interwiki-default": "Resultater fra $1:",
     "search-interwiki-more": "(mer)",
     "search-relatedarticle": "Relatert",
     "searcheverything-enable": "Søk i alle navnerom",
     "prefs-skin": "Utseende",
     "skin-preview": "Forhåndsvisning",
     "datedefault": "Ingen foretrukket",
-    "prefs-beta": "Betafunksjoner",
     "prefs-datetime": "Dato og tid",
     "prefs-labs": "Lab-funksjoner",
     "prefs-user-pages": "Brukersider",
     "rcnotefrom": "Nedenfor er endringene gjort siden <strong>$2</strong> (frem til <strong>$1</strong> vises).",
     "rclistfrom": "Vis nye endringer med start fra $1",
     "rcshowhideminor": "$1 mindre endringer",
+    "rcshowhideminor-show": "Vis",
+    "rcshowhideminor-hide": "Skjul",
     "rcshowhidebots": "$1 roboter",
+    "rcshowhidebots-show": "Vis",
+    "rcshowhidebots-hide": "Skjul",
     "rcshowhideliu": "$1 registrerte brukere",
-    "rcshowhideanons": "$1 anonyme brukere",
+    "rcshowhideliu-show": "Vis",
+    "rcshowhideliu-hide": "Skjul",
+    "rcshowhideanons": "$1 uregistrerte brukere",
+    "rcshowhideanons-show": "Vis",
+    "rcshowhideanons-hide": "Skjul",
     "rcshowhidepatr": "$1 patruljerte endringer",
+    "rcshowhidepatr-show": "Vis",
+    "rcshowhidepatr-hide": "Skjul",
     "rcshowhidemine": "$1 mine endringer",
+    "rcshowhidemine-show": "Vis",
+    "rcshowhidemine-hide": "Skjul",
     "rclinks": "Vis siste $1 endringer i de siste $2 dagene<br />$3",
     "diff": "diff",
     "hist": "hist",
     "uploaddisabledtext": "Opplasting er slått av.",
     "php-uploaddisabledtext": "PHP-filopplasting er deaktivert. Sjekk innstillingen for file_uploads.",
     "uploadscripted": "Denne filen inneholder HTML eller skripting som kan feiltolkes av en nettleser.",
+    "uploadscriptednamespace": "Denne SVG-filen inneholder et ulovlig navnerom \"$1\"",
     "uploadinvalidxml": "XML-en i den opplastede filen kunne ikke tolkes.",
     "uploadvirus": "Denne filen inneholder virus! Detaljer: $1",
     "uploadjava": "Filen er en ZIP-fil som inneholder en Java-fil av typen .class.\nDet er ikke tillatt å laste opp Java-filer, fordi de kan omgå sikkerhetsrestriksjoner.",
     "download": "last ned",
     "unwatchedpages": "Sider som ikke er overvåket",
     "listredirects": "Liste over omdirigeringer",
+    "listduplicatedfiles": "Liste av filer med duplikater",
+    "listduplicatedfiles-summary": "Dette er en liste av filer hvor den nyeste versjonen av filen er en duplikat av den nyeste versjonen av en annen fil. Bare lokale filer er sammenlignet.",
+    "listduplicatedfiles-entry": "[[:File:$1|$1]] har [[$3|{{PLURAL:$2|en duplikat|$2 duplikater}}]].",
     "unusedtemplates": "Ubrukte maler",
     "unusedtemplatestext": "Denne siden lister opp alle sider i malnavnerommet ({{ns:template}}:) som ikke er inkludert på en annen side. Husk å sjekke for andre slags lenker til malen før du sletter den.",
     "unusedtemplateswlh": "andre lenker",
     "listgrouprights-removegroup-self": "Kan ta vekk {{PLURAL:$2|gruppe|grupper}} fra egen konto: $1",
     "listgrouprights-addgroup-self-all": "Kan legge til alle grupper til egen konto",
     "listgrouprights-removegroup-self-all": "Kan ta bort alle grupper fra egen konto",
+    "trackingcategories": "Sporingskategori",
+    "trackingcategories-summary": "Denne siden lister sporingskategorier som er automatisk befolket av Mediawiki-programvaren. Deres navn kan bli endret ved å redigere de tilhørende systembeskjedene i {{ns:8}}-navnerommet.",
+    "trackingcategories-msg": "Sporingskategori",
+    "trackingcategories-name": "Beskjednavn",
+    "trackingcategories-desc": "Kategori-inklusjonskriterium",
+    "noindex-category-desc": "Denne siden er påført et <nowiki>__NOINDEX__</nowiki> magisk ord (og er i et navnerom hvor det flagget er tillatt), og blir derfor ikke indeksert av roboter.",
+    "index-category-desc": "Denne siden er påført et <nowiki>__INDEX__</nowiki> magisk ord (og er i et navnerom hvor det flagget er tillatt), og vil derfor bli indeksert av roboter mens det normalt ikke vil skje.",
+    "post-expand-template-inclusion-category-desc": "Etter ekspandering av alle malene, så er siden større enn $wgMaxArticleSize, så noen maler er ikke ekspandert.",
+    "post-expand-template-argument-category-desc": "Etter ekspandering av et malargument (noe i trippel krøllparentes, slik som {{{Foo}}}), så er siden større en $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "For mange kostbare parserfunksjoner (som <code>#ifexist</code>) er inkludert på en side. Se [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Kategorien blir lagt til hvis siden inneholder en brutt fil-lenke (en lenke for å bygge inn en fil når filen selv ikke eksisterer).",
+    "hidden-category-category-desc": "Dette er en kategori som er påført et <nowiki>__HIDDENCAT__</nowiki> magisk ord, som hindrer den fra å dukke opp i lenkeboksen for kategorier på siden, som standard.",
+    "trackingcategories-nodesc": "Ingen beskrivelse er tilgjengelig",
+    "trackingcategories-disabled": "Kategorien er deaktivert",
     "mailnologin": "Ingen avsenderadresse",
     "mailnologintext": "Du må være [[Special:UserLogin|logget inn]] og ha en gyldig e-postadresse satt i [[Special:Preferences|brukerinnstillingene]] for å sende e-post til andre brukere.",
     "emailuser": "E-post til denne brukeren",
     "nowatchlist": "Du har ingenting i overvåkningslisten.",
     "watchlistanontext": "Vennligst $1 for å vise eller redigere sider på overvåkningslisten din.",
     "watchnologin": "Ikke logget inn",
-    "watchnologintext": "Du må være [[Special:UserLogin|logget inn]] for å kunne endre overvåkningslisten.",
     "addwatch": "Legg til i overvåkningslisten",
     "addedwatchtext": "Siden «[[:$1]]» er lagt til [[Special:Watchlist|overvåkningslisten]] din.\nFremtidige endringer til denne siden og den tilhørende diskusjonssiden blir listet opp der.",
     "removewatch": "Fjern fra overvåkningslisten",
     "delete-edit-reasonlist": "Rediger begrunnelser for sletting",
     "delete-toobig": "Denne siden har en stor redigeringshistorikk, med over {{PLURAL:$1|$1&nbsp;revisjon|$1&nbsp;revisjoner}}. Muligheten til å slette slike sider er begrenset for å unngå utilsiktet forstyrring av {{SITENAME}}.",
     "delete-warning-toobig": "Denne siden har en stor redigeringshistorikk, med over {{PLURAL:$1|$1&nbsp;revisjon|$1&nbsp;revisjoner}}. Sletting av denne siden kan forstyrre databasen til {{SITENAME}}; vær varsom.",
-    "deleting-backlinks-warning": "'''Advarsel:''' Andre sider linker til eller inkluderer siden du er i ferd med å slette.",
+    "deleting-backlinks-warning": "'''Advarsel:''' [[Special:WhatLinksHere/{{FULLPAGENAME}|Andre sider]] linker til eller inkluderer siden du er i ferd med å slette.",
     "rollback": "Fjern redigeringer",
     "rollback_short": "Tilbakestill",
     "rollbacklink": "tilbakestill",
     "sp-contributions-newbies-sub": "For nybegynnere",
     "sp-contributions-newbies-title": "Bidrag av nye kontoer",
     "sp-contributions-blocklog": "blokkeringslogg",
+    "sp-contributions-suppresslog": "undertrykte brukerbidrag",
     "sp-contributions-deleted": "slettede brukerbidrag",
     "sp-contributions-uploads": "opplastinger",
     "sp-contributions-logs": "logger",
     "sp-contributions-search": "Søk etter bidrag",
     "sp-contributions-username": "IP-adresse eller brukernavn:",
     "sp-contributions-toponly": "Vis kun endringer som er gjeldende revisjoner",
+    "sp-contributions-newonly": "Bare vis bidrag som er sideopprettinger",
     "sp-contributions-submit": "Søk",
     "whatlinkshere": "Lenker hit",
     "whatlinkshere-title": "Sider som lenker til «$1»",
     "allmessagesname": "Navn",
     "allmessagesdefault": "Standardtekst",
     "allmessagescurrent": "Nåværende tekst",
-    "allmessagestext": "Dette er en liste over tilgjengelige systemmeldinger i MediaWiki-navnerommet.\nBesøk [//translatewiki.net translatewiki.net] om du ønsker å bidra med oversettelse av MediaWiki.",
+    "allmessagestext": "Dette er en liste over tilgjengelige systemmeldinger i MediaWiki-navnerommet.\nBesøk [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Oversettelse] og [//translatewiki.net translatewiki.net] om du ønsker å bidra med oversettelse av MediaWiki.",
     "allmessagesnotsupportedDB": "''{{ns:special}}:Allmessages'' kan ikke brukes fordi '''$wgUseDatabaseMessages''' er slått av.",
     "allmessages-filter-legend": "Filtrér",
     "allmessages-filter": "Filtrér etter tilpasningsgrad",
index ca755c0..ada401c 100644 (file)
     "prefs-skin": "{{SITENAME}}-uterlik",
     "skin-preview": "bekieken",
     "datedefault": "Gien veurkeur",
-    "prefs-beta": "Bètafunksies",
     "prefs-datetime": "Daotum en tied",
     "prefs-labs": "Alphafunksies",
     "prefs-user-pages": "Gebrukersziejen",
     "nowatchlist": "Gien artikels in volglieste.",
     "watchlistanontext": "$1 is verplicht um joew volglieste te bekieken of te wiezigen.",
     "watchnologin": "Niet an-emeld",
-    "watchnologintext": "Um je volglieste an te passen mu'j eerst [[Special:UserLogin|an-emeld]] ween.",
     "addwatch": "Op mien volglieste zetten",
     "addedwatchtext": "De zied \"[[:$1]]\" steet noen op joew [[Special:Watchlist|volglieste]].\nToekomstige wiezigingen op disse zied en de overlegzied zullen hier vermeld wörden.",
     "removewatch": "Van mien volglieste aofhaolen",
     "allmessagesname": "Naam",
     "allmessagesdefault": "Standardtekste",
     "allmessagescurrent": "De leste versie",
-    "allmessagestext": "Hieronder steet n lieste mit alle systeemteksten in de MediaWiki-naamruumte.\nKiek oek effen bie [https://www.mediawiki.org/wiki/Localisation MediaWiki-lokalisasie] en [//translatewiki.net translatewiki.net] a'j biedragen willen an de algemene vertaling veur MediaWiki.",
+    "allmessagestext": "Hieronder steet n lieste mit alle systeemteksten in de MediaWiki-naamruumte.\nKiek oek effen bie [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki-lokalisasie] en [//translatewiki.net translatewiki.net] a'j biedragen willen an de algemene vertaling veur MediaWiki.",
     "allmessagesnotsupportedDB": "Disse zied kan niet gebruukt wörden umdat '''$wgUseDatabaseMessages''' uutezet is.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filtreer op wiezigingen:",
index 882c5dc..7241f53 100644 (file)
     "nowatchlist": "Du hest kene Indreeg op dien Oppasslist.",
     "watchlistanontext": "$1, dat du dien Oppasslist ankieken oder ännern kannst.",
     "watchnologin": "Du büst nich anmellt",
-    "watchnologintext": "Du must [[Special:UserLogin|anmellt]] wesen, wenn du dien Oppasslist ännern willst.",
     "addedwatchtext": "De Siet „<nowiki>$1</nowiki>“ is to diene [[Special:Watchlist|Oppasslist]] toföögt worrn.\nÄnnern, de in Tokumst an disse Siet un an de tohörige Diskuschoonssiet maakt warrt, sünd dor op oplist un de Siet is op de [[Special:RecentChanges|List vun de letzten Ännern]] fett markt. Wenn du de Siet nich mehr op diene Oppasslist hebben willst, klick op „Nich mehr oppassen“.",
     "removedwatchtext": "De Sied „[[:$1]]“ is nich mehr op [[Special:Watchlist|dien Oppasslist]].",
     "watch": "Oppassen",
index f5e6c51..5ea4680 100644 (file)
     "gotaccountlink": "लग इन",
     "userlogin-resetlink": "प्रवेश सम्बन्धी विवरणहरु बिर्सनु भयो?",
     "userlogin-resetpassword-link": "पासवर्ड भुल्नुभयो?",
+    "userlogin-helplink2": "प्रवेश गर्नको लागि सहयोग",
     "userlogin-createanother": "अर्को खाता खोल्नुहोस्",
     "createacct-join": "तपाईँका जानकारीहरू तल थप्नुहोस् ।",
     "createacct-another-join": "नयाँ खाताको जानकारी तल थप्नुहोस ।",
     "throttled-mailpassword": "बितेको {{PLURAL:$1|घण्टा|$1 घण्टाहरु}} भित्र एउटा प्रवेशशब्द अनुस्मारक पठाई सकिएको छ।\nदुरुपयोगबाट बचाउकोलागि प्रत्येक {{PLURAL:$1|घण्टा|$1 घण्टाहरु}}मा केवल एउटा प्रवेशशब्द अनुस्मारक पठाइन्छ।",
     "mailerror": " चिठी :$1 पठाउँदा त्रुटी भयो",
     "acct_creation_throttle_hit": "तपाईंको आईपी ठेगानाबाट आएका आगन्तुकद्वारा बितेको चौबिस घण्टामा यस विकिमा {{PLURAL:$1|एउटा खाता बनाइसकिएको छ|$1 खाताहरु बनाइसकिएका छन्}}, यस समयावधिमा यति नैं अधिकतम सीमा हो।\nअतः यस समय यस आईपी ठेगानाको प्रयोग गर्ने आगन्तुकले अरु खाता खोल्न सक्नेछैनन्।",
-    "emailauthenticated": "तपाà¤\88à¤\82à¤\95à¥\8b à¤\88-मà¥\87ल à¤ à¥\87à¤\97ाना $2 à¤\95à¥\8b $3 à¤®à¤¾ à¤ªà¥\8dरमाणित à¤\97रियो।",
-    "emailnotauthenticated": "तपाईँको इमेल ठेगाना अहिले सम्म प्रमाणित गरिएको छैन ।\nनिम्न सुविधाको लागि कुनै पनि इ-मेल पठाइने छैन ।",
+    "emailauthenticated": "तपाà¤\88à¤\82à¤\95à¥\8b à¤\87मà¥\87ल à¤ à¥\87à¤\97ाना $2 à¤\95à¥\8b $3 à¤®à¤¾ à¤ªà¥\8dरमाणित à¤\97रिà¤\8fà¤\95à¥\8b à¤¥ियो।",
+    "emailnotauthenticated": "तपाईँको इमेल ठेगाना अहिले सम्म प्रमाणित गरिएको छैन ।\nनिम्न सुविधाको लागि कुनै पनि इमेल पठाइने छैन ।",
     "noemailprefs": "निम्न सुविधाहरु राम्ररी काम गर्नको लागि तपाईको अभिरुचिमा आफ्नो ई-मेल ठेगाना खुलाउनुहोस् ।",
     "emailconfirmlink": "तपाईंको ई-मेल ठेगाना पक्का गर्नुहोस्",
     "invalidemailaddress": "ई-मेल ठेगाना स्वीकार गर्न सकिएन किन भनें यो सही प्रारूपमा छैन, कृपया सही प्रारूपको  ठेगाना दिनुहोस्।",
     "login-abort-generic": "तपाईंको प्रवेश असफल भयो - छोड़ियो",
     "loginlanguagelabel": "भाषा: $1",
     "suspicious-userlogout": "तपाईंको निर्गमन अनुरोध अस्विकार गरिन्छ किन कि यो खराब ब्राउजर वा क्यासिङ प्रोक्सिले पठाएको जस्तो देखिन्छ।",
+    "pt-login": "प्रवेश",
+    "pt-login-button": "प्रवेश",
+    "pt-createaccount": "खाता खोल्नुहोस्",
+    "pt-userlogout": "निर्गमन (लग आउट)",
     "php-mail-error-unknown": "PHP मेल() क्रियामा अज्ञात त्रुटि",
     "user-mail-no-addy": "इमेल ठेगाना बिना नै इमेल पठाउन खोजिएको थियो।",
     "changepassword": "पासवर्ड परिवर्तन गर्नुहोस्",
-    "resetpass_announce": "तपाà¤\88à¤\82लà¥\87 à¤\85सà¥\8dथायà¥\80 à¤\88-मà¥\87ल à¤\95à¥\8bडà¤\95à¥\8b à¤\86धारमा à¤ªà¥\8dरवà¥\87श à¤\97रà¥\8dनà¥\81 à¤­à¤\8fà¤\95à¥\8bà¤\9b।\nपà¥\8dरवà¥\87शà¤\95ारà¥\8dय à¤ªà¥\82रा à¤\97रà¥\8dन à¤¨à¤¯à¤¾à¤\81 à¤ªà¥\8dरवà¥\87श à¤¶à¤µà¥\8dद à¤¯à¤¹à¤¾à¤\81 à¤¦à¤¿à¤¨à¥\81हà¥\8bसà¥\8d:",
+    "resetpass_announce": "पà¥\8dरवà¥\87श à¤ªà¥\82रा à¤\97रà¥\8dन à¤¤à¤ªà¤¾à¤\88à¤\81लà¥\87 à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤\97रà¥\8dनà¥\81परà¥\8dà¤\9b à¥¤",
     "resetpass_text": "<!-- Add text here -->",
     "resetpass_header": "खाताको प्रवेशशव्द परिवर्तन गर्ने",
     "oldpassword": "पुरानो पासवर्ड:",
     "resettokens-no-tokens": "पूर्वरुपमा फर्काउन कुनै पनि टोकन छैन ।",
     "resettokens-legend": "टोकनहरू पूर्वरुपमा फर्काउने",
     "resettokens-tokens": "टोकनहरू:",
+    "resettokens-done": "टोकन पूर्वरुपमा फर्काइयो ।",
     "bold_sample": "गाढा अक्षर",
     "bold_tip": "गाढा अक्षर",
     "italic_sample": "इटालिक पाठ",
     "revdelete-hide-image": "फाइल कमेन्ट लुकाउने",
     "revdelete-hide-name": "कार्य र गन्तब्य लुकाउने",
     "revdelete-hide-comment": "सम्पादन टिप्पणी",
-    "revdelete-hide-user": "समà¥\8dपादà¤\95à¤\95à¥\8b à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤¨à¤¾à¤®/IP à¤²à¥\81à¤\95ाà¤\89नà¥\87",
+    "revdelete-hide-user": "समà¥\8dपादà¤\95à¤\95à¥\8b à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤¨à¤¾à¤®/IP à¤ à¥\87à¤\97ाना",
     "revdelete-hide-restricted": "प्रवन्धक वा अरुबाट डेटा कम लिने",
     "revdelete-radio-same": "(परिवर्तन नगर्नुहोस्)",
     "revdelete-radio-set": "लुकाइएको",
     "compareselectedversions": "छानिएका संस्करणहरू दाँज्नुहोस्",
     "showhideselectedversions": "छानिएका पुनरावलोकनहरु देखाउने/लुकाउने",
     "editundo": "रद्द गर्ने",
+    "diff-empty": "(कुनै भिन्नता छैन)",
     "diff-multi-manyusers": "($2 {{PLURAL:$2|भन्दा अधिक प्रयोगकर्ता|भन्दा अधिक प्रयोगकर्ताहरु}}द्वारा {{PLURAL:$1|एउटा मध्यवर्ती संशोधन|$1 मध्यवर्ती संशोधनहरु}} नदेखाइएको)",
     "searchresults": "खोज नतिजाहरू",
     "searchresults-title": " \"$1\"को लागि खोज नतिजाहरु",
     "prefs-skin": "काँचुली",
     "skin-preview": "पूर्वावलोकन",
     "datedefault": "कुनै अभिरुचि छैन",
-    "prefs-beta": "बिटा गुणहरु",
     "prefs-datetime": "मिति र समय",
     "prefs-labs": "प्रयोगशाला गुणहरु",
     "prefs-user-pages": "प्रयोगकर्ता पृष्ठहरू",
     "right-hideuser": "एक प्रयोगकर्ता नाम रोक्ने, सार्वजनिकहुनबाट लुकाउने",
     "right-ipblock-exempt": "IP रोक,स्वत: रोक तथा स्तर रोक कटेर जाने",
     "right-proxyunbannable": "प्रोक्सिको स्वत: रोक कटेर जाने",
-    "right-unblockself": "तिनà¥\80हरà¥\81 à¤\86फà¥\88à¤\82लाà¤\88 à¤\96à¥\81लà¥\8dला à¤\97रà¥\8dà¤\9bन्",
+    "right-unblockself": "à¤\86फà¥\88à¤\82लाà¤\88 à¤\96à¥\81लà¥\8dला à¤\97रà¥\8dनà¥\81हà¥\8bस्",
     "right-protect": "सुरक्षा स्तर परिवर्तन गर्ने र जोगाइएका पृष्ठहरु सम्पादन गर्ने",
     "right-editprotected": "\"{{int:protect-level-sysop}}\" को हैसियतले सुरक्षित पृष्ठहरु सम्पादन गर्ने",
     "right-editinterface": "प्रयोगकर्ता अन्तरमोहडा सम्पादन गर्ने",
     "action-suppressionlog": "यो व्यक्तिगत लग हेर्ने",
     "action-block": "यो प्रयोगकर्तालाई सम्पादन गर्नबाट रोक्ने",
     "action-protect": "यो पृष्ठको सुरक्षा स्तर परिवर्तन गर्ने",
-    "action-import": "यà¥\8b à¤ªà¥\83षà¥\8dठ à¤\85रà¥\8dà¤\95à¥\8b à¤µà¤¿à¤\95िबाà¤\9f à¤\86यात à¤\97रà¥\8dनà¥\87",
-    "action-importupload": "फाà¤\87ल à¤\89रà¥\8dधà¥\8dवभरणबाà¤\9f à¤«à¤¾à¤\87ल आयात गर्ने",
+    "action-import": "पà¥\83षà¥\8dठहरà¥\82 à¤\85रà¥\8dà¤\95à¥\8b à¤µà¤¿à¤\95िबाà¤\9f à¤\86यात à¤\97रà¥\8dनà¥\81हà¥\8bसà¥\8d",
+    "action-importupload": "पà¥\83षà¥\8dठहरà¥\82 à¤«à¤¾à¤\87ल à¤\89रà¥\8dधà¥\8dवभरणबाà¤\9f आयात गर्ने",
     "action-patrol": "अरुको सम्पादनलाई निगरानीको चिन्ह लगाउने",
     "action-autopatrol": "तपाईंको सम्पादनलाई गश्त रुपमा दाग दिनुहोस्",
     "action-unwatchedpages": "अवलोकन नगरिएका  पृष्ठहरुको सूची हेर्ने",
     "recentchanges-label-minor": "यो साधारण सम्पादन हो",
     "recentchanges-label-bot": "यो सम्पादन बोट द्वारा गरिएको थियो",
     "recentchanges-label-unpatrolled": "यो सम्पादन अहिले सम्म पट्रोल गरिएको छैन",
-    "recentchanges-legend-newpage": "$1 - नयाँ पृष्ठ",
+    "recentchanges-legend-newpage": "([[Special:NewPages|list of new pages]] यो पनि हेर्नुहोस्)",
     "recentchanges-legend-plusminus": "(''±१२३'')",
     "rcnotefrom": "'''$2''' देखिका परिवर्तनहरु तल ('''$1''' सम्मका देखाइन्छ)।",
     "rclistfrom": "$1 देखिका नयाँ परिवर्तनहरू देखाउनु",
     "rcshowhideminor": "$1 सामान्य सम्पादन",
+    "rcshowhideminor-show": "देखाउनुहोस्",
+    "rcshowhideminor-hide": "लुकाउनुहोस्",
     "rcshowhidebots": "$1 बोटहरू",
-    "rcshowhideliu": "$1 प्रवेश गरेका प्रयोगकर्ताहरु",
+    "rcshowhidebots-show": "देखाउनुहोस्",
+    "rcshowhidebots-hide": "लुकाउनुहोस्",
+    "rcshowhideliu": "$1 दर्ता गरेका प्रयोगकर्ताहरु",
+    "rcshowhideliu-show": "देखाउनुहोस्",
+    "rcshowhideliu-hide": "लुकाउनुहोस्",
     "rcshowhideanons": "$1 अज्ञात प्रयोगकर्ता",
+    "rcshowhideanons-show": "देखाउनुहोस्",
+    "rcshowhideanons-hide": "लुकाउनुहोस्",
     "rcshowhidepatr": "$1 पट्रोल गरिएका सम्पादनहरु",
+    "rcshowhidepatr-show": "देखाउनुहोस्",
+    "rcshowhidepatr-hide": "लुकाउनुहोस्",
     "rcshowhidemine": "$1 मेरा सम्पादनहरु",
+    "rcshowhidemine-show": "देखाउनुहोस्",
+    "rcshowhidemine-hide": "लुकाउनुहोस्",
     "rclinks": "पछिल्ला $1 परिवर्तनहरु पछिल्ला $2 दिनहरुमा<br />$3",
     "diff": "भिन्न",
     "hist": "इतिहास",
     "listfiles_search_for": "मिडिया नामको लागि खोज्नुहोस:",
     "imgfile": "फाइल",
     "listfiles": "फाइल सूची",
+    "listfiles_thumb": "थम्बनेल",
     "listfiles_date": "मिति",
     "listfiles_name": "नाम",
     "listfiles_user": "प्रयोगकर्ता",
     "filedelete-reason-dropdown": "*मेट्नुका सामान्य कारणहरु\n** कपी राइट उल्लघन\n** सारिएको फाइल",
     "filedelete-edit-reasonlist": "मेट्नका कारण संपादन गर्नुहोस्।",
     "filedelete-maintenance": "रखरखाव चलिरहेको हुँदा अस्थायी रुपमा फाइलहरु मेटाउने र मेटाइएकोलाई पुनर्बहाली गर्न निष्क्रिय गरिएकोछ।",
+    "filedelete-maintenance-title": "फाइल मेट्न सकिएन",
     "mimesearch": "MIME खोज",
     "mimesearch-summary": "MIME-प्रकार अनुसार फ़ाइलहरु खोज्न यस पृष्ठको प्रयोग गर्न सकिन्छ।\nइनपुट: फ़ाइलको प्रकार/उपप्रकार, उदा. <code>image/jpeg</code>।",
     "mimetype": "MIME प्रकार:",
     "protectedpages": "संरक्षित पृष्ठहरू",
     "protectedpages-indef": "नखुलेको सुरक्षा मात्र",
     "protectedpages-cascade": "लामबद्ध सुरक्षाहरु मात्रा",
+    "protectedpages-noredirect": "अनुप्रेषण लुकाउने",
     "protectedpagesempty": "दिइएको प्यारामिटर प्रयोग गरि सुरक्षा गरिएका पृष्ठहरु छैनन् ।",
+    "protectedpages-timestamp": "समय चिन्ह",
     "protectedpages-page": "पृष्ठ",
     "protectedpages-expiry": "सकिनेछ",
     "protectedpages-performer": "प्रयोगकर्ता सुरक्षित गरिँदै",
     "activeusers-noresult": "प्रयोगकर्ताहरु भेटिएनन्।",
     "listgrouprights": "प्रयोगकर्ता समूह अधिकार",
     "listgrouprights-summary": "निम्न सूची यस विकिमा परिभाषित समूहहरु र तिनीहरुले प्रयोगगर्न सक्ने संबद्ध  अधिकारहरुको हो।\nयसमा निजी अधिकारहरुको बारेमा [[{{MediaWiki:Listgrouprights-helppage}}|अतिरिक्त सूचना]] हुनसक्छ।",
-    "listgrouprights-key": "* <span class=\"listgrouprights-granted\">à¤\85धिà¤\95ार à¤¦à¤¿à¤\87यà¥\8b</span>\n* <span class=\"listgrouprights-revoked\">à¤\85धिà¤\95ार à¤«à¤°à¥\8dà¤\95ाà¤\87यà¥\8b</span>",
+    "listgrouprights-key": "* <span class=\"listgrouprights-granted\">पà¥\8dरदान à¤\97रिà¤\8fà¤\95ा à¤\85धिà¤\95ारहरà¥\82</span>\n* <span class=\"listgrouprights-revoked\">फिरà¥\8dता à¤\97रिà¤\8fà¤\95ा à¤\85धिà¤\95ारहरà¥\82</span>",
     "listgrouprights-group": "समूह",
     "listgrouprights-rights": "अधिकारहरु",
     "listgrouprights-helppage": "Help:सामूहिक अधिकारहरु",
     "nowatchlist": "तपाईको अवलोकन सूचीमा कुनै पनि सामाग्री छैन।",
     "watchlistanontext": "कृपया तपाईको निगरानी सुची हेर्न या सम्पादनगर्न $1 गर्नुहोस् ।",
     "watchnologin": "प्रवेश (लग ईन) नगरिएको",
-    "watchnologintext": "आफ्नो अवलोकनलाइ परिवर्तन गर्नको लागि त तपाइ यसमा [[Special:UserLogin|प्रवेश(लगइन)]] गर्नुपर्छ।",
     "addwatch": "निगरानी सुचीमा थप्ने",
     "addedwatchtext": "\"[[:$1]]\" पृष्ठ [[Special:Watchlist|अवलोकनसूची]]मा थपियो\nयो पृष्ठ र यससित सम्बद्ध वार्तालाप पृष्ठमा भविष्यमा हुने परिवर्तन सूचिबद्ध गरिनेछ र यो पृष्ठ [[Special:RecentChanges|नयाँ परिवर्तनहरू]]मा छान्न सजिलोकोलागि गाढा अक्षरमा देखा पर्नेछ।",
     "removewatch": "निगरानी सुचीबाट हटाउने",
     "notvisiblerev": "पूर्वावलोकन हटाइयो",
     "watchlist-details": "तपाईको निगरानी सूचीमा रहेका{{PLURAL:$1|$1 पृष्ठ|$1 पृष्ठहरु}}वार्तालापमा पृष्ठमा गनिएका छैनन् ।",
     "wlheader-enotif": "ईमेल जानकारी सक्रिय गरियो ।",
-    "wlheader-showupdated": "तपाà¤\87लà¥\87 à¤ªà¤\9bिलà¥\8dलà¥\8b à¤ªà¤²à¥\8dà¤\9f à¤­à¥\8dरमण à¤\97रà¥\87पà¤\9bि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤­à¤\8fà¤\95ा à¤ªà¥\83षà¥\8dठहरà¥\82लाà¤\88 '''à¤\97ाढा''' गरेर देखाइएको छ ।",
+    "wlheader-showupdated": "तपाà¤\88à¤\81लà¥\87 à¤ªà¤\9bिलà¥\8dलà¥\8b à¤ªà¤²à¥\8dà¤\9f à¤­à¥\8dरमण à¤\97रà¥\87पà¤\9bि à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤­à¤\8fà¤\95ा à¤ªà¥\83षà¥\8dठहरà¥\82लाà¤\88 <strong>à¤\97ाढा<strong> गरेर देखाइएको छ ।",
     "watchmethod-recent": "निगरानी सुचीमा रहेका पृष्ठमा गरिएका सम्पादनहरु जाँच्दै",
     "watchmethod-list": "सम्पदान गरिएका निगरानी सुचीमा रहेका पृष्ठहरुको सम्पादन जाँच्दै",
     "watchlistcontains": "तपाईको निगरानी सुचीमा $1 {{PLURAL:$1|पृष्ठ|पृष्ठहरु}}रहेका छन् ।",
     "deletecomment": "कारण :",
     "deleteotherreason": "अरू/थप कारणहरू :",
     "deletereasonotherlist": "अरु कारण",
-    "deletereason-dropdown": "*मà¥\87à¤\9fà¥\8dनà¤\95ा à¤¸à¤¾à¤®à¤¾à¤¨à¥\8dय à¤\95ारणहरà¥\81\n** à¤²à¥\87à¤\96à¤\95à¤\95à¥\8b à¤\85नà¥\81रà¥\8bध\n** à¤\95पà¥\80राà¤\87à¤\9f à¤\89लà¥\8dलà¤\82à¤\98न\n** à¤¬à¤°à¥\8dबरता (Vandalism)",
+    "deletereason-dropdown": "*मà¥\87à¤\9fà¥\8dनà¤\95ा à¤¸à¤¾à¤®à¤¾à¤¨à¥\8dय à¤\95ारणहरà¥\81\n** à¤¸à¥\8dपà¥\8dयाम\n** à¤¹à¥\81लà¥\8dयाहापन(Vandalism) \n** à¤ªà¥\8dरतिलिपà¥\80 à¤\85धिà¤\95ार à¤\89लà¥\8dलà¤\82à¤\98न\n** à¤²à¥\87à¤\96à¤\95à¤\95à¥\8b à¤\85नà¥\81रà¥\8bध\n** à¤\9fà¥\81à¤\9fà¥\87à¤\95à¥\8b à¤\85नà¥\81पà¥\8dरà¥\87षण",
     "delete-edit-reasonlist": "मेट्नुको कारण सम्पादन गर्नुहोस्",
     "delete-toobig": "यो पृष्ठको सम्पादन इतिहास धेरै र  $1 {{PLURAL:$1|पुनरावलोक|पुनरावलोकहरु}}भन्दा बढी रहेको छ।\n {{SITENAME}}मा दुर्घटनाको कारणले गडबडी आउनसक्ने कुरालाई रोक्न यस्ता पृष्ठहरुलाई मेट्नबाट निषेध गरिएको छ ।",
     "delete-warning-toobig": "This page has a large edit history, over $1 {{PLURAL:$1|revision|revisions}}.\nDeleting it may disrupt database operations of {{SITENAME}};\nproceed with caution.",
     "allmessagesname": "नाम",
     "allmessagesdefault": "डिफल्ट सन्देश पाठ",
     "allmessagescurrent": "वर्तमान सन्देश पाठ",
-    "allmessagestext": "यो मीडियाविकि नेमस्पेसमा पाइने सिस्टम सन्देशहरूको सूची हो।\nयदि तपाईं व्यापक मीडिया विकि स्थानीयकरणमा योगदान गर्न चाहनुहुन्छ भनें कृपया [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation]मा र [//translatewiki.net translatewiki.net]मा जानुहोस्।",
+    "allmessagestext": "यो मीडियाविकि नेमस्पेसमा पाइने सिस्टम सन्देशहरूको सूची हो।\nयदि तपाईं व्यापक मीडिया विकि स्थानीयकरणमा योगदान गर्न चाहनुहुन्छ भनें कृपया [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation]मा र [//translatewiki.net translatewiki.net]मा जानुहोस्।",
     "allmessages-filter-legend": "फिल्टर",
     "allmessages-filter-unmodified": "असंशोधित",
     "allmessages-filter-all": "सबै",
index 8d30256..b8d1b46 100644 (file)
     "userlogin-resetpassword-link": "Wachtwoord vergeten?",
     "userlogin-helplink2": "Hulp bij aanmelden",
     "userlogin-loggedin": "U bent al aangemeld als {{GENDER:$1|$1}}.\nGebruik het onderstaande formulier om aan te melden als een andere gebruiker.",
-    "userlogin-createanother": "Nog een gebruiker aanmaken",
+    "userlogin-createanother": "Gebruiker aanmaken",
     "createacct-join": "Geef uw gegevens hieronder op.",
     "createacct-another-join": "Geef hieronder de informatie voor de nieuwe gebruiker op.",
     "createacct-emailrequired": "E-mailadres",
     "createacct-captcha": "Veiligheidscontrole",
     "createacct-imgcaptcha-ph": "Geef de tekst in die u hierboven ziet",
     "createacct-submit": "Gebruiker aanmaken",
-    "createacct-another-submit": "Nog een gebruiker aanmaken",
+    "createacct-another-submit": "Gebruiker aanmaken",
     "createacct-benefit-heading": "{{SITENAME}} wordt gemaakt door mensen zoals u.",
     "createacct-benefit-body1": "bewerking{{PLURAL:$1||en}}",
     "createacct-benefit-body2": "pagina{{PLURAL:$1||'s}}",
     "prefs-skin": "Vormgeving",
     "skin-preview": "Voorvertoning",
     "datedefault": "Geen voorkeur",
-    "prefs-beta": "Bètafunctionaliteit",
     "prefs-datetime": "Datum en tijd",
     "prefs-labs": "Alphafunctionaliteit",
     "prefs-user-pages": "Gebruikerspagina's",
     "listgrouprights-removegroup-self": "De volgende {{PLURAL:$2|groep|groepen}} verwijderen van eigen gebruiker: $1",
     "listgrouprights-addgroup-self-all": "Alle groepen toevoegen aan eigen gebruiker",
     "listgrouprights-removegroup-self-all": "Alle groepen verwijderen van eigen gebruiker",
+    "trackingcategories": "Volgcategorieën",
+    "trackingcategories-summary": "Op deze pagina worden volgcategorieën weergegeven die automatisch worden gevuld door de MediaWikisoftware. De namen van de categorieën kunnen gewijzigd worden door de bijbehorende systeemberichten in de naamruimte \"{{ns:8}}\" bij te werken.",
+    "trackingcategories-msg": "Volgcategorie",
+    "trackingcategories-name": "Berichtnaam",
+    "trackingcategories-desc": "Opnamecriteria",
+    "noindex-category-desc": "De pagina bevat het magische woord <nowiki>__NOINDEX__</nowiki> (en bevindt zich in een naamruimte waarin dat magische woord is toegestaan), en wordt niet geïndexeerd door robots.",
+    "index-category-desc": "De pagina bevat het magische woord <nowiki>__NOINDEX__</nowiki> (en bevindt zich in een naamruimte waarin dat magische woord is toegestaan), en wordt geïndexeerd door robots, terwijl dat normaliter niet zou gebeuren.",
+    "post-expand-template-inclusion-category-desc": "Na het uitbreiden van alle sjablonen, is de pagina groter dan <code>$wgMaxArticleSize</code>, dus zijn sommige sjablonen niet uitgebreid.",
+    "post-expand-template-argument-category-desc": "Na het uitbreiden van een sjabloonparameter (iets in de drievoudige accolades, zoals {{{Foo}}}), is de pagina groter dan <code>$wgMaxArticleSize</code>.",
+    "expensive-parserfunction-category-desc": "Op de pagina worden te veel kostbare parserfuncties (zoals <code>#ifexist</code>) gebruikt. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Meer informatie].",
+    "broken-file-category-desc": "Een categorie die wordt toegevoegd als een pagina een niet-bestaande koppeling bevat (een koppeling om een bestand toe te voegen als dat bestand niet bestaat).",
+    "hidden-category-category-desc": "Dit is een categoriepagina die het magische woord <nowiki>__HIDDENCAT__</nowiki> bevat, waardoor de categorie standaard niet zichtbaar is in de lijst met categorieën op pagina's.",
+    "trackingcategories-nodesc": "Geen beschrijving beschikbaar.",
+    "trackingcategories-disabled": "Categorie uitgeschakeld",
     "mailnologin": "Geen verzendadres beschikbaar",
     "mailnologintext": "U moet [[Special:UserLogin|aangemeld]] zijn en een geldig e-mailadres in uw [[Special:Preferences|voorkeuren]] vermelden om andere gebruikers te kunnen e-mailen.",
     "emailuser": "Deze gebruiker e-mailen",
     "nowatchlist": "Uw volglijst is leeg.",
     "watchlistanontext": "Om uw volglijst te bekijken of te bewerken moet u zich $1.",
     "watchnologin": "U bent niet aangemeld",
-    "watchnologintext": "U dient [[Special:UserLogin|aangemeld]] te zijn om uw volglijst te bewerken.",
     "addwatch": "Toevoegen aan volglijst",
     "addedwatchtext": "De pagina \"[[:$1]]\" is toegevoegd aan uw [[Special:Watchlist|volglijst]].\nToekomstige bewerkingen van deze pagina en de bijbehorende overlegpagina worden daar weergegeven.",
     "removewatch": "Verwijderen uit volglijst",
     "sp-contributions-newbies-sub": "Voor nieuwelingen",
     "sp-contributions-newbies-title": "Bijdragen van nieuwe gebruikers",
     "sp-contributions-blocklog": "blokkeerlogboek",
+    "sp-contributions-suppresslog": "onderdrukte gebruikersbijdragen",
     "sp-contributions-deleted": "verwijderde bijdragen",
     "sp-contributions-uploads": "uploads",
     "sp-contributions-logs": "logboeken",
     "sp-contributions-blocked-notice": "Deze gebruiker is op het moment geblokkeerd.\nDe laatste regel uit het blokkeerlogboek wordt hieronder ter referentie weergegeven:",
     "sp-contributions-blocked-notice-anon": "Dit IP-adres is geblokkeerd.\nDe laatste regel uit het blokkeerlogboek wordt hieronder ter referentie weergegeven:",
     "sp-contributions-search": "Zoeken naar bijdragen",
-    "sp-contributions-suppresslog": "onderdrukte gebruikersbijdragen",
     "sp-contributions-username": "IP-adres of gebruikersnaam:",
     "sp-contributions-toponly": "Alleen nieuwste versies weergeven",
     "sp-contributions-newonly": "Alleen nieuwe pagina's weergeven",
     "allmessagesname": "Naam",
     "allmessagesdefault": "Standaardinhoud",
     "allmessagescurrent": "Huidige inhoud",
-    "allmessagestext": "Hieronder staan de systeemberichten uit de MediaWiki-naamruimte.\nGa naar [https://www.mediawiki.org/wiki/Localisation MediaWiki-lokalisatie] en [//translatewiki.net translatewiki.net] als u wilt bijdragen aan de algemene vertaling voor MediaWiki.",
+    "allmessagestext": "Hieronder staan de systeemberichten uit de MediaWiki-naamruimte.\nGa naar [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki-lokalisatie] en [//translatewiki.net translatewiki.net] als u wilt bijdragen aan de algemene vertaling voor MediaWiki.",
     "allmessagesnotsupportedDB": "Deze pagina kan niet worden gebruikt, omdat '''$wgUseDatabaseMessages''' is uitgeschakeld.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filteren op aangepast:",
     "version-entrypoints": "URL's voor ingangen",
     "version-entrypoints-header-entrypoint": "Ingang",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Article path]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Script path]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Article path]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Script path]",
     "redirect": "Doorverwijzen op bestandsnaam, gebruikersnummer, paginanummer, of versienummer",
     "redirect-legend": "Doorverwijzen naar een bestand of pagina",
     "redirect-summary": "Deze speciale pagina verwijst door naar een bestand (als een bestandsnaam wordt opgegeven), een pagina (als een paginanummer of versienummer wordt opgegeven) of een gebruikerspagina (als een gebruikersnummer wordt opgegeven). Gebruik: [[{{#Special:Redirect}}/file/Voorbeeld.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] of [[{{#Special:Redirect}}/user/101]].",
index ea474c0..02cab21 100644 (file)
@@ -1,13 +1,33 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "Cocu",
+            "Dittaeva",
+            "Diupwijk",
+            "Eirik",
+            "Finnrind",
+            "Frokor",
+            "Geitost",
+            "Gunnernett",
+            "Jeblad",
+            "Jon Harald Søby",
+            "Jorunn",
+            "Kaganer",
+            "Marinsb",
+            "Najami",
+            "Nghtwlkr",
+            "Njardarlogar",
+            "Pcoombe",
+            "Ranveig",
+            "לערי ריינהארט"
+        ]
     },
     "tog-underline": "Strek under lenkjer:",
     "tog-hideminor": "Gøym småplukk i lista over siste endringar",
     "tog-hidepatrolled": "Gøym patruljerte endringar i lista over siste endringar",
     "tog-newpageshidepatrolled": "Gøym patruljerte sider frå lista over nye sider",
     "tog-extendwatchlist": "Utvid overvakingslista til å vise alle endringane, ikkje berre dei siste",
-    "tog-usenewrc": "Grupper endringar etter side i siste endringane og på overvakingslista mi (krev JavaScript)",
+    "tog-usenewrc": "Grupper endringar etter side i siste endringane og på overvakingslista",
     "tog-numberheadings": "Vis nummererte overskrifter",
     "tog-showtoolbar": "Vis endringsverktøyline",
     "tog-editondblclick": "Endre sider med dobbeltklikk",
     "youhavenewmessages": "Du har $1 ($2).",
     "youhavenewmessagesfromusers": "Du har $1 frå {{PLURAL:$3|ein annan brukar| $3 brukarar}} ($2).",
     "youhavenewmessagesmanyusers": "Du har $1 frå mange brukarar ($2).",
-    "newmessageslinkplural": "{{PLURAL:$1|ei ny melding|nye meldingar}}",
-    "newmessagesdifflinkplural": "siste {{PLURAL:$1|endringa|endringane}}",
+    "newmessageslinkplural": "{{PLURAL:$1|ei ny melding|999=nye meldingar}}",
+    "newmessagesdifflinkplural": "siste {{PLURAL:$1|endringa|999=endringane}}",
     "youhavenewmessagesmulti": "Du har nye meldingar på $1",
     "editsection": "endre",
     "editold": "endre",
     "nospecialpagetext": "Du har bede om ei spesialside som ikkje finst. Lista over spesialsider finn du [[Special:SpecialPages|her]].",
     "error": "Feil",
     "databaseerror": "Databasefeil",
+    "databaseerror-text": "Ein spørjefeil mot databasa har oppstått.\nDette kan indikere ein feil i programvara.",
     "databaseerror-error": "Feil: $1",
     "laggedslavemode": "Åtvaring: Det er mogleg at sida ikkje er heilt oppdatert.",
     "readonly": "Databasen er skriveverna",
     "loginlanguagelabel": "Språk: $1",
     "suspicious-userlogout": "Førespurnaden din om å logge ut vart nekta fordi han såg ut til å vere sendt av ein øydelagt nettlesar eller mellomtenar.",
     "pt-login": "Logg inn",
+    "pt-login-button": "Logg inn",
     "pt-createaccount": "Opprett konto",
+    "pt-userlogout": "Logg ut",
     "php-mail-error-unknown": "Ukjend feil i PHPs mail()-funksjon",
     "user-mail-no-addy": "↓Prøvde å senda e-post utan e-postadresse",
     "user-mail-no-body": "Freista å senda e-post med tom eller urimeleg stutt brødtekst.",
     "prefs-skin": "Drakt",
     "skin-preview": "førehandsvis",
     "datedefault": "Standard",
-    "prefs-beta": "Betafunksjonar",
     "prefs-datetime": "Dato og klokkeslett",
     "prefs-labs": "Testfunksjonar",
     "prefs-user-pages": "Brukarsider",
     "rcnotefrom": "Nedanfor er endringane gjorde sidan <strong>$2</strong> viste (opp til <strong>$1</strong> stykke)",
     "rclistfrom": "Vis nye endringar sidan $1",
     "rcshowhideminor": "$1 småplukk",
+    "rcshowhideminor-show": "Vis",
+    "rcshowhideminor-hide": "Gøym",
     "rcshowhidebots": "$1 robotar",
+    "rcshowhidebots-show": "Vis",
+    "rcshowhidebots-hide": "Gøym",
     "rcshowhideliu": "$1 registrerte brukarar",
+    "rcshowhideliu-show": "Vis",
+    "rcshowhideliu-hide": "Gøym",
     "rcshowhideanons": "$1 anonyme brukarar",
+    "rcshowhideanons-show": "Vis",
+    "rcshowhideanons-hide": "Gøym",
     "rcshowhidepatr": "$1 godkjende endringar",
+    "rcshowhidepatr-show": "Vis",
+    "rcshowhidepatr-hide": "Gøym",
     "rcshowhidemine": "$1 endringane mine",
+    "rcshowhidemine-show": "Vis",
+    "rcshowhidemine-hide": "Gøym",
     "rclinks": "Vis dei siste $1 endringane dei siste $2 dagane<br />$3",
     "diff": "skil",
     "hist": "hist",
     "nowatchlist": "Du har ikkje noko i overvakingslista di.",
     "watchlistanontext": "Du lyt $1 for å vise eller endre sider på overvakingslista di.",
     "watchnologin": "Ikkje innlogga",
-    "watchnologintext": "Du lyt vera [[Special:UserLogin|innlogga]] for å kunna endre overvakingslista.",
     "addwatch": "↓Legg til i overvakingslista",
     "addedwatchtext": "Sida «[[:$1]]» er lagd til i [[Special:Watchlist|overvakingslista]] di. Framtidige endringar av henne og den tilhøyrande diskusjonssida hennar vil bli oppførde der.",
     "removewatch": "Fjerna frå overvakingslista",
     "allmessagesname": "Namn",
     "allmessagesdefault": "Standardtekst",
     "allmessagescurrent": "Gjeldande meldingstekst",
-    "allmessagestext": "Dette er ei liste over systemmeldingar i MediaWiki-namnerommet.\nVitja [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] og [//translatewiki.net translatewiki.net] om du ynskjer å bidra til den generelle omsetjinga av MediaWiki.",
+    "allmessagestext": "Dette er ei liste over systemmeldingar i MediaWiki-namnerommet.\nVitja [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] og [//translatewiki.net translatewiki.net] om du ynskjer å bidra til den generelle omsetjinga av MediaWiki.",
     "allmessagesnotsupportedDB": "Denne sida kan ein ikkje bruka fordi «'''$wgUseDatabaseMessages'''» er slått av.",
     "allmessages-filter-legend": "Filtrer",
     "allmessages-filter": "Filtrer etter tilpassingsgrad:",
index e20b40c..bc5125b 100644 (file)
     "revdelete-no-file": "Lo fichièr especificat existís pas.",
     "revdelete-show-file-confirm": "Sètz segur(a) que volètz veire la revision suprimida del fichièr « <nowiki>$1</nowiki> » datant del $2 a $3?",
     "revdelete-show-file-submit": "Òc",
+    "revdelete-selected-text": "{{PLURAL:$1|Revision seleccionada|Revisions seleccionadas}} de [[:$2]] :",
+    "revdelete-selected-file": "{{PLURAL:$1|Version de fichièr seleccionada|Versions de fichièr seleccionadas}} de [[:$2]] :",
     "logdelete-selected": "{{PLURAL:$1|Eveniment d'istoric seleccionat|Eveniments d'istoric seleccionats}} :",
     "revdelete-confirm": "Confirmatz que volètz efectuar aquesta accion, que ne comprenètz las consequéncias, e qu'o fasètz en acòrd amb [[{{MediaWiki:Policy-url}}|las règlas]].",
     "revdelete-suppress-text": "La supression deu èsser utilizada '''sonque''' dins los cases seguents :\n* Informacions potencialament difamatòrias\n* Informacions personalas inapropriadas\n*: ''adreça, numèro de telefòn, numèro de seguretat sociala, ...''",
     "prefs-skin": "Aparéncia",
     "skin-preview": "Previsualizar",
     "datedefault": "Pas cap de preferéncia",
-    "prefs-beta": "Foncionalitats bèta",
     "prefs-datetime": "Data e ora",
     "prefs-labs": "Foncionalitats « labs »",
     "prefs-user-pages": "Paginas d'utilizaire",
     "listgrouprights-removegroup-self": "Se pòt levar {{PLURAL:$2|lo grop|los gropes}} de son compte pròpri : $1",
     "listgrouprights-addgroup-self-all": "Se pòt apondre totes los gropes a son compte pròpri",
     "listgrouprights-removegroup-self-all": "Se pòt levar totes los gropes de son compte pròpri",
+    "trackingcategories": "Categorias de seguiment",
+    "trackingcategories-msg": "Categoria de seguiment",
+    "trackingcategories-name": "Nom del messatge",
+    "trackingcategories-desc": "Critèri d’inclusion de la categoria",
+    "trackingcategories-nodesc": "Cap de descripcion pas disponibla.",
+    "trackingcategories-disabled": "La categoria es desactivada",
     "mailnologin": "Pas d'adreça",
     "mailnologintext": "Vos cal èsser [[Special:UserLogin|connectat(ada)]]\ne aver indicat una adreça electronica valida dins vòstras [[Special:Preferences|preferéncias]]\nper poder mandar un messatge a un autre utilizaire.",
     "emailuser": "Mandar un messatge a aqueste utilizaire",
     "nowatchlist": "Vòstra lista de seguiment conten pas cap d'article.",
     "watchlistanontext": "Per poder afichar o editar los elements de vòstra lista de seguiment, vos cal vos $1.",
     "watchnologin": "Vos sètz pas identificat(ada)",
-    "watchnologintext": "Vos cal èsser [[Special:UserLogin|connectat(ada)]]\nper modificar vòstra lista de seguiment.",
     "addwatch": "Ajustar a la lista de seguiment",
     "addedwatchtext": "La pagina « [[:$1]] » es estada aponduda a vòstra [[Special:Watchlist|lista de seguiment]]. Las modificacions venentas d'aquesta pagina e de la pagina de discussion associada i seràn repertoriadas.",
     "removewatch": "Suprimir de la lista de seguiment",
     "sp-contributions-newbies-sub": "Lista de las contribucions dels utilizaires novèls. Las paginas que son estadas suprimidas son pas afichadas.",
     "sp-contributions-newbies-title": "Las contribucions de l’utilizaire pels comptes novèls",
     "sp-contributions-blocklog": "Istoric dels blocatges",
+    "sp-contributions-suppresslog": "contribucions suprimidas d’un utilizaire",
     "sp-contributions-deleted": "contribucions suprimidas",
     "sp-contributions-uploads": "importat",
     "sp-contributions-logs": "jornals",
     "sp-contributions-blocked-notice": "Aqueste utilizaire es actualament blocat. La darrièra entrada del jornal dels blocatges es indicada çaijós a títol d’informacion :",
     "sp-contributions-blocked-notice-anon": "Aquesta adreça IP es actualament blocada.\nLa darrièra intrada del jornal dels blocatges es indicada çaijós a títol d’informacion :",
     "sp-contributions-search": "Cercar las contribucions",
-    "sp-contributions-suppresslog": "contribucions suprimidas d’un utilizaire",
     "sp-contributions-username": "Adreça IP o nom d’utilizaire :",
     "sp-contributions-toponly": "Mostrar sonque las contribucions que son lo darrièr cambiament",
     "sp-contributions-newonly": "Afichar unicament las modificacions que son de creacions de pagina",
     "allmessagesname": "Nom del camp",
     "allmessagesdefault": "Messatge per defaut",
     "allmessagescurrent": "Messatge actual",
-    "allmessagestext": "Aquò es la lista de totes los messatges disponibles dins l’espaci MediaWiki.\nVisitatz la [https://www.mediawiki.org/wiki/Localisation Localizacion MediaWiki] e [//translatewiki.net translatewiki.net] se desiratz contribuir a la localizacion MediaWiki generica.",
+    "allmessagestext": "Aquò es la lista de totes los messatges disponibles dins l’espaci MediaWiki.\nVisitatz la [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Localizacion MediaWiki] e [//translatewiki.net translatewiki.net] se desiratz contribuir a la localizacion MediaWiki generica.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:Allmessages''' es pas disponible perque '''$wgUseDatabaseMessages''' es desactivat.",
     "allmessages-filter-legend": "Filtre",
     "allmessages-filter": "Filtrar per estat de modificacion :",
index 78958cd..652e0b1 100644 (file)
@@ -2,7 +2,15 @@
     "@metadata": {
         "authors": [
             "Shijualex",
-            "Psubhashish"
+            "Psubhashish",
+            "Ansumang",
+            "Jnanaranjan Sahu",
+            "Jose77",
+            "MKar",
+            "Odisha1",
+            "Sambiwiki",
+            "Shisir 1945",
+            "ଶିତିକଣ୍ଠ ଦାଶ"
         ]
     },
     "tog-underline": "ତଳେ ଥିବା ଲିଙ୍କ:",
     "gotaccount": "ଆଗରୁ ଖାତାଟିଏ ଅଛି କି? $1.",
     "gotaccountlink": "ଲଗ ଇନ (Log in)",
     "userlogin-resetlink": "ଲଗଇନ ତଥ୍ୟ ସବୁ ଭୁଲିଗେଲେକି?",
-    "userlogin-resetpassword-link": "ପାସୱାରà­\8dଡ଼ à¬°à¬¿à¬¸à­\87à¬\9f à¬\95ରନà­\8dତà­\81",
+    "userlogin-resetpassword-link": "ପାସୱାରà­\8dଡ଼ à¬­à­\81ଲିଯାà¬\87à¬\9bନà­\8dତି ?",
     "createacct-emailrequired": "ଇମେଲ ଠିକଣା",
     "createacct-emailoptional": "ଇମେଲ ଠିକଣା (ଇଚ୍ଛାଧୀନ)",
     "createacct-email-ph": "ଆପଣଙ୍କ ଇମେଲ ଠିକଣା ନିବେଶ କରନ୍ତୁ",
     "login-abort-generic": "ଆପଣଙ୍କ ଲଗ ଇନ ଅସଫଳ ହେଲା - ନାକଚ କରିଦିଆଗଲା",
     "loginlanguagelabel": "ଭାଷା: $1",
     "suspicious-userlogout": "ଲଗ ଆଉଟ କରିବା ନିମନ୍ତେ ଆପଣ କରିଥିବା ଆବେଦନ ନାକଚ କରିଦିଆଗଲା କାରଣ ଲାଗୁଅଛି ଯେ ଏହା ଏକ ଅସ୍ଥିର ବ୍ରାଉଜରରୁ ପଠାଯାଇଅଛି ଅବା ପ୍ରକ୍ସି ଧରାଯାଇଅଛି ।",
+    "pt-login": "ଲଗ-ଇନ",
+    "pt-login-button": "ଲଗ-ଇନ",
+    "pt-createaccount": "ଖାତାଟିଏ ଖୋଲନ୍ତୁ",
+    "pt-userlogout": "ଲଗ-ଆଉଟ",
     "php-mail-error-unknown": "PHP ର ମେଲ() କାମରେ ଅଜଣା ଅସୁବିଧା ।",
     "user-mail-no-addy": "ଏକ ଇ-ମେଲ ଠିକଣା ବିନା ଇ-ମେଲ ପଠାଇବାକୁ ଚେଷ୍ଟା କଲୁଁ ।",
     "user-mail-no-body": "ଏକ ଖାଲି କିମ୍ବା ଅଦରକାରୀ ଛୋଟ ଲେଖା ଥିବା ମେଲ ପଠେଇବାକୁ ଚେଷ୍ଟା କରିଥିଲେ",
     "changepassword": "ପାସୱର୍ଡ଼ ବଦଳାନ୍ତୁ",
-    "resetpass_announce": "à¬\86ପଣ à¬\8fà¬\95 à¬\85ସà­\8dଥାà­\9fà­\80 à¬\87-ମà­\87ଲରà­\87 à¬¯à¬¾à¬\87ଥିବା à¬\95à­\8bଡ଼ à¬¸à¬¹à¬¾à­\9fତାରà­\87 à¬²à¬\97 à¬\87ନ à¬\95ରିà¬\85à¬\9bନà­\8dତି à¥¤\nଲà¬\97 à¬\87ନ à¬¶à­\87ଷ à¬\95ରିବା à¬¨à¬¿à¬®à¬¨à­\8dତà­\87 à¬\86ପଣà¬\99à­\8dà¬\95à­\81 à¬\8fହିଠାରà­\87 à¬¨à­\82à¬\86 à¬ªà¬¾à¬¸à¬¬à¬¾à¬°à­\8dଡ଼à¬\9fିà¬\8f à¬¦à­\87ବାà¬\95à­\81 à¬ªà¬¡à¬¼à¬¿à¬¬:",
+    "resetpass_announce": "ଲà¬\97à­\8d-à¬\87ନ à¬ªà­\8dରà¬\95à­\8dରିà­\9fା à¬¶à­\87ଷ à¬\95ରିବା à¬¨à¬¿à¬®à¬¨à­\8dତà­\87, à¬\86ପଣà¬\99à­\8dà¬\95à­\81 à¬\8fà¬\95 à¬¨à­\82à¬\86 à¬ªà¬¾à¬¸à­±à¬¾à¬°à­\8dଡ଼à¬\9fିà¬\8f à¬¦à­\87ବାà¬\95à­\81 à¬ªà¬¡à¬¼à¬¿à¬¬ à¥¤",
     "resetpass_header": "ଖାତାର ପାସୱାର୍ଡ଼ଟିକୁ ବଦଳାଇ ଦିଅନ୍ତୁ",
     "oldpassword": "ପୁରୁଣା ପାସୱାର୍ଡ଼:",
     "newpassword": "ନୂଆ ପାସୱାର୍ଡ଼:",
     "retypenew": "ପାସୱାର୍ଡ଼ ଆଉଥରେ ଦିଅନ୍ତୁ:",
     "resetpass_submit": "ପାସୱାର୍ଡ଼ଟିଏ ଦେଇ ଲଗ ଇନ କରନ୍ତୁ",
-    "changepassword-success": "à¬\86ପଣà¬\99à­\8dà¬\95 à¬ªà¬¾à¬¸à­±à¬¾à¬°à­\8dଡ଼à¬\9fି à¬¬à¬¦à¬³à¬¾à¬\87 à¬¦à¬¿à¬\86à¬\97ଲା !\nà¬\8fବà­\87 à¬²à¬\97 à¬\87ନ à¬\95ରà­\81à¬\85à¬\9bà­\81à¬\81...",
+    "changepassword-success": "à¬\86ପଣà¬\99à­\8dà¬\95 à¬ªà¬¾à¬¸à­±à¬¾à¬°à­\8dଡ଼à¬\9fି à¬¸à¬«à¬³à¬¤à¬¾ à¬ªà­\82ରà­\8dବà¬\95 à¬¬à¬¦à¬³à¬¾à¬\87 à¬¦à¬¿à¬\86à¬\97ଲା !",
     "resetpass_forbidden": "ପାସୱାର୍ଡ଼ମାନ ବଦଳା ଯାଇପାରିବ ନାହିଁ",
     "resetpass-no-info": "ଏହି ପୃଷ୍ଠାଟିକୁ ସିଧା ଖୋଲିବା ନିମନ୍ତେ ଆପଣଙ୍କୁ ଲଗ ଇନ କରିବାକୁ ପଡ଼ିବ ।",
     "resetpass-submit-loggedin": "ପାସୱାର୍ଡ଼ ବଦଳାନ୍ତୁ",
     "prefs-skin": "ବହିରାବରଣ",
     "skin-preview": "ସାଇତା ଆଗରୁ ଦେଖଣା",
     "datedefault": "କୌଣସି ପସନ୍ଦ ନାହିଁ",
-    "prefs-beta": "ଆଗ ବିଶେଷତାମାନ",
     "prefs-datetime": "ତାରିଖ ଓ ସମୟ",
     "prefs-labs": "ପରଖଶାଳା ସୁବିଧାସବୁ",
     "prefs-user-pages": "ବ୍ୟବହାରକାରୀଙ୍କର ପୃଷ୍ଠାଗୁଡିକ",
     "nowatchlist": "ଆପଣଙ୍କ ଦେଖଣା ତାଲିକାରେ କିଛି ବି ଜିନିଷ ନାହିଁ ।",
     "watchlistanontext": "ଆପଣା ଦେଖଣାତାଲିକାରେ କିଛି ସମ୍ପାଦନା କରିବା ନିମନ୍ତେ ଦୟାକରି  $1 କରନ୍ତୁ ।",
     "watchnologin": "ଲଗ‌‌ ଇନ କରିନାହାନ୍ତି",
-    "watchnologintext": "ଆପଣା ଦେଖଣାତାଲିକା ବଦଳାଇବା ନିମନ୍ତେ ଆପଣଙ୍କୁ [[Special:UserLogin|ଲଗ ଇନ]] କରିବାକୁ ପଡ଼ିବ ।",
     "addwatch": "ଦେଖଣାତାଲିକାରେ ଯୋଡ଼ିବେ",
     "addedwatchtext": "\"[[:$1]]\" ପୃଷ୍ଠାଟି ଆପଣଙ୍କ [[Special:Watchlist|ଦେଖଣାତାଲିକା]]ରେ ଯୋଡ଼ିଦିଆଗଲା ।\nଏହି ପୃଷ୍ଠାରେ ଭବିଷ୍ୟତର ଅଦଳ ବଦଳ ଓ ତାହା ସହ ଯୋଡ଼ା ଆଲୋଚନା ପୃଷ୍ଠା ସେଠାରେ ଦିଆଯିବ ।",
     "removewatch": "ଦେଖଣା ତାଲିକାରୁ ହଟାଇବେ",
     "allmessagesname": "ନାମ",
     "allmessagesdefault": "ଆପେଆପେ ଚିଠିରେ ରହିବା କଥା",
     "allmessagescurrent": "ଏବେକର ସନ୍ଦେଶ ଲେଖା",
-    "allmessagestext": "ଏଥିରେ ମିଡ଼ିଆଉଇକି ନେମସ୍ପେସରେ ଥିବା ସିଷ୍ଟମ ସନ୍ଦେଶର ଏକ ତାଲିକା ଦିଆଗଲା ।\nଯଦି ଆପଣ ମୂଳ ଦୟାକରି ମିଡ଼ିଆଉଇକି ଆଞ୍ଚଳିକୀକରଣରେ ଭାଗ ନେବା ପାଇଁ ଚାହାନ୍ତି ତେବେ [https://www.mediawiki.org/wiki/Localisation ମିଡ଼ିଆଉଇକି ଆଞ୍ଚଳିକୀକରଣ] ଓ [//translatewiki.net translatewiki.net] ଦେଖନ୍ତୁ ।",
+    "allmessagestext": "ଏଥିରେ ମିଡ଼ିଆଉଇକି ନେମସ୍ପେସରେ ଥିବା ସିଷ୍ଟମ ସନ୍ଦେଶର ଏକ ତାଲିକା ଦିଆଗଲା ।\nଯଦି ଆପଣ ମୂଳ ଦୟାକରି ମିଡ଼ିଆଉଇକି ଆଞ୍ଚଳିକୀକରଣରେ ଭାଗ ନେବା ପାଇଁ ଚାହାନ୍ତି ତେବେ [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation ମିଡ଼ିଆଉଇକି ଆଞ୍ଚଳିକୀକରଣ] ଓ [//translatewiki.net translatewiki.net] ଦେଖନ୍ତୁ ।",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' ଅଚଳ କରାଯାଇଥିବାରୁ ଏହି ପୃଷ୍ଠାଟି ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ ।",
     "allmessages-filter-legend": "ଛାଣିବା",
     "allmessages-filter": "ଆପଣା ପସନ୍ଦରେ ଛାଣିବେ:",
index 82b742c..2d97cce 100644 (file)
@@ -61,7 +61,8 @@
             "Wpedzich",
             "Ymar",
             "Žekřil71pl",
-            "לערי ריינהארט"
+            "לערי ריינהארט",
+            "Pan Cube"
         ]
     },
     "tog-underline": "Podkreślenie linków:",
     "pool-timeout": "Zbyt długi czas oczekiwania na blokadę",
     "pool-queuefull": "Kolejka zadań jest pełna",
     "pool-errorunknown": "Błąd nieznany",
+    "pool-servererror": "Usługa licznika nie jest dostępna ($1).",
     "aboutsite": "O {{GRAMMAR:MS.lp|{{SITENAME}}}}",
     "aboutpage": "Project:O {{GRAMMAR:MS.lp|{{SITENAME}}}}",
     "copyright": "Treść udostępniana na licencji $1, jeśli nie podano inaczej.",
     "prefs-skin": "Skórka",
     "skin-preview": "podgląd",
     "datedefault": "Domyślny",
-    "prefs-beta": "Funkcje testowe",
     "prefs-datetime": "Data i czas",
     "prefs-labs": "Funkcje doświadczalne",
     "prefs-user-pages": "Strony użytkowników",
     "listgrouprights-removegroup-self": "Możliwość usunięcia własnego konta z {{PLURAL:$2|grupy|grup:}} $1",
     "listgrouprights-addgroup-self-all": "Może dodać własne konto do wszystkich grup",
     "listgrouprights-removegroup-self-all": "Może usunąć własne konto ze wszystkich grup",
+    "trackingcategories": "Śledzenie kategorii",
+    "trackingcategories-msg": "Śledzenie kategorii",
+    "trackingcategories-name": "Nazwa komunikatu",
+    "post-expand-template-inclusion-category-desc": "Po rozwinięciu wszystkich szablonów, rozmiar strony jest większe niż $wgMaxArticleSize, więc niektóre szablony nie zostały rozwinięte.",
+    "expensive-parserfunction-category-desc": "Na stronie używanych jest zbyt wiele wymagających funkcji parsera (takich jak <code>#ifexist</code>). Więcej informacji na stronie [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "trackingcategories-nodesc": "Opis nie jest dostępny.",
+    "trackingcategories-disabled": "Kategoria jest wyłączona",
     "mailnologin": "Brak adresu",
     "mailnologintext": "Musisz się [[Special:UserLogin|zalogować]] i mieć wpisany aktualny adres e‐mailowy w swoich [[Special:Preferences|preferencjach]], aby móc wysłać e‐mail do innego użytkownika.",
     "emailuser": "Wyślij e‐mail do tego użytkownika",
     "nowatchlist": "Lista obserwowanych przez Ciebie stron jest pusta.",
     "watchlistanontext": "$1, aby obejrzeć lub edytować elementy listy obserwowanych.",
     "watchnologin": "Nie jesteś zalogowany",
-    "watchnologintext": "Musisz się [[Special:UserLogin|zalogować]] przed modyfikacją listy obserwowanych stron.",
     "addwatch": "Dodaj do listy obserwowanych",
     "addedwatchtext": "Strona „[[:$1|$1]]” została dodana do Twojej [[Special:Watchlist|listy obserwowanych]].\nKażda zmiana treści tej strony lub związanej z nią strony dyskusji zostanie odnotowana na tej liście.",
     "removewatch": "Usuń z listy obserwowanych",
     "sp-contributions-newbies-sub": "Dla nowych użytkowników",
     "sp-contributions-newbies-title": "Wkład nowych użytkowników",
     "sp-contributions-blocklog": "blokady",
+    "sp-contributions-suppresslog": "stłumiony wkład użytkownika",
     "sp-contributions-deleted": "usunięty wkład użytkownika",
     "sp-contributions-uploads": "przesłane pliki",
     "sp-contributions-logs": "rejestry",
     "allmessagesname": "Nazwa",
     "allmessagesdefault": "Tekst domyślny",
     "allmessagescurrent": "Tekst obecny",
-    "allmessagestext": "Lista wszystkich komunikatów systemowych dostępnych w przestrzeni nazw MediaWiki.\nOdwiedź [https://www.mediawiki.org/wiki/Localisation Tłumaczenie MediaWiki] oraz [//translatewiki.net translatewiki.net], jeśli chcesz uczestniczyć w tłumaczeniu oprogramowania MediaWiki.",
+    "allmessagestext": "Lista wszystkich komunikatów systemowych dostępnych w przestrzeni nazw MediaWiki.\nOdwiedź [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Tłumaczenie MediaWiki] oraz [//translatewiki.net translatewiki.net], jeśli chcesz uczestniczyć w tłumaczeniu oprogramowania MediaWiki.",
     "allmessagesnotsupportedDB": "Ta strona nie może być użyta, ponieważ zmienna '''$wgUseDatabaseMessages''' jest wyłączona.",
     "allmessages-filter-legend": "Filtr",
     "allmessages-filter": "Filtrowanie według stanu modyfikacji:",
     "redirect-revision": "Wersja strony",
     "redirect-file": "Nazwa pliku",
     "redirect-not-exists": "Nie znaleziono wartości",
-    "fileduplicatesearch": "Szukaj duplikatów pliku",
-    "fileduplicatesearch-summary": "Szukaj duplikatów pliku na podstawie wartości funkcji skrótu.",
+    "fileduplicatesearch": "Wyszukiwanie duplikatów pliku",
+    "fileduplicatesearch-summary": "Wyszukiwanie duplikatów pliku na podstawie wartości funkcji skrótu.",
     "fileduplicatesearch-legend": "Szukaj duplikatów pliku",
     "fileduplicatesearch-filename": "Nazwa pliku",
     "fileduplicatesearch-submit": "Szukaj",
index 90ce509..38348b1 100644 (file)
@@ -11,7 +11,8 @@
             "Teak",
             "The Evil IP address",
             "Ævar Arnfjörð Bjarmason <avarab@gmail.com>, Jens Frank",
-            "לערי ריינהארט"
+            "לערי ריינהארט",
+            "Shirayuki"
         ]
     },
     "tog-underline": "Anliure con la sotliniadura",
     "prefs-skin": "Facia",
     "skin-preview": "Preuva",
     "datedefault": "Franch l'istess",
-    "prefs-beta": "Caraterìstiche dla Beta",
     "prefs-datetime": "Data e ora",
     "prefs-labs": "Caraterìstiche dël laboratòri",
     "prefs-user-pages": "Pàgine utent",
     "nowatchlist": "A l'ha ancó pa marcà dj'artìcoj coma ròba da tnì sot-euj.",
     "watchlistanontext": "Për piasì, $1 për ës-ciairé ò pura modifiché j'element ëd soa lista dla ròba che as ten sot-euj.",
     "watchnologin": "A l'é ancó nen rintrà ant ël sistema",
-    "watchnologintext": "A l'ha da manca prima ëd tut ëd [[Special:UserLogin|rintré ant ël sistema]]\npër podèj modifiché soa lista dla ròba dë tnì sot-euj.",
     "addwatch": "Gionté a la lista ëd lòn ch'as ten sot-euj",
     "addedwatchtext": "La pàgina «[[:$1]]» a l'é staita giontà a soa [[Special:Watchlist|lista dla ròba da tnì sot-euj]].\nLe modìfiche che a-i saran ant costa pàgina-sì e ant soa pàgina ëd discussion a saran listà ambelessì.",
     "removewatch": "Gavé da la lista ëd lòn ch'as ten sot-euj",
     "allmessagesname": "Nòm",
     "allmessagesdefault": "Test che a-i sarìa se a-i fusso pa 'd modìfiche",
     "allmessagescurrent": "Test corent",
-    "allmessagestext": "Costa-sì a l'é na lista dij mëssagi ëd sistema disponìbij ant lë spassi nominal MediaWiki.\nPër piasì, ch'a vìsita la [https://www.mediawiki.org/wiki/Localisation Localisassion ëd MediaWiki] e [//translatewiki.net translatewiki.net] se a veul contribuì a la localisassion general ëd MediaWiki.",
+    "allmessagestext": "Costa-sì a l'é na lista dij mëssagi ëd sistema disponìbij ant lë spassi nominal MediaWiki.\nPër piasì, ch'a vìsita la [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Localisassion ëd MediaWiki] e [//translatewiki.net translatewiki.net] se a veul contribuì a la localisassion general ëd MediaWiki.",
     "allmessagesnotsupportedDB": "Sta pàgina-sì a peul pa esse dovrà përchè '''$wgUseDatabaseMessages''' a l'é stàit disabilità.",
     "allmessages-filter-legend": "Filtr",
     "allmessages-filter": "Filtré për stat ëd përsonalisassion:",
     "version-entrypoints": "Anliure dij pont d'intrada",
     "version-entrypoints-header-entrypoint": "Pont d'intrada",
     "version-entrypoints-header-url": "Adrëssa an sl'aragnà",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Senté d'artìcol]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Senté d'artìcol]",
     "redirect": "Ridirigiù da archivi, utent, pàgina o ID ëd revision",
     "redirect-legend": "Ridirige a n'archivi o na pàgina",
     "redirect-summary": "Costa pàgina special a ponta a n'archivi (dàit ël nòm dl'archivi), na pàgina (dàit n'ID ëd revision o n'ID ëd pàgina) o na pàgina d'utent (dàit n'identificativ numérich a l'utent). Usagi: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], o [[{{#Special:Redirect}}/user/101]].",
index 82f68c9..3447c94 100644 (file)
     "prefs-skin": "چھاڑ",
     "skin-preview": "کچا کم",
     "datedefault": "خاص پسند نئیں",
-    "prefs-beta": "بیٹا فیچرز",
     "prefs-datetime": "تریح تے ویلہ",
     "prefs-labs": "لیبز فیچرز",
     "prefs-personal": "ورتن آلے دا پروفائل",
     "nowatchlist": "تھواڈی اکھ تھلے لسٹ چ کوئی شے نئیں۔",
     "watchlistanontext": "مہربانی کرکے $1 نوں ویکھو یا اپنی اکھ تھلے رکھی لسٹ نوں بدلو۔",
     "watchnologin": "لاگ ان نئیں ہوۓ او",
-    "watchnologintext": "توانوں لازمی [[Special:UserLogin|لاگان]] ہونا پووے گا اپنی اکھ تھلے رکھی لسٹ نوں بدلن لئی۔",
     "addwatch": "اکھ تھلے کرو",
     "addedwatchtext": "اے صفحہ \"[[:$1]] تواڈیاں اکھاں تھلے آگیا اے۔<br />\nمستقبل وچ اس صفحہ تے ایدے بارے چ گل بات نویاں تبدیلیاں وچ موٹے نظر آن گے تا کہ آسانی نال کھوجیا جا سکے۔",
     "removewatch": "اکھ تھلیوں ہٹاؤ",
     "allmessagesname": "ناں",
     "allmessagesdefault": "ڈیفالٹ لکھائی",
     "allmessagescurrent": "موجودہ لکھائی",
-    "allmessagestext": "ایہ لسٹ اے پربندھ سنیعیاں دی  جیہڑے میڈیاوکی دی ناں تھاں تے ہیگے نیں۔\nمہربانی کرکے [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] تے [//translatewiki.net translatewiki.net] تے جاؤ۔\nاگر تسیں میڈیا وکی دے بولی وٹاندرے چ کم کرنا چاندے او۔",
+    "allmessagestext": "ایہ لسٹ اے پربندھ سنیعیاں دی  جیہڑے میڈیاوکی دی ناں تھاں تے ہیگے نیں۔\nمہربانی کرکے [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] تے [//translatewiki.net translatewiki.net] تے جاؤ۔\nاگر تسیں میڈیا وکی دے بولی وٹاندرے چ کم کرنا چاندے او۔",
     "allmessagesnotsupportedDB": "اے صفہ نئیں ورتیا جاسکدا کیوں جے '''$wgUseDatabaseMessages''' روک دتا گیا اے۔",
     "allmessages-filter-legend": "فلٹر",
     "allmessages-filter": "کسٹمائزیشن سٹیٹ فلٹر ہوئي:",
index f3b7251..4c88b1b 100644 (file)
     "nowatchlist": "Twajā listi stēisan nadirītan pāusan ast pāustan.",
     "watchlistanontext": "Madli $1, kāi widālai elamēntans stesse listin stēisan nadirītan.",
     "watchnologin": "Ni assei engūbun",
-    "watchnologintext": "Tū turri būtwei[[Special:UserLogin|engūbun]], kāi kitawīdintun listin stēisan nadirītan.",
     "addedwatchtext": "Pāusan \"[[:$1]]\" pastāi preidātan prei twajjan [[Special:Watchlist|nadirītan listin]].\nEraīna šisse pāusas ēnturas kitawīdinsna anga diskusiōnis pāusas sēitan sen tennan kitawīdinsna wīrst būwusi enpeisātan en šissei listin. Pāusas tītels wīrst būwuns '''pastarīntan''' en [[Special:RecentChanges|listei stēisan panzdauman kitawīdinsnan]], kāi lānginlai ti endirītun kitawīdinsnan.",
     "removedwatchtext": "Pāusan \"[[:$1]]\" pastāi āupausintan iz [[Special:Watchlist|twajjan listin stēisan āupausintan]].",
     "watch": "Nadirēis",
     "allmessagesname": "Emmens",
     "allmessagesdefault": "Auprestamins teksts",
     "allmessagescurrent": "Bigānts teksts",
-    "allmessagestext": "Sta ast listi wisēisan waīstin preiēiminan en MediaWikis tītelin plattibin.\nMadli kāimalukeis [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] be [//translatewiki.net translatewiki.net] ik tu kwaitēi delīkan īmtun en MediaWikis prōgraminin tulkausnai.",
+    "allmessagestext": "Sta ast listi wisēisan waīstin preiēiminan en MediaWikis tītelin plattibin.\nMadli kāimalukeis [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] be [//translatewiki.net translatewiki.net] ik tu kwaitēi delīkan īmtun en MediaWikis prōgraminin tulkausnai.",
     "allmessagesnotsupportedDB": "Šī pāusan ni mazzi būtwei tērpautan, beggi wariābli '''$wgUseDatabaseMessages''' ast izklaūtan.",
     "allmessages-filter-legend": "Filtrīs",
     "allmessages-filter": "Filtrīs pa būsenin:",
index 721c400..5b01173 100644 (file)
     "loginreqpagetext": "د نورو مخونو د کتلو لپاره تاسو بايد $1 وکړۍ.",
     "accmailtitle": "پټنوم ولېږل شو.",
     "newarticle": "(نوی)",
-    "newarticletext": "تاسې د يوې داسې تړنې څارنه کړې چې لا تر اوسه پورې نه شته.\nکه همدا مخ ليکل غواړۍ، نو په لانديني چوکاټ کې خپل متن وټاپۍ (د لا نورو مالوماتو لپاره د [$1 لارښود مخ] وگورۍ).\nکه چېرته تاسې دلته په تېروتنه راغلي ياست، نو يواځې د خپل د کتنمل '''مخ پر شا''' تڼۍ مو وټوکۍ.",
+    "newarticletext": "تاسې د يوې داسې تړنې څارنه کړې چې لا تر اوسه پورې نه شته.\nکه همدا مخ ليکل غواړۍ، نو په لانديني چوکاټ کې خپل متن وټاپئ (د لا نورو مالوماتو لپاره د [$1 لارښود مخ] وگورئ).\nکه چېرته تاسې دلته په تېروتنه راغلي ياست، نو يواځې د خپل د کتنمل '''مخ پر شا''' تڼۍ مو وټوکئ.",
     "anontalkpagetext": "----''دا د يوه ورکنومي کارن چې کارن-نوم نه لري او يا خپل کارن-نوم نه کاروي، د سکالو يوه پاڼه ده. نو د يوه کس د پېژندلو پخاطر موږ د هماغه کارن د انټرنېټ شمېره يا IP پته دلته ثبتوؤ. داسې يوه IP پته د ډېرو کارنانو لخوا هم کارېدلی شي. که تاسې يو ورکنومی کارن ياست او تاسې ته دا څرگندېږي چې تاسې ته نااړونده پېغامونه او تبصرې اشاره شوي، نو د نورو بې نومو کارنانو او ستاسې ترمېنځ د ټکنتوب د مخ نيونې لپاره لطفاً [[Special:UserLogin/signup|يو گڼون جوړ کړۍ]] او يا هم [[Special:UserLogin|غونډال ته ورننوځۍ]].''",
     "noarticletext": "دم مهال په دې مخ کې څه نشته.\nتاسې کولای شی چې په نورو مخونو کې [[Special:Search/{{PAGENAME}}|د دې مخ د سرليک پلټنه]] يا\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} د اړوندو يادښتونو پلټنه] وکړی.\nاو يا [{{fullurl:{{FULLPAGENAME}}|action=edit}} همدا مخ سم کړی]</span>.",
     "noarticletext-nopermission": "دم مهال په دې مخ کې متن نشته.\nتاسې کولای شی چې [[Special:Search/{{PAGENAME}}|همدا سرليک په نورو مخونو کې وپلټۍ]], يا هم <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} اړونده يادښتونه وپلټۍ]</span>، خو تاسې د دې مخ د جوړولو اجازه نه لرۍ.",
     "prefs-skin": "پوښۍ",
     "skin-preview": "مخکتنه",
     "datedefault": "هېڅ نه ټاکل",
-    "prefs-beta": "د آزمېښتي بڼې ځانگړنې",
     "prefs-datetime": "نېټه او وخت",
     "prefs-labs": "د آزمېښتون ځانگړنې",
     "prefs-user-pages": "کارن مخونه",
     "nowatchlist": "ستاسې کتنلړ کې څه نه شته.",
     "watchlistanontext": "د خپل کتنلړ د توکو د سمولو او کتلو لپاره $1 ترسره کړۍ.",
     "watchnologin": "غونډال کې نه ياست ننوتي.",
-    "watchnologintext": "ددې لپاره چې خپل کتنلړ کې بدلون راولی نو تاسو ته پکار ده چې لومړی غونډال کې [[Special:UserLogin|ورننوځۍ]].",
     "addwatch": "کتنلړ کې ورگډول",
     "addedwatchtext": "د \"[[:$1]]\" په نوم يو مخ ستاسې [[Special:Watchlist|کتنلړ]] کې ورگډ شو.\nپه راتلونکې کې چې په دغه مخ او د دې د خبرواترو مخ کې کوم بدلونونه راځي نو هغه به ستاسې کتنلړ کې ښکاري.",
     "removewatch": "له کتنلړ نه غورځول",
     "allmessagesname": "نوم",
     "allmessagesdefault": "تلواليزه پيغام متن",
     "allmessagescurrent": "اوسنی پيغام متن",
-    "allmessagestext": "دا د مېډياويکي په نوم-تشيال کې د غونډال د پيغامونو لړليک دی.\nکه چېرته تاسې د ميډياويکي په ځايتابه کې ونډې ترسره کول غواړۍ نو لطفاً [https://www.mediawiki.org/wiki/Localisation د ميډياويکي ځايتابه] او [//translatewiki.net translatewiki.net] څخه ليدنه وکړۍ.",
+    "allmessagestext": "دا د مېډياويکي په نوم-تشيال کې د غونډال د پيغامونو لړليک دی.\nکه چېرته تاسې د ميډياويکي په ځايتابه کې ونډې ترسره کول غواړۍ نو لطفاً [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation د ميډياويکي ځايتابه] او [//translatewiki.net translatewiki.net] څخه ليدنه وکړۍ.",
     "allmessagesnotsupportedDB": "'''Special:Allmessages''' ترېنه کار نه اخيستل کېږي ځکه چې '''$wgUseDatabaseMessages''' مړ دی.",
     "allmessages-filter-legend": "چاڼگر",
     "allmessages-filter-unmodified": "نابدلېدلي",
index de885b2..12dce84 100644 (file)
     "prefs-skin": "Tema",
     "skin-preview": "Pré-visualização",
     "datedefault": "Sem preferência",
-    "prefs-beta": "Características beta",
     "prefs-datetime": "Data e hora",
     "prefs-labs": "Características de laboratório",
     "prefs-user-pages": "Páginas de usuário",
     "nowatchlist": "A sua lista de páginas vigiadas não possui títulos.",
     "watchlistanontext": "Por favor $1 para ver ou editar os itens na sua lista de páginas vigiadas.",
     "watchnologin": "Não está autenticado",
-    "watchnologintext": "Você precisa estar [[Special:UserLogin|autenticado]] para modificar a sua lista de páginas vigiadas.",
     "addwatch": "Adicionar às páginas vigiadas",
     "addedwatchtext": "A página \"[[:$1]]\" foi adicionada à sua [[Special:Watchlist|lista de páginas vigiadas]].\nFuturas modificações em tal página e páginas de discussão relacionadas serão listadas lá.",
     "removewatch": "Remover das páginas vigiadas",
     "sp-contributions-newbies-sub": "Para contas novas",
     "sp-contributions-newbies-title": "Contribuições de contas novas",
     "sp-contributions-blocklog": "registro de bloqueios",
+    "sp-contributions-suppresslog": "Contribuições de usuário suprimidas",
     "sp-contributions-deleted": "contribuições eliminadas",
     "sp-contributions-uploads": "envios",
     "sp-contributions-logs": "registros",
     "sp-contributions-blocked-notice": "Este usuário atualmente está bloqueado. O registro de bloqueio mais recente é fornecido abaixo para referência:",
     "sp-contributions-blocked-notice-anon": "Este endereço IP encontra-se bloqueado.\nSegue, para referência, a entrada mais recente no registro de bloqueios:",
     "sp-contributions-search": "Navegar pelas contribuições",
-    "sp-contributions-suppresslog": "Contribuições de usuário suprimidas",
     "sp-contributions-username": "Endereço de IP ou usuário:",
     "sp-contributions-toponly": "Mostrar somente as edições que sejam a última alteração",
     "sp-contributions-newonly": "Mostre somente as edições que criaram uma nova página.",
     "allmessagesname": "Nome",
     "allmessagesdefault": "Texto padrão",
     "allmessagescurrent": "Texto atual",
-    "allmessagestext": "Esta é uma lista de todas as mensagens de sistema disponíveis no espaço nominal {{ns:mediawiki}}.\nAcesse [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] caso deseje contribuir para traduções do MediaWiki feitas para uso geral.",
+    "allmessagestext": "Esta é uma lista de todas as mensagens de sistema disponíveis no espaço nominal {{ns:mediawiki}}.\nAcesse [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] caso deseje contribuir para traduções do MediaWiki feitas para uso geral.",
     "allmessagesnotsupportedDB": "Esta página não pode ser utilizada, uma vez que '''$wgUseDatabaseMessages''' foi desativado.",
     "allmessages-filter-legend": "Filtro",
     "allmessages-filter": "Filtrar por estado de personalização:",
index bd9e642..6372cee 100644 (file)
     "prefs-skin": "Tema",
     "skin-preview": "Antever tema",
     "datedefault": "Sem preferência",
-    "prefs-beta": "Funcionalidades beta",
     "prefs-datetime": "Data e hora",
     "prefs-labs": "Funcionalidades dos laboratórios",
     "prefs-user-pages": "Páginas de utilizador",
     "nowatchlist": "A sua lista de páginas vigiadas está vazia.",
     "watchlistanontext": "Precisa de $1 para ver ou editar a sua lista de páginas vigiadas, por favor.",
     "watchnologin": "Não está autenticado(a)",
-    "watchnologintext": "Precisa de [[Special:UserLogin|autenticar-se]] para modificar a sua lista de páginas vigiadas.",
     "addwatch": "Adicionar às páginas vigiadas",
     "addedwatchtext": "A página \"[[:$1]]\" foi adicionada à sua [[Special:Watchlist|lista de páginas vigiadas]].\nModificações futuras desta página e da respetiva página de discussão serão listadas lá.",
     "removewatch": "Remover das páginas vigiadas",
     "sp-contributions-newbies-sub": "Para contas novas",
     "sp-contributions-newbies-title": "Contribuições de contas novas",
     "sp-contributions-blocklog": "registo de bloqueios",
+    "sp-contributions-suppresslog": "contribuições suprimidas",
     "sp-contributions-deleted": "contribuições eliminadas",
     "sp-contributions-uploads": "carregamentos",
     "sp-contributions-logs": "registos",
     "sp-contributions-blocked-notice": "Este utilizador está bloqueado neste momento.\nPara referência é apresentado abaixo o último registo de bloqueio:",
     "sp-contributions-blocked-notice-anon": "Este endereço IP está bloqueado neste momento.\nPara referência é apresentado abaixo o último registo de bloqueio:",
     "sp-contributions-search": "Pesquisar contribuições",
-    "sp-contributions-suppresslog": "contribuições suprimidas",
     "sp-contributions-username": "Endereço IP ou utilizador:",
     "sp-contributions-toponly": "Mostrar somente as revisões mais recentes",
     "sp-contributions-newonly": "Mostrar só edições que são criações de páginas",
     "allmessagesname": "Nome",
     "allmessagesdefault": "Texto padrão",
     "allmessagescurrent": "Texto atual",
-    "allmessagestext": "Esta é a lista das mensagens de sistema disponíveis no espaço nominal MediaWiki.\nSe deseja colaborar na localização genérica do MediaWiki, visite [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e a [//translatewiki.net translatewiki.net].",
+    "allmessagestext": "Esta é a lista das mensagens de sistema disponíveis no espaço nominal MediaWiki.\nSe deseja colaborar na localização genérica do MediaWiki, visite [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] e a [//translatewiki.net translatewiki.net].",
     "allmessagesnotsupportedDB": "Esta página não pode ser usada porque a <strong>$wgUseDatabaseMessages</strong> foi desativada.",
     "allmessages-filter-legend": "Filtro",
     "allmessages-filter": "Filtrar pelo estado de personalização:",
index 03fe572..939d011 100644 (file)
             "아라"
         ]
     },
+    "sidebar": "{{notranslate}}",
     "tog-underline": "[[Special:Preferences]], tab 'Misc'. Offers user a choice how to underline links. {{Gender}}",
     "tog-hideminor": "[[Special:Preferences]], tab 'Recent changes'. Offers user to hide minor edits in recent changes or not. {{Gender}}",
     "tog-hidepatrolled": "Option in Recent changes tab of [[Special:Preferences]] (if [[mw:Manual:$wgUseRCPatrol|$wgUseRCPatrol]] is enabled). {{Gender}}",
     "november-date": "A date in the Gregorian month of November. $1 is the numerical date, for example \"23\".\n{{Identical|November}}",
     "december-date": "A date in the Gregorian month of December. $1 is the numerical date, for example \"23\".",
     "pagecategories": "Used in the categories section of pages.\n\nFollowed by a colon and a list of categories.\n\nParameters:\n* $1 - number of categories",
+    "pagecategorieslink": "{{notranslate}}",
     "category_header": "In category description page. Parameters:\n* $1 - category name\nSee also:\n* {{msg-mw|Category-media-header}}",
     "subcategories": "Used as a header on category pages that have subcategories.\n{{Identical|Subcategory}}",
     "category-media-header": "In category description page. Parameters:\n* $1 - category name\nSee also:\n* {{msg-mw|Category header}}",
     "qbmyoptions": "Heading in the Cologne Blue skin user menu containing links to user (talk) page, preferences, watchlist, etc.\n{{Identical|My pages}}",
     "faq": "FAQ is short for ''frequently asked questions''.\n{{Identical|FAQ}}",
     "faqpage": "{{doc-important|Do not translate <code>Project:</code> part.}}\n\"FAQ\" is short for \"frequently asked questions\".\n\nThis page is only linked in CologneBlue (an old skin), not in Monobook or Vector.",
+    "sitetitle": "{{Ignore}}",
+    "sitesubtitle": "{{Ignore}}",
     "vector-action-addsection": "Used in the Vector skin. See for example {{canonicalurl:Talk:Main_Page|useskin=vector}}",
     "vector-action-delete": "Used in the Vector skin, as the name of a tab at the top of the page. See for example {{canonicalurl:Main_Page|useskin=vector}}\n\n{{Identical|Delete}}",
     "vector-action-move": "Used in the Vector skin, on the tabs at the top of the page. See for example {{canonicalurl:Talk:Main_Page|useskin=vector}}\n\n{{Identical|Move}}",
     "specialpage": "{{Identical|Special page}}",
     "personaltools": "Heading for a group of links to your user page, talk page, preferences, watchlist, and contributions. This heading is visible in the sidebar in some skins. For an example, see [{{canonicalurl:Main_Page|useskin=simple}} Main Page using simple skin].",
     "postcomment": "Used as link text.\n\nThe link points to the talk page and has the parameters \"action=edit&section=new\".",
+    "addsection": "{{notranslate}}\nText of the new section tab (the one next to the \"edit\" tab on non-Vector skins).\n\nSee also:\n* {{msg-mw|Addsection}}\n* {{msg-mw|Accesskey-ca-addsection}}\n* {{msg-mw|Tooltip-ca-addsection}}",
     "articlepage": "'Content page' is used for NS_MAIN and any other non-standard namespaces. Only used in the Cologne Blue skin in the bottomLinks part.\n\n{{Identical|Content page}}",
     "talk": "Used as display name for the tab to all {{msg-mw|Talk}} pages. These pages accompany all content pages and can be used for discussing the content page. Example: [[Talk:Example]].\n\nSee also:\n* {{msg-mw|Talk}}\n* {{msg-mw|Accesskey-ca-talk}}\n* {{msg-mw|Tooltip-ca-talk}}\n{{Identical|Discussion}}",
     "views": "Subtitle for the list of available views, for the current page. In \"monobook\" skin the list of views are shown as tabs, so this sub-title is not shown. For an example, see [{{canonicalurl:Main_Page|useskin=simple}} Main Page using simple skin].\n\n'''Note:''' This is \"views\" as in \"appearances\"/\"representations\", '''not''' as in \"visits\"/\"accesses\".\n{{Identical|View}}",
     "otherlanguages": "This message is shown under the toolbox. It is used if there are interwiki links added to the page, like <code><nowiki>[[</nowiki>en:Interwiki article]]</code>.\n{{Identical|Otherlanguages}}",
     "redirectedfrom": "The text displayed when a certain page is redirected to another page. Parameters:\n* $1 - the name of the page user came from",
     "redirectpagesub": "Displayed under the page title of a page which is a redirect to another page, see [{{fullurl:Project:Translators|redirect=no}} Project:Translators] for example.\n\n{{Identical|Redirect page}}",
+    "talkpageheader": "{{notranslate}}",
     "lastmodifiedat": "This message is shown below each page, in the footer with the logos and links.\n\nParameters:\n* $1 - date\n* $2 - time\nSee also:\n* {{msg-mw|Lastmodifiedatby}}",
     "viewcount": "Used as page-view counter. Parameters:\n* $1 - number of pageviews",
     "protectedpage": "This message is displayed when trying to edit a page you can't edit because it has been protected.\n\nThis message is the title for the message {{msg-mw|protectedpagetext}}.",
     "pool-timeout": "Part of {{msg-mw|view-pool-error}}.\n\nFor explanation of 'lock' see [[w:Lock_(computer_science)|wikipedia]].",
     "pool-queuefull": "Part of {{msg-mw|view-pool-error}}\n\n\"Pool\" refers to a pool of processes.",
     "pool-errorunknown": "Part of {{msg-mw|view-pool-error}}.\n{{Identical|Unknown error}}",
-    "pool-servererror": "Error message. Parameters:\n* $1 - list of server addresses",
+    "pool-servererror": "Error message. Parameters:\n* $1 - list of server addresses\n\nSee e.g. {{msg-mw|Poolcounter-desc}} (and the Pool Counter extension in general) for translation hints for “pool counter service”.",
     "aboutsite": "Used as the label of the link that appears at the footer of every page on the wiki (in most of  the skins) and leads to the page that contains the site description. The link target is {{msg-mw|aboutpage}}.\n\n[[mw:Manual:Interface/Aboutsite|MediaWiki manual]].\n\n{{doc-important|Do not change <nowiki>{{SITENAME}}</nowiki>.}}\n\n{{Identical|About}}",
     "aboutpage": "Used as the target of the link that appears at the footer of every page on the wiki (in most of  the skins) and leads to the page that contains the site description. Therefore the content should be the same with the page name of the site description page. Only the message in the [[mw:Manual:$wgLanguageCode|site language]]  ([[MediaWiki:Aboutpage]]) is used. The link label is {{msg-mw|aboutsite}}.\n\n{{doc-important|Do not translate \"Project:\" part, for this is the namespace prefix.}}",
     "copyright": "Parameters:\n* $1 - license name\n'''See also'''\n* {{msg-mw|Mobile-frontend-copyright}}",
     "disclaimers": "Used as display name for the link to [[{{MediaWiki:Disclaimerpage}}]] shown at the bottom of every page on the wiki. Example [[{{MediaWiki:Disclaimerpage}}|{{MediaWiki:Disclaimers}}]].\n{{Identical|Disclaimer}}",
     "disclaimerpage": "{{doc-important|Do not change the <code>Project:</code> part.}}\nUsed as page for that contains the site disclaimer. Used at the bottom of every page on the wiki. Example: [[{{MediaWiki:Disclaimerpage}}|{{MediaWiki:Disclaimers}}]].",
     "edithelp": "This is the text that appears on the editing help link that is near the bottom of the editing page",
+    "edithelppage": "The help page displayed when a user clicks on editing help link which is present on the right of Show changes button.\n{{doc-important|Do not change the \"<tt>Help:</tt>\" part.}}",
+    "helppage": "{{doc-important|Do not change the <code>Help:</code> part.}}\nThe link destination used by default in the sidebar, and in {{msg-mw|Noarticletext}}.",
     "mainpage": "Defines the link and display name of the main page of the wiki. Shown as the top link in the navigation part of the interface. Please do not change it too often, that could break things!\n\nSee also:\n* {{msg-mw|Mainpage}}\n* {{msg-mw|Accesskey-n-mainpage}}\n* {{msg-mw|Tooltip-n-mainpage}}\n{{Identical|Main page}}",
     "mainpage-description": "The same as {{msg-mw|mainpage}}, used as link text on [[MediaWiki:Sidebar]].\n\nThis makes it possible to the change the link destination (the message \"mainpage\") without changing the link text or without disabling translations.\n\nSee also:\n* {{msg-mw|Mainpage-description}}\n* {{msg-mw|Accesskey-n-mainpage-description}}\n* {{msg-mw|Tooltip-n-mainpage-description}}\n{{Identical|Main page}}",
     "policy-url": "{{doc-important|Do not change the <code>Project:</code> part.}}\nThe URL of the project page describing the policies of the wiki.\n\nThis is shown below every page (the left link).",
     "newmessageslinkplural": "This is the first link displayed in an orange rectangle when a user gets a message on their talk page.\n\nUsed as <code>$1</code> in the following messages:\n* {{msg-mw|youhavenewmessagesfromusers}}\n* {{msg-mw|youhavenewmessagesmanyusers}}\n* {{msg-mw|youhavenewmessages}}.\nParameters:\n* $1 - 1 or 999:\n** 1 - if there was '''one''' new edit since the last time the user has seen their talk page\n** 999 - if there was '''more than one''' new edit since the last time the user has seen their talk page\n{{Identical|New messages}}",
     "newmessagesdifflinkplural": "This is the second link displayed in an orange rectangle when a user gets a message on his talk page.\n\nUsed as <code>$2</code> in messages {{msg-mw|youhavenewmessagesfromusers}}, {{msg-mw|youhavenewmessagesmanyusers}}, {{msg-mw|youhavenewmessages}}.\n\nParameters:\n* $1 - 1 or 999:\n** 1 - if there was '''one''' new edit since the last time the user has seen their talk page\n** 999 - if there was '''more than one''' new edit since the last time the user has seen their talk page\n{{Identical|Last change}}",
     "youhavenewmessagesmulti": "The alternative of {{msg-mw|youhavenewmessages}} as used on wikis with a special setup so they can receive the \"new message\" notice on other wikis as well. Used on [http://www.wikia.com/ Wikia].\n\nThe format is: \"{{int:youhavenewmessagesmulti| [[MediaWiki:Newmessageslinkplural/{{SUBPAGENAME}}|{{int:newmessageslinkplural}}]]}}\"\n\nParameters:\n* $1 - a link points to new messages. Its text is {{msg-mw|Newmessageslinkplural}}",
+    "newtalkseparator": "{{notranslate}}",
     "editsection": "Display name of link to edit a section on a content page. Example: [{{MediaWiki:Editsection}}].\n\n{{Identical|Edit}}",
     "editold": "{{Identical|Edit}}",
     "viewsourceold": "{{Identical|View source}}",
     "page-atom-feed": "Parameters:\n* $1 - page title\nSee also:\n* {{msg-mw|Page-rss-feed}}\n{{Identical|S1 RSS/Atom feed}}",
     "feed-atom": "{{optional}}\nSee also:\n* {{msg-mw|Feed-atom}}\n* {{msg-mw|Accesskey-feed-atom}}\n* {{msg-mw|Tooltip-feed-atom}}",
     "feed-rss": "{{optional}}\nSee also:\n* {{msg-mw|Feed-rss}}\n* {{msg-mw|Accesskey-feed-rss}}\n* {{msg-mw|Tooltip-feed-rss}}",
+    "sitenotice": "{{Notranslate}}\n\nMediaWiki:Sitenotice is displayed above the page title for all users if it is defined, unless it is superseded by another notice. 'Defined' means it exists and has content other than the single character '-'.\n\nManual: [[mw:Manual:Interface/Sitenotice]]",
+    "anonnotice": "{{notranslate}}",
+    "newsectionheaderdefaultlevel": "{{notranslate}}\nParameters:\n* $1 - section name",
     "red-link-title": "Title for red hyperlinks. Indicates, that the page is empty, not written yet.\n\nParameters:\n* $1 - page title",
     "sort-descending": "JavaScript message. Used by sortable table script.",
     "sort-ascending": "JavaScript message. Used by sortable table script.",
     "nstab-template": "The name for the tab of the template namespace. Example: [[Template:Example]]\n\nSee also:\n* {{msg-mw|Nstab-template}}\n* {{msg-mw|Accesskey-ca-nstab-template}}\n* {{msg-mw|Tooltip-ca-nstab-template}}\n{{Identical|Template}}",
     "nstab-help": "The name for the tab of the help namespace. Example: [[Help:Rollback]]\n\nSee also:\n* {{msg-mw|Nstab-help}}\n* {{msg-mw|Accesskey-ca-nstab-help}}\n* {{msg-mw|Tooltip-ca-nstab-help}}",
     "nstab-category": "The name for the tab of the category namespace. Example: [[:Category:Example]]\n\nSee also:\n* {{msg-mw|Nstab-category}}\n* {{msg-mw|Accesskey-ca-nstab-category}}\n* {{msg-mw|Tooltip-ca-nstab-category}}\n{{Identical|Category}}",
+    "mainpage-nstab": "{{notranslate}}",
     "nosuchaction": "The title of the error you get when trying to open a page with invalid \"action\" parameter. The text of the warning is the message {{msg-mw|nosuchactiontext}}.\n\nSee example [{{canonicalurl:Main_page|action=x}} action=x].",
     "nosuchactiontext": "This error is shown when trying to open a page with invalid \"action\" parameter, e.g. [{{canonicalurl:Main_page|action=x}} action=x].\n* The title of this error is the message {{msg-mw|nosuchaction}}.",
     "nosuchspecialpage": "The title of the error you get when trying to open a special page which does not exist. The text of the warning is the message {{msg-mw|nospecialpagetext}}. Example: [[Special:Nosuchpage]]",
     "userlogin-yourname": "In user login & create account forms, label for username field.\n{{doc-important|<nowiki>{{</nowiki>[[Gender|GENDER]]<nowiki>}}</nowiki> is '''NOT''' supported.}}\n\nSee examples: [[Special:UserLogin]] and [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]\n{{Identical|Username}}",
     "userlogin-yourname-ph": "Placeholder text in login & create account form field.\n\nSee example: [[Special:UserLogin]] and [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]",
     "createacct-another-username-ph": "Placeholder text in create account form field when one user creates an account for another.",
+    "createacct-helpusername": "Message in new create account form providing guidance for username.\n\nRefers to {{msg-mw|createacct-helpusername-url}}.",
     "yourpassword": "In user preferences\n\n{{Identical|Password}}",
     "userlogin-yourpassword": "In login & create account forms, label for password field.\n\nSee examples: [[Special:UserLogin]] and [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]\n{{Identical|Password}}",
     "userlogin-yourpassword-ph": "Placeholder text in login form for password field.\n\nSee examples: [[Special:UserLogin]] and [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]\n{{Identical|Enter password}}",
     "gotaccountlink": "Since 1.22 no longer used in core, but may be used by some extensions. DEPRECATED.\n{{Identical|Log in}}",
     "userlogin-resetlink": "Since 1.22 no longer used in core, but may be used by some extensions. DEPRECATED.",
     "userlogin-resetpassword-link": "Used as link text in the login form.\n\nThe link points to the local page [[Special:PasswordReset]].\n\nSee example: [[Special:UserLogin]]\n\nuserlogin-resetpassword-link may have to be shorter than the old {{msg-mw|userlogin-resetlink}}.\n{{Identical|Forgot your password}}",
+    "helplogin-url": "{{doc-important|Do not translate the namespace name <code>Help</code>.}}\nUsed as name of the page that provides information about logging into the wiki.\n\nUsed as a link target in the message {{msg-mw|Userlogin-helplink}}.",
     "userlogin-helplink2": "Label for a link to login help.\n\nSee example: [[Special:UserLogin]]\n\nSee also:\n* {{msg-mw|Helplogin-url}}",
     "userlogin-loggedin": "Used as warning on [[Special:UserLogin]] when the current user is already logged in.\n\nFollowed by the Login form.\n\nSee example: [[Special:UserLogin]].\n\nParameters:\n* $1 - user name (used for display and for gender support)",
     "userlogin-createanother": "Used as label for the button on [[Special:UserLogin]] shown when the current user is already logged in.\n{{Identical|Create another account}}",
     "createacct-reason": "In create account form, label for field to enter reason to create an account when already logged-in.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]\n{{Identical|Reason}}",
     "createacct-reason-ph": "Placeholder in vertical-layout create account form for reason field.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]",
     "createacct-captcha": "Label in vertical-layout create account form for CAPTCHA input field when repositioned by JavaScript.",
+    "createacct-imgcaptcha-help": "Help text in vertical-layout create account form for image CAPTCHA input field when repositioned by JavaScript.\n\nRefers to {{msg-mw|Createacct-captcha-help-url}}.",
     "createacct-imgcaptcha-ph": "Placehodler text in vertical-layout create account form for image CAPTCHA input field when repositioned by JavaScript.",
     "createacct-submit": "Submit button on vertical-layout create account form.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]",
     "createacct-another-submit": "Submit button of  [[Special:UserLogin/signup]] ([[Special:CreateAccount]]) when accessed by a registered user.\n\nThe original means \"create an account in addition to the one you already have\"; sometimes, but not always, it means you are going to \"Create the account on behalf of somebody else\" or \"Create account for another\".\n{{Identical|Create another account}}",
     "createacct-benefit-heading": "In vertical-layout create account form, the heading for the section describing the benefits of creating an account. See example: [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]\n\nIf in your language you need to know the gender of the name for the wiki (which is the subject of the English sentence), please adapt the sentence as much as you need for your translation to fit.",
+    "createacct-benefit-icon1": "In vertical-layout create account form, the CSS style for the div next to the first benefit. If you replace this you will need probably need to adjust CSS.\n\nUsed as a CSS class name.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup&useNew=1}} Special:UserLogin?type=signup&useNew=1]",
+    "createacct-benefit-head1": "In vertical-layout create account form, the text in the heading for the first benefit. Do not edit the magic word; if you replace it you will probably need to adjust CSS.\n\nFollowed by the message {{msg-mw|Createacct-benefit-body1}}.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup&useNew=1}} Special:UserLogin?type=signup&useNew=1]",
     "createacct-benefit-body1": "In vertical-layout create account form, the text for the first benefit.\n\nPreceded by the message {{msg-mw|Createacct-benefit-head1}} (number of edits).\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]\n\nParameters:\n* $1 - number of edits\n{{Identical|Edit}}",
+    "createacct-benefit-icon2": "In vertical-layout create account form, the CSS style for the div next to the second benefit. If you replace this you will need probably need to adjust CSS.\n\nUsed as a CSS class name.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup&useNew=1}} Special:UserLogin?type=signup&useNew=1]",
+    "createacct-benefit-head2": "In vertical-layout create account form, the text in the heading for the second benefit. Do not edit the magic word; if you replace it you will probably need to adjust CSS.\n\nFollowed by the message {{msg-mw|Createacct-benefit-body2}}.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup&useNew=1}} Special:UserLogin?type=signup&useNew=1]",
     "createacct-benefit-body2": "In vertical-layout create account form, the text for the second benefit.\n\nPreceded by the message {{msg-mw|Createacct-benefit-head2}} (number of pages).\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]\n\nParameters:\n* $1 - number of pages\n{{Identical|Page}}",
+    "createacct-benefit-icon3": "In vertical-layout create account form, the CSS style for the div next to the third benefit. If you replace this you will need probably need to adjust CSS.\n\nUsed as a CSS class name.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup&useNew=1}} Special:UserLogin?type=signup&useNew=1]",
+    "createacct-benefit-head3": "In vertical-layout create account form, the text in the heading for the third benefit. Do not edit the magic word; if you replace it you will probably need to adjust CSS.\n\nFollowed by the message {{msg-mw|Createacct-benefit-body3}}.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup&useNew=1}} Special:UserLogin?type=signup&useNew=1]",
     "createacct-benefit-body3": "In vertical-layout create account form, the text for the third benefit.\n\nPreceded by the message {{msg-mw|Createacct-benefit-head3}} (number of contributors).\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]\n\nParameters:\n* $1 - number of contributors (users)",
     "badretype": "Used as error message when the new password and its retype do not match.",
     "userexists": "Used as error message in creating a user account.",
     "blocked-mailpassword": "Used as error message in password recovery.",
     "eauthentsent": "This message appears after entering an email address in [[Special:Preferences]] > {{int:prefs-personal}} > {{int:email}}, then clicking on \"{{int:saveprefs}}\".",
     "throttled-mailpassword": "Used in [[Special:PasswordReset]]. Parameters:\n* $1 - password reset email resend time (in hours)",
+    "loginstart": "{{notranslate}}",
+    "loginend": "{{notranslate}}",
+    "loginend-https": "{{notranslate}}",
+    "signupstart": "{{notranslate}}\nDefault:\n* {{msg-mw|Loginstart}}",
+    "signupend": "{{notranslate}}\nDefault:\n* {{msg-mw|Loginend}}",
+    "signupend-https": "{{notranslate}}",
     "mailerror": "Used as error message in sending confirmation mail to user. Parameters:\n* $1 - new mail address",
     "acct_creation_throttle_hit": "Error message at [[Special:CreateAccount]].\n\n\"in the last day\" precisely means: during the lasts 86400 seconds (24 hours) ending right now.\n\nParameters:\n* $1 - number of accounts",
     "emailauthenticated": "In user preferences ([[Special:Preferences]] > {{int:prefs-personal}} > {{int:email}}) and on [[Special:ConfirmEmail]].\n\nParameters:\n* $1 - (Unused) obsolete, date and time\n* $2 - date\n* $3 - time",
     "invalidemailaddress": "Shown as a warning when written an invalid email address in [[Special:Preferences]] and {{fullurl:Special:UserLogin|type=signup}} page",
     "cannotchangeemail": "Error message shown when user goes to [[Special:ChangeEmail]] but email addresses cannot be changed on the site.",
     "emaildisabled": "Error message shown when user tries to set an email address but email features are disabled.",
+    "emailsender": "{{optional}}",
     "accountcreated": "Used as page title in [[Special:UserLogin]].\n\nSee also:\n* {{msg-mw|Accountcreated|title}}\n* {{msg-mw|Accountcreatedtext|message}}",
     "accountcreatedtext": "Used in [[Special:UserLogin]]. Parameters:\n* $1 - username\nSee also:\n* {{msg-mw|Accountcreated|title}}\n* {{msg-mw|Accountcreatedtext|message}}",
     "createaccount-title": "Subject of the email sent to the email address entered at [[Special:CreateAccount]] when one user creates an account for another and clicks the checkbox labelled {{msg-mw|Createaccountmail}}.",
     "login-throttled": "Error message shown at [[Special:UserLogin]] after the user has tried to login with incorrect password too many times.\n\nThe user has to wait a certain time before trying to log in again.\n\nParameters:\n* $1 - the time to wait before the next login attempt. Automatically formatted using the following duration messages:\n** {{msg-mw|Duration-millennia}}\n** {{msg-mw|Duration-centuries}}\n** {{msg-mw|Duration-decades}}\n** {{msg-mw|Duration-years}}\n** {{msg-mw|Duration-weeks}}\n** {{msg-mw|Duration-days}}\n** {{msg-mw|Duration-hours}}\n** {{msg-mw|Duration-minutes}}\n** {{msg-mw|Duration-seconds}}\n\nThis is a protection against robots trying to find the password by trying lots of them.\nThe number of attempts and waiting time are configured via [[mw:Manual:$wgPasswordAttemptThrottle|$wgPasswordAttemptThrottle]].\nThis message is used in html.\n{{identical|Login throttled}}",
     "login-abort-generic": "The generic unsuccessful login message is used unless otherwise specified by hook writers",
     "loginlanguagelabel": "Used on [[Special:UserLogin]] if $wgLoginLanguageSelector is true. Parameters:\n* $1 - a pipe-separated list built from the names that appear in the message {{msg-mw|Loginlanguagelinks}}.\n{{Identical|Language}}",
+    "loginlanguagelinks": "{{notranslate}}",
     "suspicious-userlogout": "Used when the logout request looks suspicious, in Special:UserLogout.",
     "createacct-another-realname-tip": "{{doc-singularthey}}\nUsed on the account creation form when creating another user's account. Similar to {{msg-mw|prefs-help-realname}}.\n{{Identical|Real name attribution}}",
     "pt-login": "Shown to anonymous users in the upper right corner of the page when they can't create an account (otherwise the message {{msg-mw|nav-login-createaccount}} is shown there).\n{{Identical|Log in}}",
     "pt-login-button": "Shown as the caption of the button at [[Special:UserLogin]].\n{{Identical|Log in}}",
     "pt-createaccount": "Used on the top of the page for logged out users, where it appears next to {{msg-mw|login}}, so consider making them similar.\n{{Identical|Create account}}",
     "pt-userlogout": "{{Doc-actionlink}}\n{{Identical|Log out}}",
+    "pear-mail-error": "{{notranslate}}\nParameters:\n* $1 - error message which is returned by PEAR mailer.",
+    "php-mail-error": "{{notranslate}}\nParameters:\n* $1 - error message",
     "php-mail-error-unknown": "Used as error message when <code>mail()</code> returned empty error message.",
     "user-mail-no-addy": "This is the error message in case an email could not be sent because there was no email address to send it to.",
     "user-mail-no-body": "This is the error message in case an email has an empty or unreasonably short body.",
     "accmailtext": "{{doc-important|Do not translate <code><nowiki>[[User talk:$1|$1]]</nowiki></code> and <code>Special:ChangePassword</code>.}}\nThe message shown when a temporary password has been sent to the user's email address.\n\nParameters:\n* $1 - username\n* $2 - email address",
     "newarticle": "{{Identical|New}}",
     "newarticletext": "Text displayed above the edit box in editor when trying to create a new page.\nParameters:\n* $1 - The URL to the help page, defined in {{msg-mw|helppage}}",
+    "newarticletextanon": "{{notranslate}}\nDefault:\n* {{msg-mw|Newarticletext}}",
+    "talkpagetext": "{{notranslate}}",
     "anontalkpagetext": "Displayed at the bottom of talk pages of anonymous users.",
     "noarticletext": "This is the message that you get if you search for a term that has not yet got any entries on the wiki.\n\nSee also:\n* {{msg-mw|Noarticletext-nopermission}}",
     "noarticletext-nopermission": "See also {{msg-mw|Noarticletext}}.",
+    "noarticletextanon": "{{notranslate}}\nDefault:\n* {{msg-mw|Noarticletext}}",
     "missing-revision": "Text displayed when the requested revision does not exist using a permalink.\n\nExample: [{{canonicalurl:Project:News|oldid=9999999}} Permalink with invalid revision#]\n\nParameters:\n* $1 - the ID of the missing revision",
     "userpage-userdoesnotexist": "Error message displayed when trying to edit or create a page or a subpage that belongs to a user who is not registered on the wiki.\n\nParameters:\n* $1 - a possible username that has not been registered",
     "userpage-userdoesnotexist-view": "Shown in user pages of non existing users. See for example [{{canonicalurl:User:Foo}} User:Foo].\n\nParameters:\n* $1 - a username",
     "yourdiff": "",
     "copyrightwarning": "Copyright warning displayed under the edit box in editor. Parameters:\n* $1 - link\n* $2 - license name",
     "copyrightwarning2": "Copyright warning displayed under the edit box in editor\n*$1 - license name",
+    "editpage-tos-summary": "{{notranslate}}",
+    "longpage-hint": "{{notranslate}}\n* <tt>$1</tt>: Size of the textbox formatted for output, using an appropriate unit ({{msg-mw|size-bytes}}, {{msg-mw|size-kilobytes}}, {{msg-mw|size-megabytes}}, {{msg-mw|size-gigabytes}})\n* <tt>$2</tt>: Size of the textbox in bytes, not formatnum",
     "longpageerror": "Warning displayed when trying to save a text larger than the maximum size allowed.\n\nParameters:\n* $1 - submitted size (in kilobytes)\n* $2 - maximum size (in kilobytes)",
     "readonlywarning": "Parameters:\n* $1 - reason",
     "protectedpagewarning": "{{Related|Semiprotectedpagewarning}}",
     "edit-no-change": "Used as error message.\n\nSee also:\n* {{msg-mw|edit-hook-aborted}}\n* {{msg-mw|edit-gone-missing}}\n* {{msg-mw|edit-conflict}}\n* {{msg-mw|edit-already-exists}}",
     "postedit-confirmation": "{{gender}}\nConfirmation message that is displayed upon successful edit.\n\nParameters:\n* $1 - (Optional) the current user, for GENDER support",
     "edit-already-exists": "Used as error message.\n\nSee also:\n* {{msg-mw|edit-hook-aborted}}\n* {{msg-mw|edit-gone-missing}}\n* {{msg-mw|edit-conflict}}\n* {{msg-mw|edit-no-change}}",
+    "addsection-preload": "{{notranslate}}",
+    "addsection-editintro": "{{notranslate}}",
     "defaultmessagetext": "Caption above the default message text shown on the left-hand side of a diff displayed after clicking \"Show changes\" when creating a new page in the MediaWiki: namespace",
     "content-failed-to-parse": "Error message indicating that the page's content can not be saved because it is syntactically invalid. This may occurr for content types using serialization or a strict markup syntax.\n\nParameters:\n* $1 – content model, any one of the following messages:\n** {{msg-mw|Content-model-wikitext}}\n** {{msg-mw|Content-model-javascript}}\n** {{msg-mw|Content-model-css}}\n** {{msg-mw|Content-model-text}}\n* $2 – content format as MIME type (e.g. <code>text/css</code>)\n* $3 – specific error message",
     "invalid-content-data": "Error message indicating that the page's content can not be saved because it is invalid. This may occurr for content types with internal consistency constraints.",
     "cantcreateaccounttitle": "Used as title of the error message {{msg-mw|Cantcreateaccount-text}}.",
     "cantcreateaccount-text": "Used as error message, with the title {{msg-mw|Cantcreateaccounttitle}}.\n* $1 - target IP address\n* $2 - reason or {{msg-mw|Blockednoreason}}\n* $3 - username\nSee also:\n* {{msg-mw|Cantcreateaccount-range-text}}",
     "cantcreateaccount-range-text": "Used as more detailed version of the {{msg-mw|Cantcreateaccount-text}} error message, with the title {{msg-mw|Cantcreateaccounttitle}}.\n* $1 - target IP range\n* $2 - reason or {{msg-mw|Blockednoreason}}\n* $3 - username\n* $4 - current user's IP address",
+    "createaccount-hook-aborted": "Placeholder message to return with API errors on account create; passes through the message from a hook {{notranslate}}",
     "viewpagelogs": "Link displayed in history of pages",
     "nohistory": "Message shown when there are no history to list. See [{{canonicalurl:x|action=history}} example history].\n----\nAlso used as title of error message when the feed is empty. See [{{canonicalurl:x|action=history&feed=atom}} example feed].\n\nSee the error message:\n* {{msg-mw|history-feed-empty}}",
     "currentrev": "Used in Diff Preview page. The diff is between {{msg-mw|currentrev}} and {{msg-mw|yourtext}}.\n{{Identical|Current revision}}",
     "currentrev-asof": "Used on a difference page when comparing the current versions of a page with each other.\n\nSee {{msg-mw|Revisionasof}} for the message for non-current version.\n\nParameters:\n* $1 - a date and time\n* $2 - (Optional) a date\n* $3 - (Optional) a time",
     "revisionasof": "Used on a difference page when comparing different versions of a page or when viewing an non-current version of a page.\n\nSee {{msg-mw|Currentrev-asof}} for the message for the current version.\n\nParameters:\n* $1 - the date/time at which the revision was created. e.g. \"''Revision as of 14:44, 24 January 2008''\".\n* $2 - (Optional) the date at which the revision was created\n* $3 - (Optional) the time at which the revision was created",
     "revision-info": "Appears just below the page title when an old version of the page is being viewed.\n\nParameters:\n* $1 - date and time of revision\n* $2 - a series of links: to author of the revision, his talk page, etc.\n* $3 - (Optional) revision ID\n* $4 - (Optional) date of revision\n* $5 - (Optional) time of revision\n* $6 - (Optional) author of revision, for GENDER use",
+    "revision-info-current": "{{notranslate}}\n* $1: date and time of revision\n* $2: a series of links: to author of the revision, his talk page, etc. \n* (optional) $3: revision ID\n* (optional) $4: date of revision\n* (optional) $5: time of revision\n* (optional) $6: author of revision, for GENDER use",
+    "revision-nav": "{{notranslate}}\nRefers to {{msg-mw|Pipe-separator}}.\n\nParameters:\n* $1 - prev diff. link text is {{msg-mw|Diff}}\n* $2 - prev link. link text is {{msg-mw|Previousrevision}}\n* $3 - link. link text is {{msg-mw|Currentrevisionlink}}\n* $4 - cur diff. link text is {{msg-mw|Diff}}\n* $5 - next link. link text is {{msg-mw|Nextrevision}}\n* $6 - next diff. link text is {{msg-mw|Diff}}",
     "previousrevision": "See also:\n* {{msg-mw|Nextrevision}}",
     "nextrevision": "See also:\n* {{msg-mw|Previousrevision}}",
     "currentrevisionlink": "{{Identical|Current revision}}",
     "histlegend": "Text in history page.\n\nSee also:\n* {{msg-mw|Cur}}\n* {{msg-mw|Last}}\n* {{msg-mw|Minoreditletter}}",
     "history-fieldset-title": "Fieldset label in the edit history pages.",
     "history-show-deleted": "CheckBox to show only per [[mw:Manual:RevisionDelete|RevisonDelete]] deleted versions.\n\nUsed in History and [[Special:Contributions]].",
+    "history_copyright": "{{notranslate}}",
     "histfirst": "This is part of the navigation message on the top and bottom of Page History pages which are lists of things in date order, e.g. [{{canonicalurl:Support|action=history}} Page History of Support].\n\nIt is followed by the message {{msg-mw|Viewprevnext}}.\n{{Identical|Oldest}}",
     "histlast": "This is part of the navigation message on the top and bottom of Page History pages which are lists of things in date order, e.g. [{{canonicalurl:Support|action=history}} Page History of Support].\n\nIt is followed by the message {{msg-mw|Viewprevnext}}.\n{{Identical|Newest}}",
     "historysize": "Parameters:\n* $1 - byte count, for PLURAL support",
     "viewprevnext": "This is part of the navigation message on the top and bottom of Special pages which are lists of things, e.g. the User's contributions page (in date order) or the list of all categories (in alphabetical order). ($1) and ($2) are either {{msg-mw|Pager-older-n}} and {{msg-mw|Pager-newer-n}} (for date order) or {{msg-mw|Prevn}} and {{msg-mw|Nextn}} (for alphabetical order).\n\nIt is also used by [[Special:WhatLinksHere|Whatlinkshere]] pages, where ($1) and ($2) are {{msg-mw|Whatlinkshere-prev}} and {{msg-mw|Whatlinkshere-next}}.\n($3) is made up in all cases of the various proposed numbers of results per page, e.g. \"(20 | 50 | 100 | 250 | 500)\".\nFor Special pages, the navigation bar is prefixed by \"({{msg-mw|Page first}} | {{msg-mw|Page last}})\" (alphabetical order) or \"({{msg-mw|Histfirst}} | {{msg-mw|Histlast}})\" (date order).\n\nViewprevnext is sometimes preceded by the {{msg-mw|Showingresults}} or {{msg-mw|Showingresultsnum}} message (for Special pages) or by the {{msg-mw|Linkshere}} message (for Whatlinkshere pages).\n\nRefers to {{msg-mw|Pipe-separator}}.",
     "searchmenu-exists": "An option shown in a menu beside search form offering a link to the existing page having the specified title (when using the default MediaWiki search engine).\n\nParameters:\n* $1 - page title\n* $2 - the number of search results found",
     "searchmenu-new": "An option shown in a menu beside search form offering a red link to the not yet existing page having the specified title (when using the default MediaWiki search engine).\n\nParameters:\n* $1 - page title\n* $2 - the number of search results found",
+    "searchmenu-new-nocreate": "{{notranslate}}",
     "searchprofile-articles": "A quick link in the advanced search box on [[Special:Search]]. Clicking on this link starts a search in the content pages of the wiki.\n\nA 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For technical definition of 'content namespaces' see [[mw:Manual:Using_custom_namespaces#Content_namespaces|MediaWiki]].\n\nPossible alternatives to the word 'content' are 'subject matter' or 'wiki subject' or 'wiki purpose'.\n\n{{Identical|Content page}}",
     "searchprofile-project": "Used as an option in [[Special:Search]].\n\nSee also:\n* {{msg-mw|Searchprofile-project|message}}\n* {{msg-mw|Searchprofile-project-tooltip|tooltip}}",
     "searchprofile-images": "An option in the [[Special:Search]].\n\nSee also:\n* {{msg-mw|Searchprofile-images|message}}\n* {{msg-mw|Searchprofile-images-tooltip|tooltip}}\n{{Identical|Muitimedia}}",
     "search-suggest": "Used for \"Did you mean\" suggestions:\n* $1 - suggested link",
     "search-interwiki-caption": "Used in [[Special:Search]], when showing search results from other wikis.",
     "search-interwiki-default": "Parameters:\n* $1 - the hostname of the remote wiki from where the additional results listed below are returned",
+    "search-interwiki-custom": "#REDIRECT [[MediaWiki:Wmf-search-interwiki-custom/qqq]]",
     "search-interwiki-more": "{{Identical|More}}",
     "search-relatedarticle": "This is a search result (and I guess search engine) dependent messages. I do not know how to trigger the feature. The message is displayed if the search result contains information that related pages can also be provided from the search engine. I assume this is \"More Like This\" functionality. Microsoft glossary defines MLT as \"A way to refine search by identifying the right set of documents and then locating similar documents. This allows the searcher to control the direction of the search and focus on the most fruitful lines of inquiry.\"[http://www.microsoft.com/enterprisesearch/en/us/search-glossary.aspx]\n{{Identical|Related}}",
     "searcheverything-enable": "Used in [[Special:Preferences]], tab \"Search\".",
     "powersearch-togglenone": "\"None\" refers to namespaces. It is used in Advanced search: {{canonicalurl:Special:Search|advanced=1}}\n{{Identical|None}}",
     "search-external": "Legend of the fieldset for the input form when the internal search is disabled. Inside the fieldset [[MediaWiki:Searchdisabled]] and [[MediaWiki:Googlesearch]] is shown.",
     "searchdisabled": "{{doc-singularthey}}\nIn this sentence, \"their indexes\" refers to \"Google's indexes\".\n\nShown on [[Special:Search]] when the internal search is disabled.",
+    "googlesearch": "{{notranslate}}\nShown when [[mw:Manual:$wgDisableTextSearch|$wgDisableTextSearch]] is set to true and no [[mw:Manual:$wgSearchForwardUrl|$wgSearchForwardUrl]] is set.\n\nParameters:\n* $1 - the search term\n* $2 - \"UTF-8\" (hard-coded)\n* $3 - the message {{msg-mw|Searchbutton}}",
     "search-error": "Shown when an error has occurred when performing a search. Parameters:\n* $1 - the localized error that was returned",
     "preferences": "Title of the [[Special:Preferences]] page.\n{{Identical|Preferences}}",
     "mypreferences": "Action link label that leads to [[Special:Preferences]]; appears in the top menu (e.g. \"Username Talk Preferences Watchlist Contributions Log out\").\n\nSee also:\n* {{msg-mw|Mypreferences}}\n* {{msg-mw|Accesskey-pt-preferences}}\n* {{msg-mw|Tooltip-pt-preferences}}\n{{Identical|Preferences}}",
     "prefs-skin": "Used in user preferences.\n{{Identical|Skin}}",
     "skin-preview": "{{doc-actionlink}}\nThe link beside each skin name in [[Special:Preferences|your user preferences]], tab \"skin\".\n{{Identical|Preview}}",
     "datedefault": "Used as checkbox label in [[Special:Preferences#mw-prefsection-datetime|user preferences]], {{msg-mw|prefs-datetime}} tab.\n\nThis message indicates {{msg-mw|prefs-dateformat}} is default (= not specified).",
-    "prefs-beta": "Header of a subsection at [[Special:Preferences]], tab ''{{int:prefs-editing}}'', listing features that are in beta but mostly suitable for general use.\n{{Identical|Beta feature}}",
     "prefs-datetime": "{{Identical|Date}}",
     "prefs-labs": "Header of a subsection at [[Special:Preferences]], tab ''{{int:prefs-editing}}'', listing features that are experimental",
     "prefs-user-pages": "Header of a subsection at [[Special:Preferences]], tab ''{{int:prefs-misc}}'', listing features that are related to user pages",
     "enhancedrc-since-last-visit": "Appears on enhanced watchlist and recent changes when page has more than one change on given date and at least one that the user hasn't seen yet, linking to a diff of the unviewed changes.\n\nParameters:\n* $1 - the number of unviewed changes (1 or more)\nThree messages are shown side-by-side: ({{msg-mw|nchanges}} | {{msg-mw|enhancedrc-since-last-visit}} | {{msg-mw|enhancedrc-history}}).",
     "enhancedrc-history": "Appears on enhanced watchlist and recent changes when page has more than one change on given date, linking to its history.\n\nThis is the same as {{msg-mw|hist}}, but not abbreviated.\n\nThree messages are shown side-by-side: ({{msg-mw|nchanges}} | {{msg-mw|enhancedrc-since-last-visit}} | {{msg-mw|enhancedrc-history}}).\n{{Identical|History}}",
     "recentchanges": "The text of the link in sidebar going to the special page [[Special:RecentChanges]]. Also the page title of that special page.\n\nSee also:\n* {{msg-mw|Recentchanges}}\n* {{msg-mw|Accesskey-n-recentchanges}}\n* {{msg-mw|Tooltip-n-recentchanges}}\n{{Identical|Recent changes}}",
+    "recentchanges-url": "{{notranslate}}",
     "recentchanges-legend": "Legend of the fieldset of [[Special:RecentChanges]]",
     "recentchanges-summary": "Summary of [[Special:RecentChanges]].",
+    "recentchangestext": "Text in [[Special:RecentChanges]]",
     "recentchanges-noresult": "Used in [[Special:RecentChanges]], [[Special:RecentChangesLinked]], and [[Special:Watchlist]] when there are no changes to be shown.",
     "recentchanges-feed-description": "Used in feed of RecentChanges. See example [{{canonicalurl:Special:RecentChanges|feed=atom}} feed].",
     "recentchanges-label-newpage": "# Used as tooltip for {{msg-mw|Newpageletter}}.\n# Also used as legend. Preceded by {{msg-mw|Newpageletter}} and followed by {{msg-mw|Recentchanges-legend-newpage}}.",
     "newpageletter": "Very short form of \"'''new page'''\". Used in [[Special:RecentChanges]], [[Special:Watchlist]] and [[Special:Contributions]].",
     "boteditletter": "Abbreviation of \"'''bot'''\". Appears in [[Special:RecentChanges]] and [[Special:Watchlist]].",
     "unpatrolledletter": "{{optional}}\n\nUsed in {{msg-mw|Recentchanges-label-legend}}, meaning \"unpatrolled\".",
+    "number_of_watching_users_RCview": "{{notranslate}}\nParameters:\n* $1 - number of users who are watching",
     "number_of_watching_users_pageview": "Used if <code>$wgPageShowWatchingUsers</code> is true.\n* $1 - number of watching user(s)",
     "rc_categories": "Probably to do with 'recent changes' special page, either in a particular skin, or for a particular user group.\n\nI guess that this should appear before an input box where you can specify that recent changes should be shown for pages belonging to certain categories only. You name the categories in the input box, and separate them by a pipe character. If this is right, then you should be able to use 'restrict' instead of 'limit', or even 'show pages in the following categories only'.",
     "rc_categories_any": "Used in the CategoryFilter form on [[Special:RecentChanges]], if <code>$wgAllowCategorizedRecentChanges</code> is true.\n{{Identical|Any}}",
     "upload-permitted": "Used in [[Special:Upload]]. Parameters:\n* $1 - list of file types, defined in the variable [[mw:Special:MyLanguage/Manual:$wgFileExtensions|$wgFileExtensions]]\nSee also:\n* {{msg-mw|Upload-preferred}}\n* {{msg-mw|Upload-prohibited}}",
     "upload-preferred": "Used in [[Special:Upload]]. Parameters:\n* $1 - list of file types, defined in the variable [[mw:Special:MyLanguage/Manual:$wgFileExtensions|$wgFileExtensions]]\nSee also:\n* {{msg-mw|Upload-permitted}}\n* {{msg-mw|Upload-prohibited}}",
     "upload-prohibited": "Used in [[Special:Upload]]. Parameters:\n* $1 - list of file types, defined in the variable [[mw:Special:MyLanguage/Manual:$wgFileBlacklist|$wgFileBlacklist]]\nSee also:\n* {{msg-mw|Upload-permitted}}\n* {{msg-mw|Upload-preferred}}",
+    "uploadfooter": "{{notranslate}}",
     "uploadlogpage": "{{doc-logpage}}\n\nPage title of [[Special:Log/upload]].",
     "uploadlogpagetext": "Appears on top of [[Special:Log/upload]].",
     "filename": "{{Identical|Filename}}",
     "license": "This appears in the upload form for the license drop-down. The header in the file description page is now at {{msg-mw|License-header}}.\n{{Identical|Licensing}}",
     "license-header": "Used as section header in [[Special:Upload]].\n\nSee also:\n* {{msg-mw|Filedesc}}\n* {{msg-mw|Filestatus}}\n* {{msg-mw|Filesource}}\n{{Identical|Licensing}}",
     "nolicense": "{{Identical|None selected}}",
+    "licenses": "{{notranslate}}",
     "license-nopreview": "Error message when a certain license does not exist",
     "upload_source_url": "Used in [[Special:Upload]].\n\nSee also:\n* {{msg-mw|Sourcefilename|label}}\n* {{msg-mw|Sourceurl|label}}\n* {{msg-mw|Upload source file}}\n* {{msg-mw|Upload-maxfilesize}}",
     "upload_source_file": "Used in [[Special:Upload]].\n\nSee also:\n* {{msg-mw|Sourcefilename|label}}\n* {{msg-mw|Sourceurl|label}}\n* {{msg-mw|Upload source url}}\n* {{msg-mw|Upload-maxfilesize}}",
     "sharedupload-desc-here": "Parameters:\n* $1 - the name of the shared repository. On Wikimedia sites, $1 is {{msg-mw|Shared-repo-name-shared}}. The default value for $1 is {{msg-mw|Shared-repo}}.\n* $2 - description URL\nSee also:\n* {{msg-mw|Sharedupload}}\n* {{msg-mw|Sharedupload-desc-there}}\n* {{msg-mw|Sharedupload-desc-edit}}\n* {{msg-mw|Sharedupload-desc-create}}",
     "sharedupload-desc-edit": "Parameters:\n* $1 - the name of the shared repository. On Wikimedia sites, $1 is {{msg-mw|Shared-repo-name-shared}}. The default value for $1 is {{msg-mw|Shared-repo}}.\n* $2 - description URL\nSee also:\n* {{msg-mw|Sharedupload}}\n* {{msg-mw|Sharedupload-desc-there}}\n* {{msg-mw|Sharedupload-desc-here}}\n* {{msg-mw|Sharedupload-desc-create}}",
     "sharedupload-desc-create": "Parameters:\n* $1 - the name of the shared repository. On Wikimedia sites, $1 is {{msg-mw|Shared-repo-name-shared}}. The default value for $1 is {{msg-mw|Shared-repo}}.\n* $2 - description URL\nSee also:\n* {{msg-mw|Sharedupload}}\n* {{msg-mw|Sharedupload-desc-there}}\n* {{msg-mw|Sharedupload-desc-here}}\n* {{msg-mw|Sharedupload-desc-edit}}",
+    "shareddescriptionfollows": "{{notranslate}}\n\nSee also {{msg-mw|sharedupload-desc-here}}.",
     "filepage-nofile": "This message appears when visiting a File page for which there's no file, if the user cannot upload files, or file uploads are disabled. (Otherwise, see {{msg-mw|Filepage-nofile-link}})\n\nFilepage-nofile and Filepage-nofile-link message deprecate {{msg-mw|Noimage}}",
     "filepage-nofile-link": "This message appears when visiting a File page for which there's no file, if the user can upload files, and file uploads are enabled. (Otherwise, see {{msg-mw|Filepage-nofile}})\n\nParameters:\n* $1 - URL of upload page for this file\nFilepage-nofile and Filepage-nofile-link message deprecate {{msg-mw|Noimage}}",
     "uploadnewversion-linktext": "Used on pages in the \"File\" namespace to update the file version.",
     "unusedtemplateswlh": "Used as link text in [[Special:UnusedTemplates]].\n\nThe link points to the \"What links here\" page.",
     "randompage": "{{doc-special|RandomPage}}\nSee also:\n* {{msg-mw|Randompage}}\n* {{msg-mw|Accesskey-n-randompage}}\n* {{msg-mw|Tooltip-n-randompage}}\n{{Identical|Random page}}",
     "randompage-nopages": "Parameters:\n* $1 - list of namespaces\n* $2 - number of namespaces, for PLURAL support\nSee also:\n* {{msg-mw|Randomredirect-nopages}}",
+    "randompage-url": "{{notranslate}}",
     "randomincategory": "{{doc-special|RandomInCategory}}",
     "randomincategory-invalidcategory": "Message shown if an invalid category is specified.\n\nParameters:\n* $1 - the invalid category name given\n\n(Note, if the category is simply empty, but could possibly exist, {{msg-mw|randomincategory-nopages}} is shown instead)",
     "randomincategory-nopages": "Message shown from [[Special:RandomInCategory]] if the category is empty.\n\nParameters:\n* $1 - the category name (without the namespace prefix)",
     "statistics-users-active": "Used in [[Special:Statistics]]",
     "statistics-users-active-desc": "Description shown beneath ''Active users'' in [[Special:Statistics]]. Parameters:\n* $1 - Value of <code>$wgRCMaxAge</code> in days",
     "statistics-mostpopular": "Used in [[Special:Statistics]]",
+    "statistics-footer": "{{notranslate}}",
     "pageswithprop": "{{doc-special|PagesWithProp}}\n{{Identical|Page with page property}}",
     "pageswithprop-legend": "Legend for the input form on [[Special:PagesWithProp]].\n{{Identical|Page with page property}}",
     "pageswithprop-text": "Introductory text for the input form on [[Special:PagesWithProp]]",
     "uncategorizedpages": "{{doc-special|UncategorizedPages}}",
     "uncategorizedcategories": "{{doc-special|UncategorizedCategories}}",
     "uncategorizedimages": "{{doc-special|UncategorizedImages}}",
+    "uncategorizedimages-summary": "{{notranslate}}\nused in [[Special:Uncategorizedimages]]. [[mw:Manual:Interface/Special pages summary|mw manual]].",
     "uncategorizedtemplates": "{{doc-special|UncategorizedTemplates}}",
     "unusedcategories": "{{doc-special|UnusedCategories}}",
     "unusedimages": "{{doc-special|UnusedImages}}",
     "mostlinkedtemplates": "{{doc-special|MostLinkedTemplates}}",
     "mostcategories": "{{doc-special|MostCategories}}",
     "mostimages": "{{doc-special|MostImages}}",
+    "mostimages-summary": "{{notranslate}}\nThe summary displayed at the top of [[Special:Mostimages]]. [[mw:Manual:Interface/Special pages summary|mw manual]].",
     "mostinterwikis": "{{doc-special|MostInterwikis}}",
     "mostrevisions": "{{doc-special|MostRevisions}}",
+    "mostrevisions-summary": "{{notranslate}}\nThe summary displayed at the top of [[Special:Mostrevisions]]. [[mw:Manual:Interface/Special pages summary|mw manual]].",
     "prefixindex": "{{doc-special|PrefixIndex}}\nWhen the user limits the list to a certain namespace, {{msg-mw|allinnamespace}} is used instead.",
     "prefixindex-namespace": "The page title of [[Special:PrefixIndex]] limited to a specific namespace. Similar to {{msg-mw|allinnamespace}}. $1 is the name of the namespace",
+    "prefixindex-summary": "{{notranslate}}\n\nThe summary displayed at the top of [[Special:Prefixindex]]. [[mw:Manual:Interface/Special pages summary|MediaWiki manual]].",
     "prefixindex-strip": "Label for a checkbox. If the checkbox is checked, the prefix searched will be removed from the title displayed in the list. Used in [[Special:PrefixIndex]].\n\nSee the following search results:\n* [{{canonicalurl:Special:PrefixIndex|prefix=Doc&namespace=10}} Special:PrefixIndex?prefix=Doc&namespace=10] (prefix NOT stripped)\n* [{{canonicalurl:Special:PrefixIndex|prefix=Doc&namespace=10&stripprefix=1}} Special:PrefixIndex?prefix=Doc&namespace=10&stripprefix=1] (prefix stripped)",
     "shortpages": "{{doc-special|ShortPages}}",
+    "shortpages-summary": "{{notranslate}}\nThe summary displayed at the top of [[Special:Shortpages]]. [[mw:Manual:Interface/Special pages summary|mw manual]].",
     "longpages": "{{doc-special|LongPages}}",
+    "longpages-summary": "{{notranslate}}\nThe summary displayed at the top of [[Special:Longpages]]. [[mw:Manual:Interface/Special pages summary|mw manual]].",
     "deadendpages": "{{doc-special|DeadendPages}}",
+    "deadendpages-summary": "{{notranslate}}\nThe summary displayed at the top of [[Special:Deadendpages]]. [[mw:Manual:Interface/Special pages summary|mw manual]].",
     "deadendpagestext": "Introductory text for [[Special:DeadendPages]]",
     "protectedpages": "{{doc-special|ProtectedPages}}",
     "protectedpages-indef": "Option in [[Special:ProtectedPages]]",
     "protectedtitles-summary": "Summary of [[Special:ProtectedTitles]].\n\nSee also:\n* {{msg-mw|Protectedpages-summary}}",
     "protectedtitlesempty": "Used on [[Special:ProtectedTitles]]. This text appears if the list of protected titles is empty. See the [[mw:Project:Protected_titles|help page on MediaWiki]] for more information.",
     "listusers": "{{doc-special|ListUsers}}",
+    "listusers-summary": "{{notranslate}}\nThe summary displayed at the top of [[Special:Listusers]]. [[mw:Manual:Interface/Special pages summary|mw manual]].",
     "listusers-editsonly": "Option in [[Special:ListUsers]].",
     "listusers-creationsort": "Option in [[Special:ListUsers]].",
     "listusers-desc": "Used as label for the checkbox.",
     "usereditcount": "Shown behind every username on [[Special:ListUsers]]. Parameters:\n* $1 - number of edits",
     "usercreated": "Used in [[Special:ListUsers]]. Parameters:\n* $1 - a date\n* $2 - a time\n* $3 - the name of the user, for use in GENDER",
     "newpages": "{{doc-special|NewPages}}\n{{Identical|New page}}",
+    "newpages-summary": "{{notranslate}}\nThe summary displayed at the top of [[Special:Newpages]]. [[mw:Manual:Interface/Special pages summary|mw manual]].",
     "newpages-username": "{{Identical|Username}}",
     "ancientpages": "{{doc-special|AncientPages}}\nSee [[mw:Manual:Interface/Special pages title|manual]].",
     "move": "Name of Move tab. Should be in the imperative mood.\n\nSee also:\n* {{msg-mw|Move}}\n* {{msg-mw|Accesskey-ca-move}}\n* {{msg-mw|Tooltip-ca-move}}\n{{Identical|Move}}",
     "booksources-go": "Name of button in [[Special:BookSources]]\n\n{{Identical|Go}}",
     "booksources-text": "Used in [[Special:BookSources/1]].\n\nThis message is followed by a list of links to other sites.\n\nSee also:\n* {{msg-mw|Booksources|title}}\n* {{msg-mw|Booksources-text|text}}",
     "booksources-invalid-isbn": "This message is displayed after an invalid ISBN is entered on [[Special:Booksources]].",
+    "rfcurl": "{{notranslate}}\nParameters:\n* $1 - RFC number\nSee also:\n* {{msg-mw|Pubmedurl}}",
+    "pubmedurl": "{{notranslate}}\nParameters:\n* $1 - Pubmed number\nSee also:\n* {{msg-mw|Rfcurl}}",
     "specialloguserlabel": "Used in [[Special:Log]] as a label for an input field with which the log can be filtered for entries describing actions ''performed'' by the specified user.  \"Carried out\" and \"done\" are possible alternatives for \"performed\".",
     "speciallogtitlelabel": "Used in [[Special:Log]] as a label for an input field with which the log can be filtered.  This filter selects for pages or users on which a log action was performed.",
     "log": "{{doc-special|Log}}",
     "listgrouprights-removegroup-self": "This is an individual right for groups, used on [[Special:ListGroupRights]].\n* $1 - the group names\n* $2 - the number of group names in $1",
     "listgrouprights-addgroup-self-all": "Used on [[Special:ListGroupRights]].\n{{Related|Listgrouprights}}",
     "listgrouprights-removegroup-self-all": "Used on [[Special:ListGroupRights]].\n{{Related|Listgrouprights}}",
+    "trackingcategories": "[[Special:TrackingCategories]] page implementing list of Tracking categories [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]].\n{{Identical|Tracking category}}",
+    "trackingcategories-summary": "Description for [[Special:TrackingCategories]] page [[mw:Help:Tracking categories|tracking category]]",
+    "trackingcategories-msg": "Header for the message column of the table on [[Special:TrackingCategories]]. This column lists the mediawiki message that controls the tracking category in question.\n{{Identical|Tracking category}}",
+    "trackingcategories-name": "Header for the message column of the table on [[Special:TrackingCategories]]. This column lists the name of the tracking category in the content language.",
+    "trackingcategories-desc": "Header for the message column of the table on [[Special:TrackingCategories]]. This column lists the inclusion criteria for the category.",
+    "noindex-category-desc": "No-index category-description. Shown on [[Special:TrackingCategories]]",
+    "index-category-desc": "Index category-description. Shown on [[Special:TrackingCategories]]",
+    "post-expand-template-inclusion-category-desc": "Post expand template inclusion category description. Shown on [[Special:TrackingCategories]]",
+    "post-expand-template-argument-category-desc": "Post expand template argument category description. Shown on [[Special:TrackingCategories]]",
+    "expensive-parserfunction-category-desc": "Expensive parserfunction category description. Shown on [[Special:TrackingCategories]]",
+    "broken-file-category-desc": "Broken file category description. Shown on [[Special:TrackingCategories]]",
+    "hidden-category-category-desc": "Hidden-category category description. Shown on [[Special:TrackingCategories]]",
+    "trackingcategories-nodesc": "Tracking category description not available message",
     "mailnologin": "Used in [[Special:EmailUser]].\n\nUsed as title of the error message {{msg-mw|Mailnologintext}}.",
     "mailnologintext": "Used as error message in [[Special:EmailUser]].\n\nThe title of this error message is {{msg-mw|Mailnologin}}.",
     "emailuser": "Link in the sidebar to send an e-mail to a user.\n\nSee also:\n* {{msg-mw|Emailuser}}\n* {{msg-mw|Accesskey-t-emailuser}}\n* {{msg-mw|Tooltip-t-emailuser}}",
     "nowatchlist": "Displayed when there is no pages in the watchlist.",
     "watchlistanontext": "Parameters:\n* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description",
     "watchnologin": "Used as error page title.\n\nThe error message for this title is:\n* {{msg-mw|Watchnologintext}}\n{{Identical|Not logged in}}",
-    "watchnologintext": "Used as error message.\n\nThe title for this error is {{msg-mw|Watchnologin}}.",
     "addwatch": "Link to a dialog box, displayed at the end of the list of categories at the foot of each page.\n\nSee also:\n* {{msg-mw|Removewatch}}",
     "addedwatchtext": "Explanation shown when clicking on the {{msg-mw|Watch}} tab. Parameters:\n* $1 - page title\nSee also:\n* {{msg-mw|Addedwatch}}",
     "removewatch": "Link to a dialog box, displayed at the end of the list of categories at the foot of each page.\n\nSee also:\n* {{msg-mw|Addwatch}}",
     "sp-contributions-newbies-sub": "Note at the top of the page of results for a search on [[Special:Contributions]] where 'Show contributions for new accounts only' has been selected.",
     "sp-contributions-newbies-title": "The page title in your browser bar, but not the page title.\n\nSee also:\n* {{msg-mw|Sp-contributions-newbies-sub}}",
     "sp-contributions-blocklog": "Used as a display name for a link to the block log on for example [[Special:Contributions/Mediawiki default]]\n\nUsed as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].\n\nSee also:\n* {{msg-mw|Sp-contributions-talk}}\n* {{msg-mw|Change-blocklink}}\n* {{msg-mw|Unblocklink}}\n* {{msg-mw|Blocklink}}\n* {{msg-mw|Sp-contributions-uploads}}\n* {{msg-mw|Sp-contributions-logs}}\n* {{msg-mw|Sp-contributions-deleted}}\n* {{msg-mw|Sp-contributions-userrights}}\n{{Identical|Block log}}",
+    "sp-contributions-suppresslog": "Used as a display name for a link to log entries of suppressed edits made by that user.\n\nUsed as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].\n\nSee also {{msg-mw|sp-contributions-deleted}}, {{msg-mw|sp-deletedcontributions-contribs}}, {{msg-mw|contributions}}, {{msg-mw|deletedcontributions-title}}.",
     "sp-contributions-deleted": "This is a link anchor used in [[Special:Contributions]]/''name'', when user viewing the page has the right to delete pages, or to restore deleted pages.\n\nUsed as link title in [[Special:Contributions]].\n\nSee also:\n* {{msg-mw|Sp-contributions-talk}}\n* {{msg-mw|Change-blocklink}}\n* {{msg-mw|Unblocklink}}\n* {{msg-mw|Blocklink}}\n* {{msg-mw|Sp-contributions-blocklog}}\n* {{msg-mw|Sp-contributions-uploads}}\n* {{msg-mw|Sp-contributions-logs}}\n* {{msg-mw|Sp-contributions-userrights}}",
     "sp-contributions-uploads": "Used as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].\n\nSee also:\n* {{msg-mw|Sp-contributions-talk}}\n* {{msg-mw|Change-blocklink}}\n* {{msg-mw|Unblocklink}}\n* {{msg-mw|Blocklink}}\n* {{msg-mw|Sp-contributions-blocklog}}\n* {{msg-mw|Sp-contributions-logs}}\n* {{msg-mw|Sp-contributions-deleted}}\n* {{msg-mw|Sp-contributions-userrights}}\n{{Identical|Upload}}",
     "sp-contributions-logs": "Appears as an action link in the header of the Special:Contributions/''Username'' pages (e.g. \"For Somebody (talk | block log | logs)\").\n\nUsed as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].\n\nSee also:\n* {{msg-mw|Sp-contributions-talk}}\n* {{msg-mw|Change-blocklink}}\n* {{msg-mw|Unblocklink}}\n* {{msg-mw|Blocklink}}\n* {{msg-mw|Sp-contributions-blocklog}}\n* {{msg-mw|Sp-contributions-uploads}}\n* {{msg-mw|Sp-contributions-deleted}}\n* {{msg-mw|Sp-contributions-userrights}}",
     "sp-contributions-blocked-notice": "Shown on top of contributions special page of currently blocked users.\n\nParameters:\n* $1 - (Optional) the blocked user. Can be used for GENDER\nAnon version:\n* {{msg-mw|Sp-contributions-blocked-notice-anon}}",
     "sp-contributions-blocked-notice-anon": "Same as {{msg-mw|Sp-contributions-blocked-notice}} but for anonymous users.",
     "sp-contributions-search": "Used on [[Special:Contributions]]",
-    "sp-contributions-suppresslog": "Used as a display name for a link to log entries of suppressed edits made by that user.\n\nUsed as link title in [[Special:Contributions]] and in [[Special:DeletedContributions]].\n\nSee also {{msg-mw|sp-contributions-deleted}}, {{msg-mw|sp-deletedcontributions-contribs}}, {{msg-mw|contributions}}, {{msg-mw|deletedcontributions-title}}.",
     "sp-contributions-username": "This message appears whenever someone requests [[Special:Contributions]].\n{{Identical|IP address or username}}",
     "sp-contributions-toponly": "A checkbox at [[Special:Mycontributions|Special:Contributions]]",
     "sp-contributions-newonly": "Used as checkbox label at [[Special:Mycontributions|Special:Contributions]].\n\n\"page creation\" means the \"first revision\" of a page.\n\nPreceded by {{msg-mw|Sp-contributions-toponly}}.",
     "sp-contributions-submit": "{{Identical|Search}}",
     "sp-contributions-explain": "{{optional}}",
+    "sp-contributions-footer": "{{notranslate}}",
+    "sp-contributions-footer-anon": "{{notranslate}}",
     "whatlinkshere": "The text of the link in the toolbox (on the left, below the search menu) going to [[Special:WhatLinksHere]].\n\nSee also:\n* {{msg-mw|Whatlinkshere}}\n* {{msg-mw|Accesskey-t-whatlinkshere}}\n* {{msg-mw|Tooltip-t-whatlinkshere}}",
     "whatlinkshere-title": "Title of the special page [[Special:WhatLinksHere]]. This page appears when you click on the 'What links here' button in the toolbox. $1 is the name of the page concerned.",
     "whatlinkshere-page": "{{Identical|Page}}",
     "import-logentry-interwiki": "Used as action listed in the log. Parameters:\n* $1 - page title",
     "import-logentry-interwiki-detail": "Used as success message. Parameters:\n* $1 - number of succeeded revisions\n* $2 - interwiki name\nSee also:\n* {{msg-mw|Import-logentry-upload-detail}}",
     "javascripttest": "Title of the special page [[Special:JavaScriptTest]].\n\nSee also:\n* {{msg-mw|Javascripttest|title}}\n* {{msg-mw|Javascripttest-pagetext-noframework|summary}}\n* {{msg-mw|Javascripttest-pagetext-unknownframework|error message}}",
+    "javascripttest-backlink": "{{optional}}\nUsed as subtitle in [[Special:JavaScriptTest]]. Parameters:\n* $1 - page title",
     "javascripttest-title": "Title of the special page when running a test suite. Parameters:\n* $1 is the name of the framework, for example QUnit.",
     "javascripttest-pagetext-noframework": "Used as summary when no framework specified.\n\nSee also:\n* {{msg-mw|Javascripttest|title}}\n* {{msg-mw|Javascripttest-pagetext-noframework|summary}}\n* {{msg-mw|Javascripttest-pagetext-unknownframework|error message}}",
     "javascripttest-pagetext-unknownframework": "Error message when given framework ID is not found. Parameters:\n* $1 - the ID of the framework\nSee also:\n* {{msg-mw|Javascripttest|title}}\n* {{msg-mw|Javascripttest-pagetext-noframework|summary}}\n* {{msg-mw|Javascripttest-pagetext-unknownframework|error message}}",
     "javascripttest-pagetext-frameworks": "Parameters:\n* $1 - frameworks list which contain a link text {{msg-mw|Javascripttest-qunit-name}}",
     "javascripttest-pagetext-skins": "Used as label in [[Special:JavaScriptTest]].",
+    "javascripttest-qunit-name": "{{Ignore}}",
     "javascripttest-qunit-intro": "Used as summary. Parameters:\n* $1 - the configured URL to the documentation\nSee also:\n* {{msg-mw|Javascripttest-qunit-heading}}",
     "javascripttest-qunit-heading": "See also:\n* {{msg-mw|Javascripttest-qunit-intro}}",
+    "accesskey-pt-userpage": "{{doc-accesskey}}\nSee also:\n<!--* username-->\n* {{msg-mw|Accesskey-pt-userpage}}\n* {{msg-mw|Tooltip-pt-userpage}}",
+    "accesskey-pt-anonuserpage": "{{doc-accesskey}}",
+    "accesskey-pt-mytalk": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Mytalk}}\n* {{msg-mw|Accesskey-pt-mytalk}}\n* {{msg-mw|Tooltip-pt-mytalk}}",
+    "accesskey-pt-anontalk": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Anontalk}}\n* {{msg-mw|Accesskey-pt-anontalk}}\n* {{msg-mw|Tooltip-pt-anontalk}}",
+    "accesskey-pt-preferences": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Mypreferences}}\n* {{msg-mw|Accesskey-pt-preferences}}\n* {{msg-mw|Tooltip-pt-preferences}}",
+    "accesskey-pt-watchlist": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Mywatchlist}}\n* {{msg-mw|Accesskey-pt-watchlist}}\n* {{msg-mw|Tooltip-pt-watchlist}}",
+    "accesskey-pt-mycontris": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Mycontris}}\n* {{msg-mw|Accesskey-pt-mycontris}}\n* {{msg-mw|Tooltip-pt-mycontris}}",
+    "accesskey-pt-login": "{{doc-accesskey}}",
+    "accesskey-pt-logout": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Logout}}\n* {{msg-mw|Accesskey-pt-logout}}\n* {{msg-mw|Tooltip-pt-logout}}",
+    "accesskey-ca-talk": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Talk}}\n* {{msg-mw|Accesskey-ca-talk}}\n* {{msg-mw|Tooltip-ca-talk}}",
+    "accesskey-ca-edit": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Edit}}\n* {{msg-mw|Accesskey-ca-edit}}\n* {{msg-mw|Tooltip-ca-edit}}",
+    "accesskey-ca-addsection": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Addsection}}\n* {{msg-mw|Accesskey-ca-addsection}}\n* {{msg-mw|Tooltip-ca-addsection}}",
+    "accesskey-ca-viewsource": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Viewsource}}\n* {{msg-mw|Accesskey-ca-viewsource}}\n* {{msg-mw|Tooltip-ca-viewsource}}",
+    "accesskey-ca-history": "{{doc-accesskey}}",
+    "accesskey-ca-protect": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Protect}}\n* {{msg-mw|Accesskey-ca-protect}}\n* {{msg-mw|Tooltip-ca-protect}}",
+    "accesskey-ca-unprotect": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Unprotect}}\n* {{msg-mw|Accesskey-ca-unprotect}}\n* {{msg-mw|Tooltip-ca-unprotect}}",
+    "accesskey-ca-delete": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Delete}}\n* {{msg-mw|Accesskey-ca-delete}}\n* {{msg-mw|Tooltip-ca-delete}}",
+    "accesskey-ca-undelete": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Undelete}}\n* {{msg-mw|Accesskey-ca-undelete}}\n* {{msg-mw|Tooltip-ca-undelete}}",
+    "accesskey-ca-move": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Move}}\n* {{msg-mw|Accesskey-ca-move}}\n* {{msg-mw|Tooltip-ca-move}}",
+    "accesskey-ca-watch": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Watch}}\n* {{msg-mw|Accesskey-ca-watch}}\n* {{msg-mw|Tooltip-ca-watch}}",
+    "accesskey-ca-unwatch": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Unwatch}}\n* {{msg-mw|Accesskey-ca-unwatch}}\n* {{msg-mw|Tooltip-ca-unwatch}}",
+    "accesskey-search": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Search}}\n* {{msg-mw|Accesskey-search}}\n* {{msg-mw|Tooltip-search}}",
+    "accesskey-search-go": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Go}}\n* {{msg-mw|Accesskey-search-go}}\n* {{msg-mw|Tooltip-search-go}}",
+    "accesskey-search-fulltext": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Search}}\n* {{msg-mw|Accesskey-search-fulltext}}\n* {{msg-mw|Tooltip-search-fulltext}}",
+    "accesskey-p-logo": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Accesskey-p-logo}}\n* {{msg-mw|Tooltip-p-logo}}",
+    "accesskey-n-mainpage": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Mainpage}}\n* {{msg-mw|Accesskey-n-mainpage}}\n* {{msg-mw|Tooltip-n-mainpage}}",
+    "accesskey-n-mainpage-description": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Mainpage-description}}\n* {{msg-mw|Accesskey-n-mainpage-description}}\n* {{msg-mw|Tooltip-n-mainpage-description}}",
+    "accesskey-n-portal": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Portal}}\n* {{msg-mw|Portal-url}}\n* {{msg-mw|Accesskey-n-portal}}\n* {{msg-mw|Tooltip-n-portal}}",
+    "accesskey-n-currentevents": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Currentevents}}\n* {{msg-mw|Currentevents-url}}\n* {{msg-mw|Accesskey-n-currentevents}}\n* {{msg-mw|Tooltip-n-currentevents}}",
+    "accesskey-n-recentchanges": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Recentchanges}}\n* {{msg-mw|Accesskey-n-recentchanges}}\n* {{msg-mw|Tooltip-n-recentchanges}}",
+    "accesskey-n-randompage": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Randompage}}\n* {{msg-mw|Accesskey-n-randompage}}\n* {{msg-mw|Tooltip-n-randompage}}",
+    "accesskey-n-help": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Help}}\n* {{msg-mw|Accesskey-n-help}}\n* {{msg-mw|Tooltip-n-help}}",
+    "accesskey-t-whatlinkshere": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Whatlinkshere}}\n* {{msg-mw|Accesskey-t-whatlinkshere}}\n* {{msg-mw|Tooltip-t-whatlinkshere}}",
+    "accesskey-t-recentchangeslinked": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Recentchangeslinked}}\n* {{msg-mw|Accesskey-t-recentchangeslinked}}\n* {{msg-mw|Tooltip-t-recentchangeslinked}}",
+    "accesskey-feed-rss": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Feed-rss}}\n* {{msg-mw|Accesskey-feed-rss}}\n* {{msg-mw|Tooltip-feed-rss}}",
+    "accesskey-feed-atom": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Feed-atom}}\n* {{msg-mw|Accesskey-feed-atom}}\n* {{msg-mw|Tooltip-feed-atom}}",
+    "accesskey-t-contributions": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Contributions}}\n* {{msg-mw|Accesskey-t-contributions}}\n* {{msg-mw|Tooltip-t-contributions}}",
+    "accesskey-t-emailuser": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Emailuser}}\n* {{msg-mw|Accesskey-t-emailuser}}\n* {{msg-mw|Tooltip-t-emailuser}}",
+    "accesskey-t-permalink": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Permalink}}\n* {{msg-mw|Accesskey-t-permalink}}\n* {{msg-mw|Tooltip-t-permalink}}",
+    "accesskey-t-print": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Printableversion}}\n* {{msg-mw|Accesskey-t-print}}\n* {{msg-mw|Tooltip-t-print}}",
+    "accesskey-t-upload": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Upload}}\n* {{msg-mw|Accesskey-t-upload}}\n* {{msg-mw|Tooltip-t-upload}}",
+    "accesskey-t-specialpages": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Specialpages}}\n* {{msg-mw|Accesskey-t-specialpages}}\n* {{msg-mw|Tooltip-t-specialpages}}",
+    "accesskey-ca-nstab-main": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Nstab-main}}\n* {{msg-mw|Accesskey-ca-nstab-main}}\n* {{msg-mw|Tooltip-ca-nstab-main}}",
+    "accesskey-ca-nstab-user": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Nstab-user}}\n* {{msg-mw|Accesskey-ca-nstab-user}}\n* {{msg-mw|Tooltip-ca-nstab-user}}",
+    "accesskey-ca-nstab-media": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Nstab-media}}\n* {{msg-mw|Accesskey-ca-nstab-media}}\n* {{msg-mw|Tooltip-ca-nstab-media}}",
+    "accesskey-ca-nstab-special": "{{doc-accesskey}}",
+    "accesskey-ca-nstab-project": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Nstab-project}}\n* {{msg-mw|Accesskey-ca-nstab-project}}\n* {{msg-mw|Tooltip-ca-nstab-project}}",
+    "accesskey-ca-nstab-image": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Nstab-image}}\n* {{msg-mw|Accesskey-ca-nstab-image}}\n* {{msg-mw|Tooltip-ca-nstab-image}}",
+    "accesskey-ca-nstab-mediawiki": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Nstab-mediawiki}}\n* {{msg-mw|Accesskey-ca-nstab-mediawiki}}\n* {{msg-mw|Tooltip-ca-nstab-mediawiki}}",
+    "accesskey-ca-nstab-template": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Nstab-template}}\n* {{msg-mw|Accesskey-ca-nstab-template}}\n* {{msg-mw|Tooltip-ca-nstab-template}}",
+    "accesskey-ca-nstab-help": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Nstab-help}}\n* {{msg-mw|Accesskey-ca-nstab-help}}\n* {{msg-mw|Tooltip-ca-nstab-help}}",
+    "accesskey-ca-nstab-category": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Nstab-category}}\n* {{msg-mw|Accesskey-ca-nstab-category}}\n* {{msg-mw|Tooltip-ca-nstab-category}}",
+    "accesskey-minoredit": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Minoredit}}\n* {{msg-mw|Accesskey-minoredit}}\n* {{msg-mw|Tooltip-minoredit}}",
+    "accesskey-save": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Savearticle}}\n* {{msg-mw|Accesskey-save}}\n* {{msg-mw|Tooltip-save}}",
+    "accesskey-preview": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Showpreview}}\n* {{msg-mw|Accesskey-preview}}\n* {{msg-mw|Tooltip-preview}}",
+    "accesskey-diff": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Showdiff}}\n* {{msg-mw|Accesskey-diff}}\n* {{msg-mw|Tooltip-diff}}",
+    "accesskey-compareselectedversions": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Compareselectedversions}}\n* {{msg-mw|Accesskey-compareselectedversions}}\n* {{msg-mw|Tooltip-compareselectedversions}}",
+    "accesskey-watch": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Watchthis}}\n* {{msg-mw|Accesskey-watch}}\n* {{msg-mw|Tooltip-watch}}",
+    "accesskey-upload": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Uploadbtn}}\n* {{msg-mw|Accesskey-upload}}\n* {{msg-mw|Tooltip-upload}}",
+    "accesskey-preferences-save": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Saveprefs}}\n* {{msg-mw|Accesskey-preferences-save}}\n* {{msg-mw|Tooltip-preferences-save}}",
+    "accesskey-summary": "{{doc-accesskey}}\nSee also:\n* {{msg-mw|Summary}}\n* {{msg-mw|Accesskey-summary}}\n* {{msg-mw|Tooltip-summary}}",
+    "accesskey-userrights-set": "{{doc-accesskey}}",
+    "accesskey-blockip-block": "{{doc-accesskey}}",
+    "accesskey-export": "{{doc-accesskey}}",
+    "accesskey-import": "{{doc-accesskey}}",
+    "accesskey-watchlistedit-normal-submit": "{{doc-accesskey|watchlistedit-normal-submit}}\nSee also:\n* {{msg-mw|Watchlistedit-normal-submit}}\n* {{msg-mw|Accesskey-watchlistedit-normal-submit}}\n* {{msg-mw|Tooltip-watchlistedit-normal-submit}}",
+    "accesskey-watchlistedit-raw-submit": "{{doc-accesskey|watchlistedit-raw-submit}}\nSee also:\n* {{msg-mw|Watchlistedit-raw-submit}}\n* {{msg-mw|Accesskey-watchlistedit-raw-submit}}\n* {{msg-mw|Tooltip-watchlistedit-raw-submit}}",
     "tooltip-pt-userpage": "Tooltip shown when hovering the mouse over the link to your own User page in the upper-side personal toolbox.\n\nSee also:\n<!--* username-->\n* {{msg-mw|Accesskey-pt-userpage}}\n* {{msg-mw|Tooltip-pt-userpage}}",
     "tooltip-pt-mytalk": "Tooltip shown when hovering over the {{msg-mw|Mytalk}} link in your personal toolbox (upper right side).\n\nSee also:\n* {{msg-mw|Mytalk}}\n* {{msg-mw|Accesskey-pt-mytalk}}\n* {{msg-mw|Tooltip-pt-mytalk}}",
     "tooltip-pt-anontalk": "Used as tooltip for link {{msg-mw|Anontalk}}.\n\nSee also:\n* {{msg-mw|Anontalk}}\n* {{msg-mw|Accesskey-pt-anontalk}}\n* {{msg-mw|Tooltip-pt-anontalk}}",
     "skinname-modern": "{{optional}}\n{{Identical|Modern}}",
     "skinname-vector": "{{optional}}",
     "markaspatrolleddiff": "{{doc-actionlink}}\nSee also:\n* {{msg-mw|Markaspatrolledtext}}",
+    "markaspatrolledlink": "{{notranslate}}\nParameters:\n* $1 - link which has text {{msg-mw|Markaspatrolledtext}}",
     "markaspatrolledtext": "{{doc-actionlink}}\nSee also:\n* {{msg-mw|Markaspatrolleddiff}}",
     "markedaspatrolled": "Used as title of the message {{msg-mw|Markedaspatrolledtext}}, when marking a change as patrolled.\n{{Related|Markedaspatrolled}}",
     "markedaspatrolledtext": "Used when marking a change as patrolled.\n\nThe title for this message is {{msg-mw|Markedaspatrolled}}.\n\nParameters:\n* $1 - page title\n{{Related|Markedaspatrolled}}",
     "friday-at": "Phrase for indicating that something occurred at a particular time on the most recent Friday.\n\nParameters:\n* $1 - the time (localized)\n{{Related|Day-at}}",
     "saturday-at": "Phrase for indicating that something occurred at a particular time on the most recent Saturday.\n\nParameters:\n* $1 - the time (localized)\n{{Related|Day-at}}",
     "sunday-at": "Phrase for indicating that something occurred at a particular time on the most recent Sunday.\n\nParameters:\n* $1 - the time (localized)\n{{Related|Day-at}}",
+    "today-at": "Phrase for indicating that something occurred at a particular time today.\n\nParameters:\n* $1 - the time (localized)\n{{Related|Day-at}}",
     "yesterday-at": "Phrase for indicating that something occurred at a particular time yesterday.\n\nParameters:\n* $1 - the time (localized)\n{{Related|Day-at}}",
     "bad_image_list": "箇条信息只出现在引导管理员用正确个格式加链接。弗会徕Mediawiki别荡处出现。",
     "variantname-zh-hans": "{{Optional}}\n\nVariant option for wikis with variants conversion enabled.",
     "exif-personinimage": "Name of person depicted in image",
     "exif-originalimageheight": "Height of image before it was cropped in pixels",
     "exif-originalimagewidth": "Width of image before it was cropped in pixels",
+    "exif-make-value": "{{notranslate}}\nParameters:\n* $1 - make name",
+    "exif-model-value": "{{notranslate}}\nIt's used for local customizations (it allows some wiki syntax). Parameters:\n* $1 - the name of the camera, shown in the metadata table alongside {{msg-mw|Exif-model}}",
+    "exif-software-value": "{{notranslate}}\nParameters:\n* $1 - software name",
+    "exif-software-version-value": "{{notranslate}}\nParameters:\n* $1 - software name\n* $2 - version number",
     "exif-contact-value": "{{optional}}\nParameters:\n* $1 - email\n* $2 - URL of website\n* $3 - street address\n* $4 - city\n* $5 - region\n* $6 - postal code\n* $7 - country\n* $8 - telephone number\nNote, not all fields are guaranteed to be present, some may be empty strings.",
     "exif-subjectnewscode-value": "{{Optional}}\nParameters:\n* $1 - numeric IPTC subject news code (one of http://cv.iptc.org/newscodes/subjectcode )\n* $2 - one of 17 broad categories that the code falls into. For example any code starting with 15 has the contents of {{msg-mw|Exif-iimcategory-spo}} for $2.",
     "exif-compression-1": "{{Related|Exif-compression}}",
     "semicolon-separator": "{{optional}}",
     "comma-separator": "{{optional}}\n\nWarning: languages have different usages of punctuation, and sometimes they are swapped (e.g. openining and closing quotation marks, or full stop and colon in Armenian), or change their form (the full stop in Chinese and Japanese, the prefered \"colon\" in Armenian used in fact as the regular full stop, the comma in Arabic, Armenian, and Chinese...)\n\nTheir spacing (before or after) may also vary across languages (for example French requires a non-breaking space, preferably narrow if the browser supports NNBSP, on the inner side of some punctuations like quotation/question/exclamation marks, colon, and semicolons).",
     "colon-separator": "{{optional}}\nChange it only if your language uses another character for ':' or it needs an extra space before the colon.",
+    "autocomment-prefix": "{{optional}}",
     "pipe-separator": "{{optional}}",
     "word-separator": "{{optional}}\nThis is a string which is (usually) put between words of the language. It is used, e.g. when messages are concatenated (appended to each other). Note that you must express a space as html entity &amp;#32; because the editing and updating process strips leading and trailing spaces from messages.\n\nMost languages use a space, but some Asian languages, such as Thai and Chinese, do not.",
     "ellipsis": "{{optional}}",
     "autosumm-replace": "The auto summary when a user removes a lot of characters in the page.\n\nParameters:\n* $1 - truncated text",
     "autoredircomment": "The auto summary when making a redirect. Parameters:\n* $1 - the page where it redirects to\n* $2 - (Optional) the first X number of characters of the redirect ($2 is usually only used when end users customize the message)",
     "autosumm-new": "The auto summary when creating a new page. $1 are the first X number of characters of the new page.",
+    "autoblock_whitelist": "{{notranslate}}",
     "size-bytes": "{{optional}}\nSize (of a page, typically) in bytes.",
     "size-kilobytes": "{{optional}}\nSize (of a page, typically) in kibibytes (1 kibibyte = 1024 bytes).",
     "size-megabytes": "{{optional}}\nSize (of a file, typically) in mebibytes (1 mebibyte = 1024×1024 bytes).",
     "hebrew-calendar-m11-gen": "{{optional}}\nName of month in Hebrew calendar.",
     "hebrew-calendar-m12-gen": "{{optional}}\nName of month in Hebrew calendar.",
     "signature": "This will be substituted in the signature (~<nowiki></nowiki>~~ or ~~<nowiki></nowiki>~~ excluding timestamp).\n\nParameters:\n* $1 - the username that is currently login\n* $2 - the customized signature which is specified in [[Special:Preferences|user's preferences]] as non-raw\nUse your language default parentheses ({{msg-mw|parentheses}}), but not use the message direct.\n\nSee also:\n* {{msg-mw|Signature-anon}} - signature for anonymous user",
+    "signature-anon": "{{notranslate}}\nUsed as signature for anonymous user. Parameters:\n* $1 - username (IP address?)\n* $2 - nickname (IP address?)\nSee also:\n* {{msg-mw|Signature}} - signature for registered user",
     "timezone-utc": "{{optional}}",
     "unknown_extension_tag": "This is an error shown when you use an unknown extension tag name.\n\nThis feature allows tags like <code><nowiki><pre></nowiki></code> to be called with a parser like <code><nowiki>{{#tag:pre}}</nowiki></code>.\n\nParameters:\n* $1 - the unknown extension tag name",
     "duplicate-defaultsort": "See definition of [[w:Sorting|sort key]] on Wikipedia. Parameters:\n* $1 - old default sort key\n* $2 - new default sort key",
     "version-entrypoints-header-url": "Header for the second column in the entry points table on [[Special:Version]].\n{{Identical|URL}}",
     "version-entrypoints-articlepath": "{{Optional}}\nA short description of the article path entry point. Links to the mediawiki.org documentation page for $wgArticlePath.",
     "version-entrypoints-scriptpath": "{{Optional}}\nA short description of the script path entry point. Links to the mediawiki.org documentation page for $wgScriptPath.",
+    "version-entrypoints-index-php": "A short description of the index.php entry point. Links to the mediawiki.org documentation page for index.php.",
+    "version-entrypoints-api-php": "A short description of the api.php entry point. Links to the mediawiki.org documentation page for api.php.",
+    "version-entrypoints-load-php": "A short description of the load.php entry point. Links to the mediawiki.org documentation page for load.php.",
     "redirect": "{{doc-special|Redirect}}\nThis means \"Redirect by file'''name''', user '''ID''', page '''ID''', or revision ID\".",
     "redirect-legend": "Legend of fieldset around input box in [[Special:Redirect]]",
+    "redirect-text": "Inside fieldset for [[Special:Redirect]]",
     "redirect-summary": "Shown at top of [[Special:Redirect]]",
     "redirect-submit": "Button label in [[Special:Redirect]].\n{{Identical|Go}}",
     "redirect-lookup": "First field label in [[Special:Redirect]].\n\nFollowed by the select box which has the following options:\n* {{msg-mw|Redirect-user}}\n* {{msg-mw|Redirect-page}}\n* {{msg-mw|Redirect-revision}}\n* {{msg-mw|Redirect-file}}",
     "logentry-rights-rights-legacy": "* $1 - username\n* $2 - (see below)\n* $3 - username\n----\n{{Logentry|[[Special:Log/rights]]}}",
     "logentry-rights-autopromote": "* $1 - username\n* $2 - (see below)\n* $3 - (see below)\n* $4 - comma separated list of old user groups or {{msg-mw|Rightsnone}}\n* $5 - comma separated list of new user groups\n----\n{{Logentry|[[Special:Log/rights]]}}",
     "rightsnone": "Default rights for registered users.\n\n{{Identical|None}}",
+    "revdelete-logentry": "{{RevisionDelete}}\nThis is the message for the log entry in [[Special:Log/delete]] when changing visibility restrictions for page revisions.\n\nFollowed by the message {{msg-mw|revdelete-log-message}} in brackets.\n\nPreceded by the name of the user doing this task.\n\nParameters:\n* $1 - the page name\nSee also:\n* {{msg-mw|Logdelete-logentry}}",
+    "logdelete-logentry": "{{RevisionDelete}}\nThis is the message for the log entry in [[Special:Log/delete]] when changing visibility restrictions for log events.\n\nFollowed by the message {{msg-mw|logdelete-log-message}} in brackets.\n\nPreceded by the name of the user who did this task.\n\nParameters:\n* $1 - the log name in brackets\nSee also:\n* {{msg-mw|Revdelete-logentry}}",
+    "revdelete-content": "This message is used as parameter $1 in {{msg-mw|revdelete-hid}} and {{msg-mw|revdelete-unhid}} when hiding or unhiding the content of a revision or event.\n{{Identical|Content}}",
+    "revdelete-summary": "This message is used as parameter $1 in {{msg-mw|revdelete-hid}} and {{msg-mw|revdelete-unhid}} when hiding or unhiding the edit summary of a revision or event.",
+    "revdelete-uname": "This message is used as parameter $1 in {{msg-mw|revdelete-hid}} and {{msg-mw|revdelete-unhid}} when hiding or unhiding the username for a revision or event.\n\n{{Identical|Username}}",
+    "revdelete-hid": "This message is used as <code>$1</code>:\n* in {{msg-mw|revdelete-log-message}} when hiding revisions\n* in {{msg-mw|logdelete-log-message}} when hiding information in the log entry about hiding revisions\nParameters:\n* $1 - any one of the following:\n** {{msg-mw|Revdelete-content}} (when hiding the page content)\n** {{msg-mw|Revdelete-summary}} (when hiding the edit summary)\n** {{msg-mw|Revdelete-uname}} (when hiding the user name)\n** a combination of these three messages\nSee also:\n* {{msg-mw|Revdelete-unhid}}",
+    "revdelete-unhid": "This message is used as <code>$1</code>:\n* in {{msg-mw|Revdelete-log-message}} when unhiding revisions\n* in {{msg-mw|Logdelete-log-message}} when unhiding information in the log entry about unhiding revisions\nParameters:\n* $1 - any one of the following:\n** {{msg-mw|Revdelete-content}} (when unhiding the page content)\n** {{msg-mw|Revdelete-summary}} (when unhiding the edit summary)\n** {{msg-mw|Revdelete-uname}} (when unhiding the user name)\n** a combination of these three messages\nSee also:\n* {{msg-mw|Revdelete-hid}}",
+    "revdelete-log-message": "This log message is used together with {{msg-mw|revdelete-logentry}} in the deletion or suppression logs when changing visibility restrictions for page revisions.\n\nParameters:\n* $1 - any one of the following\n** {{msg-mw|revdelete-hid}} (when hiding data)\n** {{msg-mw|revdelete-unhid}} (when unhiding data)\n** {{msg-mw|revdelete-restricted}} (when applying restrictions for sysops)\n** {{msg-mw|revdelete-unrestricted}} (when removing restrictions for sysops)\n** a combination of those messages\n* $2 - the number of revisions for which the restrictions are changed\n\nPlease note that the parameters in a log entry will appear in the log only in the default language of the wiki. View [[Special:Log]] for examples on translatewiki.net with English default language.\n\nSee also:\n* {{msg-mw|Logdelete-log-message}}",
+    "logdelete-log-message": "This log message appears in brackets after the message {{msg-mw|logdelete-logentry}} in the deletion or suppression logs when changing the visibility of a log entry for events. For a brief description of the process of changing the visibility of events and their log entries see this [http://www.mediawiki.org/wiki/RevisionDelete mediawiki explanation].\n\nParameters:\n* $1 - any one of the following\n** {{msg-mw|revdelete-hid}} (when hiding data)\n** {{msg-mw|revdelete-unhid}} (when unhiding data)\n** {{msg-mw|revdelete-restricted}} (when applying restrictions for sysops)\n** {{msg-mw|revdelete-unrestricted}} (when removing restrictions for sysops)\n** a combination of those messages\n* $2 - the number of events for which the restrictions are changed\n\nPlease note that the parameters in a log entry will appear in the log only in the default language of the wiki. View [[Special:Log]] for examples on translatewiki.net with English default language.\n\nSee also:\n* {{msg-mw|Revdelete-log-message}}",
+    "deletedarticle": "This is a ''logentry'' message. Parameters:\n* $1 - deleted page name",
+    "suppressedarticle": "Part of a [[mw:Manual:RevisionDelete|RevisionDelete]] log entry. Parameters:\n* $1 - suppressed page name\n{{Identical|Suppressed}}",
+    "undeletedarticle": "This is a ''logentry'' message. Parameters:\n* $1 - restored (undeleted) page name",
+    "patrol-log-line": "Text of notes on entries in the [http://translatewiki.net/w/i.php?title=Special%3ALog&type=patrol&user=&page=&year=&month=-1 patrol log].\nParameters:\n* $1 - the link whose text is {{msg-mw|patrol-log-diff}}\n* $2 - the name of the page\n* $3 - appears to be {{msg-mw|Patrol-log-auto}} (at least sometimes)\n\nThe message appears after the name of the patroller.",
+    "patrol-log-auto": "Automated edit summary when patrolling.\n\n{{Identical|Automatic}}",
+    "patrol-log-diff": "The text of the diff link in {{msg-mw|Patrol-log-line}} (inside <code>$1</code> there).\n\nParameters:\n* $1 - revision ID\n{{Identical|Revision}}",
+    "1movedto2": "{{ignored}}This is ''logentry'' message only used on IRC. Parameters:\n* $1 - the original page name\n* $2 - the destination page name\nSee also:\n* {{msg-mw|1movedto2 redir}}",
+    "1movedto2_redir": "{{ignored}}This is ''logentry'' message only used on IRC. Parameters:\n* $1 - the original page name\n* $2 - the destination page name\nSee also:\n* {{msg-mw|1movedto2}}",
+    "newuserlog-create-entry": "Part of the \"Newuserlog\" extension. It is the summary in the [[Special:RecentChanges|recent changes]] and on [[Special:Log/newusers]].",
+    "newuserlog-create2-entry": "Part of the \"Newuserlog\" extension.\n\nIt is the summary in the [[Special:RecentChanges|recent changes]] and on [[Special:Log/newusers]] when creating an account for someone else (\"$1\").\n\nPreceded by the name of the user doing this task.\n\nParameters:\n* $1 - username",
+    "newuserlog-autocreate-entry": "This message is used in the [[:mw:Extension:Newuserlog|new user log]] to mark an account that was created by MediaWiki as part of a [[:mw:Extension:CentralAuth|CentralAuth]] global account.",
+    "rightslogentry": "This message is displayed in the [[Special:Log/rights|User Rights Log]] when a bureaucrat changes the user groups for a user.\n\nParameters:\n* $1 - the username\n* $2 - list of user groups or {{msg-mw|Rightsnone}}\n* $3 - list of user groups or {{msg-mw|Rightsnone}}\n\nThe name of the bureaucrat who did this task appears before this message.\n\nSimilar to {{msg-mw|Gur-rightslog-entry}}",
+    "rightslogentry-autopromote": "This message is displayed in the [[Special:Log/rights|User Rights Log]] when a user is automatically promoted to a user group.\n\nParameters:\n* $1 - (Unused)\n* $2 - a comma separated list of old user groups or {{msg-mw|Rightsnone}}\n* $3 - a comma separated list of new user groups",
     "feedback-bugornote": "When feedback dialog box is opened, this introductory message in small print explains the options to report a bug or add simple feedback.\n\nWe expect that people in a hurry will not read this.\n\nParameters:\n* $1 - Bug note URL\n* $2 - \"Feedback\"\n* $3 - Feedback page URL",
     "feedback-subject": "Label for a text input\n{{Identical|Subject}}",
     "feedback-message": "Label for a textarea; signature referrs to a Wikitext signature.\n{{Identical|Message}}",
     "expand_templates_remove_nowiki": "Option on [[Special:Expandtemplates]]\n\nHere's what the tick box does:\n\nFor:\n<pre>\n&lt;nowiki>test&lt;/nowiki>\n</pre>\n\nNot ticked:\n<pre>\n&lt;nowiki>test&lt;/nowiki>\n</pre>\n\nTicked:\n<pre>\ntest\n</pre>",
     "expand_templates_generate_xml": "Used as checkbox label.",
     "expand_templates_generate_rawhtml": "Used as checkbox label.",
-    "expand_templates_preview": "{{Identical|Preview}}",
-    "trackingcategories": "[[Special:TrackingCategories]] page implementing list of Tracking categories [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]].\n{{Identical|Tracking category}}",
-    "trackingcategories-summary": "Description for [[Special:TrackingCategories]] page [[mw:Help:Tracking categories|tracking category]]",
-    "trackingcategories-msg": "Header for the message column of the table on [[Special:TrackingCategories]]. This column lists the mediawiki message that controls the tracking category in question.\n{{Identical|Tracking category}}",
-    "trackingcategories-name": "Header for the message column of the table on [[Special:TrackingCategories]]. This column lists the name of the tracking category in the content language.",
-    "trackingcategories-desc": "Header for the message column of the table on [[Special:TrackingCategories]]. This column lists the inclusion criteria for the category.",
-    "noindex-category-desc": "No-index category-description. Shown on [[Special:TrackingCategories]]",
-    "index-category-desc": "Index category-description. Shown on [[Special:TrackingCategories]]",
-    "post-expand-template-inclusion-category-desc": "Post expand template inclusion category description. Shown on [[Special:TrackingCategories]]",
-    "post-expand-template-argument-category-desc": "Post expand template argument category description. Shown on [[Special:TrackingCategories]]",
-    "expensive-parserfunction-category-desc": "Expensive parserfunction category description. Shown on [[Special:TrackingCategories]]",
-    "broken-file-category-desc": "Broken file category description. Shown on [[Special:TrackingCategories]]",
-    "hidden-category-category-desc": "Hidden-category category description. Shown on [[Special:TrackingCategories]]",
-    "trackingcategories-nodesc": "Tracking category description not available message"
+    "expand_templates_preview": "{{Identical|Preview}}"
 }
index 62abc6f..3ab68a2 100644 (file)
     "password-change-forbidden": "Kay wikipi yaykuna rimataqa manam hukchayta atinkichu.",
     "externaldberror": "Hawa yaykuna pantasqam karqan, ichataq manam saqillasunkichu hawa rakiqunaykita musuqchayta.",
     "login": "Yaykuy",
-    "nav-login-createaccount": "Yaykuy",
+    "nav-login-createaccount": "Yaykuy / rakiqunata kamariy",
     "loginprompt": "{{SITENAME}}man yaykunaykipaqqa wamp'unaykipi <i>cookies</i> nisqakunaman ari ninaykim tiyan.",
     "userlogin": "Yaykuy / rakiqunata kamariy",
     "userloginnocreate": "Yaykuy",
     "nologinlink": "Kichariy",
     "createaccount": "Musuq rakiqunata kichariy",
     "gotaccount": "Rakiqunaykiñachu kachkan? '''$1'''.",
-    "gotaccountlink": "Rakiqunaykita willaway",
+    "gotaccountlink": "Yaykuy",
     "userlogin-resetlink": "Yaykuna willayniykikunatari qunqarqankichu?",
     "userlogin-resetpassword-link": "Yaykuna rimaykita qunqarqankichu?",
+    "userlogin-helplink2": "Yaykuywan yanapay",
     "userlogin-createanother": "Huk rakiqunata kamariy",
     "createacct-join": "Kay qatiqpi willaykita yaykuchiy.",
     "createacct-emailrequired": "E-chaski imamayta",
     "suspicious-userlogout": "Lluqsiy mañakuyniykiqa mananchasqam karqan, waqllisqa wamp'unamanta icha pakaq proksimanta kachasqa kaspanchá.",
     "createacct-another-realname-tip": "* Chiqap sutiqa munanallapaqmi. Quwaptiykiqa, llamk'apusqakunam paywan sananchasqa kanqa.",
     "pt-login": "Yaykuy",
+    "pt-login-button": "Yaykuy",
     "pt-createaccount": "Musuq rakiqunata kichariy",
     "pt-userlogout": "Lluqsiy",
     "php-mail-error-unknown": "Mana riqsisqa pantasqa PHP mail() rurananpi",
     "nosuchsectiontitle": "Manam tarinichu chay rakita",
     "nosuchsectiontext": "Allichaykacharqunki mana kachkaq rakitam.\nAstasqachá icha qullusqachá qhawachkaptiyki.",
     "loginreqtitle": "Yaykunaykim tiyan",
-    "loginreqlink": "yaykuna",
+    "loginreqlink": "yaykuy",
     "loginreqpagetext": "Huk p'anqakunata rikunaykipaqqa $1ykim tiyan.",
     "accmailtitle": "Yaykuna rimaqa kachasqañam.",
     "accmailtext": "Kikinmanta kamarisqa [[User talk:$1|$1]]-paq yaykuna rimaqa $2-manmi kachasqaña.\n\nYaykurqaspaqa ''[[Special:ChangePassword|yaykuna rima hukchana]]'' p'anqapi kay yaykuna rimata hukchaytam atinki.",
     "prefs-skin": "Qara",
     "skin-preview": "Ñawpaqta qhaway",
     "datedefault": "Kikinmanta allinkachina",
-    "prefs-beta": "Beta nisqap kaqninkuna",
     "prefs-datetime": "P'unchaw, pacha",
     "prefs-labs": "Laburaturyu nisqap kaqninkuna",
     "prefs-user-pages": "Ruraqpa p'anqankuna",
     "nowatchlist": "Manam watiqasqakunachu kachkan.",
     "watchlistanontext": "Ama hina kaspa, $1 watiqana sutisuyuykipi imakunatapas qhawanaykipaq icha hukchanaykipaq.",
     "watchnologin": "Manam yaykurqankichu",
-    "watchnologintext": "[[Special:UserLogin|Yaykunaykim]] tiyan watiqana sutisuyuykita hukchanaykipaq.",
     "addwatch": "Watiqasqaykunaman yapay",
     "addedwatchtext": "Kunanqa \"[[:$1]]\" sutiyuq p'anqa [[Special:Watchlist|watiqasqayki p'anqakunaman]] yapasqañam. Chay p'anqapi rimanakuy p'anqanpipas hukchanakunata kay watiqana p'anqapim rikunki.",
     "removewatch": "Watiqasqaykunamanta qichuy",
     "allmessagesname": "Suti",
     "allmessagesdefault": "Ñawpaq qillqa",
     "allmessagescurrent": "Kunan kachkaq qillqa",
-    "allmessagestext": "Kayqa MediaWiki suti k'itipi llamk'achinalla willaykunayuq sutisuyum.\nAma hina kaspa, [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] nisqata, [//translatewiki.net translatewiki.net] nisqatapas watukuy, MediaWiki nisqata t'ikraywan yanapayta munaspaykiqa.",
+    "allmessagestext": "Kayqa MediaWiki suti k'itipi llamk'achinalla willaykunayuq sutisuyum.\nAma hina kaspa, [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] nisqata, [//translatewiki.net translatewiki.net] nisqatapas watukuy, MediaWiki nisqata t'ikraywan yanapayta munaspaykiqa.",
     "allmessagesnotsupportedDB": "Kay p'anqaqa manam llamk'achinallachu, '''$wgUseDatabaseMessages''' nisqaman ama nisqa kaptinmi.",
     "allmessages-filter-legend": "Ch'illchina",
     "allmessages-filter": "Ch'illchina, allinchasqa kachkaykama:",
index 7bc45ab..0d836da 100644 (file)
     "prefs-skin": "Skin",
     "skin-preview": "Prevista",
     "datedefault": "Nagina preferenza",
-    "prefs-beta": "Funcziuns da Beta",
     "prefs-datetime": "Data e temp",
     "prefs-labs": "Funcziuns experimentalas",
     "prefs-user-pages": "Paginas dad utilisader",
     "nowatchlist": "Ti n'has nagins elements sin tia glista d'observaziun.",
     "watchlistanontext": "Ti stos $1 per vesair u modifitgar elements sin tia glista d'observaziun",
     "watchnologin": "Ti n'es betg t'annunzià!",
-    "watchnologintext": "Ti stos [[Special:UserLogin|t'annunziar]] per midar tia glista d'observaziun.",
     "addwatch": "Agiuntar a la glista d'observaziun",
     "addedwatchtext": "La pagina \"[[:$1]]\" è vegnida agiuntada a tia [[Special:Watchlist|glista dad observaziun]].\nMidadas futuras vid questa pagina e la pagina da discussiun appertegnenta vegnan mussadas là.",
     "removewatch": "Allontanar da la glista d'observaziun",
     "allmessagesname": "num",
     "allmessagesdefault": "text original",
     "allmessagescurrent": "text actual",
-    "allmessagestext": "Quai è ina glista da tut ils messadis dals differents tips da paginas da MediaWiki che vegnan utilisadas da la software MediaWiki.\nFai ina visita sin [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] sche ti vuls gidar da translatar la software MediaWiki.",
+    "allmessagestext": "Quai è ina glista da tut ils messadis dals differents tips da paginas da MediaWiki che vegnan utilisadas da la software MediaWiki.\nFai ina visita sin [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] sche ti vuls gidar da translatar la software MediaWiki.",
     "allmessagesnotsupportedDB": "Questa pagina na po betg vegnir mussada, perquai che '''$wgUseDatabaseMessages''' è vegnì deactivà.",
     "allmessages-filter-legend": "Filtrar",
     "allmessages-filter": "Filtrar tenor standi da modificaziun:",
index 9d36cf8..fbf5590 100644 (file)
     "prefs-skin": "Aspect",
     "skin-preview": "Previzualizare",
     "datedefault": "Nici o preferință",
-    "prefs-beta": "Opțiuni beta",
     "prefs-datetime": "Data și ora",
     "prefs-labs": "Opțiuni „labs”",
     "prefs-user-pages": "Pagini de utilizator",
     "listgrouprights-removegroup-self": "{{PLURAL:$2|Poate fi șters grupul|Pot fi șterse grupurile}} pentru contul propriu: $1",
     "listgrouprights-addgroup-self-all": "Pot fi adăugate toate grupurile contului propriu",
     "listgrouprights-removegroup-self-all": "Pot fi șterse toate grupurile din contul propriu",
+    "trackingcategories": "Categorii de urmărire",
+    "trackingcategories-summary": "Această pagină conține categorii de urmărire care sunt populate în mod automat de către software-ul MediaWiki. Numele acestora se pot schimba modificând mesajele de sistem relevante din spațiul de nume {{ns:8}}.",
+    "trackingcategories-msg": "Categorie de urmărire",
+    "trackingcategories-name": "Numele mesajului",
+    "trackingcategories-desc": "Criteriile de includere în categorie",
+    "noindex-category-desc": "Pagina conține cuvântul magic <nowiki>__NOINDEX__</nowiki> (aflându-se într-un spațiu de nume care permite acest marcaj) și, drept urmare, nu este indexată de roboți.",
+    "index-category-desc": "Pagina conține cuvântul magic <nowiki>__INDEX__</nowiki> (aflându-se într-un spațiu de nume care permite acest marcaj) și, ca urmare, este indexată de roboți, deși în mod normal acest lucru nu s-ar fi întâmplat.",
+    "post-expand-template-inclusion-category-desc": "După extinderea tuturor formatelor, dimensiunea paginii a depășit $wgMaxArticleSize, astfel că anumite formate nu au fost extinse.",
+    "post-expand-template-argument-category-desc": "După extinderea argumentului unui format (ceva plasat între acolade triple, precum {{{Foo}}}), pagina a depășit $wgMaxArticleSize.",
+    "broken-file-category-desc": "Categorie adăugată dacă pagina conține o legătură întreruptă către un fișier (o legătură folosită pentru încorporarea unui fișier atunci când fișierul nu există).",
+    "hidden-category-category-desc": "Această categorie conține <nowiki>__HIDDENCAT__</nowiki>, ceea ce împiedică în mod implicit afișarea ei în zona cu legături către categorii din cadrul paginilor.",
+    "trackingcategories-nodesc": "Nicio descriere disponibilă.",
+    "trackingcategories-disabled": "Categoria este dezactivată",
     "mailnologin": "Nu există adresă de trimitere",
     "mailnologintext": "Trebuie să fii [[Special:UserLogin|autentificat]] și să ai o adresă validă de e-mail în [[Special:Preferences|preferințe]] pentru a trimite e-mail altor utilizatori.",
     "emailuser": "Trimiteți un e-mail",
     "nowatchlist": "Lista dumneavoastră de pagini urmărite nu conține nici o pagină.",
     "watchlistanontext": "Vă rugăm să vă $1 pentru a vizualiza sau edita elementele din lista dumneavoastră de pagini urmărite.",
     "watchnologin": "Nu sunteți autentificat",
-    "watchnologintext": "Trebuie să fiți [[Special:UserLogin|autentificat]] pentru a vă modifica lista de pagini urmărite.",
     "addwatch": "Adăugă la lista de pagini urmărite",
     "addedwatchtext": "Pagina „[[:$1]]” a fost adăugată la lista dumneavoastră de [[Special:Watchlist|pagini urmărite]].\nModificările viitoare efectuate asupra acestei pagini dar și asupra paginii de discuție asociată vor fi listate acolo.",
     "removewatch": "Elimină din lista de pagini urmărite",
     "sp-contributions-newbies-sub": "Pentru începători",
     "sp-contributions-newbies-title": "Contribuțiile utilizatorului pentru conturile noi",
     "sp-contributions-blocklog": "jurnal blocări",
+    "sp-contributions-suppresslog": "contribuții suprimate ale utilizatorului",
     "sp-contributions-deleted": "contribuțiile șterse ale utilizatorului",
     "sp-contributions-uploads": "încărcări",
     "sp-contributions-logs": "jurnale",
     "sp-contributions-blocked-notice": "Acest utilizator este momentan blocat.\nUltima blocare este indicată mai jos pentru informare:",
     "sp-contributions-blocked-notice-anon": "Această adresă IP este blocată acum.\nIată aici ultima înregistrare relevantă din jurnalul blocărilor:",
     "sp-contributions-search": "Căutare contribuții",
-    "sp-contributions-suppresslog": "contribuții suprimate ale utilizatorului",
     "sp-contributions-username": "Adresă IP sau nume de utilizator:",
     "sp-contributions-toponly": "Afișează numai versiunile recente",
     "sp-contributions-newonly": "Afișează numai modificările care au dus la crearea de pagini",
     "allmessagesname": "Nume",
     "allmessagesdefault": "Textul standard",
     "allmessagescurrent": "Textul curent",
-    "allmessagestext": "Aceasta este lista completă a mesajelor disponibile în domeniul MediaWiki.\nVă rugăm să vizitați [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] și [//translatewiki.net translatewiki.net] dacă vreți să contribuiți la localizarea programului MediaWiki generic.",
+    "allmessagestext": "Aceasta este lista completă a mesajelor disponibile în domeniul MediaWiki.\nVă rugăm să vizitați [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] și [//translatewiki.net translatewiki.net] dacă vreți să contribuiți la localizarea programului MediaWiki generic.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:Allmessages''' nu poate fi folosit deoarece '''$wgUseDatabaseMessages''' este închisă.",
     "allmessages-filter-legend": "Filtru",
     "allmessages-filter": "Filtru după statutul de modificare:",
index c9ba9e0..8dcd9df 100644 (file)
     "prefs-skin": "Skin",
     "skin-preview": "Andeprime",
     "datedefault": "Nisciuna preferenze",
-    "prefs-beta": "Funziune de Beta",
     "prefs-datetime": "Date e ore",
     "prefs-labs": "Funziune de Labs",
     "prefs-user-pages": "Pàgene de l'utende",
     "nowatchlist": "Non ge tine pàggene jndr'à liste de le pàggene condrollete.",
     "watchlistanontext": "Pe piacere $1 pe vedè o cangià le vosce sus a liste de le pàggene condrollete.",
     "watchnologin": "Non ge sinde colleghete",
-    "watchnologintext": "Tu a essere [[Special:UserLogin|colleghete]] pe cangià le pàggene condrollete tue.",
     "addwatch": "Mitte jndr'à le pàggene condrollate",
     "addedwatchtext": "'A pàgene \"[[:$1]]\" ha state aggiunde jndr'à le [[Special:Watchlist|pàggene condrollate]].\nLe cangiaminde future a sta pàgene e 'a pàgene de le 'ngazzaminde associete le puè acchià aqquà.",
     "removewatch": "Live da le pàggene condrollate",
     "allmessagesname": "Nome",
     "allmessagesdefault": "Teste de default",
     "allmessagescurrent": "Teste corrende",
-    "allmessagestext": "Queste jè 'na liste de tutte le messagge d'u sisteme ca se ponne acchià jndr'à le namespace de MediaUicchi.\nPe piacere vè vide [https://www.mediawiki.org/wiki/Localisation Localizzazione de MediaUicchi] e [//translatewiki.net translatewiki.net] ce tu vuè ccu condrebbuisce a 'a localizzazione de MediaUicchi.",
+    "allmessagestext": "Queste jè 'na liste de tutte le messagge d'u sisteme ca se ponne acchià jndr'à le namespace de MediaUicchi.\nPe piacere vè vide [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Localizzazione de MediaUicchi] e [//translatewiki.net translatewiki.net] ce tu vuè ccu condrebbuisce a 'a localizzazione de MediaUicchi.",
     "allmessagesnotsupportedDB": "Sta pàgene non ge pò essere ausate purcè '''$wgUseDatabaseMessages''' ha state disabbilitate.",
     "allmessages-filter-legend": "Filtre",
     "allmessages-filter": "Filtre cu 'nu state personalizzate:",
index 49298f5..6b27db6 100644 (file)
@@ -1,6 +1,69 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "Ahonc",
+            "Aleksandrit",
+            "AlexSm",
+            "Alexandr Efremov",
+            "Altai uul",
+            "Amikeco",
+            "Amire80",
+            "Askarmuk",
+            "BellaIlabekyan",
+            "Bouron",
+            "Chilin",
+            "Cinemantique",
+            "Claymore",
+            "Cryptocoryne",
+            "DCamer",
+            "Dim Grits",
+            "Don Alessandro",
+            "Eleferen",
+            "Erdemaslancan",
+            "EugeneZelenko",
+            "Eugrus",
+            "Ferrer",
+            "Flrn",
+            "G0rn",
+            "Geitost",
+            "Grigol",
+            "Haffman",
+            "HalanTul",
+            "Ignatus",
+            "Illusion",
+            "Iluvatar",
+            "Iniquity",
+            "Innv",
+            "Ivan Shmakov",
+            "JenVan",
+            "KPu3uC B Poccuu",
+            "Kaganer",
+            "Kalan",
+            "KorneySan",
+            "Kv75",
+            "Lockal",
+            "Lunacy1911",
+            "Matma Rex",
+            "MaxSem",
+            "Milicevic01",
+            "NBS",
+            "Nemo bis",
+            "Okras",
+            "Ole Yves",
+            "Putnik",
+            "Rave",
+            "Rubin16",
+            "Soul Train",
+            "Spider",
+            "Sunpriat",
+            "VasilievVV",
+            "Volkov",
+            "Ytsukeng Fyvaprol",
+            "Александр Сигачёв",
+            "ОйЛ",
+            "Умар",
+            "לערי ריינהארט"
+        ]
     },
     "tog-underline": "Подчёркивание ссылок:",
     "tog-hideminor": "Скрывать малые правки в списке свежих правок",
     "pool-timeout": "Истекло время ожидания блокировки",
     "pool-queuefull": "Накопитель запросов полон",
     "pool-errorunknown": "Неизвестная ошибка",
+    "pool-servererror": "Служба счётчика пула недоступна ($1).",
     "aboutsite": "Описание {{grammar:genitive|{{SITENAME}}}}",
     "aboutpage": "Project:Описание",
     "copyright": "Содержимое доступно по лицензии $1 (если не указано иное).",
     "prefs-skin": "Тема оформления",
     "skin-preview": "Предпросмотр",
     "datedefault": "По умолчанию",
-    "prefs-beta": "Бета-возможности",
     "prefs-datetime": "Дата и время",
     "prefs-labs": "Экспериментальные возможности",
     "prefs-user-pages": "Страницы участника",
     "listgrouprights-removegroup-self": "может удалять свою учётную запись из {{PLURAL:$2|1=группы|групп}}: $1",
     "listgrouprights-addgroup-self-all": "Может добавлять все группы к своей учётной записи",
     "listgrouprights-removegroup-self-all": "может удалять все группы со своей учётной записи",
+    "trackingcategories": "Отслеживающие категории",
+    "trackingcategories-summary": "На этой странице перечислены отслеживающие категории, которые автоматически заполняются программным обеспечением MediaWiki. Их можно переименовать, изменив соответствующие системные сообщения в пространстве имён {{ns:8}}.",
+    "trackingcategories-msg": "Отслеживающая категория",
+    "trackingcategories-name": "Имя сообщения",
+    "trackingcategories-desc": "Критерий включения в категорию",
+    "noindex-category-desc": "На странице имеется «волшебное слово» <nowiki>__NOINDEX__</nowiki> (и страница находится в пространстве имён, где разрешён этот флаг), поэтому она не индексируются поисковыми роботами.",
+    "index-category-desc": "На странице имеется «волшебное слово» __INDEX__ (и страница находится в пространстве имён, где разрешён этот флаг), поэтому она индексируются поисковыми роботами в тех случаях, когда этого обычно не происходит.",
+    "post-expand-template-inclusion-category-desc": "После показа всех шаблонов размер страницы станет больше, чем $wgMaxArticleSize, поэтому некоторые шаблоны не были показаны полностью.",
+    "post-expand-template-argument-category-desc": "После раскрытия аргумента шаблона (что-нибудь в тройных фигурных скобках, например, {{{Foo}}}), страница станет больше, чем $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "На странице используется слишком много ресурсоёмких функций (таких, как <code>#ifexist</code>). Подробнее — на странице [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Категория добавляется, если страница содержит некорректную файловую ссылку (ссылку на несуществующий файл).",
+    "hidden-category-category-desc": "Это категория с добавленной меткой <nowiki>__HIDDENCAT__</nowiki> в ней, что по умолчанию предотвращает её отображение на страницах в разделе категорий.",
+    "trackingcategories-nodesc": "Описание отсутствует.",
+    "trackingcategories-disabled": "Категория отключена",
     "mailnologin": "Адрес для отправки отсутствует",
     "mailnologintext": "Вы должны [[Special:UserLogin|представиться системе]] и иметь действительный адрес электронной почты в ваших [[Special:Preferences|настройках]], чтобы иметь возможность отправлять электронную почту другим участникам.",
     "emailuser": "Письмо участнику",
     "nowatchlist": "Ваш список наблюдения пуст.",
     "watchlistanontext": "Вы должны $1, чтобы просмотреть или отредактировать список наблюдения.",
     "watchnologin": "Нужно представиться системе",
-    "watchnologintext": "Вы должны [[Special:UserLogin|представиться системе]], чтобы иметь возможность изменять свой список наблюдения",
     "addwatch": "Добавить в список наблюдения",
     "addedwatchtext": "Страница «[[:$1]]» была добавлена в ваш [[Special:Watchlist|список наблюдения]].\nТам будут отмечаться последующие изменения этой страницы, а также связанной с ней страницы обсуждения.",
     "removewatch": "Удалить из списка наблюдения",
     "sp-contributions-newbies-sub": "С новых учётных записей",
     "sp-contributions-newbies-title": "Вклад с недавно созданных учётных записей",
     "sp-contributions-blocklog": "блокировки",
+    "sp-contributions-suppresslog": "удалённый вклад участника",
     "sp-contributions-deleted": "удалённые правки",
     "sp-contributions-uploads": "загрузки",
     "sp-contributions-logs": "журналы",
     "sp-contributions-blocked-notice": "Этот участник в данный момент заблокирован. Ниже приведена последняя запись из журнала блокировок:",
     "sp-contributions-blocked-notice-anon": "Этот IP-адрес в данный момент заблокирован.\nНиже приведена последняя запись из журнала блокировок:",
     "sp-contributions-search": "Поиск вклада",
-    "sp-contributions-suppresslog": "удалённый вклад участника",
     "sp-contributions-username": "IP-адрес или имя участника:",
     "sp-contributions-toponly": "Показывать только правки, являющиеся последними версиями",
     "sp-contributions-newonly": "Показывать только правки, являющиеся созданием страниц",
     "allmessagesname": "Сообщение",
     "allmessagesdefault": "Текст по умолчанию",
     "allmessagescurrent": "Текущий текст",
-    "allmessagestext": "Это список системных сообщений, доступных в пространстве имён «MediaWiki».\nЕсли вы хотите внести вклад в общую локализацию MediaWiki, пожалуйста, посетите страницу [https://www.mediawiki.org/wiki/Localisation описания локализации] и проект [//translatewiki.net translatewiki.net].",
+    "allmessagestext": "Это список системных сообщений, доступных в пространстве имён «MediaWiki».\nЕсли вы хотите внести вклад в общую локализацию MediaWiki, пожалуйста, посетите страницу [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation описания локализации] и проект [//translatewiki.net translatewiki.net].",
     "allmessagesnotsupportedDB": "Эта страница недоступна, так как отключена опция '''$wgUseDatabaseMessages'''.",
     "allmessages-filter-legend": "Фильтр",
     "allmessages-filter": "Фильтр по статусу изменения:",
     "version-entrypoints": "Адреса точек входа",
     "version-entrypoints-header-entrypoint": "Точка входа",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Путь к статье]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Путь к скрипту]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Путь к статье]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Путь к скрипту]",
     "redirect": "Перенаправление с файла, участника, страницы или идентификатора версии",
     "redirect-legend": "Перенаправление на файл или страницу",
     "redirect-summary": "Эта служебная страница перенаправляет на файл (с имени файла), страницу (с идентификатора версии или страницы) или страницу участника (с числового идентификатора участника). Использование: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] или [[{{#Special:Redirect}}/user/101]].",
     "expand_templates_remove_nowiki": "Подавлять теги <nowiki> в результате",
     "expand_templates_generate_xml": "Показать дерево разбора XML",
     "expand_templates_generate_rawhtml": "Показать HTML",
-    "expand_templates_preview": "Предпросмотр",
-    "trackingcategories": "Отслеживающие категории",
-    "trackingcategories-summary": "На этой странице перечислены отслеживающие категории, которые автоматически заполняются программным обеспечением MediaWiki. Их можно переименовать, изменив соответствующие системные сообщения в пространстве имён {{ns:8}}.",
-    "trackingcategories-msg": "Отслеживающая категория",
-    "trackingcategories-name": "Имя сообщения",
-    "trackingcategories-desc": "Критерий включения в категорию",
-    "broken-file-category-desc": "Категория добавляется, если страница содержит некорректную файловую ссылку (ссылку на несуществующий файл).",
-    "trackingcategories-nodesc": "Описание отсутствует.",
-    "trackingcategories-disabled": "Категория отключена"
+    "expand_templates_preview": "Предпросмотр"
 }
index 0889819..ec805a8 100644 (file)
     "prefs-skin": "Взгляд",
     "skin-preview": "Попереднїй нагляд",
     "datedefault": "Імпліцітный",
-    "prefs-beta": "Бета-функції",
     "prefs-datetime": "Датум і час",
     "prefs-labs": "Експеріменталны функції",
     "prefs-user-pages": "Сторінкы хоснователя",
     "nowatchlist": "Ваш список слїдованых сторінок є порожнїй.",
     "watchlistanontext": "Про перезераня ці управу списку слїдованых сторінок ся мусите $1.",
     "watchnologin": "Не сьте приголошеный(а)",
-    "watchnologintext": "Про слїдованя сторінок ся мусите [[Special:UserLogin|приголосити]].",
     "addwatch": "Придати до списку слїдованых сторінок",
     "addedwatchtext": "Сторінка «[[:$1]]» была придана до вашого [[Special:Watchlist|списку слїдованых]].\nБудучі зміны той статї і з нёв повязаной сторінков діскузії будуть зображены у тім списку.",
     "removewatch": "Вымазати зо списку слїдованых сторінок",
     "allmessagesname": "Назва",
     "allmessagesdefault": "Штандартный текст",
     "allmessagescurrent": "Актуалный текст",
-    "allmessagestext": "Тото є список вшыткых повідомлїнь доступных в просторї назв «MediaWiki».\nКідь хочете приспівати ку локалізації софтверу MediaWiki, навщівте [https://www.mediawiki.org/wiki/Localisation локалізачну сторінку на mediawiki.org] і [//translatewiki.net сервер server translatewiki.net].",
+    "allmessagestext": "Тото є список вшыткых повідомлїнь доступных в просторї назв «MediaWiki».\nКідь хочете приспівати ку локалізації софтверу MediaWiki, навщівте [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation локалізачну сторінку на mediawiki.org] і [//translatewiki.net сервер server translatewiki.net].",
     "allmessagesnotsupportedDB": "{{ns:special}}:AllMessages не є підпороване, бо wgUseDatabaseMessages є выпнуте.",
     "allmessages-filter-legend": "Філтер",
     "allmessages-filter": "Філтер за станом:",
index f31c634..45fea28 100644 (file)
     "pool-timeout": "संरक्षणार्थं कालावधिः समाप्ता",
     "pool-queuefull": "Pool इति पङ्कतिः पूर्णा अस्ति ।",
     "pool-errorunknown": "अज्ञातदोषः",
+    "pool-servererror": "Pool counter सेवा नोपलभ्यते ।",
     "aboutsite": "{{SITENAME}} विषयकं",
     "aboutpage": "Project:विषयकम्",
     "copyright": "भिन्नोल्लखः न भवति तावत् $1 अत्र उल्लेखो भवति ।",
     "noemailcreate": "भवता/भवत्या मान्यः ई-पत्रसङ्केतः दातव्यः ।",
     "passwordsent": "\"$1\" इत्यस्य पञ्जीकृताय ई-पत्रसङ्केताय नवीनः कूटशब्दः प्रेषितः अस्ति । \n\nकृपया तस्य कूटशब्दस्य उपयोगेन पुनः प्रविश्यताम् ।",
     "blocked-mailpassword": "भवतः/भवत्याः अन्तर्जालसंविद् (IP) प्रतिबन्धितः अस्ति । \nसम्पादनाय अनुमतिः नास्ति, अतः कूटशब्दस्य पुनःप्राप्तिः भवितुं नार्हति ।",
-    "eauthentsent": "भवता à¤ªà¥\8dरदतà¥\8dतà¥\87 à¤µà¤¿à¤¦à¥\8dयà¥\81तà¥\8dपतà¥\8dर-सà¤\82à¤\95à¥\87तà¥\87 à¤\8fà¤\95à¤\83 à¤ªà¤°à¤¿à¤ªà¥\81षà¥\8dà¤\9fिरà¥\82पà¤\83 à¤µà¤¿à¤¦à¥\8dयà¥\81तà¥\8dसनà¥\8dदà¥\87शà¤\83 à¤ªà¥\8dरà¥\87षितà¥\8bऽसà¥\8dति।\nà¤\85नà¥\8dयà¤\83 à¤\95शà¥\8dà¤\9aिदà¥\8d à¤µà¤¿à¤¦à¥\8dयà¥\81तà¥\8dसनà¥\8dदà¥\87शà¤\83 à¤ªà¥\8dरà¥\87षितà¥\8b à¤­à¤µà¥\87तà¥\8d à¤\87तà¥\8dयà¥\87तदरà¥\8dथà¤\82 à¤­à¤µà¤¤à¤¾ à¤¤à¤¤à¥\8dसनà¥\8dदà¥\87शà¥\87 à¤ªà¥\8dरदतà¥\8dताà¤\83 à¤¨à¤¿à¤°à¥\8dदà¥\87शाà¤\83 à¤ªà¤¾à¤²à¤¿à¤¤à¤µà¥\8dयाà¤\83, à¤¯à¥\87न à¤¹à¤¿ à¤¸à¤¾ à¤µà¤¿à¤¦à¥\8dयà¥\81तà¥\8dसनà¥\8dदà¥\87शलà¥\87à¤\96ा à¤­à¤µà¤¦à¥\80या à¤\8fव à¤\87ति à¤¸à¤¤à¥\8dयापितà¥\8b à¤­à¤µà¥\87तà¥\8d।",
-    "throttled-mailpassword": "पà¥\82रà¥\8dवतनायाà¤\82 {{PLURAL:$1|हà¥\8bरसà¥\8dय|$1 à¤¹à¥\8bराणाà¤\82}} à¤\85वधà¥\8c à¤­à¤µà¤¦à¤°à¥\8dथà¤\82 à¤\8fà¤\95à¤\83 à¤\95à¥\82à¤\9fशबà¥\8dद-पà¥\81नà¤\83सà¥\8dमारà¤\95मà¥\8d à¤ªà¥\8dरà¥\87षितà¥\8bऽसà¥\8dति।\nदà¥\81षà¥\8dपà¥\8dरयà¥\8bà¤\97ादà¥\8d à¤µà¤¾à¤°à¤¯à¤¿à¤¤à¥\81à¤\82 à¤ªà¥\8dरति {{PLURAL:$1|हà¥\8bरà¥\87|$1 à¤¹à¥\8bरà¥\87षà¥\81}} à¤\95à¥\87वलमà¥\8d à¤\8fà¤\95à¤\82 à¤\95à¥\82à¤\9fशबà¥\8dद-पà¥\81नà¤\83सà¥\8dमारà¤\95à¤\82 à¤ªà¥\8dरà¥\87षयितà¥\81à¤\82 à¤¶à¤\95à¥\8dयतà¥\87।",
-    "mailerror": "विदà¥\8dयà¥\81तà¥\8dसनà¥\8dदà¥\87शपà¥\8dरà¥\87षणà¥\87 à¤¤à¥\8dरà¥\81à¤\9fिà¤\83: $1",
-    "acct_creation_throttle_hit": "à¤\97तà¥\87 à¤¦à¤¿à¤µà¤¸à¥\87 à¤\85सà¥\8dयाà¤\82 à¤µà¤¿à¤\95à¥\8dयाà¤\82 à¤­à¤µà¤¤à¤\83 à¤\86à¤\87पà¥\80सà¤\82à¤\95à¥\87तमà¥\8d à¤\86धà¥\83तà¥\8dय à¤\86à¤\97नà¥\8dतà¥\81à¤\95ाà¤\83 {{PLURAL:$1|1 à¤²à¥\87à¤\96ाà¤\82|$1 à¤²à¥\87à¤\96ाà¤\83}} à¤¸à¥\83à¤\9cितवनà¥\8dतà¤\83 à¤¸à¤¨à¥\8dति। à¤¤à¤¦à¥\87व à¤\8fततà¥\8dसमयावधà¥\8c à¤\85धिà¤\95तममà¥\8d à¤\85नà¥\81मतमà¥\8d।\nतसà¥\8dमातà¥\8d, à¤\8fतदà¥\8d à¤\86à¤\87पà¥\80सà¤\82à¤\95à¥\87तà¥\87 à¤\86à¤\97नà¥\8dतà¥\81à¤\95ाà¤\83 à¤\8fततà¥\8dसमयà¥\87 à¤¨à¤¾à¤§à¤¿à¤\95à¤\82 à¤²à¥\87à¤\96ाà¤\82 à¤¸à¥\8dरषà¥\8dà¤\9fà¥\81à¤\82 à¤¶à¤\95à¥\8dनà¥\81वनà¥\8dति।",
-    "emailauthenticated": "भवतः विद्युत्सन्देशसंकेतः $2 दिनांके $3 वादने परिपुष्टीकृतः आसीत्।",
-    "emailnotauthenticated": "भवतà¤\83 à¤µà¤¿à¤¦à¥\8dयà¥\81तà¥\8dसà¤\82दà¥\87श-सà¤\82à¤\95à¥\87तà¤\83 à¤\85धà¥\81नायावतà¥\8d à¤ªà¤°à¤¿à¤ªà¥\81षà¥\8dà¤\9fà¥\80à¤\95à¥\83तà¤\83 à¤¨à¤¾à¤¸à¥\8dति।\nà¤\85धसà¥\8dतातà¥\8d à¤\89लà¥\8dलिà¤\96ितà¥\87षà¥\81 à¤\95सà¥\8dमिà¤\82शà¥\8dà¤\9aिदपि à¤µà¤¿à¤·à¤¯à¥\87 à¤­à¤µà¤¾à¤¨à¥\8d à¤µà¤¿à¤¦à¥\8dयà¥\81तà¥\8dसनà¥\8dदà¥\87शà¤\82 à¤ªà¥\8dरषयितà¥\81à¤\82 à¤¨ à¤¶à¤\95à¥\8dनà¥\8bसि।",
-    "noemailprefs": "à¤\8fताà¤\83 à¤¸à¥\81विधाà¤\83 à¤\95ारà¥\8dयशà¥\80लाà¤\83 à¤­à¤µà¥\87यà¥\81à¤\83 à¤\87तà¥\8dयà¥\87तदरà¥\8dथà¤\82 à¤¸à¥\8dवà¤\95à¥\80यà¥\87 à¤µà¤°à¥\80याà¤\82सि à¤\87ति à¤ªà¥\8dरभाà¤\97à¥\87 à¤µà¤¿à¤¦à¥\8dयà¥\81तà¥\8dसनà¥\8dदà¥\87शसà¤\82à¤\95à¥\87त à¤\8fà¤\95à¤\83 à¤¦à¤¾à¤¤à¤µà¥\8dयà¤\83।",
-    "emailconfirmlink": "सà¥\8dवà¤\95à¥\80यà¤\82 à¤µà¤¿à¤¦à¥\8dयà¥\81तà¥\8dसनà¥\8dदà¥\87शसà¤\82à¤\95à¥\87तà¤\82 à¤ªà¥\8dरमाणà¥\80à¤\95रà¥\8bतà¥\81।",
-    "invalidemailaddress": "पà¥\8dरतà¥\80यतà¥\87 à¤¯à¤¦à¥\8d à¤µà¤¿à¤¦à¥\8dयà¥\81तà¥\8dसनà¥\8dदà¥\87शसà¤\82à¤\95à¥\87तà¤\83 à¤\85मानà¥\8dयà¥\87 à¤ªà¥\8dरारà¥\82पà¥\87 à¤µà¤¿à¤¦à¥\8dयतà¥\87। à¤\85तà¤\8fव à¤\8fततà¥\8d à¤¸à¥\8dवà¥\80à¤\95रà¥\8bतà¥\81à¤\82 à¤¨ à¤¶à¤\95à¥\8dयतà¥\87।\nà¤\95à¥\83पया à¤\8fà¤\95à¤\82 à¤ªà¥\8dरारà¥\82पसमà¥\8dमतà¤\82 à¤¸à¤\82à¤\95à¥\87तà¤\82 à¤¦à¤¦à¤¾à¤¤à¥\81, à¤\85थवा à¤¤à¤¤à¥\8d à¤\95à¥\8dषà¥\87तà¥\8dरà¤\82 à¤°à¤¿à¤\95à¥\8dतमà¥\87व à¤\95रà¥\8bतà¥\81।",
-    "cannotchangeemail": "अस्मिन् विकिमध्ये सदस्य-ईपत्र-सङ्केतः परिवर्तयितुं न शक्यते ।",
-    "emaildisabled": "स्थानमेतत् विद्युन्मनपत्रं न प्रेषयति ।",
+    "eauthentsent": "à¤\85धिà¤\95à¥\83तपà¥\81षà¥\8dà¤\9fà¥\88 à¤­à¤µà¤¤à¤¾/भवतà¥\8dया à¤ªà¤\9eà¥\8dà¤\9cà¥\80à¤\95à¥\83ताय à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87ताय à¤\88-पतà¥\8dरà¤\82 à¤ªà¥\8dरà¥\87षितमसà¥\8dति à¥¤ à¤¤à¤¸à¥\8dय à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87तसà¥\8dयà¥\88व à¤\87तà¤\83 à¤ªà¤°à¤®à¥\8d à¤\89पयà¥\8bà¤\97à¤\83 à¤­à¤µà¤¤à¥\81 à¤\87ति à¤\87à¤\9aà¥\8dà¤\9bति à¤\9aà¥\87तà¥\8d à¤ªà¥\8dरà¥\87षितà¥\87 à¤\88-पतà¥\8dरà¥\87 à¤¯à¤¥à¤¾ à¤²à¤¿à¤\96ितमसà¥\8dति, à¤¤à¤¥à¤¾ à¤\95रà¥\8bतà¥\81 à¥¤ à¤\8fवà¤\82 à¤¤à¤¸à¥\8dय à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87तसà¥\8dय à¤\85धिà¤\95à¥\83तपà¥\81षà¥\8dà¤\9fता à¤­à¤µà¤¿à¤·à¥\8dयति ।",
+    "throttled-mailpassword": "à¤\95à¥\82à¤\9fशबà¥\8dदà¤\82 à¤ªà¤°à¤¿à¤°à¥\8dवतितà¥\81à¤\82 à¤­à¤µà¤¤à¤\83/भवतà¥\8dयाà¤\83 à¤ªà¤\9eà¥\8dà¤\9cà¥\80à¤\95à¥\83ताय à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87ताय à¤\85नà¥\8dतिम{{PLURAL:$1|हà¥\8bरायाà¤\82|$1 à¤¹à¥\8bरासà¥\81}} à¤¨à¥\82तनà¤\95à¥\82à¤\9fशबà¥\8dदà¤\83 à¤ªà¥\8dरà¥\87षितà¤\83 à¤\85सà¥\8dति à¥¤\n\nदà¥\81रà¥\81पयà¥\8bà¤\97à¤\82 à¤µà¤¾à¤°à¤¯à¤¿à¤¤à¥\81मà¥\8d à¤ªà¥\8dरति {{PLURAL:$1|हà¥\8bरायाà¤\82|$1 à¤¹à¥\8bरासà¥\81}} à¤\95à¥\87वलमà¥\8d à¤\8fà¤\95मà¥\8d à¤\88-पतà¥\8dरà¤\82 à¤ªà¥\8dरà¥\87षà¥\8dयतà¥\87 ।",
+    "mailerror": "à¤\88-पतà¥\8dरसमà¥\8dपà¥\8dरà¥\87षणà¥\87 à¤¦à¥\8bषà¤\83 : $1",
+    "acct_creation_throttle_hit": "à¤\9aतà¥\81à¥\8dरà¥\8dविà¤\82शतिà¤\98णà¥\8dà¤\9fासà¥\81 à¤\85सà¥\8dय à¤¸à¤\99à¥\8dà¤\97णà¤\95सà¥\8dय à¤\86नà¥\8dतरà¥\8dà¤\9cालसà¤\82विदा (IP) {{PLURAL:$1|1 à¤¯à¥\8bà¤\9cà¤\95à¤\83|$1 à¤¯à¥\8bà¤\9cà¤\95ाà¤\83}} à¤¸à¤¦à¤¸à¥\8dयताà¤\82 à¤ªà¥\8dरापà¥\8dतवानà¥\8d/वनà¥\8dतà¤\83 à¥¤ à¤\85दà¥\8dय à¤\87तà¥\8bपि à¤\85धिà¤\95सदसà¥\8dयाà¤\83 à¤ªà¥\8dरापà¥\8dतà¥\81à¤\82 à¤¨ à¤¶à¤\95à¥\8dयनà¥\8dतà¥\87 ।",
+    "emailauthenticated": "$2 दिनाङ्के $3 वादने भवतः/भवत्याः ई-पत्रसङ्केतः पुष्टितः ।",
+    "emailnotauthenticated": "à¤\8fतावता à¤­à¤µà¤¤à¤\83/भवतà¥\8dयाà¤\83 à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87तà¤\83 à¤ªà¥\81षà¥\8dà¤\9fà¤\83 à¤¨à¤¾à¤­à¤µà¤¤à¥\8d à¥¤ \nनिमà¥\8dनलिà¤\96िताय à¤¨ à¤\95िमपि à¤\88-पतà¥\8dरà¤\82 à¤ªà¥\8dरà¥\87षयितà¥\81à¤\82 à¤¶à¤\95à¥\8dयतà¥\87 ।",
+    "noemailprefs": "à¤\8fनà¤\82 à¤µà¤¿à¤\95लà¥\8dपà¤\82 à¤¸à¤®à¤°à¥\8dथितà¥\81मà¥\8d \"à¤\87षà¥\8dà¤\9fतमानि\" à¤®à¤§à¥\8dयà¥\87 à¤­à¤µà¤¤à¤\83/भवतà¥\8dयाà¤\83 à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87तसà¥\8dय à¤\89लà¥\8dलà¥\87à¤\96à¤\83 à¤\86वशà¥\8dयà¤\95à¤\83 ।",
+    "emailconfirmlink": "सà¥\8dवसà¥\8dय à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95तà¤\82 à¤ªà¥\81षà¥\8dà¤\9fà¤\82 à¤\95रà¥\8bतà¥\81",
+    "invalidemailaddress": "à¤\8fषà¤\83 à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87तà¤\83 à¤\86वशà¥\8dयà¤\95पà¥\8dरारà¥\81पà¥\87 à¤¨à¤¾à¤¸à¥\8dति à¥¤ à¤\95à¥\83पया à¤¯à¥\8bà¤\97à¥\8dयपà¥\8dरारà¥\81पानà¥\81à¤\95à¥\82लà¤\83 à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87तà¤\83 à¤²à¤¿à¤\96à¥\8dयतामà¥\8d à¥¤ à¤\85थवा à¤¸à¤¾ à¤ªà¥\87à¤\9fिà¤\95ा à¤°à¤¿à¤\95à¥\8dता à¤¤à¥\8dयà¤\9cà¥\8dयतामà¥\8d ।",
+    "cannotchangeemail": "अस्मिन् विकि-जालस्थाने योजक-ईपत्र-सङ्केताः परिवर्तयितुं न शक्यन्ते ।",
+    "emaildisabled": "स्थानमेतत् (site) ई-पत्रं प्रेषयितुं न शक्यते ।",
     "accountcreated": "सदस्यता प्राप्ता",
-    "accountcreatedtext": "$1 इत्येतस्य सदस्यता प्राप्ता अस्ति।",
-    "createaccount-title": "{{SITENAME}} à¤\87तà¥\8dयतà¥\8dर सदस्यता प्राप्यताम्",
-    "createaccount-text": "भवतः विद्युत्संदेशसंकेतार्थं केनचित् $2 इति जनेन {{SITENAME}} ($4) इत्यत्र  $3 इति कूटशब्दं दत्वा लेखा सृष्टाऽस्ति।\nभवता अधुना प्रवेशं कृत्वा कूटशब्दः परिवर्तितव्यः।\n\nचेत् सा लेखा त्रुटिवशात् सृष्टा, तर्हि भवान् एतत्सन्देशम् उपेक्षितुं शक्नोति।\n\nTranslation in English: \nSomeone created an account for your e-mail address on {{SITENAME}} ($4) named \"$2\", with password \"$3\".\nYou should log in and change your password now.\n\nYou may ignore this message, if this account was created in error.",
-    "usernamehasherror": "प्रयोक्तृनाम्नि हेश् इत्यक्षरं (#) न अन्तर्भवितुं शक्नोति।",
-    "login-throttled": "भवता सद्य एव प्रभूततया प्रवेशप्रयासाः कृताः।\nकृपया पुनः प्रयासार्थं किंचित् प्रतीक्षताम्।",
-    "login-abort-generic": "भवतः प्रवेशप्रयासः विफलीभूतः - परित्यक्तः",
+    "accountcreatedtext": "[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) कृते \"योजसम्भाषणम्\" इति पृष्ठं रचितम् ।",
+    "createaccount-title": "{{SITENAME}} à¤\95à¥\83तà¥\87 सदस्यता प्राप्यताम्",
+    "createaccount-text": "{{SITENAME}} ($4) इत्यत्र, \"$2\" नाम्ना, \"$3\" कूटशब्देन, च कोऽपि भवतः/भवत्याः ई-पत्रसङ्केतस्य उपयोगं कृत्वा सदस्यतां प्रापत् ।\nअधुना भवान्/भवती प्रवेशं कृत्वा गुप्तसङ्ख्यां परिवर्तयितं शक्नोति ।\nएषा सदस्यताप्राप्तिः क्षत्या अभवत् चेत्, एनं सन्देशम् अवगणोतु ।",
+    "usernamehasherror": "# इत्यस्य सङ्केतस्य उपयोगः योजकनाम्नि कर्तुं न शक्यते ।",
+    "login-throttled": "भवता/भवत्या अत्यधिकाः प्रवेशप्रयासाः कृताः । \nकृपया $1 कालं यावत् प्रतिक्षां करोतु ।",
+    "login-abort-generic": "भवतः/भवत्याः प्रवेशप्रयासः विफलीभूतः - परित्यक्तः",
     "loginlanguagelabel": "भाषा : $1",
-    "suspicious-userlogout": "भवतः सत्राद् बहिर्गमनस्य अनुरोधः अस्वीकृतोऽस्ति, यस्मादेतत् भग्नादेकस्मात् ब्राउज़र्तः अथवा स्वल्पसञ्चयि-प्रॉक्सितः प्रेषित आसीत्।",
+    "suspicious-userlogout": "भवतः/भवत्याः \"निर्गमनम्\" इत्यस्य विनतिं स्वीकर्तुं न शक्यते । कारणं भवता/भवत्या एषा विनतिः तृटियुक्तगवेक्षणात् प्रतिनिधि(proxy)-तः वा कृता ।",
+    "createacct-another-realname-tip": "वास्तविकनाम ऐच्छकम् अस्ति । भवान्/भवती एनं विकल्पं समर्थयति चेत्, भवतः/भवत्याः योगदानश्रेयस्य उल्लेखसमये अस्य उपयोगः भविष्यति ।",
     "pt-login": "प्रविश्यताम्",
     "pt-login-button": "प्रविश्यताम्",
     "pt-createaccount": "सदस्यता प्राप्यताम्",
     "pt-userlogout": "निर्गमनम्",
-    "php-mail-error-unknown": "पीएच्पी इत्येतस्य mail() फलने अज्ञाता काऽपि त्रुटिर्जाता।",
-    "user-mail-no-addy": "ईपत्रसङ्केतं विना ईपत्रप्रेषणस्य प्रयासः कृतः ।",
-    "user-mail-no-body": "भवता खलु विद्युत्पत्रं रिक्ततया अथवा अतिलघुरूपेण प्रेषितुं चेष्टितम्।",
+    "php-mail-error-unknown": "PHP लिप्याः मुख्यनियोगे (in main()) अज्ञातत्रुटिः प्राप्ता ।",
+    "user-mail-no-addy": "ई-पत्रसङ्केतं विना ई-पत्रप्रेषणस्य प्रयासः कृतः ।",
+    "user-mail-no-body": "भवता/भवत्या रिक्तं लघुसन्देशयुक्तं वा ई-पत्रं प्रेषणस्य प्रयासः कृतः ।",
     "changepassword": "कूटशब्दः परिवर्त्यताम्",
-    "resetpass_announce": "भवानà¥\8d à¤¤à¤¾à¤¤à¥\8dà¤\95ालिà¤\95-à¤\88पतà¥\8dरदà¥\8dवारा à¤\85तà¥\8dर à¤ªà¥\8dरविषà¥\8dà¤\9fà¤\83 à¤\85सà¥\8dति à¥¤\nपà¥\8dरवà¥\87शनसà¥\8dय à¤¸à¤®à¤¾à¤ªà¤¨à¤¾à¤¯ à¤­à¤µà¤¤à¤¾ à¤\85तà¥\8dर à¤¨à¥\82तनà¤\83 à¤\95à¥\82à¤\9fशबà¥\8dदà¤\83 à¤¦à¤¾à¤¤à¤µà¥\8dयà¤\83:",
+    "resetpass_announce": "सदसà¥\8dयतापà¥\8dरà¤\95à¥\8dरियाà¤\82 à¤ªà¥\82रà¥\8dणà¤\82 à¤\95रà¥\8dतà¥\81à¤\82 à¤¨à¥\82तनà¤\83 à¤\95à¥\82à¤\9fशबà¥\8dदà¤\83 à¤²à¥\87à¤\96नà¥\80यà¤\83 à¤\8fव à¥¤",
     "resetpass_text": "<!-- पाठं अत्र लिखतु -->",
-    "resetpass_header": "सदस्यतायाः कूटशब्दः परिवर्त्यताम्",
+    "resetpass_header": "सदस्यतायाः कूटशब्दः परिवर्त्यताम्",
     "oldpassword": "पुरातनः कूटशब्दः",
     "newpassword": "नूतनः कूटशब्दः",
-    "retypenew": "नूतनः कूटशब्दः पुनः लिख्यताम्:",
-    "resetpass_submit": "कूटशब्दः योज्यतां प्रविश्यतां च",
-    "changepassword-success": "भवतः कूटशब्दः सफलतया परिवर्तितः!\nअधुना भवान् प्रवेश्यते ...",
+    "retypenew": "नूतनकूटशब्दः पुनः लिख्यताम् :",
+    "resetpass_submit": "कूटशब्दः योज्यतां, प्रविश्यतां च",
+    "changepassword-success": "भवतः/भवत्याः कूटशब्दः सफलतया परिवर्तितः ।",
+    "changepassword-throttled": "भवता/भवत्या अत्यधिकाः प्रवेशप्रयासाः कृताः । \nकृपया $1 कालं यावत् प्रतिक्षां करोतु ।",
     "resetpass_forbidden": "कूटशब्दाः परिवर्तयितुं न शक्यन्ते",
-    "resetpass-no-info": "भवता à¤\8fततà¥\8dपà¥\83षà¥\8dठà¤\82 à¤ªà¥\8dरतà¥\8dयà¤\95à¥\8dषतया à¤¸à¤®à¥\8dपà¥\8dरापà¥\8dतà¥\81à¤\82 à¤ªà¥\8dरवà¥\87शà¤\83 à¤\85वशà¥\8dयमà¥\87व à¤\95रà¥\8dतà¥\8dतवà¥\8dयà¤\83।",
+    "resetpass-no-info": "à¤\8fततà¥\8d à¤ªà¥\83षà¥\8dठà¤\82 à¤¸à¤®à¥\8dपादयितà¥\81à¤\82 à¤ªà¥\8dरवà¥\87शà¤\83 à¤\85निवारà¥\8dयà¤\83 ।",
     "resetpass-submit-loggedin": "कूटशब्दः परिवर्त्यताम्",
     "resetpass-submit-cancel": "निरस्यताम्",
-    "resetpass-wrong-oldpass": "अल्पकालीनः अथवा सद्यःकालीनः कूटशब्दः अमान्यः अस्ति।\nभवता पूर्वे एव सफलतया स्वकीयः कूटशब्दः परिवर्तितः स्यात्, अथवा एकः नूतनः अल्पकालीनः कूटशब्दः प्रार्थितः स्यात्।",
-    "resetpass-temp-password": "अस्थिर रहस्यवाक् :",
-    "passwordreset": "कूटशब्द पुनःस्थापनम्",
-    "passwordreset-legend": "कूटशब्द पुनःस्थापनम्",
-    "passwordreset-disabled": "अस्मिन् विक्यां कूटशब्द पुनःस्थापनं असमर्थीकृतमस्ति।",
-    "passwordreset-username": "योजकनामन्:",
+    "resetpass-wrong-oldpass": "अल्पकालीनः सद्यःकालीनः वा कूटशब्दः अमान्यः अस्ति ।\nभवता/भवत्या पूर्वम् एव सफलतया स्वकीयः कूटशब्दः परिवर्तितः स्यात्, एकः नूतनः अल्पकालीनः कूटशब्दः प्रार्थितः स्यात् वा ।",
+    "resetpass-recycled": "कूटशब्दं परिवर्तनावसरे नवीनकूटशब्दे पुरानतकूटशब्दस्य उपयोगं मा करोतु ।",
+    "resetpass-temp-emailed": "भवता/भवत्या अल्पकालीन(temporary)कूटशब्देन प्रवेशः प्राप्तः । \nसदस्यताप्रक्रियां पूर्णं कर्तुं नूतनः कूटशब्दः लेखनीयः एव ।",
+    "resetpass-temp-password": "अल्पकालीनकूटशब्दः :",
+    "resetpass-expired": "भवतः/भवत्याः कृटशब्दस्य अवधिः समाप्ता । प्रवेष्टुं नवीनकूटशब्दं निर्धारयतु ।",
+    "resetpass-expired-soft": "भवतः/भवत्याः कृटशब्दस्य अवधिः समाप्ता । कृपया नवीनकूटशब्दं निर्धारयतु । पश्चात् नवीनकूटशब्दं निर्धारयितुं \"{{int:resetpass-submit-cancel}}\" नुदतु ।",
+    "resetpass-validity-soft": "भवतः/भवत्याः कृटशब्दः अयोग्यः अस्ति । कृपया नवीनकूटशब्दं निर्धारयतु । पश्चात् नवीनकूटशब्दं निर्धारयितुं \"{{int:resetpass-submit-cancel}}\" नुदतु ।",
+    "passwordreset": "कूटशब्दः परिवर्त्यताम्",
+    "passwordreset-text-one": "ई-पत्रमाध्यमेन अल्पकालीनकूटशब्दं प्राप्तुम् अधस्तनं प्रपत्रं पूरयतु ।",
+    "passwordreset-text-many": "{{PLURAL:$1|ई-पत्रमाध्यमेन अल्पकालीनकूटशब्दं प्राप्तुम् अधस्तनां कामपि एकां पेटिकां पूरयतु ।}}",
+    "passwordreset-legend": "कूटशब्दः परिवर्त्यताम्",
+    "passwordreset-disabled": "अस्मिन् विकि-जालस्थाने कूटशब्दं परिर्तितुं निषेधः अस्ति ।",
+    "passwordreset-emaildisabled": "अस्मिन् विकि-जालस्थाने ई-पत्रसम्बद्धाः सेवाः असमर्थिताः सन्ति ।",
+    "passwordreset-username": "योजकनाम:",
     "passwordreset-domain": "क्षेत्रम्:",
-    "passwordreset-capture": "फलितरà¥\82पमà¥\8d à¤\88पतà¥\8dरà¤\82 à¤\95िà¤\82 à¤¦à¥\83शà¥\8dयतà¥\87 ?",
+    "passwordreset-capture": "परिणामसà¥\8dवरà¥\82पनिरà¥\8dमितानि à¤\88-पतà¥\8dराणि à¤¦à¥\8dरषà¥\8dà¤\9fà¥\81मà¥\8d à¤\87à¤\9aà¥\8dà¤\9bति ?",
     "passwordreset-capture-help": "अस्यां मञ्जूषायां यदि भवता अङ्क्यते तर्हि ईपत्रम् (अस्थायिकूटशब्देन सह) दर्श्यते प्रेष्यते च ।",
-    "passwordreset-email": "परमाणà¥\81पतà¥\8dरसà¤\99à¥\8dà¤\97à¥\87त:",
-    "passwordreset-emailtitle": "{{SITENAME}} à¤\87तà¥\8dयतà¥\8dर à¤²à¥\87à¤\96ा-विवरणमà¥\8d",
+    "passwordreset-email": "à¤\88-पतà¥\8dरसà¤\99à¥\8dà¤\95à¥\87तà¤\83",
+    "passwordreset-emailtitle": "{{SITENAME}} à¤\87तà¥\8dयतà¥\8dर à¤¯à¥\8bà¤\9cà¤\95विषयà¥\87",
     "passwordreset-emailtext-ip": "कश्चित् (भवान् अपि स्यात्, $1 इति ऐ. पि. सङ्केतात्) {{SITENAME}} ($4) इत्यस्य प्रवेशसम्बद्धं विवरणं प्रार्थितवान् । अधः सूचितस्य उपयोक्तुः {{PLURAL:$3 | प्रवेशविवरणं | प्रवेशविवरणानि}} \n$2\nइत्यनेन ईपत्रसङ्केतेन सम्बद्धम् अस्ति / सम्बद्धानि सन्ति ।\n{{PLURAL:$3|अयं तात्कालिकः कूटशब्दः | इमे तात्कालिकाः कूटशब्दाः}}  {{PLURAL:$5| एकं दिनं | $5 दिनानि}} यावत् सक्रियः भवति / सक्रियाः भवन्ति ।",
     "passwordreset-emailtext-user": "कश्चित् (भवान् अपि स्यात्, $1 इति ऐ. पि. सङ्केतात्) {{SITENAME}} ($4) इत्यस्य प्रवेशसम्बद्धं विवरणं प्रार्थितवान् । अधः सूचितस्य उपयोक्तुः {{PLURAL:$3 | प्रवेशविवरणं | प्रवेशविवरणानि}} \n$2\nइत्यनेन ईपत्रसङ्केतेन सम्बद्धम् अस्ति / सम्बद्धानि सन्ति ।\n{{PLURAL:$3|अयं तात्कालिकः कूटशब्दः | इमे तात्कालिकाः कूटशब्दाः}}  {{PLURAL:$5| एकं दिनं | $5 दिनानि}} यावत् सक्रियः भवति / सक्रियाः भवन्ति ।",
     "passwordreset-emailelement": "प्रयोक्तृनाम: $1\nअल्पकालिकः कूटशब्दः : $2",
     "prefs-skin": "त्वक्",
     "skin-preview": "प्राग्दृश्यम्",
     "datedefault": "वरीयांसि नास्ति",
-    "prefs-beta": "आवर्णलक्षणानि ।",
     "prefs-datetime": "दिनाङ्कः, समयः च",
     "prefs-labs": "प्रयोगशालालक्षणानि ।",
     "prefs-user-pages": "योजकपुटानि ।",
     "nowatchlist": "अवलोकनावल्यां पदार्थः नास्ति ।",
     "watchlistanontext": "अवलोकनपट्टिकायां पुटं दृष्टुं सम्पादयितुं वा  $1  करोतु ।",
     "watchnologin": "न नामाभिलितम्",
-    "watchnologintext": "अवलोकनावलीं परिवर्तयितुं भवता नामाभिलेखनं करणीयम् ।[[Special:UserLogin|logged in]]",
     "addwatch": "अवलोकनावलीं योजयतु ।",
     "addedwatchtext": "भवतः [[Special:Watchlist|ध्यानसूचिकायां]] \"[[:$1]]\" इत्येतत् योजितमस्ति।\nइदानींप्रभृति अस्मिन् पृष्ठे तथा अस्य चर्चापृष्ठे सन्तः परिवर्तनानि भवतः निरीक्षासूचिकायां द्रक्ष्यन्ते तथा च [[Special:RecentChanges|सद्यःपरिवर्तितानां सूचिकायां]] इदं पृष्ठं स्थूलाक्षरैः द्रक्ष्यते, यस्मात् भवान् सरलतया इदं पश्यतु <p>निरीक्षासूचिकातः निराकर्तुमिच्छति चेत्, \"मा निरीक्षताम्\" इत्यसमिन् नोदयतु।",
     "removewatch": "अवलोकनावलीतः अपनयतु ।",
     "allmessagesname": "नाम",
     "allmessagesdefault": "मूलसन्देशः",
     "allmessagescurrent": "सद्यः सन्देशपाठः ।",
-    "allmessagestext": "à¤\8fषा à¤®à¥\80डियाविà¤\95िनामसà¥\8dथानà¥\87 à¤\89पलबà¥\8dधा à¤\95ाà¤\9aितà¥\8d à¤¤à¤¨à¥\8dतà¥\8dरसनà¥\8dदà¥\87शसà¥\8dय à¤¸à¥\82à¤\9aिà¤\95ा à¤\85सà¥\8dति à¥¤  à¤¯à¤¦à¤¿ à¤­à¤µà¤¾à¤¨à¥\8d à¤¸à¤¾à¤®à¤¾à¤¨à¥\8dयमà¥\80डियाविà¤\95ि à¤\95à¥\8dषà¥\87तà¥\8dरà¥\80यà¤\95रणà¥\87 à¤¯à¥\8bà¤\97दानà¤\82 à¤\95रà¥\8dतà¥\81मिà¤\9aà¥\8dà¤\9bति à¤¤à¤°à¥\8dहि[https://www.mediawiki.org/wiki/Localisation à¤®à¥\80डियाविà¤\95ि à¤\95à¥\8dषà¥\87तà¥\8dरà¥\80यà¤\95रणमà¥\8d] à¤\85थवा [//translatewiki.net translatewiki.net] à¤\87तà¥\8dयतà¥\8dर गच्छतु ।",
+    "allmessagestext": "मà¥\80डियाविà¤\95ि à¤\87तà¥\8dयनà¥\87न à¤¨à¤¾à¤®à¤¾à¤\95ाशà¥\87न à¤¸à¤¹ à¤¸à¤²à¥\8dलà¤\97à¥\8dनानाà¤\82 à¤¯à¤¨à¥\8dतà¥\8dरà¤\9cनà¥\80तानाà¤\82 à¤¸à¥\82à¤\9aनानामà¥\8d à¤\86वलिà¤\83 à¤\85तà¥\8dर à¤\85सà¥\8dति à¥¤ à¤\95à¥\83पया à¤\85तà¥\8dर [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation], à¤\85तà¥\8dर [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation. à¤\9a गच्छतु ।",
     "allmessagesnotsupportedDB": "अस्य पुटस्य उपयोगः नैव शक्यते यतः '''$wgUseDatabaseMessages''' तटास्थम् अस्ति ।",
     "allmessages-filter-legend": "शोधनी ।",
     "allmessages-filter": "ग्राहकीकरणस्य स्थितौ शोधनी ।",
index 27b4abf..a79d3e3 100644 (file)
     "prefs-skin": "Тас көстүү",
     "skin-preview": "Хайдах буолара",
     "datedefault": "Көннөрү көстүүтэ",
-    "prefs-beta": "Бета-туруоруулар",
     "prefs-datetime": "Күнэ-дьыла уонна кэмэ",
     "prefs-labs": "Тургутуллар туруоруулар",
     "prefs-user-pages": "Кыттааччы сирэйдэрэ",
     "nowatchlist": "Эн кэтиир сирэйдэриҥ суохтар.",
     "watchlistanontext": "Кэтэбилиҥ сирэйин көрөргөр эбэтэр уларытаргар маны оҥор: $1.",
     "watchnologin": "Бэйэҕин билиһиннэр",
-    "watchnologintext": "Бэйэҕин [[Special:UserLogin|билиһиннэрдэххинэ]] кэтэбил сирэйгин уларытыаххын сөп.",
     "addwatch": "Кэтэбил тиһигэр киллэр",
     "addedwatchtext": "«[[:$1]]» сирэй [[Special:Watchlist|кэтэбил тиһигэр]] киирдэ.\nСирэй уларытыылара уонна кинини кытта ситимнээх ырытыы сирэйин уларытыылара бүгүҥҥүттэн онно көстөр буолуохтара.",
     "removewatch": "Кэтэбил тиһигиттэн сот",
     "allmessagesname": "Биллэрии",
     "allmessagesdefault": "Туспа этиллибэтэҕинэ суруллар тиэкис",
     "allmessagescurrent": "Билиҥҥи тиэкис",
-    "allmessagestext": "Манна MediaWiki биллэриилэрин испииһэгэ көстөр.\nЭн MediaWiki движогун тылбаастыырга көмөлөһүөххүн баҕарар буоллаххына манна [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] уонна манна [//translatewiki.net translatewiki.net] киир.",
+    "allmessagestext": "Манна MediaWiki биллэриилэрин испииһэгэ көстөр.\nЭн MediaWiki движогун тылбаастыырга көмөлөһүөххүн баҕарар буоллаххына манна [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] уонна манна [//translatewiki.net translatewiki.net] киир.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:Allmessages''' туттуллар кыаҕа суох, тоҕо диэтэххэ '''$wgUseDatabaseMessages''' араарыллыбыт.",
     "allmessages-filter-legend": "Сиидэ",
     "allmessages-filter": "Уларытыы көрүҥүнэн наардыыр сиидэ:",
index 602b65b..a4478a5 100644 (file)
     "prefs-skin": "Aspettu",
     "skin-preview": "Antiprima",
     "datedefault": "Nudda prifirenza",
-    "prefs-beta": "Funzioni beta",
     "prefs-datetime": "Data e ura",
     "prefs-labs": "Funziunalità dî labboratoria",
     "prefs-personal": "Prufilu utenti",
     "nowatchlist": "Nun hai innicatu pàggini a tèniri d'occhiu.",
     "watchlistanontext": "Pi visualizzari e canciari l'alencu di l'ossirvati spiciali è nicissariu $1.",
     "watchnologin": "Nun hai effittuatu lu login",
-    "watchnologintext": "Hai a fari prima lu [[Special:UserLogin|login]] pi canciari la tò lista di ossirvati spiciali.",
     "addedwatchtext": "La pàggina \"[[:$1]]\" è stata agghiunciuta â propia [[Special:Watchlist|lista di l'ossirvati spiciali]]. D'ora n poi, li mudìfichi appurtati â pàggina e â sò discussioni vèninu alincati n chidda sedi; lu tìtulu dâ pàggina appari n '''grassettu''' ntâ pàggina di l' [[Special:RecentChanges|ùrtimi canciamenti]] pi rinnìrilu cchiù visìbbili. Siddu n un secunnu tempu s'addisìa eliminari la pàggina dâ lista di l'ossirvati spiciali, fari clic supra \"nun sèquiri\" ntâ barra n àutu.",
     "removedwatchtext": "La pàggina \"[[:$1]]\" hà statu eliminata dâ lista di l'ossirvati spiciali.",
     "watch": "talìa",
     "allmessagesname": "Nomu",
     "allmessagesdefault": "Testu pridifinitu",
     "allmessagescurrent": "Testu attuali",
-    "allmessagestext": "Chista è na lista di missaggi di sistema chi s'attròvanu sutta MediaWiki:''nomu''.\nVisita [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] si voi cuntribbuiri â localizzazioni generica di MediaWiki.",
+    "allmessagestext": "Chista è na lista di missaggi di sistema chi s'attròvanu sutta MediaWiki:''nomu''.\nVisita [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] si voi cuntribbuiri â localizzazioni generica di MediaWiki.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:Allmessages''' nun è suppurtatu pirchì lu flag '''$wgUseDatabaseMessages''' nun è attivu.",
     "allmessages-filter-legend": "Filtru",
     "allmessages-filter": "Filtru pi statu di canciamentu:",
index 6a29ead..eb0830a 100644 (file)
     "delete": "Delyte",
     "deletethispage": "Delyte this page",
     "undeletethispage": "Ondelyte this page",
-    "undelete_short": "Undelete {{PLURAL:$1|ane edit|$1 edits}}",
+    "undelete_short": "Ondelyte {{PLURAL:$1|yin eedit|$1 eedits}}",
     "viewdeleted_short": "See {{PLURAL:$1|yin delytit eedit|$1 delytit eedits}}",
     "protect": "Fend",
     "protect_change": "chynge",
     "pool-timeout": "Timeout waitin fer the lock",
     "pool-queuefull": "Pool line is ful",
     "pool-errorunknown": "Onknawn mistak.",
+    "pool-servererror": "The puil coonter service is na available ($1).",
     "aboutsite": "Aboot {{SITENAME}}",
     "aboutpage": "Project:Aboot",
     "copyright": "Content is available unner $1 onless itherwise noted.",
     "anontalkpagetext": "----\n<em>This is the discussion page fer aen anonymoos uiser that's naw cræftit aen accoont yet, or that disna uise it.</em>\nWe maun therefore uise the numerical IP address tae identifie him/her.\nSic aen IP address can be shaired bi several uisers.\nGif ye'r aen anonymos uiser n feel that onreelavant comments hae been directed at ye, please [[Special:UserLogin/signup|cræft aen accoont]] or [[Special:UserLogin|log in]] tae avoid futur confusion wi ither anonymoos uisers.",
     "noarticletext": "Thaur's naw tex oan this page the nou. \nYe can [[Special:Search/{{PAGENAME}}|rake fer this page teitle]] in ither pages,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rake the related logs],\n or [{{fullurl:{{FULLPAGENAME}}|action=edit}} eidit this page].</span>",
     "noarticletext-nopermission": "Thaur's nae tex in this page the nou.\nYe can [[Special:Search/{{PAGENAME}}|rake fer this page title]] in ither pages, or <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rake the relatit logs]</span>, but ye dinna hae permeession tae cræft this page.",
-    "missing-revision": "The reveesion #$1 o the page named \"{{FULLPAGENAME}}\" disna exeest.\n\nThis is uissuallie caused bi follaein aen ootdated histerie link til ae page that haes been delytit.\nDetails can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].",
+    "missing-revision": "The reveesion #$1 o the page named \"{{FULLPAGENAME}}\" disna exeest.\n\nThis is uissuallie caused bi follaein aen ootdated histerie airtin til ae page that haes been delytit.\nDetails can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].",
     "userpage-userdoesnotexist": "Uiser accoont \"<nowiki>$1</nowiki>\" hasnae been registerit. Please check gin ye wint tae mak or eidit this page.",
     "userpage-userdoesnotexist-view": "Uiser accoont \"$1\" isna registered.",
     "blocked-notice-logextract": "This uiser is nou blockit.\nThe laitest block log entrie is gien ablo fer referance:",
     "rev-suppressed-no-diff": "Ye cannae see this diff cause yin o the reveesions haes been <strong>delytit</strong>.",
     "rev-deleted-unhide-diff": "Yin o the reveesions o this diff haes been <strong>delytit</strong>.\nDetails can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].\nYe can still [$1 see this diff] gif ye wish tae proceed.",
     "rev-suppressed-unhide-diff": "Yin o the luikowers o this diff haes been <strong>suppressed</strong>.\nDetails can be foond in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].\nYe can still [$1 see this diff] gif ye wish tae proceed.",
-    "rev-deleted-diff-view": "Ane o the reveesions o this diff haes been '''delytit'''.\nYe can see this diff; details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].",
+    "rev-deleted-diff-view": "Yin o the reveesions o this diff haes been '''delytit'''.\nYe can see this diff; details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].",
     "rev-suppressed-diff-view": "Yin o the luikowers o this diff haes been <strong>suppressed</strong>.\nYe can see this diff; the details can be foond in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].",
     "rev-delundel": "chynge veesibilitie",
     "rev-showdeleted": "shaw",
     "revdelete-no-change": "<strong>Warnishment:</strong> The eetem dated $2, $1 awreadie haed the requested veesibeelitie settins.",
     "revdelete-concurrent-change": "Mistak modifiein the eitem dated $2, $1: Its status appears tae'v been chynged bi some ither bodie while ye attempted tae modifie it.\nPlease check the logs.",
     "revdelete-only-restricted": "Mistak skaukin the eetem dated $2, $1: Ye canna suppress eetems fae sicht bi admeenistraters wioot selectin yin o the ither veesibeelitie opties ava.",
-    "revdelete-reason-dropdown": "*Commyn delete raisons\n** Copiericht violation\n** Onappropriate comment or personal information\n** Onappropriate username\n** Potentially libelous information",
+    "revdelete-reason-dropdown": "*Commyn delyte raisons\n** Copiericht violation\n** Galus comment or personal information\n** Galus uisername\n** Potentiallie libelous information",
     "revdelete-otherreason": "Ither/addeetional raison:",
     "revdelete-reasonotherlist": "Ither raison",
     "revdelete-edit-reasonlist": "Eidit delyte raisons",
     "prefs-skin": "Huil",
     "skin-preview": "First Leuk",
     "datedefault": "Nae preference",
-    "prefs-beta": "Beta features.",
     "prefs-datetime": "Date n time",
     "prefs-labs": "Labs featurs",
     "prefs-user-pages": "Uiser pages",
     "upload_directory_read_only": "The uplaid directerie ($1) is naw writable bi the wabserver.",
     "uploaderror": "Uplaid mistak",
     "upload-recreate-warning": "'''Warnishment: Ae file bi that name haes been delytit or muived.'''\n\nThe delytion n muiv log fer this page ar gien here fer conveeneeance:",
-    "uploadtext": "Uise the form ablo tae uplaid files.\nTae see or rake preeveeislie uplaided files gang til the [[Special:FileList|leet o uplaided files]], (re)uplaids ar loggit in the [[Special:Log/upload|uplaid log]] ava, delytions in the [[Special:Log/delete|delytion log]].\n\nTae incluid ae file in ae page, uise aen airtin in yin o the follaein forms:\n* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code></strong> tae uise the ful version o the file\n* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|alt tex]]</nowiki></code></strong> tae uise ae 200 pixel wide rendeetion in ae kist in the cair margin wi \"alt tex\" aes descreeption\n* <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code></strong> fer linkin directlie til the file wioot displeyin the file.",
+    "uploadtext": "Uise the form ablo tae uplaid files.\nTae see or rake aforegaun uplaided files gang til the [[Special:FileList|leet o uplaided files]], (re)uplaids ar loggit in the [[Special:Log/upload|uplaid log]] aes weel, n delytions in the [[Special:Log/delete|delytion log]].\n\nTae incluid ae file in ae page, uise aen airtin in yin o the follaein forms:\n* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code></strong> tae uise the ful version o the file\n* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|alt tex]]</nowiki></code></strong> tae uise ae 200 pixel wide rendeetion in ae kist in the cair margin wi \"alt tex\" aes descreeption\n* <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code></strong> fer linkin directlie til the file wioot displeyin the file.",
     "upload-permitted": "Permitit file types: $1.",
     "upload-prohibited": "Proheebited file types: $1.",
     "uploadlog": "uplaid log",
     "listgrouprights-removegroup-self": "Remuiv {{PLURAL:$2|groop|groops}} fae yer accoont: $1",
     "listgrouprights-addgroup-self-all": "Eik aw groops til yer accoont",
     "listgrouprights-removegroup-self-all": "Remuiv aw groops fae yer accoont",
+    "trackingcategories": "Keepin track o categeries",
+    "trackingcategories-summary": "This page leets the trackin categeries that ar autæmateecallie populatit bi the MediaWiki saffware. Thair names can be chynged bi alterin the reelavant system messages in the {{ns:8}} namespace.",
+    "trackingcategories-msg": "The Trackin Categerie",
+    "trackingcategories-name": "The Message name",
+    "trackingcategories-desc": "Categerie inclusion criteria",
+    "noindex-category-desc": "The page haes ae <nowiki>__NOINDEX__</nowiki> mageec waird oan it (n is in ae namespace whaur that flag is permitit), n sae it's na indext bi the robots.",
+    "index-category-desc": "The page haes ae <nowiki>__INDEX__</nowiki> oan it (n is in ae namespace whaur that flag is permitit), n sae it's indext bi the robots whaur it widna normallie be.",
+    "post-expand-template-inclusion-category-desc": "Efter makin aw o the templates muckler, the page size is muckler than $wgMaxArticleSize, sae some templates were na makit muckler.",
+    "post-expand-template-argument-category-desc": "Efter makin ae template argument muckler (sommit in triple braces, lik {{{Foo}}}), the page is muckler than $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "Ower monie expenseeve parser functions (lik <code>#ifexist</code>) incluidit oan ae page. See [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Categerie eikit gif the page contains ae broken file airtin (aen airtin tae embed ae file whan the file disna exeest).",
+    "hidden-category-category-desc": "This is ae categerie wi <nowiki>__HIDDENCAT__</nowiki> oan it, This prevents it fae shawin up in the categerie airtins kist oan pages, bi defaut.",
+    "trackingcategories-nodesc": "Nae descreeption is available.",
+    "trackingcategories-disabled": "The categerie is disabled",
     "mailnologin": "Nae send address",
     "mailnologintext": "Ye maun be [[Special:UserLogin|loggit in]] n hae ae valid wab-mail address in yer [[Special:Preferences|preferences]] tae send Wab-mail til ither uisers.",
     "emailuser": "E-mail this uiser",
     "nowatchlist": "Ye'v nae eitems oan yer watchleet.",
     "watchlistanontext": "Please $1 tae see or eedit eetems oan yer watchlet.",
     "watchnologin": "Nae loggit in",
-    "watchnologintext": "Ye maun be [[Special:UserLogin|loggit in]] tae modify yer watchleet.",
     "addwatch": "Eik til watchleet",
     "addedwatchtext": "The page \"[[:$1]]\" haes been added til yer [[Special:Watchlist|watchleet]].\nFutur chynges til this page n its associated tauk page will be leeted thaur.",
     "removewatch": "Remuiv fae watchleet",
     "undeletedrevisions": "{{PLURAL:$1|1 reveesion|$1 reveesions}} restored",
     "undeletedrevisions-files": "{{PLURAL:$1|1 reveesion|$1 reveesions}} n {{PLURAL:$2|1 file|$2 files}} restored",
     "cannotundelete": "Ondelyte failed:\n$1",
-    "undeletedpage": "<strong>$1 haes been restored</strong>\n\nConsult the [[Special:Log/delete|delytion log]] fer ae record o recent delytions an restorâtions.",
-    "undelete-header": "See [[Special:Log/delete|the delytion log]] fer recentlie delytit pages.",
+    "undeletedpage": "<strong>$1 haes been restored</strong>\n\nConsult the [[Special:Log/delete|delytion log]] fer ae record o recynt delytions n restorations.",
+    "undelete-header": "See [[Special:Log/delete|the delytion log]] fer the recentlie delytit pages.",
     "undelete-search-title": "Rake delytit pages",
     "undelete-search-box": "Rake delytit pages",
     "undelete-search-prefix": "Shaw pages stairtin wi:",
     "sp-contributions-newbies-sub": "Fer new accoonts",
     "sp-contributions-newbies-title": "Uiser contreebutions fer new accoonts",
     "sp-contributions-blocklog": "block log",
+    "sp-contributions-suppresslog": "suppressed uiser contreebutions",
     "sp-contributions-deleted": "delytit uiser contreebutions",
     "sp-contributions-uploads": "uploads",
     "sp-contributions-logs": "logs",
     "sp-contributions-blocked-notice": "This uiser is nou blockit.\nThe latest block log entrie is gien ablo fer referance:",
     "sp-contributions-blocked-notice-anon": "This IP address is blockit the nou.\nThe latest block log entrie is gien ablo fer referance:",
     "sp-contributions-search": "Rake fer contreebutions",
-    "sp-contributions-suppresslog": "suppressed uiser contreebutions",
     "sp-contributions-username": "IP address or uisername:",
     "sp-contributions-toponly": "Ainlie shaw eedits that ar laitest reveesions",
     "sp-contributions-newonly": "Yinlie shaw eidits that ar page cræftins",
     "allmessagesname": "Name",
     "allmessagesdefault": "Defaut message tex",
     "allmessagescurrent": "Message tex the nou",
-    "allmessagestext": "This is ae leet o system messages available in the MediaWiki namespace.\nPlease veesit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] n [//translatewiki.net translatewiki.net] gif ye wish tae contreebute til the generic MediaWiki localisation.",
+    "allmessagestext": "This is ae leet o system messages available in the MediaWiki namespace.\nPlease veesit [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] n [//translatewiki.net translatewiki.net] gif ye wish tae contreebute til the generic MediaWiki localisation.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:AllMessages''' nae supportit acause '''$wgUseDatabaseMessages''' is aff.",
     "allmessages-filter": "Filter b custymization state:",
     "allmessages-filter-unmodified": "Onmodified",
index a38bfcf..99ad4fc 100644 (file)
     "nowatchlist": "La listha di l'abbaidaddi ippiziari è biodda.",
     "watchlistanontext": "Pa visuarizzà e mudìfiggà l'erencu di l'abbaidaddi ippiziari è nezzessàriu $1.",
     "watchnologin": "Intradda nò effettuadda",
-    "watchnologintext": "Pa mudìfiggà la listha di l'abbaidaddi ippiziari è nezzessàriu primma [[Special:UserLogin|intrà]].",
     "addedwatchtext": "La pàgina  \"[[:$1]]\" è isthadda aggiunta a la propria [[Special:Watchlist|listha di l'abbaidaddi ippiziari]]. D'abà innanzi, tutti li mudìfigghi arriggaddi a la pàgina e a la sóia dischussioni sarani erencaddi in chidda listha; lu tìturu di la pàgina apparirà in '''grasseddu''' i' la pàgina\ndi l'[[Special:RecentChanges|ulthimi mudìfigghi]] pa rindiru più visìbiri.\n\nSi daboi s'à gana d'eliminà la pàgina da la listha di l'abbaidaddi ippiziarii, fà clic i' \"nò sighì\" i' la barra in althu.",
     "removedwatchtext": "La pàgina  \"[[:$1]]\" è isthadda eliminadda da la listha di l'abbaidaddi ippiziari.",
     "watch": "Sighi",
     "allmessagesname": "Nommu",
     "allmessagesdefault": "Testhu pridifiniddu",
     "allmessagescurrent": "Testhu attuari",
-    "allmessagestext": "Chistha è la listha di tutti l'imbasciaddi di sisthema dipunìbiri i' lu tipu di pàgina MediaWiki.\nPa piazeri utirizà [https://www.mediawiki.org/wiki/Localisation MediaWiki Lucarizazioni] e [//translatewiki.net translatewiki.net] pa l'althri traduzioni.",
+    "allmessagestext": "Chistha è la listha di tutti l'imbasciaddi di sisthema dipunìbiri i' lu tipu di pàgina MediaWiki.\nPa piazeri utirizà [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Lucarizazioni] e [//translatewiki.net translatewiki.net] pa l'althri traduzioni.",
     "allmessagesnotsupportedDB": "Chistha pàgina nò è supporthadda parchí l'indicadori '''$wgUseDatabaseMessages''' nò è attibuu.",
     "allmessages-filter-unmodified": "Nò mudifiggaddi",
     "allmessages-filter-all": "Tutti",
index c501a77..0679de6 100644 (file)
     "prefs-skin": "Izgled (skin)",
     "skin-preview": "Pretpregled",
     "datedefault": "Bez preferenci",
-    "prefs-beta": "Beta mogućnosti",
     "prefs-datetime": "Datum i vrijeme",
     "prefs-labs": "Eksperimentalne mogućnosti",
     "prefs-user-pages": "Korisničke stranice",
     "nowatchlist": "Nemate ništa na svom spisku praćenih članaka.",
     "watchlistanontext": "Molimo da $1 da možete vidjeti ili urediti stavke na Vašem spisku praćenja.",
     "watchnologin": "Niste logovani / Нисте логовани",
-    "watchnologintext": "Morate da budete [[Special:Userlogin|prijavljeni]] da biste sređivali spisak praćenja.",
     "addwatch": "Dodaj u popis praćenja",
     "addedwatchtext": "Stranica \"[[:$1]]\" je dodata vašem [[Special:Watchlist|spisku praćenih članaka]]. \nBuduće promjene ove stranice i njoj pridružene stranice za razgovor će biti navedene ovde.",
     "removewatch": "Ukloni sa spiska praćenja",
     "allmessagesname": "Naziv",
     "allmessagesdefault": "Uobičajeni tekst",
     "allmessagescurrent": "Trenutni tekst",
-    "allmessagestext": "Ovo je spisak svih sistemskih poruka u dostupnih u MediaWiki imenskom prostoru.\nMolimo posjetite [https://www.mediawiki.org/wiki/Localisation MediaWiki lokalizaciju] i [//translatewiki.net translatewiki.net] ako želite doprinijeti općoj lokalizaciji MediaWikija.",
+    "allmessagestext": "Ovo je spisak svih sistemskih poruka u dostupnih u MediaWiki imenskom prostoru.\nMolimo posjetite [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki lokalizaciju] i [//translatewiki.net translatewiki.net] ako želite doprinijeti općoj lokalizaciji MediaWikija.",
     "allmessagesnotsupportedDB": "Ova stranica ne može biti korištena jer je '''$wgUseDatabaseMessages''' isključen.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filter po stanju podešavanja:",
index c91a98a..cb518a0 100644 (file)
     "prefs-skin": "ඡවිය",
     "skin-preview": "පෙරදසුන",
     "datedefault": "අභිරුචියක් නොමැත",
-    "prefs-beta": "බීටා අනුවාදයේ ලක්ෂණ",
     "prefs-datetime": "දිනය සහ වේලාව",
     "prefs-labs": "Labs features",
     "prefs-user-pages": "පරිශීලක පිටු",
     "nowatchlist": "ඔබගේ මුර-ලැයිස්තුවේ කිසිදු අයිතමයක් නොමැත.",
     "watchlistanontext": "ඔබගේ මුර-ලැයිස්තුවෙහි අයිතම නැරඹීමට හෝ සංස්කරණය කිරීමට හෝ කරුණාකර $1 සපුරන්න.",
     "watchnologin": "ප්‍රවිෂ්ට වී නොමැත",
-    "watchnologintext": "ඔබගේ මුරලැයිස්තුව විකරණය කිරීමට පෙරාතුව ඔබ [[Special:UserLogin|ප්‍රවිෂ්ට වී]] සිටිය යුතුය.",
     "addwatch": "මුර ලැයිස්තුවට එක් කරන්න",
     "addedwatchtext": "\"[[:$1]]\" පිටුව ඔබගේ [[Special:Watchlist|මුර-ලැයිස්තුවට]] එක් කොට ඇත.\nමෙම පිටුවට සහ එයට අදාළ සාකච්ඡා පිටුවට ඉදිරියෙහිදී සිදු කෙරෙන වෙනස්කිරීම් ලයිස්තුගත වන අතර, ‍තෝරාගැනීමේගැනීමෙහි පහසුව තකා,  [[Special:RecentChanges|මෑත වෙනස්වීම් ලැයිස්තුව]]  තුල මෙම පිටුව  '''තදකුරු''' වලින් දක්වනු ඇත.",
     "removewatch": "මුරලැයිස්තුවෙන් ඉවත් කරන්න",
     "allmessagesname": "නම",
     "allmessagesdefault": "සාමාන්‍ය පණිවුඩ පෙළ",
     "allmessagescurrent": "වත්මන් පෙළ",
-    "allmessagestext": "මේ මාධ්‍යවිකි නාමඅවකාශයෙහිදී  හමුවන පද්ධති පණිවුඩයන් ලැයිස්තුවකි.\nවර්ගීය මාධ්‍යවිකි ප්‍රාදේශීයකරණයට දායක වීමට ඔබ රිසි නම් කරුණාකර [https://www.mediawiki.org/wiki/Localisation මාධ්‍යවිකි ප්‍රාදේශීයකරණය]  සහ [//translatewiki.net බීටාවිකි] වෙත පිවිසෙන්න.",
+    "allmessagestext": "මේ මාධ්‍යවිකි නාමඅවකාශයෙහිදී  හමුවන පද්ධති පණිවුඩයන් ලැයිස්තුවකි.\nවර්ගීය මාධ්‍යවිකි ප්‍රාදේශීයකරණයට දායක වීමට ඔබ රිසි නම් කරුණාකර [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation මාධ්‍යවිකි ප්‍රාදේශීයකරණය]  සහ [//translatewiki.net බීටාවිකි] වෙත පිවිසෙන්න.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' අක්‍රීය කොට ඇති බැවින්, මෙම පිටුව භාවිතා කල නොහැක.",
     "allmessages-filter-legend": "පෙරහන",
     "allmessages-filter": "පාරිභෝගීකරණ තත්ත්වය අනුව පෙරීම:",
index ab06009..dc73f51 100644 (file)
     "prefs-skin": "Vzhľad",
     "skin-preview": "Náhľad",
     "datedefault": "štandardný",
-    "prefs-beta": "Nové funkcie",
     "prefs-datetime": "Dátum a čas",
     "prefs-labs": "Laboratórne funkcie",
     "prefs-user-pages": "Stránky používateľa",
     "nowatchlist": "V zozname sledovaných stránok nemáte žiadne položky.",
     "watchlistanontext": "Prosím $1 pre prezeranie alebo úpravu vášho zoznamu sledovaných stránok.",
     "watchnologin": "Nie ste prihlásený/á",
-    "watchnologintext": "Musíte byť [[Special:UserLogin|prihlásený/á]], aby ste mohli modifikovať vaše sledované stránky.",
     "addwatch": "Pridať do zoznamu sledovaných stránok",
     "addedwatchtext": "Stránka „[[:$1]]“ bola pridaná do vášho zoznamu [[Special:Watchlist|sledovaných stránok]].\nBudú tam uvedené aj budúce úpravy tejto stránky a jej diskusie.",
     "removewatch": "Odstrániť zo zoznamu sledovaných",
     "allmessagesname": "Názov",
     "allmessagesdefault": "štandardný text",
     "allmessagescurrent": "aktuálny text",
-    "allmessagestext": "Toto je zoznam všetkých správ dostupných v mennom priestore MediaWiki.\nProsím, navštívte [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] a [//translatewiki.net translatewiki.net] ak chcete prispieť k všeobecnej lokalizácii MediaWiki.",
+    "allmessagestext": "Toto je zoznam všetkých správ dostupných v mennom priestore MediaWiki.\nProsím, navštívte [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] a [//translatewiki.net translatewiki.net] ak chcete prispieť k všeobecnej lokalizácii MediaWiki.",
     "allmessagesnotsupportedDB": "Túto stránku nemožno použiť, pretože '''$wgUseDatabaseMessages''' je vypnuté.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filter podľa stavu prispôsobenia:",
index e73d2af..6682eee 100644 (file)
@@ -1,6 +1,14 @@
 {
     "@metadata": {
-        "authors": []
+        "authors": [
+            "Dbc334",
+            "Eleassar",
+            "Freakolowsky",
+            "Matej1234",
+            "Smihael",
+            "Vadgt",
+            "Yerpo"
+        ]
     },
     "tog-underline": "Podčrtavanje povezav:",
     "tog-hideminor": "Skrij manjše popravke v zadnjih spremembah",
     "pool-timeout": "Časovno obdobje čakanja na zaklep",
     "pool-queuefull": "Čakalna vrsta zaloge je polna",
     "pool-errorunknown": "Neznana napaka",
+    "pool-servererror": "Storitev založnega pulta ni na voljo ($1).",
     "aboutsite": "O {{GRAMMAR:dajalnik|{{SITENAME}}}}",
     "aboutpage": "Project:O {{GRAMMAR:dajalnik|{{SITENAME}}}}",
     "copyright": "Razen, kjer je navedeno drugače, je besedilo na razpolago pod pogoji licence $1.",
     "prefs-skin": "Koža",
     "skin-preview": "Predogled",
     "datedefault": "Kakor koli",
-    "prefs-beta": "Betafunkcije",
     "prefs-datetime": "Datum in čas",
     "prefs-labs": "Funkcije laboratorija",
     "prefs-user-pages": "Uporabniške strani",
     "listgrouprights-removegroup-self": "Odstranitev svojega računa iz {{PLURAL:$2|skupine|skupin}}: $1",
     "listgrouprights-addgroup-self-all": "Lastni račun dodaj v vse skupine",
     "listgrouprights-removegroup-self-all": "Lastni račun odstrani iz vseh skupin",
+    "trackingcategories": "Sledilne kategorije",
+    "trackingcategories-summary": "Stran navaja sledilne kategorije, ki jih samodejno napolni programje MediaWiki. Njihova imena lahko spremenite s spreminjanjem ustreznih sistemskih sporočil v imenskem prostoru {{ns:8}}.",
+    "trackingcategories-msg": "Sledilna kategorija",
+    "trackingcategories-name": "Ime sporočila",
+    "trackingcategories-desc": "Merila za vključitev v kategorijo",
+    "noindex-category-desc": "Stran vsebuje čarobno besedo <nowiki>__NOINDEX__</nowiki> (in je v imenskem prostoru, ki dovoljuje to oznako) in posledično je roboti ne indeksirajo.",
+    "index-category-desc": "Stran vsebuje čarobno besedo <nowiki>__INDEX__</nowiki> (in je v imenskem prostoru, ki dovoljuje to oznako) in posledično jo roboti indeksirajo, čeprav je drugače ne bi.",
+    "post-expand-template-inclusion-category-desc": "Po razširitvi vseh predlog je velikost strani več kot $wgMaxArticleSize, zato nekaterih predlog nismo razširili.",
+    "post-expand-template-argument-category-desc": "Po razširitvi argumentov predloge (nekaj v trojnih narekovajih, npr. {{{Foo}}}) je stran večja od $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "Stran vsebuje preveč dragih razčlenitvenih funkcij (npr. <code>#ifexist</code>). Glejte [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Kategorijo smo dodali, če stan vsebuje pokvarjeno povezavo na datoteko (povezavo na vključeno datoteko, ki ne obstaja).",
+    "hidden-category-category-desc": "To je kategorija s <nowiki>__HIDDENCAT__</nowiki>, kar ji preprečuje, da se po privzetem prikazuje v okvirju s povezavami na kategorije strani.",
+    "trackingcategories-nodesc": "Opis ni na voljo.",
+    "trackingcategories-disabled": "Kategorija je onemogočena",
     "mailnologin": "Manjka naslov pošiljatelja",
     "mailnologintext": "Za pošiljanje e-pošte drugim uporabnikom se [[Special:UserLogin|prijavite]] in v [[Special:Preferences|nastavitvah]] vpišite veljaven e-poštni naslov.",
     "emailuser": "Pošlji uporabniku e-pismo",
     "nowatchlist": "Vaš spisek nadzorov je prazen.",
     "watchlistanontext": "Za pregled ali urejanje vsebine vašega spiska nadzorov se morate $1.",
     "watchnologin": "Niste prijavljeni",
-    "watchnologintext": "Za urejanje spiska nadzorov morate biti [[Special:UserLogin|prijavljeni]].",
     "addwatch": "Dodaj na spisek nadzorov",
     "addedwatchtext": "Stran »[[:$1]]« je bila dodana na vaš [[Special:Watchlist|spisek nadzorov]].\nTam bodo navedene prihodnje spremembe te strani in pripadajoče pogovorne strani.",
     "removewatch": "Odstrani s spiska nadzorov",
     "sp-contributions-newbies-sub": "Prispevki novincev",
     "sp-contributions-newbies-title": "Uporabniški prispevki novih računov",
     "sp-contributions-blocklog": "dnevnik blokiranja",
+    "sp-contributions-suppresslog": "zatrti uporabnikovi prispevki",
     "sp-contributions-deleted": "izbrisani uporabnikovi prispevki",
     "sp-contributions-uploads": "naložene datoteke",
     "sp-contributions-logs": "dnevniki",
     "sp-contributions-blocked-notice": "Ta uporabnik je trenutno blokiran.\nNajnovejši vnos v dnevniku blokad je naveden spodaj:",
     "sp-contributions-blocked-notice-anon": "Ta IP-naslov je trenutno blokiran.\nNajnovejši vnos v dnevniku blokad je naveden spodaj:",
     "sp-contributions-search": "Išči prispevke",
-    "sp-contributions-suppresslog": "zatrti uporabnikovi prispevki",
     "sp-contributions-username": "IP-naslov ali uporabniško ime:",
     "sp-contributions-toponly": "Prikaži samo vrhnje redakcije",
     "sp-contributions-newonly": "Prikaži samo urejanja, ki so ustvarila nove strani",
     "allmessagesname": "Ime",
     "allmessagesdefault": "Prednastavljeno besedilo",
     "allmessagescurrent": "Trenutno besedilo",
-    "allmessagestext": "Navedena so v imenskem prostoru MediaWiki dostopna sistemska sporočila.\nZa lokalizacijo in prevajanje obiščite [https://www.mediawiki.org/wiki/Localisation MediaWiki] in [//translatewiki.net translatewiki.net] ter tako prispevajte k splošnemu prevodu programja.",
+    "allmessagestext": "Navedena so v imenskem prostoru MediaWiki dostopna sistemska sporočila.\nZa lokalizacijo in prevajanje obiščite [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki] in [//translatewiki.net translatewiki.net] ter tako prispevajte k splošnemu prevodu programja.",
     "allmessagesnotsupportedDB": "Te strani ni mogoče uporabljati, ker je bilo '''$wgUseDatabaseMessages''' izključeno.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filtriraj po prilagoditvenem stanju:",
     "version-entrypoints": "URL-ji vstopnih točk",
     "version-entrypoints-header-entrypoint": "Vstopna točka",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Pot članka]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Pot skripta]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Pot članka]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Pot skripta]",
     "redirect": "Preusmeri po datoteki, uporabniku, strani ali ID-ju redakcije",
     "redirect-legend": "Preusmeritev na datoteko ali stran",
     "redirect-summary": "Posebna stran preusmeri na datoteko (če podate ime datoteke), stran (če podate ID redakcije ali ID strani) ali uporabniško stran (če podate številski ID uporabnika). Uporaba: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] ali [[{{#Special:Redirect}}/user/101]].",
index 8c24a86..80a5d85 100644 (file)
     "nowatchlist": "Du host kenne Einträge uff denner Beobachtungsliste.",
     "watchlistanontext": "Du muoßt diech $1, im denne Beobachtungsliste zu sahn oder Einträge uff ihr zu bearbta.",
     "watchnologin": "Du best ne oagemeldet",
-    "watchnologintext": "Du muoßt [[Special:UserLogin|oagemeldet]] sei, im denne Beobachtungsliste bearbta zu kinna.",
     "addedwatchtext": "De Seite „<nowiki>$1</nowiki>“ wurde zu denner [[Special:Watchlist|Beobachtungsliste]] hinzugefiegt.\n\nSpätere Änneronga oa dieser Seite und der dazugeheeriga Dischkursseite waan durt gelistet und\nei der Iebersicht der [[Special:RecentChanges|letzta Änneronga]] ei Fettschrift dargestellt.\n\nWenn du de Seite wieder vu denner Beobachtungsliste entferna mechtest, klicke uff der jeweiligen Seite uff „nee meh beobachta“.",
     "removedwatchtext": "De Seite „[[:$1]]“ wurde vun denner [[Special:Watchlist|Beobachtungsliste]] entfernt.",
     "watch": "Beobachta",
     "export-pagelinks": "Verlinkte Seyta automatisch miet exportiera, bis zer Rekursionstiefe vu:",
     "allmessagesname": "Noame",
     "allmessagesdefault": "Standardtext",
-    "allmessagestext": "Dies ies anne Liste dar MediaWiki-Systemtexte.\nBesiche de Seyta [https://www.mediawiki.org/wiki/Localisation MediaWiki-Lokalisierung] und [//translatewiki.net translatewiki.net], wenn du diech oa dar Lokalisierung vu MediaWiki beteiliga mechtest.",
+    "allmessagestext": "Dies ies anne Liste dar MediaWiki-Systemtexte.\nBesiche de Seyta [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki-Lokalisierung] und [//translatewiki.net translatewiki.net], wenn du diech oa dar Lokalisierung vu MediaWiki beteiliga mechtest.",
     "allmessagesnotsupportedDB": "Diese Spezialseyte stieht ne zur Verfigung, do se ieber dann Parameter <tt>$wgUseDatabaseMessages</tt> deaktiviert wurde.",
     "allmessages-filter-all": "Olle",
     "allmessages-language": "Sproache:",
index 80c4bf7..a70edcb 100644 (file)
     "nowatchlist": "Waxba kuma jiraan liiskaaga waardiyeynta.",
     "watchlistanontext": "Fadlan $1 si aad u fiirisid ama wax uga bedeshid qoraalada ku jira liiska waardiyeyska.",
     "watchnologin": "Gudaha kuma jirtid",
-    "watchnologintext": "Waa ina aad [[Special:UserLogin|gudaha ku jirtaa]] si aad wax uga bedeshid liiskaaga waardiyeynta.",
     "addedwatchtext": "Bogga \"[[:$1]]\" waxaa lagudaray [[Special:Watchlist|liiska-waardiyahaaga]].\nIsbedelka mustaqbalka ku dhaca boggan iyo bogga wadahadalka la'xiriira waxaa lagu soo qoridoonaa inta,\nboggana wuxuu noqonaayaa mid la' '''nuuriyey''' dhinaca [[Special:RecentChanges|Liiska isbedelada show]] si\nay u fududdayso sidii loo dalbanlahaa.\n\nHadii aad rabootid in aad boggan ka saartid wardiyeynta, dhagsii \"Ha' wardiyeynin\" oo ku yaala dhinaca.",
     "removedwatchtext": "Bogga \"[[:$1]]\" waa laga saaray [[Special:Watchlist|liiskaaga waardiyaha]].",
     "watch": "Waardiyey",
     "allmessagesname": "Magac",
     "allmessagesdefault": "Qoraalka la'isku ogyahay",
     "allmessagescurrent": "Qoraalka hada qoran",
-    "allmessagestext": "Kan waa liiska fariimaha systemka oo laga heli karo xarun magaceedka MediaWiki.\nFadlan booqo [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] iyo [//translatewiki.net translatewiki.net] hadii aad rabto in aad wax ku darsatid guud ahaanba MediaWiki ku fasirida luqadaada.",
+    "allmessagestext": "Kan waa liiska fariimaha systemka oo laga heli karo xarun magaceedka MediaWiki.\nFadlan booqo [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] iyo [//translatewiki.net translatewiki.net] hadii aad rabto in aad wax ku darsatid guud ahaanba MediaWiki ku fasirida luqadaada.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:Allmessages''' la'ma isticmaalikaro, '''$wgUseDatabaseMessages''' oo dansan daraadeed.",
     "allmessages-language": "Luqad:",
     "allmessages-filter-submit": "Soco",
index df31f5c..f3fb702 100644 (file)
     "prefs-skin": "Pamja",
     "skin-preview": "Parapamje",
     "datedefault": "Parazgjedhje",
-    "prefs-beta": "Karakteristikat Beta",
     "prefs-datetime": "Data dhe Ora",
     "prefs-labs": "Karakteristikat laboratorik",
     "prefs-user-pages": "Faqet e përdoruesit",
     "nowatchlist": "Nuk keni asnjë faqe në listën mbikqyrëse.",
     "watchlistanontext": "Ju lutemi $1 për të parë redaktimet e artikujve në listë tuaj mbikqyrëse.",
     "watchnologin": "Nuk keni hyrë brënda",
-    "watchnologintext": "Duhet të keni [[Special:UserLogin|hyrë brenda]] për të ndryshuar listën mbikqyrëse.",
     "addwatch": "Shto tek lista mbikqyrëse",
     "addedwatchtext": "Faqja \"[[:$1]]\"  i është shtuar [[Special:Watchlist|listës mbikqyrëse]] tuaj. Ndryshimet e ardhshme të kësaj faqeje dhe faqes së diskutimit të saj do të jepen më poshtë, dhe emri i faqes do të duket i '''trashë''' në [[Special:RecentChanges|listën e ndryshimeve së fundmi]] për t'i dalluar më kollaj.\n\nNë qoftë se dëshironi të hiqni një faqe nga lista mbikqyrëse më vonë, shtypni \"çmbikqyre\" në tabelën e sipërme.",
     "removewatch": "Largo nga lista mbikqyrëse",
     "sp-contributions-newbies-sub": "Për newbies",
     "sp-contributions-newbies-title": "Kontributet e përdoruesit për kontot e reja",
     "sp-contributions-blocklog": "Regjistri i bllokimeve",
+    "sp-contributions-suppresslog": "Anëtar me Kontribute të kufizuara",
     "sp-contributions-deleted": "kontributet e grisura",
     "sp-contributions-uploads": "ngarkimet",
     "sp-contributions-logs": "Regjistrat",
     "sp-contributions-blocked-notice": "Ky përdorues është i bllokuar.\nBllokimi i fundit është shfaqur më poshtë për referencë:",
     "sp-contributions-blocked-notice-anon": "Kjo adresë IP është e bllokuar aktualisht.\nBllokimi i funditë është më poshtë për referencë:",
     "sp-contributions-search": "Kërko tek kontributet",
-    "sp-contributions-suppresslog": "Anëtar me Kontribute të kufizuara",
     "sp-contributions-username": "IP Addresa ose Përdoruesi:",
     "sp-contributions-toponly": "Trego vetëm redaktimet që janë versionet më të fundit",
     "sp-contributions-submit": "Kërko",
     "allmessagesname": "Emri",
     "allmessagesdefault": "Teksti i parazgjedhur",
     "allmessagescurrent": "Teksti i tanishëshm",
-    "allmessagestext": "Kjo është një listë e të gjitha faqeve në hapësirën MediaWiki:\nJu lutemi vizitoni [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] dhe [//translatewiki.net translatewiki.net] nëse dëshironi të kontribuoni në lokalizimin e përgjithshëm MediaWiki",
+    "allmessagestext": "Kjo është një listë e të gjitha faqeve në hapësirën MediaWiki:\nJu lutemi vizitoni [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] dhe [//translatewiki.net translatewiki.net] nëse dëshironi të kontribuoni në lokalizimin e përgjithshëm MediaWiki",
     "allmessagesnotsupportedDB": "Kjo faqe nuk mund të përdoret sepse '''$wgUseDatabaseMessages''' është çaktivizuar.",
     "allmessages-filter-legend": "Filtër",
     "allmessages-filter": "Filtroni nga shteti",
index b03a32b..63d4441 100644 (file)
     "user-mail-no-addy": "Покушали сте да пошаљете поруку без е-адресе.",
     "user-mail-no-body": "Покушано слање електронске поруке с празним или неразумно кратким садржајем.",
     "changepassword": "Промени лозинку",
-    "resetpass_announce": "Ð\9fÑ\80иÑ\98авÑ\99ени Ñ\81Ñ\82е Ñ\81 Ð¿Ñ\80ивÑ\80еменом Ð»Ð¾Ð·Ð¸Ð½ÐºÐ¾Ð¼.\nÐ\94а Ð±Ð¸Ñ\81Ñ\82е Ð·Ð°Ð²Ñ\80Ñ\88или Ð¿Ñ\80иÑ\98авÑ\83, Ð¿Ð¾Ð´ÐµÑ\81иÑ\82е Ð½Ð¾Ð²Ñ\83 Ð»Ð¾Ð·Ð¸Ð½ÐºÑ\83 Ð¾Ð²Ð´Ðµ:",
+    "resetpass_announce": "Ð\94а Ð±Ð¸Ñ\81Ñ\82е Ð·Ð°Ð²Ñ\80Ñ\88или Ð¿Ñ\80иÑ\98авÑ\83, Ð¿Ð¾Ð´ÐµÑ\81иÑ\82е Ð½Ð¾Ð²Ñ\83 Ð»Ð¾Ð·Ð¸Ð½ÐºÑ\83 Ð¾Ð²Ð´Ðµ.",
     "resetpass_text": "<!-- Овде унесите текст -->",
     "resetpass_header": "Промена лозинке налога",
     "oldpassword": "Стара лозинка:",
     "resetpass-temp-password": "Привремена лозинка:",
     "resetpass-abort-generic": "Промену лозинке је спречио додатак.",
     "resetpass-expired": "Ваша лозинка је истекла. Поставите нову лозинку да бисте се пријавили.",
-    "resetpass-expired-soft": "Ваша лозинка је истекла и морате поставити нову. Поставите нову лозинку или кликните откажи да је поставите касније.",
+    "resetpass-expired-soft": "Ваша лозинка је истекла и морате поставити нову. Поставите нову лозинку или кликните „{{int:resetpass-submit-cancel}}“ да је поставите касније.",
     "passwordreset": "Обнављање лозинке",
     "passwordreset-text-one": "Попуните овај образац да бисте ресетовали лозинку.",
     "passwordreset-text-many": "{{PLURAL:$1|Испуните једно од поља како би сте добили привремену лозинку на е-пошту.}}",
     "content-failed-to-parse": "Не могу да рашчланим садржај типа $2 за модел $1: $3",
     "invalid-content-data": "Неисправни подаци садржаја",
     "content-not-allowed-here": "Садржај модела „$1“ није дозвољен на страници [[$2]]",
-    "editwarning-warning": "Ако напустите ову страницу, изгубићете све измене које сте направили.\nАко сте пријављени, можете онемогућити ово упозорење у својим подешавањима, у одељку „Уређивање“.",
+    "editwarning-warning": "Ако напустите ову страницу, изгубићете све измене које сте направили.\nАко сте пријављени, можете онемогућити ово упозорење у својим подешавањима, у одељку „{{int:prefs-editing}}“.",
     "content-model-wikitext": "викитекст",
     "content-model-text": "чист текст",
     "content-model-javascript": "јаваскрипт",
     "page_last": "последња",
     "histlegend": "Избор разлика: изаберите кутијице измена за упоређивање и притисните ентер или дугме на дну.<br />\nОбјашњење: '''({{int:cur}})''' – разлика с тренутном изменом,\n'''({{int:last}})''' – разлика с претходном изменом, '''{{int:minoreditletter}}''' – мала измена",
     "history-fieldset-title": "Преглед историје",
-    "history-show-deleted": "само обрисано",
+    "history-show-deleted": "Само обрисано",
     "histfirst": "најстарије",
     "histlast": "најновије",
     "historysize": "({{PLURAL:$1|1 бајт|$1 бајта|$1 бајтова}})",
     "prefs-skin": "Тема",
     "skin-preview": "Прегледај",
     "datedefault": "Свеједно",
-    "prefs-beta": "Бета могућности",
     "prefs-datetime": "Датум и време",
     "prefs-labs": "Пробне могућности",
     "prefs-user-pages": "Корисничке странице",
     "nowatchlist": "Ваш списак надгледања је празан.",
     "watchlistanontext": "Морате бити $1 да бисте гледали и уређивали ставке на вашем списку надгледања.",
     "watchnologin": "Нисте пријављени",
-    "watchnologintext": "Морате бити [[Special:UserLogin|пријављени]] да бисте мењали списак надгледања.",
     "addwatch": "Додај на списак надгледања",
     "addedwatchtext": "Страница „[[:$1]]“ је додата на ваш [[Special:Watchlist|списак надгледања]].\nБудуће измене ове странице и њене странице за разговор биће наведене овде.",
     "removewatch": "Уклони са списка надгледања",
     "allmessagesname": "Назив",
     "allmessagesdefault": "Подразумевани текст",
     "allmessagescurrent": "Тренутни текст поруке",
-    "allmessagestext": "Ово је списак свих системских порука које су доступне у именском простору „Медијавики“.\nПосетите [https://www.mediawiki.org/wiki/Localisation Медијавики локализацију] и [//translatewiki.net Транслејтвики] ако желите да помогнете у превођењу.",
+    "allmessagestext": "Ово је списак свих системских порука које су доступне у именском простору „Медијавики“.\nПосетите [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Медијавики локализацију] и [//translatewiki.net Транслејтвики] ако желите да помогнете у превођењу.",
     "allmessagesnotsupportedDB": "Ова страница не може да се користи јер је '''$wgUseDatabaseMessages''' онемогућен.",
     "allmessages-filter-legend": "Филтер",
     "allmessages-filter": "Филтрирај по стању:",
     "semicolon-separator": ";&#32;",
     "comma-separator": ",&#32;",
     "colon-separator": ":&#32;",
-    "pipe-separator": "&#32;&#32;",
+    "pipe-separator": "&#32;|&#32;",
     "word-separator": "&#32;",
     "ellipsis": "…",
     "percent": "$1%",
index 4d52e08..24141d1 100644 (file)
     "page_last": "poslednja",
     "histlegend": "Izbor razlika: izaberite kutijice izmena za upoređivanje i pritisnite enter ili dugme na dnu.<br />\nObjašnjenje: '''({{int:cur}})''' – razlika s trenutnom izmenom,\n'''({{int:last}})''' – razlika s prethodnom izmenom, '''{{int:minoreditletter}}''' – mala izmena",
     "history-fieldset-title": "Pregled istorije",
-    "history-show-deleted": "samo obrisano",
+    "history-show-deleted": "Samo obrisane",
     "histfirst": "najstarije",
     "histlast": "najnovije",
     "historysize": "({{PLURAL:$1|1 bajt|$1 bajta|$1 bajtova}})",
     "prefs-skin": "Tema",
     "skin-preview": "Pregledaj",
     "datedefault": "Svejedno",
-    "prefs-beta": "Beta mogućnosti",
     "prefs-datetime": "Datum i vreme",
     "prefs-labs": "Probne mogućnosti",
     "prefs-user-pages": "Korisničke stranice",
     "nowatchlist": "Vaš spisak nadgledanja je prazan.",
     "watchlistanontext": "Morate biti $1 da biste gledali i uređivali stavke na vašem spisku nadgledanja.",
     "watchnologin": "Niste prijavljeni",
-    "watchnologintext": "Morate biti [[Special:UserLogin|prijavljeni]] da biste menjali spisak nadgledanja.",
     "addwatch": "Dodaj na spisak nadgledanja",
     "addedwatchtext": "Stranica „[[:$1]]“ je dodata na vaš [[Special:Watchlist|spisak nadgledanja]].\nBuduće izmene ove stranice i njene stranice za razgovor biće navedene ovde.",
     "removewatch": "Ukloni sa spiska nadgledanja",
     "allmessagesname": "Naziv",
     "allmessagesdefault": "Podrazumevani tekst",
     "allmessagescurrent": "Trenutni tekst poruke",
-    "allmessagestext": "Ovo je spisak svih sistemskih poruka koje su dostupne u imenskom prostoru „Medijaviki“.\nPosetite [https://www.mediawiki.org/wiki/Localisation Medijaviki lokalizaciju] i [//translatewiki.net Translejtviki] ako želite da pomognete u prevođenju.",
+    "allmessagestext": "Ovo je spisak svih sistemskih poruka koje su dostupne u imenskom prostoru „Medijaviki“.\nPosetite [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Medijaviki lokalizaciju] i [//translatewiki.net Translejtviki] ako želite da pomognete u prevođenju.",
     "allmessagesnotsupportedDB": "Ova stranica ne može da se koristi jer je '''$wgUseDatabaseMessages''' onemogućen.",
     "allmessages-filter-legend": "Filter",
     "allmessages-filter": "Filtriraj po stanju:",
     "semicolon-separator": ";&#32;",
     "comma-separator": ",&#32;",
     "colon-separator": ":&#32;",
-    "pipe-separator": "&#32;&#32;",
+    "pipe-separator": "&#32;|&#32;",
     "word-separator": "&#32;",
     "ellipsis": "…",
     "percent": "$1%",
index 2eba66d..378278b 100644 (file)
     "prefs-skin": "Skin",
     "skin-preview": "Foarskau",
     "datedefault": "Neen Preferenz",
-    "prefs-beta": "Beta-Funktione",
     "prefs-datetime": "Doatum un Tied",
     "prefs-labs": "Alpha-Funktione",
     "prefs-personal": "Benutserdoaten",
     "nowatchlist": "Du hääst neen Iendraage ap dien Beooboachtengslieste. Du moast anmälded weese, dät die een Beooboachtengslieste tou Ferföigenge stoant.",
     "watchlistanontext": "Du moast die $1, uum dien Beooboachtengslieste tou sjoon of Iendraage ap hier tou beoarbaidjen.",
     "watchnologin": "Du bäst nit anmälded",
-    "watchnologintext": "Du moast [[Special:UserLogin|anmälded]] weese, uum dien Beooboachtengslieste tou beoarbaidjen.",
     "addwatch": "Tou Beooboachtengslieste bietouföigje",
     "addedwatchtext": "Die Artikkel \"[[:$1]]\" wuude an dien [[Special:Watchlist|Foulgelieste]] touföiged.\nLeetere Annerengen an dissen Artikkel un ju touheerende Diskussionssiede wäide deer liested\nun die Artikkel wäd in ju [[Special:RecentChanges|fon do lääste Annerengen]] in '''Fatskrift''' anroat.\n\nWan du die Artikkel wier fon ju Foulgelieste ou hoalje moatest, klik ap ju Siede ap \"Ferjeet disse Siede\".",
     "removewatch": "Fon ju Beooboachtengslieste wächhoalje",
     "allmessagesname": "Noome",
     "allmessagesdefault": "Standardtext",
     "allmessagescurrent": "Dissen Text",
-    "allmessagestext": "Dit is ne Lieste fon aal System-Ättergjuchte do in dän MediaWiki-Noomenruum tou Ferföigenge stounde.\nBesäik jädden [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] un [//translatewiki.net translatewiki.net], wan du mee-oarbaidje wolt an ju MediaWiki-Sortierenge.",
+    "allmessagestext": "Dit is ne Lieste fon aal System-Ättergjuchte do in dän MediaWiki-Noomenruum tou Ferföigenge stounde.\nBesäik jädden [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] un [//translatewiki.net translatewiki.net], wan du mee-oarbaidje wolt an ju MediaWiki-Sortierenge.",
     "allmessagesnotsupportedDB": "Disse Spezioalsiede stoant nit tou Ferföigenge, deer ju uur dän Parameter <tt>$wgUseDatabaseMessages</tt> deaktivierd wuude.",
     "allmessages-filter-legend": "Sieuwe",
     "allmessages-filter": "Sieuwe foar anpaaseden Toustand:",
index fe20a0a..73e67a9 100644 (file)
     "pool-timeout": "Timeout i väntan på låsning",
     "pool-queuefull": "Kön är full",
     "pool-errorunknown": "Okänt fel",
+    "pool-servererror": "Pool counter-tjänsten är inte tillgänglig ($1).",
     "aboutsite": "Om {{SITENAME}}",
     "aboutpage": "Project:Om",
     "copyright": "Innehållet är tillgängligt under $1 om inte annat anges.",
     "prefs-skin": "Utseende",
     "skin-preview": "Förhandsvisning",
     "datedefault": "Ovidkommande",
-    "prefs-beta": "Betafunktioner",
     "prefs-datetime": "Datum och tid",
     "prefs-labs": "Testfunktioner",
     "prefs-user-pages": "Användarsidor",
     "listgrouprights-removegroup-self": "Ta bort {{PLURAL:$2|gruppen|grupperna}} från eget konto: $1",
     "listgrouprights-addgroup-self-all": "Lägg till alla grupperna till eget konto",
     "listgrouprights-removegroup-self-all": "Ta bort alla grupperna från eget konto",
+    "trackingcategories": "Spårningskategorier",
+    "trackingcategories-summary": "Denna sida listar spårningskategorier som automatiskt befolkas av MediaWiki-mjukvaran. Deras namn kan ändras genom att ändra det relevanta systemmeddelandena i {{ns:8}}-namnrymden.",
+    "trackingcategories-msg": "Spårningskategori",
+    "trackingcategories-name": "Meddelandenamn",
+    "trackingcategories-desc": "Inklusionskriterier för kategori",
+    "noindex-category-desc": "Sidan innehåller det magiska ordet <nowiki>__NOINDEX__</nowiki> (och är i en namnrymd där denna flagga tillåts), och indexeras därför inte av robotar.",
+    "index-category-desc": "Denna sidan innehåller ett <nowiki>__INDEX__</nowiki> (och är i en namnrymd där denna flagga tillåts), och indexeras därför av robotar även där detta normalt inte skulle ske.",
+    "post-expand-template-inclusion-category-desc": "Efter att alla mallar har expanderats är denna sidan större än $wgMaxArticleSize, därför har vissa mallar inte expanderats.",
+    "post-expand-template-argument-category-desc": "Efter att ett mallargument (något inom trippla parenteser, som {{{Foo}}}) expanderats är denna sidan större än $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "För många kostsamma parser-funktioner (som <code>#ifexist</code>) har inkluderats på en sida. Se [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit användarhandboken].",
+    "broken-file-category-desc": "Kategori som läggs till om sidan innehåller en bruten fillänk (en länk som bäddar in en fil som inte finns).",
+    "hidden-category-category-desc": "Detta är en kategori som innehåller <nowiki>__HIDDENCAT__</nowiki> vilket, som standard, förhindrar den från att visas i kategorirutan.",
+    "trackingcategories-nodesc": "Ingen beskrivning tillgänglig.",
+    "trackingcategories-disabled": "Kategorin är inaktiverad",
     "mailnologin": "Ingen adress att skicka till",
     "mailnologintext": "För att kunna skicka e-post till andra användare, måste du vara [[Special:UserLogin|inloggad]] och ha angivit en korrekt e-postadress i dina [[Special:Preferences|användarinställningar]].",
     "emailuser": "Skicka e-post till den här användaren",
     "nowatchlist": "Du har inga sidor i din bevakningslista.",
     "watchlistanontext": "Du måste $1 för att se eller redigera din bevakningslista.",
     "watchnologin": "Inte inloggad",
-    "watchnologintext": "Du måste vara [[Special:UserLogin|inloggad]] för att kunna ändra din bevakningslista.",
     "addwatch": "Lägg till i bevakningslistan",
     "addedwatchtext": "Sidan \"[[:$1]]\" har lagts till på din [[Special:Watchlist|bevakningslista]].\nFramtida ändringar av den här sidan och dess diskussionssida kommer att listas där.",
     "removewatch": "Ta bort från bevakningslistan",
     "sp-contributions-newbies-sub": "Från nya konton",
     "sp-contributions-newbies-title": "Bidrag från nya konton",
     "sp-contributions-blocklog": "blockeringslogg",
+    "sp-contributions-suppresslog": "undanhållna användarbidrag",
     "sp-contributions-deleted": "raderade användarbidrag",
     "sp-contributions-uploads": "uppladdningar",
     "sp-contributions-logs": "loggar",
     "sp-contributions-blocked-notice": "Användaren är blockerad.\nOrsaken till senaste blockeringen kan ses nedan:",
     "sp-contributions-blocked-notice-anon": "Denna IP-adress är för närvarande blockerad.\nDen senaste posten i blockeringsloggen visas nedan som referens:",
     "sp-contributions-search": "Sök efter användarbidrag",
-    "sp-contributions-suppresslog": "undanhållna användarbidrag",
     "sp-contributions-username": "IP-adress eller användarnamn:",
     "sp-contributions-toponly": "Visa endast aktuella sidversioner",
     "sp-contributions-newonly": "Visa endast redigeringar där sidor skapas",
     "allmessagesname": "Namn",
     "allmessagesdefault": "Standardtext",
     "allmessagescurrent": "Nuvarande text",
-    "allmessagestext": "Detta är en lista över alla meddelanden i namnrymden MediaWiki.\nBesök [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] eller [//translatewiki.net translatewiki.net] om du vill bidra till översättningen av MediaWiki.",
+    "allmessagestext": "Detta är en lista över alla meddelanden i namnrymden MediaWiki.\nBesök [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] eller [//translatewiki.net translatewiki.net] om du vill bidra till översättningen av MediaWiki.",
     "allmessagesnotsupportedDB": "Den här sidan kan inte användas eftersom '''$wgUseDatabaseMessages''' är avstängd.",
     "allmessages-filter-legend": "Filtrera",
     "allmessages-filter": "Filtrera efter anpassningsgrad:",
index a5c3d62..6719ed1 100644 (file)
     "prefs-skin": "Umbo",
     "skin-preview": "Hakiki",
     "datedefault": "Chaguo-msingi",
-    "prefs-beta": "Zana za Beta",
     "prefs-datetime": "Tarehe na saa",
     "prefs-labs": "Maumbile ya maabara",
     "prefs-user-pages": "Kurasa za watumiaji",
     "nowatchlist": "Hamna vitu katika maangalizi yako.",
     "watchlistanontext": "Tafadhali $1 ili kutazama au kuhariri vitu vilivyopo katika orodha yako ya maangalizi.",
     "watchnologin": "Hujaingia",
-    "watchnologintext": "Lazima uwe [[Special:UserLogin|umeshaingia]] ili uweze kuhariri orodha ya maangalizi yako.",
     "addwatch": "Ongeza kwenye orodha ya maangalizi",
     "addedwatchtext": "Ukurasa \"[[:$1]]\" umewekwa kwenye [[Special:Watchlist|maangalizi]] yako.\nMabadiliko katika ukurasa huo na ukurasa wake wa majadiliano utaonekana hapo.",
     "removewatch": "Ondoa kutoka orodha ya maangalizi",
     "allmessagesname": "Jina",
     "allmessagesdefault": "Ujumbe uliopo bidhaa pepe",
     "allmessagescurrent": "Ujumbe unapo sasa hivi",
-    "allmessagestext": "Hii ni orodha ya jumbe za mfumo zilizopo katika eneo la MediaWiki.\nUkitaka kusaidia kazi ya kutohoa MediaWiki yote katika lugha nyingi, tafadhali uende tovuti ya [https://www.mediawiki.org/wiki/Localisation Kutohoa MediaWiki Kwenye Lugha Nyingi] na [//translatewiki.net translatewiki.net].",
+    "allmessagestext": "Hii ni orodha ya jumbe za mfumo zilizopo katika eneo la MediaWiki.\nUkitaka kusaidia kazi ya kutohoa MediaWiki yote katika lugha nyingi, tafadhali uende tovuti ya [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Kutohoa MediaWiki Kwenye Lugha Nyingi] na [//translatewiki.net translatewiki.net].",
     "allmessagesnotsupportedDB": "Ukurasa huu hauwezi kutumika kwa sababu '''$wgUseDatabaseMessages''' imelemazwa.",
     "allmessages-filter-legend": "Chuja",
     "allmessages-filter": "Zichujwe kwa hali ya kutengenezwa:",
index 3b26fb1..d0d868b 100644 (file)
     "prefs-skin": "Skůrka",
     "skin-preview": "podglůnd",
     "datedefault": "Důmyślny",
-    "prefs-beta": "Testowe funkcyje",
     "prefs-datetime": "Data a czas",
     "prefs-labs": "Funkcyje \"labs\"",
     "prefs-user-pages": "Zajty używaczy",
     "nowatchlist": "Ńy ma žodnych pozycyji na liśće zajtůw, na kere dowoš pozůr.",
     "watchlistanontext": "$1 coby uobejřeć abo sprowjać elymynty listy zajtůw, na kere dowoš pozůr",
     "watchnologin": "Ńy jest žeś zalůgowany",
-    "watchnologintext": "Muśyš śe [[Special:UserLogin|zalůgować]] coby modyfikować lista zajtůw, na kere dowoš pozůr.",
     "addedwatchtext": "Zajta \"[[:$1]]\" zostoua dodano do Twojij [[Special:Watchlist|listy artiklůw, na kere dowoš pozůr]].\nNa tyi liśće bydźeš mjou rejer přišuych sprowjyń tyi zajty i jeji zajty godki, a mjano zajty bydźeš mjou škryflane '''tustym''' na [[Special:RecentChanges|liśće půmjyńanych na ůostatku]], cobyś mjou wygoda w jei pomjyńańa filować.",
     "removedwatchtext": "Artikel \"[[:$1]]\" zostou wyćepńjynty s [[Special:Watchlist|Twojij pozorlisty]].",
     "watch": "Dej pozůr",
     "allmessagesname": "Mjano",
     "allmessagesdefault": "Tekst důmyślny",
     "allmessagescurrent": "Tekst uobecny",
-    "allmessagestext": "Uoto lista wšyjstkych kůmůńikatůw systymowych dostympnych w přestřyńi mjan MedjaWiki.\nUodwjydź [https://www.mediawiki.org/wiki/Localisation Tuůmačyńy MediaWiki] a tyž [//translatewiki.net translatewiki.net] kejbyś chćou učestńičyć w tuůmačyńu uoprůgramowańo MediaWiki.",
+    "allmessagestext": "Uoto lista wšyjstkych kůmůńikatůw systymowych dostympnych w přestřyńi mjan MedjaWiki.\nUodwjydź [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Tuůmačyńy MediaWiki] a tyž [//translatewiki.net translatewiki.net] kejbyś chćou učestńičyć w tuůmačyńu uoprůgramowańo MediaWiki.",
     "allmessagesnotsupportedDB": "Ta zajta ńy može być užyta, bez tůž co zmjynna '''$wgUseDatabaseMessages''' je wůuůnčůno.",
     "thumbnail-more": "Zwjynksz",
     "filemissing": "Njy mo pliku",
index 904bdf3..8bc961e 100644 (file)
     "prefs-skin": "முகப்புறை",
     "skin-preview": "முன்தோற்றம்",
     "datedefault": "விருப்பத்தேர்வுகள் இல்லை",
-    "prefs-beta": "சோதனைநிலை அம்சங்கள்",
     "prefs-datetime": "நாள் நேரம்",
     "prefs-labs": "ஆய்வகச் சிறப்புக்கூறுகள்",
     "prefs-user-pages": "பயனர் பக்கங்கள்",
     "nowatchlist": "உங்களுடைய கவனிப்புப் பட்டியலில் ஒரு விடயமும் இல்லை.",
     "watchlistanontext": "உங்கள் கவனிப்புப் பட்டியலைப் பார்க்க அல்லது தொகுக்க அருள் கூர்ந்து $1 செய்யுங்கள்.",
     "watchnologin": "புகுபதிகை செய்யப்படவில்லை.",
-    "watchnologintext": "உங்கள் கவனிப்புப் பட்டியலில் திருத்தம் செய்வதற்கு, நீங்கள்[[Special:UserLogin|புகுபதிகை செய்திருக்கவேண்டும்]].",
     "addwatch": "கவனிப்புப் பட்டியலில் சேர்",
     "addedwatchtext": "\"[[:$1]]\" பக்கம் உங்கள் [[Special:Watchlist|கவனிப்புப் பக்கத்தில்]] சேர்க்கப்பட்டுள்ளது. இந்தப் பக்கத்துக்கு எதிர்காலத்தில் செய்யப்படவுள்ள மாற்றங்களும், அதனோடிணைந்த பேச்சுப் பக்கமும், அங்கே பட்டியலிடப்படும். அத்துடன் தெரிந்தெடுக்க வசதியாக [[Special:RecentChanges|அண்மைய மாற்றங்களின் பட்டியலில்]] இது தடித்த எழுத்துக்களில் காட்டப்படும். பின்னர், இப் பக்கத்தை உங்கள் கவனிப்புப் பட்டியலிலிருந்து நீக்க விரும்பினால், பக்கச் சட்டத்திலுள்ள ''கவனிப்பு நீக்கு'' என்ற இணைப்பைச் சொடுக்கவும்.",
     "removewatch": "கவனிப்புப் பட்டியலிருந்து நீக்கு",
     "sp-contributions-newbies-sub": "புதிய கணக்குகளுக்கு",
     "sp-contributions-newbies-title": "புதிய கணக்குகளுக்கு பயனரின் பங்களிப்புகள்",
     "sp-contributions-blocklog": "தடைப் பதிகை",
+    "sp-contributions-suppresslog": "பயனரின் நீக்கப்பட்ட பங்களிப்புகள்",
     "sp-contributions-deleted": "பயனரின் நீக்கப்பட்ட பங்களிப்புக்கள்",
     "sp-contributions-uploads": "பதிவேற்றங்கள்",
     "sp-contributions-logs": "பதிகைகள்",
     "sp-contributions-blocked-notice": "இந்தப் பயனர் தற்சமயம் தடை செய்யப்பட்டுள்ளார்.\nதடை பதிகையின் அண்மைய மாற்றம் குறிப்புதவிக்காக கீழே தரப்பட்டுள்ளது:",
     "sp-contributions-blocked-notice-anon": "இந்த IP முகவரி தற்போது தடுக்கப்பட்டுள்ளது.\nசமீபத்திய தடுப்பு குறிப்பேடு  கீழே குறிப்பிற்காக வழங்கப்பட்டுள்ளது :",
     "sp-contributions-search": "பங்களிப்புகளைத் தேடு",
-    "sp-contributions-suppresslog": "பயனரின் நீக்கப்பட்ட பங்களிப்புகள்",
     "sp-contributions-username": "ஐ.பி. அல்லது பயனர் பெயர்:",
     "sp-contributions-toponly": "சமீபத்திய பரிசீலனைகளுக்குட்பட்ட  திருத்தங்களை மட்டும் காண்பி",
     "sp-contributions-submit": "தேடுக",
     "allmessagesname": "பெயர்",
     "allmessagesdefault": "இயல்பிருப்பு உரை",
     "allmessagescurrent": "தற்போதைய உரை",
-    "allmessagestext": "இது மீடியாவிக்கி பெயர்வெளியிலுள்ள எல்லா முறைமை தகவல்களினதும் பட்டியலாகும்.\nமொழிபெயர்ப்பில் உதவ விரும்பின் அருள்கூர்ந்து [//translatewiki.net பீட்டாவிக்கி], [https://www.mediawiki.org/wiki/Localisation மீடியாவிக்கி மொழியாக்க]  தளங்களுக்குச் செல்லவும்.",
+    "allmessagestext": "இது மீடியாவிக்கி பெயர்வெளியிலுள்ள எல்லா முறைமை தகவல்களினதும் பட்டியலாகும்.\nமொழிபெயர்ப்பில் உதவ விரும்பின் அருள்கூர்ந்து [//translatewiki.net பீட்டாவிக்கி], [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation மீடியாவிக்கி மொழியாக்க]  தளங்களுக்குச் செல்லவும்.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' முடக்கப்பட்டுள்ளப் படியால் இப்பக்கததை பயன்படுத்த முடியாது.",
     "allmessages-filter-legend": "வடிகட்டி",
     "allmessages-filter": "தனிப்பயனாக்கத்தின்படி வடிகட்டு.",
index eb0b67c..0b5e91b 100644 (file)
     "pool-timeout": "తాళం కొరకు వేచివుండడానికి కాలపరిమితి అయిపోయింది",
     "pool-queuefull": "సమూహపు వరుస నిండుగా ఉంది",
     "pool-errorunknown": "తెలియని లోపం",
+    "pool-servererror": "పూల్ కౌంటర్ సేవ అందుబాటులో లేదు ($1).",
     "aboutsite": "{{SITENAME}} గురించి",
     "aboutpage": "Project:గురించి",
     "copyright": "విషయం $1 కి లోబడి లభ్యం, వేరుగా పేర్కొంటే తప్ప.",
     "prefs-skin": "రూపు",
     "skin-preview": "మునుజూడు",
     "datedefault": "ఏదైనా పరవాలేదు",
-    "prefs-beta": "బీటా సౌలభ్యాలు",
     "prefs-datetime": "తేదీ, సమయం",
     "prefs-labs": "ప్రయోగాత్మక సౌలభ్యాలు",
     "prefs-user-pages": "వాడుకరి పేజీలు",
     "unwatchedpages": "వీక్షణలో లేని పేజీలు",
     "listredirects": "దారిమార్పుల జాబితా",
     "listduplicatedfiles": "నకళ్ళు కలిగిన ఫైళ్ళ జాబితా",
+    "listduplicatedfiles-summary": "ఇది ఒక ఫైలు యొక్క సరికొత్త సంచిక మరొక ఫైలు యొక్క సరికొత్త సంచికతో సమానంగా ఉండే నకిలీ ఫైళ్ళ జాబితా. స్థానిక ఫైళ్ళు మాత్రమే పరిగణించబడ్డాయి.",
     "listduplicatedfiles-entry": "[[:File:$1|$1]] కు [[$3|{{PLURAL:$2|ఓ నకలు ఉంది|$2 నకళ్ళున్నాయి}}]].",
     "unusedtemplates": "వాడని మూసలు",
     "unusedtemplatestext": "వేరే ఇతర పేజీలలో చేర్చని {{ns:template}} పేరుబరిలోని పేజీలన్నింటినీ ఈ పేజీ చూపిస్తుంది.\nమూసలను తొలగించే ముందు వాటికి ఉన్న ఇతర లింకుల కోసం చూడడం గుర్తుంచుకోండి.",
     "listgrouprights-removegroup-self": "{{PLURAL:$2|సమూహాన్ని|సమూహాలని}} తన స్వంత ఖాతా నుండి తొలగించుకోవడం: $1",
     "listgrouprights-addgroup-self-all": "అన్ని సమూహాలని స్వంత ఖాతాకు చేర్చుకోలగడటం",
     "listgrouprights-removegroup-self-all": "స్వంత ఖాతా నుండి అన్ని సమూహాలనూ తొలగించుకోగలగడం",
+    "trackingcategories-name": "సందేశం పేరు",
+    "trackingcategories-nodesc": "వివరణ లేదు.",
+    "trackingcategories-disabled": "వర్గం అచేతనమై ఉంది",
     "mailnologin": "పంపించవలసిన చిరునామా లేదు",
     "mailnologintext": "ఇతరులకు ఈ-మెయిలు పంపించాలంటే, మీరు [[Special:UserLogin|లాగిన్‌]] అయి ఉండాలి, మరియు మీ [[Special:Preferences|అభిరుచుల]]లో సరైన ఈ-మెయిలు చిరునామా ఇచ్చి ఉండాలి.",
     "emailuser": "ఈ వాడుకరికి ఈ-మెయిలుని పంపించండి",
     "nowatchlist": "మీ వీక్షణ జాబితా ఖాళీగా ఉంది.",
     "watchlistanontext": "మీ వీక్షణ జాబితా లోని అంశాలను చూసేందుకు లేదా మార్చేందుకు మీరు $1.",
     "watchnologin": "లాగిన్‌ అయిలేరు",
-    "watchnologintext": "మీ వీక్షణ జాబితాను మార్చడానికి మీరు [[Special:UserLogin|లాగిన్‌]] అయి ఉండాలి.",
     "addwatch": "వీక్షణ జాబితాలో చేర్చు",
     "addedwatchtext": "\"[[:$1]]\" అనే పుట మీ [[Special:Watchlist|వీక్షణ జాబితా]]లో చేరింది.\nభవిష్యత్తులో ఈ పుటకి మరియు సంబంధిత చర్చాపుటకి జరిగే మార్పులు అక్కడ కనిపిస్తాయి.",
     "removewatch": "వీక్షణ జాబితా నుండి తొలగించు",
     "sp-contributions-newbies-sub": "కొత్తవారి కోసం",
     "sp-contributions-newbies-title": "కొత్త ఖాతాల వాడుకరుల మార్పుచేర్పులు",
     "sp-contributions-blocklog": "నిరోధాల చిట్టా",
+    "sp-contributions-suppresslog": "అణచిపెట్టబడిన వాడుకరి రచనలు",
     "sp-contributions-deleted": "తొలగించబడిన వాడుకరి రచనలు",
     "sp-contributions-uploads": "ఎక్కింపులు",
     "sp-contributions-logs": "చిట్టాలు",
     "sp-contributions-blocked-notice": "ఈ వాడుకరిపై ప్రస్తుతం నిరోధం ఉంది.\nనిరోధపు చిట్టాలోని చివరి పద్దుని మీ సమాచారంకోసం ఇస్తున్నాం:",
     "sp-contributions-blocked-notice-anon": "ఈ ఐపీ చిరునామాపై ప్రస్తుతం నిరోధం ఉంది.\nనిరోధపు చిట్టాలోని చివరి పద్దుని మీ సమాచారంకోసం ఇస్తున్నాం:",
     "sp-contributions-search": "రచనల కోసం అన్వేషణ",
-    "sp-contributions-suppresslog": "అణచిపెట్టబడిన వాడుకరి రచనలు",
     "sp-contributions-username": "ఐపీ చిరునామా లేదా వాడుకరిపేరు:",
     "sp-contributions-toponly": "చిట్టచివరి కూర్పులను మాత్రమే చూపించు",
     "sp-contributions-newonly": "పేజీని సృష్టించిన మార్పులను మాత్రమే చూపించు",
     "allmessagesname": "పేరు",
     "allmessagesdefault": "అప్రమేయ సందేశపు పాఠ్యం",
     "allmessagescurrent": "ప్రస్తుత పాఠ్యం",
-    "allmessagestext": "మీడియావికీ పేరుబరిలో ఉన్న అంతరవర్తి సందేశాల జాబితా ఇది.\nసాధారణ మీడియావికీ స్థానికీకరణకి మీరు తోడ్పడాలనుకుంటే, దయచేసి [https://www.mediawiki.org/wiki/Localisation మీడియావికీ స్థానికీకరణ] మరియు [//translatewiki.net ట్రాన్స్&zwnj;లేట్&zwnj;వికీ.నెట్] సైట్లను చూడండి.",
+    "allmessagestext": "మీడియావికీ పేరుబరిలో ఉన్న అంతరవర్తి సందేశాల జాబితా ఇది.\nసాధారణ మీడియావికీ స్థానికీకరణకి మీరు తోడ్పడాలనుకుంటే, దయచేసి [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation మీడియావికీ స్థానికీకరణ] మరియు [//translatewiki.net ట్రాన్స్&zwnj;లేట్&zwnj;వికీ.నెట్] సైట్లను చూడండి.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' అన్నది అచేతనం చేసి ఉన్నందువల్ల ఈ పేజీని వాడలేరు.",
     "allmessages-filter-legend": "వడపోత",
     "allmessages-filter": "కస్టమైజేషను స్థితిని బట్టి వడకట్టు:",
index 4d4ab9f..e44d6b7 100644 (file)
     "nowatchlist": "Дар феҳристи пайгириҳои шумо ҳеҷ мавриде нест.",
     "watchlistanontext": "Лутфан барои мушоҳида ва вироиши феҳристи пайгириҳои худ аз $1 истифода кунед.",
     "watchnologin": "Вуруд нашуда",
-    "watchnologintext": "Барои тағйири феҳристи пайгириҳои худ бояд [[Special:UserLogin|ба систем ворид шавед]].",
     "addedwatchtext": "Ин саҳифа \"[[:$1]]\" ва [[Special:Watchlist|феҳристи назароти]] Шумо илова шуд.\nДигаргуниҳои ояндаи ин саҳифа ва саҳифи баҳси алоқаманд дар рӯихати онҷо хоҳад шуд,\nва саҳифа '''ғафс''' дар [[Special:RecentChanges|рӯихати тағйироти охирин]] барои бо осони дарёфт кардан хоҳад ба назар расид.\n\nАгар шумо дертар аз феҳристи назаротатон ин саҳифаро ҳазв кардан хоҳед, дар меню \"Назар накардан\"-ро пахш кунед.",
     "removedwatchtext": "Саҳифаи \"[[:$1]]\" аз [[Special:Watchlist|феҳристи пайгириҳои шумо]] бардошта шуд.",
     "watch": "Назар кардан",
     "allmessagesname": "Ном",
     "allmessagesdefault": "Матни қарордодӣ",
     "allmessagescurrent": "Матни кунунӣ",
-    "allmessagestext": "Ин феҳристи паёмҳои системавии дастрас дар фазои номи MediaWiki мебошад.\nАгар майли ҳиссагузорӣ карданро ба маҳалликунонии MediaWiki доред, пас лутан саҳифаҳои [https://www.mediawiki.org/wiki/Localisation Маҳалликунонии MediaWiki] ва [//translatewiki.net translatewiki.net] нигаред.",
+    "allmessagestext": "Ин феҳристи паёмҳои системавии дастрас дар фазои номи MediaWiki мебошад.\nАгар майли ҳиссагузорӣ карданро ба маҳалликунонии MediaWiki доред, пас лутан саҳифаҳои [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Маҳалликунонии MediaWiki] ва [//translatewiki.net translatewiki.net] нигаред.",
     "allmessagesnotsupportedDB": "Аз ин саҳифа наметавон истифода бурд, чун '''$wgUseDatabaseMessages''' ғайрифаъол гардонида шудааст.",
     "allmessages-filter-legend": "Филтр",
     "allmessages-filter-all": "Ҳама",
index bebd969..8b293a4 100644 (file)
     "nowatchlist": "Dar fehristi pajgirihoi şumo heç mavride nest.",
     "watchlistanontext": "Lutfan baroi muşohida va viroişi fehristi pajgirihoi xud az $1 istifoda kuned.",
     "watchnologin": "Vurud naşuda",
-    "watchnologintext": "Baroi taƣjiri fehristi pajgirihoi xud bojad [[Special:UserLogin|ba sistem vorid şaved]].",
     "addedwatchtext": "In sahifa \"[[:$1]]\" va [[Special:Watchlist|fehristi nazaroti]] Şumo ilova şud.\nDigargunihoi ojandai in sahifa va sahifi bahsi aloqamand dar rūixati onço xohad şud,\nva sahifa '''ƣafs''' dar [[Special:RecentChanges|rūixati taƣjiroti oxirin]] baroi bo osoni darjoft kardan xohad ba nazar rasid.\n\nAgar şumo dertar az fehristi nazarotaton in sahifaro hazv kardan xohed, dar menju \"Nazar nakardan\"-ro paxş kuned.",
     "removedwatchtext": "Sahifai \"[[:$1]]\" az [[Special:Watchlist|fehristi pajgirihoi şumo]] bardoşta şud.",
     "watch": "Nazar kardan",
     "allmessagesname": "Nom",
     "allmessagesdefault": "Matni qarordodī",
     "allmessagescurrent": "Matni kununī",
-    "allmessagestext": "In fehristi pajomhoi sistemaviji dastras dar fazoi nomi MediaWiki meboşad.\nAgar majli hissaguzorī kardanro ba mahallikunoniji MediaWiki dored, pas lutan sahifahoi [https://www.mediawiki.org/wiki/Localisation Mahallikunoniji MediaWiki] va [//translatewiki.net translatewiki.net] nigared.",
+    "allmessagestext": "In fehristi pajomhoi sistemaviji dastras dar fazoi nomi MediaWiki meboşad.\nAgar majli hissaguzorī kardanro ba mahallikunoniji MediaWiki dored, pas lutan sahifahoi [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Mahallikunoniji MediaWiki] va [//translatewiki.net translatewiki.net] nigared.",
     "allmessagesnotsupportedDB": "Az in sahifa nametavon istifoda burd, cun '''$wgUseDatabaseMessages''' ƣajrifa'ol gardonida şudaast.",
     "allmessages-filter-legend": "Filtr",
     "allmessages-filter-all": "Hama",
index 40794a1..74b6d8b 100644 (file)
     "watchthis": "เฝ้าดูหน้านี้",
     "savearticle": "บันทึก",
     "preview": "ตัวอย่าง",
-    "showpreview": "à¹\81สà¸\94à¸\87ตัวอย่าง",
+    "showpreview": "à¸\94ูตัวอย่าง",
     "showlivepreview": "แสดงตัวอย่างทันที",
     "showdiff": "แสดงความเปลี่ยนแปลง",
     "anoneditwarning": "'''คำเตือน:''' คุณมิได้ล็อกอิน เลขที่อยู่ไอพีของคุณจะถูกบันทึกไว้ในประวัติการแก้ไขของหน้านี้",
     "storedversion": "รุ่นที่เก็บไว้",
     "nonunicodebrowser": "'''คำเตือน: เว็บเบราว์เซอร์นี้ไม่สนับสนุนการใช้งานแบบยูนิโคด ตัวอักษรที่ไม่ใช่แบบแอสกีจะแสดงในกล่องการแก้ไขในลักษณะรหัสเลขฐานสิบหก'''",
     "editingold": "'''คำเตือน: ข้อมูลที่แก้ไขอยู่ไม่ใช่ข้อมูลใหม่ล่าสุดของหน้านี้ ถ้าทำการบันทึกไป การเปลี่ยนแปลงที่เกิดขึ้นระหว่างรุ่นนี้กับรุ่นใหม่จะสูญหาย'''",
-    "yourdiff": "à¸\82à¹\89อแตกต่าง",
+    "yourdiff": "à¸\84วามแตกต่าง",
     "copyrightwarning": "โปรดอย่าลืมว่างานเขียนทั้งหมดใน {{SITENAME}} ผู้เขียนทั้งหมดยินดีให้งานเก็บไว้ภายใต้สัญญาลิขสิทธิ์ $2 (ดู $1 สำหรับข้อมูลเพิ่มเติม)\nถ้าคุณไม่ต้องการให้งานของคุณถูกแก้ไข หรือไม่ต้องการให้งานเผยแพร่ตามที่ได้กล่าวไว้ อย่าส่งข้อความเข้ามาที่นี่<br />\nนอกจากนี้แน่ใจว่าข้อความที่ส่งเข้ามาได้เขียนด้วยตัวเอง ไม่ได้คัดลอก หรือทำซ้ำจากแหล่งอื่น\n'''อย่าส่งงานที่มีลิขสิทธิ์เข้ามาก่อนได้รับอนุญาตจากเจ้าของ!'''",
     "copyrightwarning2": "โปรดอย่าลืมว่างานเขียนทั้งหมดใน {{SITENAME}} อาจจะถูกแก้ไข ดัดแปลง หรือลบออกโดยผู้ร่วมเขียนคนอื่น\nถ้าคุณไม่ต้องการให้งานของคุณถูกแก้ไข หรือไม่ต้องการให้งานเผยแพร่ตามที่กล่าวไว้ อย่าส่งข้อความของคุณเข้ามาที่นี่<br />\nนอกจากนี้คุณแน่ใจว่าข้อความที่ส่งเข้ามาคุณได้เขียนด้วยตัวเอง ไม่ได้คัดลอก ทำซ้ำส่วนหนึ่งส่วนใดหรือทั้งหมดจากแหล่งอื่น (ดูรายละเอียดที่ $1)\n'''อย่าส่งงานที่มีลิขสิทธิ์เข้ามาก่อนได้รับอนุญาตจากเจ้าของ!'''",
     "longpageerror": "'''ข้อผิดพลาด: ข้อความที่คุณส่งเข้ามามีขนาด $1 กิโลไบต์\nซึ่งเกินกว่าขนาดสูงสุดซึ่งกำหนดไว้ที่ $2 กิโลไบต์ จึงไม่สามารถบันทึกได้'''",
     "revdelete-no-file": "ไม่มีไฟล์ที่ระบุ",
     "revdelete-show-file-confirm": "คุณแน่ใจที่จะดูรุ่นที่ถูกลบของไฟล์ \"<nowiki>$1</nowiki>\" เมื่อวันที่ $2 เวลา $3 หรือไม่",
     "revdelete-show-file-submit": "ใช่",
+    "revdelete-selected-text": "{{PLURAL:$1|รุ่นที่เลือก}}ของ [[:$2]]:",
+    "revdelete-selected-file": "{{PLURAL:$1|รุ่นไฟล์ที่เลือก}}ของ [[:$2]]:",
     "logdelete-selected": "{{PLURAL:$1|เหตุการณ์ปูมที่เลือก|เหตุการณ์ปูมที่เลือก}} :",
     "revdelete-text-text": "รุ่นที่ถูกลบจะยังปรากฏในประวัติหน้า แต่สาธารณะจะไม่สามารถเข้าถึงเนื้อหาบางส่วนได้",
     "revdelete-text-file": "รุ่นที่ถูกลบจะยังปรากฏในประวัติไฟล์ แต่สาธารณะจะไม่สามารถเข้าถึงเนื้อหาบางส่วนได้",
     "prefs-skin": "หน้าตา",
     "skin-preview": "แสดงตัวอย่าง",
     "datedefault": "ค่าตั้งต้น",
-    "prefs-beta": "คุณลักษณะรุ่นทดสอบ",
     "prefs-datetime": "วันที่และเวลา",
     "prefs-labs": "คุณสมบัติทดลอง",
     "prefs-user-pages": "หน้าผู้ใช้",
     "listgrouprights-removegroup-self": "ลบ{{PLURAL:$2|กลุ่ม|กลุ่ม}}ออกจากบัญชี: $1",
     "listgrouprights-addgroup-self-all": "เพิ่มทุกกลุ่มเข้าไปในบัญชีนี้",
     "listgrouprights-removegroup-self-all": "นำทุกกลุ่มออกจากบัญชีนี้",
+    "hidden-category-category-desc": "นี่คือหมวดหมู่ที่ติด <nowiki>__HIDDENCAT__</nowiki> ซึ่งป้องกันมิให้แสดงในกล่องลิงก์หมวดหมู่ในหน้าโดยปริยาย",
     "mailnologin": "ไม่มีที่อยู่ส่ง",
     "mailnologintext": "คุณต้อง[[Special:UserLogin|ล็อกอิน]]และมีที่อยู่อีเมลที่สมเหตุสมผลใน[[Special:Preferences|การตั้งค่า]]ของคุณ ในการส่งอีเมลหาผู้ใช้อื่น",
     "emailuser": "ส่งอีเมลหาผู้ใช้นี้",
     "nowatchlist": "ไม่มีรายการในรายการเฝ้าดูของคุณ",
     "watchlistanontext": "กรุณา$1เพื่อดูหรือแก้ไขรายการในรายการเฝ้าดูของคุณ",
     "watchnologin": "ยังไม่ได้ล็อกอิน",
-    "watchnologintext": "ต้อง[[Special:UserLogin|ล็อกอิน]]เพื่อแก้ไขรายการเฝ้าดูของคุณ",
     "addwatch": "เพิ่มเข้ารายการเฝ้าดู",
     "addedwatchtext": "หน้า \"[[:$1]]\" ได้เพิ่มลงใน[[Special:Watchlist|รายการเฝ้าดู]]ของคุณแล้ว การเปลี่ยนแปลงในหน้านี้หรือหน้าพูดคุยที่เกี่ยวข้องจะแสดงในรายการดังกล่าว",
     "removewatch": "นำออกจากรายการเฝ้าดู",
     "sp-contributions-username": "เลขที่อยู่ไอพีหรือชื่อผู้ใช้:",
     "sp-contributions-toponly": "แสดงเฉพาะการแก้ไขรุ่นล่าสุด",
     "sp-contributions-newonly": "แสดงเฉพาะการแก้ไขที่เป็นการสร้างหน้า",
-    "sp-contributions-submit": "สืà¸\9aà¸\84à¹\89à¸\99",
+    "sp-contributions-submit": "à¸\84à¹\89à¸\99หา",
     "whatlinkshere": "หน้าที่ลิงก์มา",
     "whatlinkshere-title": "หน้าที่ลิงก์มายัง \"$1\"",
     "whatlinkshere-page": "หน้า:",
     "allmessagesname": "ชื่อ",
     "allmessagesdefault": "ข้อความตามค่าตั้งต้น",
     "allmessagescurrent": "ข้อความปัจจุบัน",
-    "allmessagestext": "นี่คือรายการข้อความของระบบที่อยู่ในเนมสเปซมีเดียวิกิ\nกรุณาอ่านหน้า[https://www.mediawiki.org/wiki/Localisation เทศวิวัตน์ของมีเดียวิกิ] และ [//translatewiki.net translatewiki.net] ถ้าคุณอยากที่จะช่วยแปลข้อความของระบบมีเดียวิกิ",
+    "allmessagestext": "นี่คือรายการข้อความของระบบที่อยู่ในเนมสเปซมีเดียวิกิ\nกรุณาอ่านหน้า[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation เทศวิวัตน์ของมีเดียวิกิ] และ [//translatewiki.net translatewiki.net] ถ้าคุณอยากที่จะช่วยแปลข้อความของระบบมีเดียวิกิ",
     "allmessagesnotsupportedDB": "หน้านี้ไม่สามารถใช้งานได้เนื่องจาก '''$wgUseDatabaseMessages''' ถูกระงับการใช้งาน",
     "allmessages-filter-legend": "กรอง",
     "allmessages-filter": "กรองตามสถานะที่เลือก:",
     "version-software": "ซอฟต์แวร์ที่ติดตั้ง",
     "version-software-product": "ชื่อ",
     "version-software-version": "รุ่น",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath เส้นทางบทความ]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath เส้นทางสคริปต์]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath เส้นทางบทความ]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath เส้นทางสคริปต์]",
     "redirect": "การเปลี่ยนทางตามชื่อไฟล์ รหัสประจำผู้ใช้ หน้าหรือรุ่น",
     "redirect-legend": "การเปลี่ยนทางไปยังไฟล์หรือหน้า",
     "redirect-summary": "หน้าพิเศษนี้เปลี่ยนทางไปยังไฟล์ (ระบุเป็นชื่อไฟล์) หน้า (ระบุเป็นรหัสรุ่นหรือรหัสหน้า) หรือหน้าผู้ใช้ (ระบุเป็นรหัสผู้ใช้ตัวเลข) การใช้งาน: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] หรือ [[{{#Special:Redirect}}/user/101]]",
index f0468a1..4e0f00a 100644 (file)
     "prefs-skin": "Bezeg",
     "skin-preview": "Deslapky syn",
     "datedefault": "Gaýybana",
-    "prefs-beta": "Beta funksiýalar",
     "prefs-datetime": "Sene we wagt",
     "prefs-labs": "Synag funksiýalar",
     "prefs-personal": "Ulanyjy maglumatlary",
     "nowatchlist": "Gözegçilik sanawyňyzda hiçhili sahypa ýok.",
     "watchlistanontext": "Gözegçilik sanawyňyzdaky sahypalary görmek ýa-da redaktirlemek üçin $1.",
     "watchnologin": "Sessiýa açmansyňyz",
-    "watchnologintext": "Gözegçilik sanawyňyzy üýtgetmek üçin [[Special:UserLogin|sessiýa açmagyňyz]] zerurdyr.",
     "addedwatchtext": "[[:$1]]  atly sahypa [[Special:Watchlist|gözegçilik sanawyňyza]] goşuldy.\n\nGeljekde, bu sahypada we degişli çekişme sahypasynda ediljek üýtgeşmeler şu ýerde sanawlanjakdyr.\n\nAňsatlyk bilen saýlap almak üçin bolsa, [[Special:RecentChanges|soňky üýtgeşmeleriň sanawynda]] '''goýy''' harp bilen görkeziljekdir.",
     "removedwatchtext": "\"[[:$1]]\" sahypasy [[Special:Watchlist|gözegçilik sanawyňyzdan]] aýyryldy.",
     "watch": "Gözegçilikde sakla",
     "allmessagesname": "At",
     "allmessagesdefault": "Gaýybana habarlaşyk teksti",
     "allmessagescurrent": "Häzirki habarlaşyk teksti",
-    "allmessagestext": "Bu sanaw MediaWiki at giňişliginde bar bolan ulgam habarlaşyklarynyň sanawydyr.\nUmumy MediaWiki lokalizasiýasyna goşan goşmak isleýän bolsaňyz, [https://www.mediawiki.org/wiki/Localisation MediaWiki lokalizasiýasy] we [//translatewiki.net translatewiki.net] sahypalaryna baryp görmegiňizi haýyş edýäris.",
+    "allmessagestext": "Bu sanaw MediaWiki at giňişliginde bar bolan ulgam habarlaşyklarynyň sanawydyr.\nUmumy MediaWiki lokalizasiýasyna goşan goşmak isleýän bolsaňyz, [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki lokalizasiýasy] we [//translatewiki.net translatewiki.net] sahypalaryna baryp görmegiňizi haýyş edýäris.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' ýapykdygy zerarly bu sahypany ulanyp bolmaýar.",
     "allmessages-filter-legend": "Filtr",
     "allmessages-filter": "Üýtgediş statusy boýunça filtr:",
index 18859fa..50131bf 100644 (file)
     "prefs-skin": "Pabalat",
     "skin-preview": "Unang tingin",
     "datedefault": "Walang kagustuhan",
-    "prefs-beta": "Mga kaangkapang-katangiang pang-beta",
     "prefs-datetime": "Petsa at oras",
     "prefs-labs": "Mga kasangkapang-katangiang pang-Labs",
     "prefs-user-pages": "Mga pahina ng tagagamit",
     "nowatchlist": "Wala kang pahinang binabantayan.",
     "watchlistanontext": "Paki $1 upang makita o mabago ang mga aytem sa iyong binabantayan.",
     "watchnologin": "Hindi nakalagda",
-    "watchnologintext": "Dapat kang [[Special:UserLogin|nakalagda]] upang mabago ang talaan mo ng mga binabantayan.",
     "addwatch": "Idagdag sa bantayan",
     "addedwatchtext": "Dinagdag na ang pahinang \"[[:$1]]\" sa iyong [[Special:Watchlist|Babantayan]].\nMakikita doon ang lahat ng mga susunod na pagbabago sa pahinang ito pati na ang usapang pahina, at ang pahina ay makikitang sa '''malalaking titik''' ('''''bold''''') sa [[Special:RecentChanges|tala ng mga huling binago]] para madaling makita.",
     "removewatch": "Alisin mula sa bantayan",
     "allmessagesname": "Pangalan",
     "allmessagesdefault": "Tinakdang teksto",
     "allmessagescurrent": "Kasalukuyang teksto",
-    "allmessagestext": "Isa itong talaan ng mga mensahe ng sistema na makukuha mula sa namespace ng MediaWiki.\nPakidalaw ang [https://www.mediawiki.org/wiki/Localisation Lokalisasyong MediaWiki] at [//translatewiki.net translatewiki.net] kung ibig mong magambag sa heneriko o pangkalahatang lokalisasyon ng MediaWiki.",
+    "allmessagestext": "Isa itong talaan ng mga mensahe ng sistema na makukuha mula sa namespace ng MediaWiki.\nPakidalaw ang [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Lokalisasyong MediaWiki] at [//translatewiki.net translatewiki.net] kung ibig mong magambag sa heneriko o pangkalahatang lokalisasyon ng MediaWiki.",
     "allmessagesnotsupportedDB": "Hindi magagamit ang '''{{ns:special}}:AllMessages''' dahil hindi gumagana ang '''$wgUseDatabaseMessages'''.",
     "allmessages-filter-legend": "Salain",
     "allmessages-filter": "Salain ayon sa katayuan ng pagbabagay:",
     "version-entrypoints": "Mga URL na butas-pasukan",
     "version-entrypoints-header-entrypoint": "Butas na pasukan",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Landas ng artikulo]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Landas ng panitik]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Landas ng artikulo]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Landas ng panitik]",
     "fileduplicatesearch": "Maghanap ng kaparehong mga talaksan",
     "fileduplicatesearch-summary": "Maghanap ng mga kaparehong mga talaksan sa baba ng kanyang halaga ng ''hash''.",
     "fileduplicatesearch-legend": "Maghanap ng mga kapareho",
index 11c903e..151c751 100644 (file)
     "prefs-skin": "Görünüm",
     "skin-preview": "Önizleme",
     "datedefault": "Tercih yok",
-    "prefs-beta": "Beta özellikleri",
     "prefs-datetime": "Tarih ve saat",
     "prefs-labs": "Deneysel özellikler",
     "prefs-user-pages": "Kullanıcı sayfaları",
     "rcshowhidebots-show": "Göster",
     "rcshowhidebots-hide": "Gizle",
     "rcshowhideliu": "Kayıtlı kullanıcıları $1",
-    "rcshowhideliu-show": "Göster",
-    "rcshowhideliu-hide": "Gizle",
+    "rcshowhideliu-show": "göster",
+    "rcshowhideliu-hide": "gizle",
     "rcshowhideanons": "Anonim kullanıcıları $1",
     "rcshowhideanons-show": "Göster",
     "rcshowhideanons-hide": "Gizle",
     "nowatchlist": "İzleme listesinde hiçbir madde bulunmuyor.",
     "watchlistanontext": "Lütfen izleme listenizdeki maddeleri görmek ya da değiştirmek için $1.",
     "watchnologin": "Oturum açık değil.",
-    "watchnologintext": "İzleme listenizi değiştirebilmek için [[Special:UserLogin|oturum açmalısınız]].",
     "addwatch": "İzleme listesine ekle",
     "addedwatchtext": "\"[[:$1]]\" sayfası [[Special:Watchlist|izleme listenize]] eklenmiştir.\nBundan sonra, bu sayfaya ve ilgili tartışma sayfasına yapılacak değişiklikler burada listelenecek.",
     "removewatch": "İzleme listesinden kaldır",
     "sp-contributions-search": "Katkıları ara",
     "sp-contributions-username": "IP adresi veya kullanıcı adı:",
     "sp-contributions-toponly": "Sadece son revizyon olan değişiklikleri göster",
+    "sp-contributions-newonly": "Yalnızca yeni sayfa oluşturan değişiklikleri görüntüle",
     "sp-contributions-submit": "Ara",
     "whatlinkshere": "Sayfaya bağlantılar",
     "whatlinkshere-title": "\"$1\" maddesine bağlantı veren sayfalar",
     "allmessagesname": "Ad",
     "allmessagesdefault": "Varsayılan mesaj metni",
     "allmessagescurrent": "Kullanımdaki metin",
-    "allmessagestext": "Bu liste  MediaWiki ad alanında mevcut olan sistem mesajlarının listesidir.\nGenel MediaWiki yerelleştirmesine katkıda bulunmak isterseniz, lütfen [https://www.mediawiki.org/wiki/Localisation MediaWiki Yerelleştirmesi] ve [//translatewiki.net translatewiki.net] sayfalarını ziyaret edin.",
+    "allmessagestext": "Bu liste  MediaWiki ad alanında mevcut olan sistem mesajlarının listesidir.\nGenel MediaWiki yerelleştirmesine katkıda bulunmak isterseniz, lütfen [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Yerelleştirmesi] ve [//translatewiki.net translatewiki.net] sayfalarını ziyaret edin.",
     "allmessagesnotsupportedDB": "'''$wgUseDatabaseMessages''' kapalı olduğu için '''{{ns:special}}:Allmessages''' kullanıma açık değil.",
     "allmessages-filter-legend": "Filtre",
     "allmessages-filter": "Özelleştirme durumuna göre filtrele:",
index b185e5b..82fe130 100644 (file)
     "prefs-skin": "Күренеш",
     "skin-preview": "Алдан карау",
     "datedefault": "Баштагы көйләнмәләр",
-    "prefs-beta": "Бета-мөмкинчелекләр",
     "prefs-datetime": "Дата һәм вакыт",
     "prefs-labs": "Сынаулы мөмкинчелекләр",
     "prefs-personal": "Шәхси мәгълүматлар",
     "watchlistfor2": "$1 $2 өчен",
     "nowatchlist": "Күзәтү исемлегегездә битләр юк.",
     "watchnologin": "Кермәдегез",
-    "watchnologintext": "Күзәтү исемлегегезне үзгәртү өчен сез [[Special:UserLogin|керергә]] тиешсез.",
     "addedwatchtext": "\"[[:$1]]\" бите [[Special:Watchlist|күзәтү исемлегегезгә]] өстәлде.\nБу биттә һәм аның бәхәслегендә барлык булачак үзгәртүләр шунда күрсәтелер, һәм, [[Special:RecentChanges|соңгы үзгәртүләр]] исемлегендә бу битне җиңелрәк табу өчен, ул '''калын мәтен''' белән күрсәтелер.",
     "removedwatchtext": "«[[:$1]]» бите [[Special:Watchlist|сезнең күзәтү исемлегеннән]] бетерелде.",
     "watch": "Күзәтү",
     "allmessages": "Система хәбәрләре",
     "allmessagesname": "Исем",
     "allmessagesdefault": "Баштан ук куелган текс",
-    "allmessagestext": "Бу исемлек MediaWiki исемнәр мәйданында булган система хәбәрләренең исемлеге.\nГомуми MediaWiki локализациясендә катнашырга теләсәгез, зинһар [https://www.mediawiki.org/wiki/Localisation MediaWiki Локализациясе] һәм [//translatewiki.net translatewiki.net] сәхифәләрне кулланыгыз.",
+    "allmessagestext": "Бу исемлек MediaWiki исемнәр мәйданында булган система хәбәрләренең исемлеге.\nГомуми MediaWiki локализациясендә катнашырга теләсәгез, зинһар [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Локализациясе] һәм [//translatewiki.net translatewiki.net] сәхифәләрне кулланыгыз.",
     "allmessages-filter-legend": "Фильтр",
     "allmessages-filter-unmodified": "Үзгәртелмәгән",
     "allmessages-filter-all": "Барысы",
index 7362578..84ebc57 100644 (file)
     "mywatchlist": "Küzätü isemlegem",
     "nowatchlist": "Küzätü isemlegegezdä bitlär yuq.",
     "watchnologin": "Kermädegez",
-    "watchnologintext": "Küzätü isemlegegezne üzgärtü öçen, sez [[Special:UserLogin|kerergä]] tieşsez.",
     "addedwatchtext": "\"[[:$1]]\" bite [[Special:Watchlist|küzätü isemlegegezgä]] östälde.\nBu bittä häm anıñ bäxäslegendä barlıq bulaçaq üzgärtülär şunda kürsäteler, häm, [[Special:RecentChanges|soñğı üzgärtülär]] isemlegendä bu bitne ciñelräk tabu öçen, ul '''qalın mäten''' belän kürsäteler.",
     "removedwatchtext": "«[[:$1]]» bite [[Special:Watchlist|sezneñ küzätü isemlegennän]] beterelde.",
     "watch": "Küzätü",
     "allmessagesname": "İsem",
     "allmessagesdefault": "Töpcay yazma",
     "allmessagescurrent": "Eligi yazma",
-    "allmessagestext": "Bu isemlek MediaWiki isemnär mäydanında bulğan sistema xäbärläreneñ isemlege.\nĞomumi MediaWiki lokalizatsiäsendä qatnaşırğa teläsägez, zinhar [https://www.mediawiki.org/wiki/Localisation MediaWiki Lokalizatsiäse] häm [//translatewiki.net translatewiki.net] säxifälärne qullanığız.",
+    "allmessagestext": "Bu isemlek MediaWiki isemnär mäydanında bulğan sistema xäbärläreneñ isemlege.\nĞomumi MediaWiki lokalizatsiäsendä qatnaşırğa teläsägez, zinhar [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Lokalizatsiäse] häm [//translatewiki.net translatewiki.net] säxifälärne qullanığız.",
     "allmessages-filter-legend": "Filtr",
     "allmessages-filter-unmodified": "Üzgärtelmägän",
     "allmessages-filter-all": "Barısı",
index 5c980d6..4be92c9 100644 (file)
     "prefs-skin": "تېرە",
     "skin-preview": "ئالدىن كۆزەت",
     "datedefault": "مايىللىق يوق",
-    "prefs-beta": "سىناق ئىقتىدارلىرى",
     "prefs-datetime": "چېسلا ۋە ۋاقىت",
     "prefs-labs": "تەجرىبە ئىقتىدارلىرى",
     "prefs-user-pages": "ئىشلەتكۈچى بېتى",
     "nowatchlist": "كۆزەت تىزىملىكىڭىز بوش.",
     "watchlistanontext": "$1 كۆزەت تىزىملىكىڭىزنى كۆرۈپ تەھرىرلەڭ.",
     "watchnologin": "تىزىمغا كىرمىدى",
-    "watchnologintext": "سىز [[Special:UserLogin|تىزىمغا كىر]]گەندىلا ئاندىن كۆزەت تىزىملىكىڭىزنى ئۆزگەرتەلەيسىز.",
     "addwatch": "كۆزەت تىزىملىكىگە قوش",
     "addedwatchtext": "\"[[:$1]]\" بېتى [[Special:Watchlist|كۆزەت تىزىملىكى]]ڭىزگە قوشۇلدى.\nكەلگۈسىدە بۇ بەت ۋە ئۇنىڭ مۇنازىرە بېتىگە مۇناسىۋەتلىك ھەر قانداق ئۆزگەرتىش شۇ جايدا كۆرسىتىلدۇ.",
     "removewatch": "كۆزەت تىزىملىكىدىن چىقىرىۋەت",
     "allmessagesname": "ئاتى",
     "allmessagesdefault": "كۆڭۈلدىكى ئۇچۇر تېكستى",
     "allmessagescurrent": "نۆۋەتتىكى ئۇچۇر تېكستى",
-    "allmessagestext": "بۇ جايدا تەڭشىگىلى بولىدىغان ھەممە سىستېما كۆرۈنۈش ئۇچۇرلىرى كۆرسىتىلدى.\nئەگەر ھەقىقىي يەرلەشتۈرۈلگەن MediaWiki غا تۆھپە قوشماقچى بولسىڭىز[https://www.mediawiki.org/wiki/Localisation MediaWiki يەرلىكلەشتۈرۈش] ۋە [//translatewiki.net translatewiki.net] نى زىيارەت قىلىڭ.",
+    "allmessagestext": "بۇ جايدا تەڭشىگىلى بولىدىغان ھەممە سىستېما كۆرۈنۈش ئۇچۇرلىرى كۆرسىتىلدى.\nئەگەر ھەقىقىي يەرلەشتۈرۈلگەن MediaWiki غا تۆھپە قوشماقچى بولسىڭىز[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki يەرلىكلەشتۈرۈش] ۋە [//translatewiki.net translatewiki.net] نى زىيارەت قىلىڭ.",
     "allmessagesnotsupportedDB": "بۇ بەتنى ئىشلەتكىلى بولمايدۇ، سەۋەبى '''$wgUseDatabaseMessages''' چەكلەنگەن.",
     "allmessages-filter-legend": "سۈزگۈچ",
     "allmessages-filter": "ئىختىيارىچە سۈزگۈچ ھالىتى:",
index 3be5706..1522484 100644 (file)
     "prefs-skin": "Оформлення",
     "skin-preview": "Попередній перегляд",
     "datedefault": "Стандартний",
-    "prefs-beta": "Бета-функції",
     "prefs-datetime": "Дата й час",
     "prefs-labs": "Експериментальні функції",
     "prefs-user-pages": "Сторінки користувача",
     "nowatchlist": "Ваш список спостереження порожній.",
     "watchlistanontext": "Вам необхідно $1, щоб переглянути чи редагувати список спостереження.",
     "watchnologin": "Ви не ввійшли до системи",
-    "watchnologintext": "Ви повинні [[Special:UserLogin|ввійти до системи]], щоб мати можливість змінювати список спостереження.",
     "addwatch": "Додати до списку спостереження",
     "addedwatchtext": "Сторінку «[[:$1]]» додано до вашого [[Special:Watchlist|списку спостереження]].\nПодальші редагування цієї сторінки (та пов'язаної з нею сторінки обговорення) відображатимуться в цьому списку.",
     "removewatch": "Видалити зі списку спостереження",
     "sp-contributions-newbies-sub": "Внесок новачків",
     "sp-contributions-newbies-title": "Внесок з нових облікових записів",
     "sp-contributions-blocklog": "журнал блокувань",
+    "sp-contributions-suppresslog": "вилучений внесок користувача",
     "sp-contributions-deleted": "вилучені редагування користувача",
     "sp-contributions-uploads": "завантаження",
     "sp-contributions-logs": "журнали",
     "sp-contributions-blocked-notice": "Цей користувач наразі заблокований. Останній запис у журналі блокувань такий:",
     "sp-contributions-blocked-notice-anon": "Доступ з цієї IP-адреси зараз заблокований.\nДалі наведено останній запис з журналу блокувань:",
     "sp-contributions-search": "Пошук внеску",
-    "sp-contributions-suppresslog": "вилучений внесок користувача",
     "sp-contributions-username": "IP-адреса або ім'я користувача:",
     "sp-contributions-toponly": "Показувати тільки редагування, що є останніми версіями",
     "sp-contributions-newonly": "Показувати тільки редагування, які є створеннями сторінок",
     "allmessagesname": "Назва",
     "allmessagesdefault": "Стандартний текст",
     "allmessagescurrent": "Поточний текст",
-    "allmessagestext": "Це список усіх системних повідомлень, які доступні в просторі назв «MediaWiki».\nБудь ласка, відвідайте [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] і [//translatewiki.net translatewiki.net], якщо ви хочете зробити внесок до спільної локалізації MediaWiki.",
+    "allmessagestext": "Це список усіх системних повідомлень, які доступні в просторі назв «MediaWiki».\nБудь ласка, відвідайте [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] і [//translatewiki.net translatewiki.net], якщо ви хочете зробити внесок до спільної локалізації MediaWiki.",
     "allmessagesnotsupportedDB": "Ця сторінка не може використовуватися, оскільки вимкнена опція '''$wgUseDatabaseMessages'''.",
     "allmessages-filter-legend": "Фільтр",
     "allmessages-filter": "Фільтр за внесеними змінами:",
     "version-entrypoints": "URL-адреса точки входу",
     "version-entrypoints-header-entrypoint": "Точка входу",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Шлях до статей]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Шлях до скриптів]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Шлях до статей]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Шлях до скриптів]",
     "redirect": "Перенаправлення за файлом, користувачем, сторінкою або ID версії",
     "redirect-legend": "Перенаправити на файл чи сторінку",
     "redirect-summary": "Ця спеціальна сторінка перенаправляє на файл (за поданою назвою файлу), сторінку (за поданим ID версії або сторінки) або сторінку користувача (за поданим числовим ID користувача). Використання: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]],[[{{#Special:Redirect}}/revision/328429]] або [[{{#Special:Redirect}}/user/101]].",
index b1d2111..abcc91c 100644 (file)
     "prefs-skin": "Aspeto grafico",
     "skin-preview": "Anteprima",
     "datedefault": "Nissuna preferensa",
-    "prefs-beta": "Funsionałidà beta",
     "prefs-datetime": "Data e ora",
     "prefs-labs": "Funsionałidà de i laboratori",
     "prefs-user-pages": "Pàjine utente",
     "nowatchlist": "No te ghè indicà pagine da tegner d'ocio.",
     "watchlistanontext": "Per vardar e modifegar l'ełenco de i osservati speciałi bisogna $1.",
     "watchnologin": "Acesso mia efetuà",
-    "watchnologintext": "Te ghè prima da far el [[Special:UserLogin|login]] par modificar la to lista de osservati speciali.",
     "addwatch": "Tien d'ocio",
     "addedwatchtext": "Ła pagina \"[[:$1]]\" ła xe stà xontà a ła to [[Special:Watchlist|lista de pàjine da tegner d'ocio]].\nI futuri canbiamenti a sta pàjina e a ła so pàjina de discusion i vegnarà elencai in cheła pàjina là.",
     "removewatch": "Cava da łe tegnùe d'ocio",
     "allmessagesname": "Nome",
     "allmessagesdefault": "Testo predefinìo",
     "allmessagescurrent": "Testo come che el xe desso",
-    "allmessagestext": "Sta quà l'è na lista de tuti i messagi disponibili nel namespace MediaWiki.\nPar piaser visita [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se te voli jutarne par la traduzion del software MediaWiki ne le varie lengue.",
+    "allmessagestext": "Sta quà l'è na lista de tuti i messagi disponibili nel namespace MediaWiki.\nPar piaser visita [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se te voli jutarne par la traduzion del software MediaWiki ne le varie lengue.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:Allmessages''' no'l xè supportà parché '''$wgUseDatabaseMessages''' no'l xè ativo.",
     "allmessages-filter-legend": "Filtro",
     "allmessages-filter": "Filtra par stato de personalixassion:",
index 53f1e4d..0aa8c41 100644 (file)
     "invalidtitle-knownnamespace": "Tựa trang không hợp lệ có không gian tên “$2” và văn bản “$3”",
     "invalidtitle-unknownnamespace": "Tựa trang không hợp lệ có không gian tên số $1 không rõ và văn bản “$2”",
     "exception-nologin": "Chưa đăng nhập",
-    "exception-nologin-text": "Xin vui lòng [[Special:Userlogin|đăng nhập]] để truy cập trang hoặc tác vụ này.",
+    "exception-nologin-text": "Xin vui lòng [[Special:Userlogin|đăng nhập]] để truy cập trang hoặc thực hiện tác vụ này.",
     "exception-nologin-text-manual": "Xin vui lòng $1 để truy cập trang hoặc tác vụ này.",
     "virus-badscanner": "Cấu hình sau: không nhận ra bộ quét virus: ''$1''",
     "virus-scanfailed": "quét thất bại (mã $1)",
     "prefs-skin": "Hình dạng",
     "skin-preview": "Xem trước",
     "datedefault": "Không quan tâm",
-    "prefs-beta": "Tính năng beta",
     "prefs-datetime": "Ngày tháng",
     "prefs-labs": "Tính năng phòng thí nghiệm",
     "prefs-user-pages": "Trang cá nhân",
     "listgrouprights-removegroup-self": "Có thể loại tài khoản của chính mình ra khỏi {{PLURAL:$2|nhóm|các nhóm}}: $1",
     "listgrouprights-addgroup-self-all": "Có thể đưa tài khoản của chính mình vào tất cả các nhóm",
     "listgrouprights-removegroup-self-all": "Có thể loại tài khoản của chính mình ra khỏi tất cả các nhóm",
+    "trackingcategories": "Thể loại phần mềm",
+    "trackingcategories-summary": "Đây là danh sách các thể loại được phần mềm MediaWiki tự động xếp trang vào. Các tên thể loại được định rõ trong các thông điệp thuộc không gian tên {{ns:8}}.",
+    "trackingcategories-msg": "Thể loại phần mềm",
+    "trackingcategories-name": "Tên thông điệp",
+    "trackingcategories-desc": "Tiêu chuẩn xếp thể loại",
+    "noindex-category-desc": "Trang này có từ thần chú <nowiki>__NOINDEX__</nowiki> và nằm trong không gian tên cho phép từ thần chú này, nên không được các robot đánh chỉ mục.",
+    "index-category-desc": "Trang này có từ thần chú <nowiki>__INDEX__</nowiki> và nằm trong một không gian tên cho phép từ thần chú này, nên được các robot đánh chỉ mục, trong khi bình thường nó không được đánh chỉ mục.",
+    "post-expand-template-inclusion-category-desc": "Nếu bung tất cả các bản mẫu, kích thước trang sẽ vượt quá $wgMaxArticleSize, nên một số bản mẫu không được bung.",
+    "post-expand-template-argument-category-desc": "Nếu bung một tham số bản mẫu (tức định danh có mỗi bên ba dấu ngoặc móc, thí dụ {{{Thí dụ}}}), trang này sẽ vượt quá $wgMaxArticleSize.",
+    "expensive-parserfunction-category-desc": "Trang có quá nhiều hàm cú pháp cần mức độ xử lý cao (chẳng hạn như <code>#ifexist</code>). Xem [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit?uselang=vi Manual:$wgExpensiveParserFunctionLimit].",
+    "broken-file-category-desc": "Trang này muốn nhúng một tập tin không tồn tại.",
+    "hidden-category-category-desc": "Thể loại này có <nowiki>__HIDDENCAT__</nowiki>, nên, theo mặc định, thể loại không xuất hiện trong hộp thể loại trên các trang được xếp vào thể loại.",
+    "trackingcategories-nodesc": "Không có miêu tả.",
+    "trackingcategories-disabled": "Thể loại bị tắt",
     "mailnologin": "Không có địa chỉ gửi thư",
     "mailnologintext": "Bạn phải [[Special:UserLogin|đăng nhập]] và khai báo một địa chỉ thư điện tử hợp lệ trong phần [[Special:Preferences|tùy chọn cá nhân]] thì mới gửi được thư cho người khác.",
     "emailuser": "Gửi thư cho người này",
     "nowatchlist": "Danh sách theo dõi của bạn không có gì.",
     "watchlistanontext": "Xin hãy $1 để xem hay sửa đổi các trang được theo dõi.",
     "watchnologin": "Chưa đăng nhập",
-    "watchnologintext": "Bạn phải [[Special:UserLogin|đăng nhập]] mới sửa đổi được danh sách theo dõi.",
     "addwatch": "Thêm vào danh sách theo dõi",
     "addedwatchtext": "Trang “[[:$1]]” đã vào [[Special:Watchlist|danh sách theo dõi]] của bạn.\nNhững sửa đổi đối với trang này và trang thảo luận của nó sẽ được liệt kê ở đấy.",
     "removewatch": "Gỡ khỏi danh sách theo dõi",
     "sp-contributions-newbies": "Chỉ hiển thị đóng góp của tài khoản mới",
     "sp-contributions-newbies-sub": "Các thành viên mới",
     "sp-contributions-newbies-title": "Đóng góp của các thành viên mới",
-    "sp-contributions-blocklog": "Nhật trình cấm",
+    "sp-contributions-blocklog": "nhật trình cấm",
+    "sp-contributions-suppresslog": "đóng góp đã bị đàn áp của thành viên",
     "sp-contributions-deleted": "đóng góp đã bị xóa của thành viên",
     "sp-contributions-uploads": "tập tin tải lên",
     "sp-contributions-logs": "nhật trình",
     "sp-contributions-blocked-notice": "Thành viên này hiện đang bị cấm sửa đổi. Nhật trình cấm gần nhất được ghi ở dưới để tiện theo dõi:",
     "sp-contributions-blocked-notice-anon": "Địa chỉ IP này đang bị cấm. Hãy tham khảo mục mới nhất trong nhật trình cấm IP này:",
     "sp-contributions-search": "Tìm kiếm đóng góp",
-    "sp-contributions-suppresslog": "đóng góp đã bị đàn áp của thành viên",
     "sp-contributions-username": "Địa chỉ IP hay tên thành viên:",
     "sp-contributions-toponly": "Chỉ hiện các phiên bản mới nhất",
     "sp-contributions-newonly": "Chỉ hiện các sửa đổi tạo trang",
     "allmessagesname": "Tên thông điệp",
     "allmessagesdefault": "Nội dung mặc định",
     "allmessagescurrent": "Nội dung hiện thời",
-    "allmessagestext": "Đây là toàn bộ thông điệp hệ thống có trong không gian tên MediaWiki.\nMời vào [https://www.mediawiki.org/wiki/Localisation?uselang=vi Địa phương hóa MediaWiki] và [//translatewiki.net/wiki/?uselang=vi translatewiki.net] nếu bạn muốn đóng góp dịch chung cả MediaWiki.",
+    "allmessagestext": "Đây là toàn bộ thông điệp hệ thống có trong không gian tên MediaWiki.\nMời vào [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation?uselang=vi Địa phương hóa MediaWiki] và [//translatewiki.net/wiki/?uselang=vi translatewiki.net] nếu bạn muốn đóng góp dịch chung cả MediaWiki.",
     "allmessagesnotsupportedDB": "Trang này không dùng được vì biến '''$wgUseDatabaseMessages''' đã bị tắt.",
     "allmessages-filter-legend": "Bộ lọc",
     "allmessages-filter": "Lọc theo tình trạng sửa đổi:",
     "version-entrypoints": "Các URL lối vào",
     "version-entrypoints-header-entrypoint": "Lối vào",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath?uselang=vi Đường dẫn bài]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath?uselang=vi Đường dẫn kịch bản]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath?uselang=vi Đường dẫn bài]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath?uselang=vi Đường dẫn kịch bản]",
     "redirect": "Đổi hướng đến tập tin, người dùng, trang, hoặc số phiên bản",
     "redirect-legend": "Đổi hướng đến tập tin hoặc trang",
     "redirect-summary": "Trang đặc biệt này đổi hướng đến một tập tin (theo tên tập tin được cho vào), trang (theo số phiên bản hoặc số trang được cho vào), hoặc trang cá nhân (theo số thành viên). Cách sử dụng: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], hoặc [[{{#Special:Redirect}}/user/101]].",
     "expand_templates_remove_nowiki": "Bỏ qua thẻ <nowiki> trong kết quả",
     "expand_templates_generate_xml": "Xem cây phân tích XML",
     "expand_templates_generate_rawhtml": "Hiển thị HTML thô",
-    "expand_templates_preview": "Xem trước",
-    "trackingcategories": "Thể loại phần mềm",
-    "trackingcategories-summary": "Đây là danh sách các thể loại được phần mềm MediaWiki tự động xếp trang vào. Các tên thể loại được định rõ trong các thông điệp thuộc không gian tên {{ns:8}}.",
-    "trackingcategories-msg": "Thể loại phần mềm",
-    "trackingcategories-name": "Tên thông điệp",
-    "trackingcategories-desc": "Tiêu chuẩn xếp thể loại",
-    "noindex-category-desc": "Trang này có từ thần chú <nowiki>__NOINDEX__</nowiki> và nằm trong không gian tên cho phép từ thần chú này, nên không được các robot đánh chỉ mục.",
-    "index-category-desc": "Trang này có từ thần chú <nowiki>__INDEX__</nowiki> và nằm trong một không gian tên cho phép từ thần chú này, nên được các robot đánh chỉ mục, trong khi bình thường nó không được đánh chỉ mục.",
-    "post-expand-template-inclusion-category-desc": "Nếu bung tất cả các bản mẫu, kích thước trang sẽ vượt quá $wgMaxArticleSize, nên một số bản mẫu không được bung.",
-    "post-expand-template-argument-category-desc": "Nếu bung một tham số bản mẫu (tức định danh có mỗi bên ba dấu ngoặc móc, thí dụ {{{Thí dụ}}}), trang này sẽ vượt quá $wgMaxArticleSize.",
-    "expensive-parserfunction-category-desc": "Trang có quá nhiều hàm cú pháp cần mức độ xử lý cao (chẳng hạn như #ifexists). Xem [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit?uselang=vi Manual:$wgExpensiveParserFunctionLimit].",
-    "broken-file-category-desc": "Trang này muốn nhúng một tập tin không tồn tại.",
-    "hidden-category-category-desc": "Thể loại này có <nowiki>__HIDDENCAT__</nowiki>, nên, theo mặc định, thể loại không xuất hiện trong hộp thể loại trên các trang được xếp vào thể loại.",
-    "trackingcategories-nodesc": "Không có miêu tả.",
-    "trackingcategories-disabled": "Thể loại bị tắt"
+    "expand_templates_preview": "Xem trước"
 }
index 736e025..5fe1403 100644 (file)
     "nowatchlist": "Labol nosi in galädalised olik.",
     "watchlistanontext": "$1 ad logön u redakön lienis galädaliseda olik",
     "watchnologin": "No enunädon oki",
-    "watchnologintext": "Mutol [[Special:UserLogin|nunädön oli]] büä kanol votükön galädalisedi olik.",
     "addwatch": "Peläükön lä galädalised",
     "addedwatchtext": "Pad: \"[[:$1]]\" peläükon lä [[Special:Watchlist|galädalised]] olik.\nVotükams fütürik pada at, äsi bespikapada onik, polisedons us, e pad popenon '''me tonats dagik'''  in [[Special:RecentChanges|lised votükamas nulik]] ad fasilükön tuvi ona.\n\nIf vilol poso moükön padi de galädalised olik, välolös lä on knopi: „negalädön“.",
     "removewatch": "Pemoükön de galädalised",
     "allmessagesname": "Nem",
     "allmessagesdefault": "Vödem rigädik",
     "allmessagescurrent": "Vödem nuik",
-    "allmessagestext": "Is binon lised sitanunas valik lonöföl in nemaspad: Sitanuns.\nGebolös [https://www.mediawiki.org/wiki/Localisation Topükami ela MediaWiki] ed el [//translatewiki.net translatewiki.net] if vilol keblünön topükame valemik ela MediaWiki.",
+    "allmessagestext": "Is binon lised sitanunas valik lonöföl in nemaspad: Sitanuns.\nGebolös [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Topükami ela MediaWiki] ed el [//translatewiki.net translatewiki.net] if vilol keblünön topükame valemik ela MediaWiki.",
     "allmessagesnotsupportedDB": "Pad at no kanon pagebön bi el '''$wgUseDatabaseMessages''' penemögükon.",
     "allmessages-filter-legend": "Sul",
     "allmessages-filter-unmodified": "Penevotüköl",
index 3540a7a..581b44d 100644 (file)
     "nowatchlist": "Perräkaemisnimekiri om tühi.",
     "watchlistanontext": "Perräkaemisnimekirä pruukmisõs $1.",
     "watchnologin": "Olõ-i nimega sisse mint",
-    "watchnologintext": "Perräkaemisnimekirä muutmisõs piät [[Special:UserLogin|nimega sisse minemä]].",
     "addedwatchtext": "Lehekülg \"<nowiki>$1</nowiki>\" om pant su [[Special:Watchlist|perräkaemisnimekirjä]]. Edespididseq muutmisõq seo lehe ja tä arotuskülgi pääl pandasõq ritta siin ja [[Special:RecentChanges|viimätside muutmiisi lehe pääl]] tuvvasõq '''paksun kirän'''. Ku tahat taad lehte perräkaemisnimekiräst vällä võttaq, klõpsaq nuppi \"Lõpõdaq perräkaeminõ ärq\".",
     "removedwatchtext": "Leht \"[[:$1]]\" om [[Special:Watchlist|perräkaemisnimekiräst]] maaha võet.",
     "watch": "Kaeq perrä",
     "allmessagesname": "Nimi",
     "allmessagesdefault": "Vaikimiisi tekst",
     "allmessagescurrent": "Parhillanõ tekst",
-    "allmessagestext": "Taan nimekirän ommaq kõik MediaWiki nimeruumi tallitusteedüseq.\nPlease visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
+    "allmessagestext": "Taan nimekirän ommaq kõik MediaWiki nimeruumi tallitusteedüseq.\nPlease visit [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
     "allmessagesnotsupportedDB": "Taad lehte saa-i pruukiq, selle et '''$wgUseDatabaseMessages'''-säädmine om välän.",
     "thumbnail-more": "Suurõndaq",
     "filemissing": "Olõ-i teedüstüt",
index a954501..e3aaa2e 100644 (file)
     "nowatchlist": "Vosse djivêye des pådjes a shuve est vude.",
     "watchlistanontext": "I vs fåt $1 po vey ou candjî les cayets di vosse djivêye des shuvous.",
     "watchnologin": "Vos n' estoz nén elodjî",
-    "watchnologintext": "I vs fåt esse [[Special:UserLogin|elodjî]] po pleur candjî vosse djivêye des pådjes a shuve.",
     "addedwatchtext": "Li pådje «<nowiki>$1</nowiki>» a stî radjoutêye a vosse [[Special:Watchlist|djivêye des pådjes a shuve]].\nTos les candjmints k' i gn årè di cisse pådje chal,\neyet di si pådje di copene, seront håynés chal, eyet li pådje serè metowe e '''cråssès letes'''\nel [[Special:RecentChanges|djivêye des dierins candjmints]] po k' ça soeye pus åjhey por vos del rimårker.\n\nSi vos vloz bodjî l' pådje foû di vosse djivêye des shuvous, clitchîz so «Èn pus shuve li pådje» dins l' bår di menu sol costé.",
     "removedwatchtext": "Li pådje «[[:$1]]» a stî bodjeye foû di vosse djivêye des pådjes a shuve.",
     "watch": "Shuve",
     "allmessagesname": "No del variåve",
     "allmessagesdefault": "Tecse prémetou",
     "allmessagescurrent": "Tecse pol moumint",
-    "allmessagestext": "Çouchal est ene djivêye des messaedjes sistinme k' i gn a dins l' espåce di lomaedje ''MediaWiki:''.\nLoukîz les pådjes sol [https://www.mediawiki.org/wiki/Localisation Locålijhaedje di MediaWiki] et \n[//translatewiki.net/ translatewiki.net] si vos vloz pårticiper avou l' ratournaeje djenerike di MediaWiki.",
+    "allmessagestext": "Çouchal est ene djivêye des messaedjes sistinme k' i gn a dins l' espåce di lomaedje ''MediaWiki:''.\nLoukîz les pådjes sol [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Locålijhaedje di MediaWiki] et \n[//translatewiki.net/ translatewiki.net] si vos vloz pårticiper avou l' ratournaeje djenerike di MediaWiki.",
     "allmessagesnotsupportedDB": "'''{{ns:special}}:AllMessages''' n' est nén sopoirté paski '''$wgUseDatabaseMessages''' est dismetou.",
     "allmessages-filter-legend": "Passete",
     "allmessages-filter": "Sorlon l' estat d' candjaedje:",
index 7aeec72..60007df 100644 (file)
@@ -6,7 +6,8 @@
             "JinJian",
             "Kaganer",
             "Wiki indio",
-            "לערי ריינהארט"
+            "לערי ריינהארט",
+            "Kolega2357"
         ]
     },
     "tog-underline": "Bagisa ha ilarom an mga sumpay:",
     "prefs-skin": "Panit",
     "skin-preview": "Pahiuna nga pagawas",
     "datedefault": "Waray pinaurog nga karuyag",
-    "prefs-beta": "Beta nga mga nahihigamitan",
     "prefs-datetime": "Pitsa ngan oras",
     "prefs-labs": "Mga labs feature",
     "prefs-user-pages": "Mga pakli hin gumaramit",
     "rollback_short": "Libot-pabalik",
     "rollbacklink": "libot-pabalik",
     "rollbackfailed": "Diri malinamposon an paglibot-pabalik",
+    "revertpage": "Ginpabalik an ginliwat ni [[Special:Contributions/|$2]] ([[User talk:$2|hiruhimangraw]]) ngadto ha urhi nga rebisyon ni [[User:$1|$1]] ngan",
     "sessionfailure-title": "Pakyas an sesyon",
     "protectlogpage": "Talaan han pinasaliporan",
     "protectedarticle": "pinasaliporan \"[[$1]]\"",
     "watchlisttools-view": "Kitaa an mga nanginginlabot nga mga pagbabag-o",
     "watchlisttools-edit": "Kitaa ngan igliwat an talaan han binabantayan",
     "watchlisttools-raw": "Igliwat an hilaw nga talaan han binabantayan",
+    "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|hiruhimangraw]])",
     "duplicate-defaultsort": "'''Pahimatngon:''' An daan-aada nga paglainlain nga piridlitan nga \"$2\" in igsasapaw an durudaan nga daan-aada nga paglainlain nga piridlitan nga \"$1\".",
     "version": "Bersyon",
     "version-specialpages": "Mga pinaurog nga pakli",
index 15355db..b006441 100644 (file)
     "prefs-skin": "סקין",
     "skin-preview": "פארויסדיגע ווייזונג",
     "datedefault": "נישטא קיין פרעפערענץ",
-    "prefs-beta": "בעטאַ אייגנשאַפֿטן",
     "prefs-datetime": "דאטום און צייט",
     "prefs-labs": "לאַבאראַטאריע מעגלעכקייטן",
     "prefs-user-pages": "באניצער בלעטער",
     "nowatchlist": "איר האט נישט קיין שום בלעטער אין אייער אויפפַּאסונג ליסטע.",
     "watchlistanontext": "ביטע $1 כדי צו זען אדער ענדערן בלעטער אין אייער אַכטגעבן ליסטע.",
     "watchnologin": "איר זענט נישט אַרײַנלאגירט",
-    "watchnologintext": "איר דארפֿט זיין [[Special:UserLogin|אריינגלאגירט]] צו מאדיפֿיצירן אייער אויפפַּאסונג־ליסטע.",
     "addwatch": "צולייגן צו דער אויפֿפאַסונג ליסטע",
     "addedwatchtext": "דער בלאט \"[[:$1]]\" איז צוגעלײגט געוואָרן צו אײַער [[Special:Watchlist|אויפֿפאַסונג ליסטע]].\n\nווײַטערע ענדערונגען צו דעם בלאַט און צו זײַן פארבינדענעם רעדן בלאַט וועלן זײַן אויסגערעכנט דארט.",
     "removewatch": "אַראָפּנעמען פון דער אויפֿפאַסונג ליסטע",
     "allmessagesname": "נאָמען",
     "allmessagesdefault": "גרונטלעכער טעקסט",
     "allmessagescurrent": "איצטיגער טעקסט",
-    "allmessagestext": "אט דאס איז א ליסטע פון אלע סיסטעם מעלדונגען וואס זענען פאראן אין דעם  {{ns:mediawiki}}  נאמענטייל, וואס באדינען דעם אויפהאלט פונעם סייט.\n\nסיסאפן קענען ענדערן די מעלדונגען דורך דרוקן אויפן נאמען פון דער מעלדונג.\n\nביטע באזוכט [https://www.mediawiki.org/wiki/Localisation מעדיעוויקי לאקאליזאציע] און [//translatewiki.net בעטאוויקי] אויב איר ווילט ביישטייערן צו דער גענערישער מעדיעוויקי לאקאליזאציע.",
+    "allmessagestext": "אט דאס איז א ליסטע פון אלע סיסטעם מעלדונגען וואס זענען פאראן אין דעם  {{ns:mediawiki}}  נאמענטייל, וואס באדינען דעם אויפהאלט פונעם סייט.\n\nסיסאפן קענען ענדערן די מעלדונגען דורך דרוקן אויפן נאמען פון דער מעלדונג.\n\nביטע באזוכט [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation מעדיעוויקי לאקאליזאציע] און [//translatewiki.net בעטאוויקי] אויב איר ווילט ביישטייערן צו דער גענערישער מעדיעוויקי לאקאליזאציע.",
     "allmessagesnotsupportedDB": "מען קען זיך נישט באניצן מיט דעם בלאט וויבאלד די $wgUseDatabseMessages איז געווארן בטל.",
     "allmessages-filter-legend": "פילטער",
     "allmessages-filter": "פֿילטערן לויטן סטאטוס פון מעלדונג:",
index 94b1333..de61292 100644 (file)
     "prefs-skin": "Skin (Àwọ̀)",
     "skin-preview": "Àkọ́yẹ̀wò",
     "datedefault": "Kò sí ìfẹ́ràn",
-    "prefs-beta": "Àwọn ìní Beta",
     "prefs-datetime": "Ọjọ́ọdún àti àkókò",
     "prefs-labs": "Àwọn ìní ibiàdánwò",
     "prefs-user-pages": "Àwọn ojúewé oníṣe",
     "nowatchlist": "Ẹ kò ní ohun kankan nínú ìmójútó yín.",
     "watchlistanontext": "Ẹ jọ̀wọ́ $1 láti wò tàbí ṣàtúnṣe àwọn ohun inú ìmójútó yín.",
     "watchnologin": "Ẹ kò tíì wọlé",
-    "watchnologintext": "Ẹ gbọ́dọ̀ [[Special:UserLogin|wọlè]] láti ṣàtúnṣe ìmójútó yín.",
     "addwatch": "Ìfikún mọ́ ìmójútó",
     "addedwatchtext": "A ti ṣ'àfikún \"[[:$1]]\" sí [[Special:Watchlist|ìmójútó]] yín.\nA óò ṣ'àkójọ àwọn àtúnṣe ọjọ́wajú sí ojúewé yìí àti ojúewé ọ̀rọ̀ rẹ̀ sí bẹ̀.",
     "removewatch": "Ìyọkúrò nínú ìmójútó",
     "allmessagesname": "Orúkọ",
     "allmessagesdefault": "Ìkọ ìránṣẹ́ àtìbẹ̀rẹ̀",
     "allmessagescurrent": "Ìkọ ìránṣẹ́ lọ́wọ́",
-    "allmessagestext": "Èyí ni àtòjọ àwọn ìránṣẹ́ sístẹ́mù tó wà nínú orúkọàyè MediaWiki.\nẸ lọ sí [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] àti [//translatewiki.net translatewiki.net] tí ẹ bá fẹ́ kópa nínú ìyèdèpadà ìsiṣẹ́ MediaWiki.",
+    "allmessagestext": "Èyí ni àtòjọ àwọn ìránṣẹ́ sístẹ́mù tó wà nínú orúkọàyè MediaWiki.\nẸ lọ sí [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] àti [//translatewiki.net translatewiki.net] tí ẹ bá fẹ́ kópa nínú ìyèdèpadà ìsiṣẹ́ MediaWiki.",
     "allmessagesnotsupportedDB": "Ojúewé yìí kò ṣe é lò nítorípé '''$wgUseDatabaseMessages''' ti jẹ́ dídálẹkun.",
     "allmessages-filter-legend": "Ajọ̀",
     "allmessages-filter": "Ajọ̀ gẹ́gẹ́bí ipò ìṣàyàn:",
index aa64cd4..f6277c0 100644 (file)
     "prefs-skin": "畫面",
     "skin-preview": "預覽",
     "datedefault": "冇喜好",
-    "prefs-beta": "試緊嘅特色",
     "prefs-datetime": "日期同埋時間",
     "prefs-labs": "實驗性嘅特色",
     "prefs-personal": "用戶簡介",
     "nowatchlist": "你嘅監視清單度並冇任何項目。",
     "watchlistanontext": "請先$1去睇或者改響你監視清單度嘅項目。",
     "watchnologin": "未登入",
-    "watchnologintext": "你必須先[[Special:UserLogin|登入]]至可以更改你嘅監視清單。",
     "addedwatchtext": "頁面「[[:$1]]」已加入到你嘅[[Special:Watchlist|監視清單]]度。\n呢個頁面以及佢個討論頁以後嘅修改都會列喺嗰度,佢喺[[Special:RecentChanges|最近更改清單]]度會以'''粗體'''顯示,等你可以容易啲睇到佢。",
     "removedwatchtext": "頁面「[[:$1]]」已經喺[[Special:Watchlist|你嘅監視清單]]度刪除。",
     "watch": "監視",
     "allmessagesname": "名稱",
     "allmessagesdefault": "預設訊息文字",
     "allmessagescurrent": "現時訊息文字",
-    "allmessagestext": "以下係 MediaWiki 空間名入邊現有系統信息嘅清單。\n如果想貢獻正宗嘅MediaWiki本地化嘅話,請參閱[https://www.mediawiki.org/wiki/Localisation MediaWiki本地化]同埋[//translatewiki.net translatewiki.net]。",
+    "allmessagestext": "以下係 MediaWiki 空間名入邊現有系統信息嘅清單。\n如果想貢獻正宗嘅MediaWiki本地化嘅話,請參閱[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki本地化]同埋[//translatewiki.net translatewiki.net]。",
     "allmessagesnotsupportedDB": "呢一版唔可以用,因為'''$wgUseDatabaseMessages'''已經閂咗。",
     "allmessages-filter-legend": "過濾",
     "allmessages-filter": "以自定狀況過濾:",
index f207d92..645b6ae 100644 (file)
     "delete": "删除",
     "deletethispage": "删除本页",
     "undeletethispage": "还原本页",
-    "undelete_short": "还原{{PLURAL:$1|$1个编辑}}",
+    "undelete_short": "还原$1次编辑",
     "viewdeleted_short": "查看$1个已被删除的编辑",
     "protect": "保护",
     "protect_change": "更改",
     "pool-timeout": "等待锁超时",
     "pool-queuefull": "请求队列已满",
     "pool-errorunknown": "未知错误",
+    "pool-servererror": "池计数器服务不可用($1)。",
     "aboutsite": "关于{{SITENAME}}",
     "aboutpage": "Project:关于",
     "copyright": "除非另有声明,本网站内容采用$1授权。",
     "privacypage": "Project:隐私权政策",
     "badaccess": "权限错误",
     "badaccess-group0": "你被禁止执行你刚才请求的操作。",
-    "badaccess-groups": "你刚才请求的操作只对属于{{PLURAL:$2|该用户组|这些用户组}}的用户开放:$1",
+    "badaccess-groups": "您刚才请求的操作只对以下$2个用户组开放:$1。",
     "versionrequired": "需要$1版本的MediaWiki",
     "versionrequiredtext": "使用本页需要$1版本的MediaWiki。请见[[Special:Version|版本页面]]。",
     "ok": "确定",
     "userlogin-resetlink": "忘记你的登录信息?",
     "userlogin-resetpassword-link": "忘记密码?",
     "userlogin-helplink2": "登录帮助",
-    "userlogin-loggedin": "你已经以{{GENDER:$1|$1}}的身份登录。使用下面的表格以其他用户的身份登录。",
+    "userlogin-loggedin": "您已经以{{GENDER:$1|$1}}的身份登录。使用以下表格以其他用户的身份登录。",
     "userlogin-createanother": "创建另一个账户",
     "createacct-join": "请在下面输入你的信息。",
     "createacct-another-join": "在下方输入新帐户信息。",
     "emailconfirmlink": "确认您的邮箱地址",
     "invalidemailaddress": "邮箱地址格式不正确,请输入正确的邮箱地址或清空该输入框。",
     "cannotchangeemail": "本wiki不允许对账户的电子邮件地址进行更改。",
-    "emaildisabled": "此站点不能发送电子邮件。",
+    "emaildisabled": "该网站无法发送电子邮件。",
     "accountcreated": "已建立账户",
     "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]])的账户已创建。",
     "createaccount-title": "在{{SITENAME}}中创建新账户",
     "templatesusedsection": "该段落使用的{{PLURAL:$1|模板}}:",
     "template-protected": "(保护)",
     "template-semiprotected": "(半保护)",
-    "hiddencategories": "页面属于$1个隐藏分类:",
+    "hiddencategories": "页面属于$1个隐藏分类:",
     "edittools": "<!-- 这里的文字将显示在编辑和上传表格下面。 -->",
     "nocreatetext": "{{SITENAME}}已经限制创建新页面功能。你可以返回编辑现有页面或[[Special:UserLogin|登录或创建账户]]。",
     "nocreate-loggedin": "你没有权限创建新页面。",
     "editwarning-warning": "离开本页面可能导致你失去任何你已经作出的更改。如果你处于登录状态,你可以在你的设置的“{{int:prefs-editing}}”部分停用该警告。",
     "editpage-notsupportedcontentformat-title": "内容格式尚不支持",
     "editpage-notsupportedcontentformat-text": "内容模型$2尚不支持内容格式$1。",
-    "content-model-wikitext": "wiki文本",
+    "content-model-wikitext": "维基文字",
     "content-model-text": "纯文本",
     "content-model-javascript": "JavaScript",
     "content-model-css": "CSS",
     "prefs-skin": "皮肤",
     "skin-preview": "预览",
     "datedefault": "默认格式",
-    "prefs-beta": "测试功能",
     "prefs-datetime": "日期时间",
     "prefs-labs": "实验室特性",
     "prefs-user-pages": "用户页面",
     "filereuploadsummary": "文件更改:",
     "filestatus": "著作权状况:",
     "filesource": "来源:",
-    "uploadedfiles": "已上传文件",
+    "uploadedfiles": "上传的文件",
     "ignorewarning": "忽略警告,继续保存文件",
     "ignorewarnings": "忽略所有警告",
     "minlength1": "文件名至少要有一个字符。",
     "filehist-comment": "备注",
     "filehist-missing": "文件遗失",
     "imagelinks": "文件用途",
-    "linkstoimage": "以下{{PLURAL:$1|页面|$1个页面}}链接至本文件:",
+    "linkstoimage": "以下$1个页面链接至本文件:",
     "linkstoimage-more": "超过$1个页面连接到这个文件。\n此处只列出首$1个链接到该文件的页面。\n您也可以查看[[Special:WhatLinksHere/$2|完整的列表]]。",
     "nolinkstoimage": "没有页面链接到本文件。",
     "morelinkstoimage": "查看连接到这个文件的[[Special:WhatLinksHere/$1|更多链接]]。",
     "statistics-articles": "内容页面",
     "statistics-pages": "页面",
     "statistics-pages-desc": "本wiki的所有页面,包括讨论页面、重定向等。",
-    "statistics-files": "已上传文件",
+    "statistics-files": "上传的文件",
     "statistics-edits": "自{{SITENAME}}建立以来的页面编辑数",
     "statistics-edits-average": "每页平均编辑数",
     "statistics-views-total": "查看总数",
     "listgrouprights-removegroup-self": "删除自己的账户的{{PLURAL:$2|用户组}}:$1",
     "listgrouprights-addgroup-self-all": "添加所有用户组至自己的账户",
     "listgrouprights-removegroup-self-all": "删除自己的账户的所有用户组",
+    "trackingcategories": "跟踪分类",
+    "trackingcategories-summary": "本页面列举由MediaWiki软件自动添加的跟踪分类。它们的名字可通过修改{{ns:8}}名字空间对应的系统信息而变更。",
+    "trackingcategories-msg": "跟踪分类",
+    "trackingcategories-name": "信息名",
+    "trackingcategories-desc": "分类收录标准",
+    "noindex-category-desc": "页面中有<nowiki>__NOINDEX__</nowiki>魔术字(并且在标记允许的名字空间)且因此未被机器人索引的。",
+    "index-category-desc": "页面中有<nowiki>__INDEX__</nowiki>魔术字(并且在标记允许的名字空间)且因此被机器人索引但本不应索引的。",
+    "post-expand-template-inclusion-category-desc": "在展开了所有模板后,页面大小大于$wgMaxArticleSize,所以一些模板未展开。",
+    "post-expand-template-argument-category-desc": "展开了模板参数(三对花括号内,例如{{{Foo}}})之后,页面大于$wgMaxArticleSize。",
+    "expensive-parserfunction-category-desc": "页面包含了太多的高开销函数解析器(例如<code>#ifexist</code>)。参见[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit]。",
+    "broken-file-category-desc": "当页面包含损坏文件连接(连接至嵌入的一个不存在文件)时分类被加入。",
+    "hidden-category-category-desc": "这是一个带<nowiki>__HIDDENCAT__</nowiki>的分类,它默认防止在页面的分类连接盒中显示。",
+    "trackingcategories-nodesc": "没有说明。",
+    "trackingcategories-disabled": "分类被禁用",
     "mailnologin": "无电子邮件地址",
     "mailnologintext": "你必须[[Special:UserLogin|登录]]并在你的[[Special:Preferences|系统设置]]中拥有有效的电子邮件地址才能向其他用户发送电子邮件。",
     "emailuser": "电邮联系",
     "nowatchlist": "你的监视列表为空。",
     "watchlistanontext": "请$1以查看或编辑您的监视列表。",
     "watchnologin": "未登录",
-    "watchnologintext": "您必须先[[Special:UserLogin|登录]]才能更改您的监视列表。",
     "addwatch": "添加至监视列表",
     "addedwatchtext": "页面“[[:$1]]”已添加至你的[[Special:Watchlist|监视列表]]。本页面及其讨论页面的新增更改将会列入监视列表。",
     "removewatch": "从监视列表中删除",
     "protect-summary-cascade": "联锁",
     "protect-expiring": "终止于$1(UTC)",
     "protect-expiring-local": "$1到期",
-    "protect-expiry-indefinite": "限期",
+    "protect-expiry-indefinite": "限期",
     "protect-cascade": "保护本页中包含的页面(连锁保护)",
     "protect-cantedit": "您无法更改这个页面的保护等级,因为您没有权限去编辑它。",
     "protect-othertime": "其它时间:",
     "protect-otherreason-op": "其他原因",
     "protect-dropdown": "*常见保护原因\n** 过度破坏\n** 过多垃圾信息\n** 负面的编辑战\n** 高流量页面",
     "protect-edit-reasonlist": "编辑保护原因",
-    "protect-expiry-options": "1小时:1 hour,1天:1 day,1周:1 week,2周:2 weeks,1个月:1 month,3个月:3 months,6个月:6 months,1年:1 year,限期:infinite",
+    "protect-expiry-options": "1小时:1 hour,1天:1 day,1周:1 week,2周:2 weeks,1个月:1 month,3个月:3 months,6个月:6 months,1年:1 year,限期:infinite",
     "restriction-type": "权限:",
     "restriction-level": "限制级别:",
     "minimum-size": "最小尺寸",
     "sp-contributions-newbies-sub": "新账户的贡献",
     "sp-contributions-newbies-title": "新账户的用户贡献",
     "sp-contributions-blocklog": "封禁日志",
+    "sp-contributions-suppresslog": "已被删除的用户贡献",
     "sp-contributions-deleted": "已被删除的用户贡献",
     "sp-contributions-uploads": "上传",
     "sp-contributions-logs": "日志",
     "sp-contributions-blocked-notice": "这位用户现时正在被封锁中。\n最近的封锁日志项目在下面提供以便参考:",
     "sp-contributions-blocked-notice-anon": "这个IP地址现时正在被封锁中。\n最近的封锁日志项目在下面提供以便参考:",
     "sp-contributions-search": "搜索贡献",
-    "sp-contributions-suppresslog": "已被删除的用户贡献",
     "sp-contributions-username": "IP地址或用户名:",
     "sp-contributions-toponly": "仅显示最后版本的编辑",
     "sp-contributions-newonly": "仅显示创建页面的编辑",
     "ipbenableautoblock": "自动封禁该用户最后使用的IP地址,以及他们随后试图用于编辑的所有IP地址",
     "ipbsubmit": "封禁该用户",
     "ipbother": "其它时间:",
-    "ipboptions": "2小时:2 hours,1天:1 day,3天:3 days,1周:1 week,2周:2 weeks,1个月:1 month,3个月:3 months,6个月:6 months,1年:1 year,限期:infinite",
+    "ipboptions": "2小时:2 hours,1天:1 day,3天:3 days,1周:1 week,2周:2 weeks,1个月:1 month,3个月:3 months,6个月:6 months,1年:1 year,限期:infinite",
     "ipbhidename": "在编辑及列表中隐藏用户名",
     "ipbwatchuser": "监视该用户的用户页面和讨论页面",
     "ipb-disableusertalk": "阻止用户在封禁期间编辑自己的讨论页面",
     "ipblocklist-submit": "搜索",
     "ipblocklist-localblock": "本地封禁",
     "ipblocklist-otherblocks": "其他{{PLURAL:$1|封禁}}",
-    "infiniteblock": "限期",
+    "infiniteblock": "限期",
     "expiringblock": "$1 $2到期",
     "anononlyblock": "仅匿名用户",
     "noautoblockblock": "自动封禁停用",
     "ipb_expiry_invalid": "无效的终止时间。",
     "ipb_expiry_temp": "隐藏用户名的封禁必须是永久性的。",
     "ipb_hide_invalid": "无法封禁此账户;它拥有多于$1次编辑。",
-    "ipb_already_blocked": "“$1”已被封禁",
+    "ipb_already_blocked": "“$1”已被封禁",
     "ipb-needreblock": "$1已被封禁。您是否想更改封禁设置?",
     "ipb-otherblocks-header": "其他{{PLURAL:$1|封禁}}",
     "unblock-hideuser": "您无法取消封禁该用户,因为他们的用户名已被隐藏。",
     "allmessagesname": "名称",
     "allmessagesdefault": "默认信息文字",
     "allmessagescurrent": "当前信息文字",
-    "allmessagestext": "此处列出了MediaWiki名字空间下的所有有效系统消息。\n如果想为MediaWiki的本地化贡献翻译,请访问[https://www.mediawiki.org/wiki/Localisation MediaWiki本地化]和[//translatewiki.net translatewiki.net]。",
+    "allmessagestext": "此处列出了MediaWiki名字空间下的所有有效系统消息。\n如果想为MediaWiki的本地化贡献翻译,请访问[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki本地化]和[//translatewiki.net translatewiki.net]。",
     "allmessagesnotsupportedDB": "此页面无法使用,因为'''$wgUseDatabaseMessages'''已被设置关闭。",
     "allmessages-filter-legend": "过滤",
     "allmessages-filter": "按自定义状态过滤:",
     "pageinfo-few-watchers": "少于$1个监视者",
     "pageinfo-redirects-name": "至该页面的重定向数",
     "pageinfo-subpages-name": "该页面的子页面数",
-    "pageinfo-subpages-value": "$1($2个重定向页,$3个非重定向页)",
+    "pageinfo-subpages-value": "$1($2个{{PLURAL:$2|重定向}},$3个{{PLURAL:$3|非重定向}})",
     "pageinfo-firstuser": "页面创建者",
     "pageinfo-firsttime": "页面创建日期",
     "pageinfo-lastuser": "最后编辑者",
     "exif-gpsareainformation": "GPS区域名称",
     "exif-gpsdatestamp": "GPS日期",
     "exif-gpsdifferential": "GPS差动修正",
-    "exif-jpegfilecomment": "JPEG 文件注释",
+    "exif-jpegfilecomment": "JPEG文件备注",
     "exif-keywords": "关键词",
     "exif-worldregioncreated": "照片中的世界区域",
     "exif-countrycreated": "在拍摄图片的国家",
     "exif-morepermissionsurl": "其他授权协议信息",
     "exif-attributionurl": "二次使用本作品时,请链接至",
     "exif-preferredattributionname": "二次使用本作品时,请署名",
-    "exif-pngfilecomment": "PNG文件注释",
+    "exif-pngfilecomment": "PNG文件备注",
     "exif-disclaimer": "免责声明",
     "exif-contentwarning": "内容的警告",
-    "exif-giffilecomment": "GIF文件注释",
+    "exif-giffilecomment": "GIF文件备注",
     "exif-intellectualgenre": "项目类型",
     "exif-subjectnewscode": "主题代码",
     "exif-scenecode": "IPTC 现场代码",
     "version-entrypoints": "接入点URL",
     "version-entrypoints-header-entrypoint": "接入点",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath 条目路径]",
-    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Manual:$wgScriptPath 脚本路径]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath 条目路径]",
+    "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath 脚本路径]",
     "redirect": "重定向(按文件、用户、页面或版本ID)",
     "redirect-legend": "重定向至文件或页面",
     "redirect-summary": "本特殊页面可以跳转至一个文件(提供文件名)、页面(提供版本ID或页面ID)或用户页面(提供数字用户ID)。用法:[[{{#Special:Redirect}}/file/Example.jpg]]、[[{{#Special:Redirect}}/page/64308]]、[[{{#Special:Redirect}}/revision/328429]]或[[{{#Special:Redirect}}/user/101]]。",
     "expand_templates_remove_nowiki": "在结果中隐藏<nowiki>标签",
     "expand_templates_generate_xml": "显示XML语法树",
     "expand_templates_generate_rawhtml": "显示原始HTML",
-    "expand_templates_preview": "预览",
-    "trackingcategories": "跟踪分类",
-    "trackingcategories-summary": "本页面列举由MediaWiki软件自动添加的跟踪分类。它们的名字可通过修改{{ns:8}}名字空间对应的系统信息而变更。",
-    "trackingcategories-msg": "跟踪分类",
-    "trackingcategories-name": "信息名",
-    "trackingcategories-desc": "分类收录标准",
-    "noindex-category-desc": "页面中有<nowiki>__NOINDEX__</nowiki>魔术字(并且在标记允许的名字空间)且因此未被机器人索引的。",
-    "index-category-desc": "页面中有<nowiki>__INDEX__</nowiki>魔术字(并且在标记允许的名字空间)且因此被机器人索引但本不应索引的。",
-    "post-expand-template-inclusion-category-desc": "在展开了所有模板后,页面大小大于$wgMaxArticleSize,所以一些模板未展开。",
-    "post-expand-template-argument-category-desc": "展开了模板参数(三对花括号内,例如{{{Foo}}})之后,页面大于$wgMaxArticleSize。",
-    "expensive-parserfunction-category-desc": "页面包含了太多的高开销函数解析器(例如#ifexists)。参见[https://www.mediawiki.org/wiki/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit]。",
-    "broken-file-category-desc": "当页面包含损坏文件连接(连接至嵌入的一个不存在文件)时分类被加入。",
-    "hidden-category-category-desc": "这是一个带<nowiki>__HIDDENCAT__</nowiki>的分类,它默认防止在页面的分类连接盒中显示。",
-    "trackingcategories-nodesc": "没有说明。",
-    "trackingcategories-disabled": "分类被禁用"
+    "expand_templates_preview": "预览"
 }
index 532f14c..6898201 100644 (file)
     "pool-timeout": "等待鎖定逾時",
     "pool-queuefull": "請求池已滿",
     "pool-errorunknown": "未知錯誤",
+    "pool-servererror": "池計數器服務不可用($1)。",
     "aboutsite": "關於 {{SITENAME}}",
     "aboutpage": "Project:關於",
     "copyright": "除非另有說明,否則本站內容均以$1條款提供。",
     "editwarning-warning": "離開這個頁面可能會令您失去之前作出的所有更改。若您已經登入,您可在偏好設定的「{{int:prefs-editing}}」部份裡關閉此警告。",
     "editpage-notsupportedcontentformat-title": "內容格式尚無法支援",
     "editpage-notsupportedcontentformat-text": "內容模型$2尚無法支援內容格式$1。",
-    "content-model-wikitext": "圍記文字(Wikitext)",
+    "content-model-wikitext": "維基文字",
     "content-model-text": "純文字",
     "content-model-javascript": "JavaScript",
     "content-model-css": "CSS",
     "prefs-skin": "外觀",
     "skin-preview": "預覽",
     "datedefault": "預設值",
-    "prefs-beta": "測試功能",
     "prefs-datetime": "日期和時間",
     "prefs-labs": "實驗中的功能",
     "prefs-user-pages": "使用者頁面",
     "listgrouprights-removegroup-self": "在自己的賬戶中移除的{{PLURAL:$2|一個|多個}}群組: $1",
     "listgrouprights-addgroup-self-all": "在自己的賬戶中加入所有群組",
     "listgrouprights-removegroup-self-all": "在自己的賬戶中移除所有群組",
+    "trackingcategories": "跟蹤分類",
+    "trackingcategories-summary": "當前頁面收錄由MediaWiki軟體自動加入的跟蹤分類。名稱可經由{{ns:8}}名字空間對於系統資訊修改之。",
+    "trackingcategories-msg": "跟蹤分類",
+    "trackingcategories-name": "資訊名",
+    "trackingcategories-desc": "分類收錄準則",
+    "noindex-category-desc": "頁面中存在<nowiki>__NOINDEX__</nowiki>魔術字(並且於標記允許名字空間)並藉此未被機械人索引。",
+    "index-category-desc": "頁面中存在<nowiki>__INDEX__</nowiki>魔術字(並且於標記允許名字空間)並藉此被機械人錯誤索引。",
+    "post-expand-template-inclusion-category-desc": "展開所有模板后,頁面大小大於$wgMaxArticleSize,藉此某些模板未展開。",
+    "post-expand-template-argument-category-desc": "展開模板參數(三隊花括弧內,例如{{{Foo}}})後,頁面大於$wgMaxArticleSize。",
+    "expensive-parserfunction-category-desc": "頁面包含太多高開銷函數解析器(例如<code>#ifexist</code>)。參見[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit]。",
+    "broken-file-category-desc": "黨頁面包含受損檔案連接(連入被嵌入之不存在檔案)時。",
+    "hidden-category-category-desc": "此分類帶有<nowiki>__HIDDENCAT__</nowiki>,它預設防止於頁面分類連接盒中顯示。",
+    "trackingcategories-nodesc": "並無說明。",
+    "trackingcategories-disabled": "分類被禁用",
     "mailnologin": "無電郵地址",
     "mailnologintext": "您必須先[[Special:UserLogin|登入]]\n並在[[Special:Preferences|偏好設定]]\n中有一個有效的 e-mail 地址才可以電郵其他用戶。",
     "emailuser": "E-mail該用戶",
     "nowatchlist": "您的監視列表為空。",
     "watchlistanontext": "請$1以檢視或編輯您的監視列表。",
     "watchnologin": "未登入",
-    "watchnologintext": "您必須先[[Special:UserLogin|登入]],才能更改您的監視列表。",
     "addwatch": "加至監視列表",
     "addedwatchtext": "已將頁面「[[:$1]]」加入您的[[Special:Watchlist|監視列表]]。將來此頁面及其討論頁如有更動都會在那裡列出。",
     "removewatch": "停止監視",
     "protect-otherreason-op": "其它理由",
     "protect-dropdown": "*通用保護理由\n** 過量的破壞\n** 過量的灌水\n** 反生產性編輯戰\n** 高流量頁面",
     "protect-edit-reasonlist": "編輯保護理由",
-    "protect-expiry-options": "1小時:1 hour,1天:1 day,1周:1 week,2周:2 weeks,1個月:1 month,3個月:3 months,6個月:6 months,1年:1 year,永久:infinite",
+    "protect-expiry-options": "1小時:1 hour,1天:1 day,1周:1 week,2周:2 weeks,1個月:1 month,3個月:3 months,6個月:6 months,1年:1 year,不限期:infinite",
     "restriction-type": "權限:",
     "restriction-level": "限制級別:",
     "minimum-size": "最小大小",
     "sp-contributions-newbies-sub": "新手",
     "sp-contributions-newbies-title": "新手的用戶貢獻",
     "sp-contributions-blocklog": "封禁記錄",
+    "sp-contributions-suppresslog": "已隱藏的用戶貢獻",
     "sp-contributions-deleted": "已刪除的用戶貢獻",
     "sp-contributions-uploads": "上傳",
     "sp-contributions-logs": "日誌",
     "sp-contributions-blocked-notice": "這位用戶現時正在被封鎖中。\n最近的封鎖日誌項目在下面提供以便參考:",
     "sp-contributions-blocked-notice-anon": "這個IP地址現時正在被封鎖中。\n最近的封鎖日誌項目在下面提供以便參考:",
     "sp-contributions-search": "搜尋貢獻記錄",
-    "sp-contributions-suppresslog": "已隱藏的用戶貢獻",
     "sp-contributions-username": "IP位址或用戶名稱:",
     "sp-contributions-toponly": "只顯示最新修訂版本的編輯",
     "sp-contributions-newonly": "僅顯示建立頁面之編輯",
     "allmessagesname": "名稱",
     "allmessagesdefault": "預設的訊息文字",
     "allmessagescurrent": "現時的訊息文字",
-    "allmessagestext": "這裡列出所有可定製的系統界面。\n如果想貢獻正宗的MediaWiki本地化的話,請參閱[https://www.mediawiki.org/wiki/Localisation MediaWiki本地化]以及[//translatewiki.net translatewiki.net]。",
+    "allmessagestext": "這裡列出所有可定製的系統界面。\n如果想貢獻正宗的MediaWiki本地化的話,請參閱[https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki本地化]以及[//translatewiki.net translatewiki.net]。",
     "allmessagesnotsupportedDB": "這個頁面無法使用,因為'''$wgUseDatabaseMessages'''已被設定關閉。",
     "allmessages-filter-legend": "搜尋",
     "allmessages-filter": "以自定狀況過濾:",
     "tooltip-ca-move": "移動本頁",
     "tooltip-ca-watch": "將此頁面加入監視列表",
     "tooltip-ca-unwatch": "將此頁面從監視列表中移除",
-    "tooltip-search": "搜尋該網站",
+    "tooltip-search": "搜尋{{SITENAME}}",
     "tooltip-search-go": "如果相同的標題存在的話便直接前往該頁面",
     "tooltip-search-fulltext": "搜尋該文字的頁面",
     "tooltip-p-logo": "訪問首頁",
     "version-entrypoints": "入口點URL",
     "version-entrypoints-header-entrypoint": "入口點",
     "version-entrypoints-header-url": "URL",
-    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Manual:$wgArticlePath 條目路徑]",
+    "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath 條目路徑]",
     "redirect": "重定向檔案、用戶、頁面或修訂ID",
     "redirect-legend": "重定向到檔案或頁面",
     "redirect-summary": "此特殊頁面重定向到檔案(請指定檔案名)、頁面(請指定修訂ID或頁面ID)或用戶頁(請指定用戶ID數值)。用法:[[{{#Special:Redirect}}/file/Example.jpg]]、[[{{#Special:Redirect}}/page/64308]]、[[{{#Special:Redirect}}/revision/328429]]或[[{{#Special:Redirect}}/user/101]]。",
     "expand_templates_remove_nowiki": "在結果中隱藏<nowiki>標記",
     "expand_templates_generate_xml": "顯示XML語法樹",
     "expand_templates_generate_rawhtml": "顯示原始HTML",
-    "expand_templates_preview": "預覽",
-    "trackingcategories": "跟蹤分類",
-    "trackingcategories-summary": "當前頁面收錄由MediaWiki軟體自動加入的跟蹤分類。名稱可經由{{ns:8}}名字空間對於系統資訊修改之。",
-    "trackingcategories-msg": "跟蹤分類",
-    "trackingcategories-name": "資訊名",
-    "trackingcategories-desc": "分類收錄準則",
-    "noindex-category-desc": "頁面中存在<nowiki>__NOINDEX__</nowiki>魔術字(並且於標記允許名字空間)並藉此未被機械人索引。",
-    "index-category-desc": "頁面中存在<nowiki>__INDEX__</nowiki>魔術字(並且於標記允許名字空間)並藉此被機械人錯誤索引。",
-    "post-expand-template-inclusion-category-desc": "展開所有模板后,頁面大小大於$wgMaxArticleSize,藉此某些模板未展開。",
-    "post-expand-template-argument-category-desc": "展開模板參數(三隊花括弧內,例如{{{Foo}}})後,頁面大於$wgMaxArticleSize。",
-    "expensive-parserfunction-category-desc": "頁面包含太多高開銷函數解析器(例如#ifexists)。參見[https://www.mediawiki.org/wiki/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit]。",
-    "broken-file-category-desc": "黨頁面包含受損檔案連接(連入被嵌入之不存在檔案)時。",
-    "hidden-category-category-desc": "此分類帶有<nowiki>__HIDDENCAT__</nowiki>,它預設防止於頁面分類連接盒中顯示。",
-    "trackingcategories-nodesc": "並無說明。",
-    "trackingcategories-disabled": "分類被禁用"
+    "expand_templates_preview": "預覽"
 }
index 05db874..6d40d8a 100644 (file)
@@ -408,7 +408,7 @@ $specialPageAliases = array(
        'DoubleRedirects'           => array( 'DoubleRedirects' ),
        'EditWatchlist'             => array( 'EditWatchlist' ),
        'Emailuser'                 => array( 'EmailUser' ),
-       'ExpandTemplates'           => array( 'ExpandTemplates', 'Expantemplates' ),
+       'ExpandTemplates'           => array( 'ExpandTemplates' ),
        'Export'                    => array( 'Export' ),
        'Fewestrevisions'           => array( 'FewestRevisions' ),
        'FileDuplicateSearch'       => array( 'FileDuplicateSearch' ),
@@ -518,7 +518,6 @@ $imageFiles = array(
        'button-headline' => 'button_headline.png',
        'button-image'    => 'button_image.png',
        'button-media'    => 'button_media.png',
-       'button-math'     => 'button_math.png',
        'button-nowiki'   => 'button_nowiki.png',
        'button-sig'      => 'button_sig.png',
        'button-hr'       => 'button_hr.png',
index 3eff534..9f11c63 100644 (file)
@@ -70,7 +70,7 @@ class BenchmarkDeleteTruncate extends Benchmarker {
        }
 
        /**
-        * @param  $dbw DatabaseBase
+        * @param $dbw DatabaseBase
         * @return void
         */
        private function insertData( $dbw ) {
@@ -83,7 +83,7 @@ class BenchmarkDeleteTruncate extends Benchmarker {
        }
 
        /**
-        * @param  $dbw DatabaseBase
+        * @param $dbw DatabaseBase
         * @return void
         */
        private function delete( $dbw ) {
@@ -91,7 +91,7 @@ class BenchmarkDeleteTruncate extends Benchmarker {
        }
 
        /**
-        * @param  $dbw DatabaseBase
+        * @param $dbw DatabaseBase
         * @return void
         */
        private function truncate( $dbw ) {
index c9736df..0635769 100644 (file)
        "--external": "HTMLElement,HTMLDocument,Window",
        "--": [
                "./external.js",
-               "../../resources/mediawiki",
-               "../../resources/mediawiki.action/mediawiki.action.edit.js",
-               "../../resources/mediawiki.action/mediawiki.action.view.postEdit.js",
-               "../../resources/mediawiki.page/mediawiki.page.startup.js",
-               "../../resources/mediawiki.page/mediawiki.page.watch.ajax.js",
-               "../../resources/mediawiki.api",
-               "../../resources/mediawiki.language",
-               "../../resources/jquery/jquery.arrowSteps.js",
-               "../../resources/jquery/jquery.autoEllipsis.js",
-               "../../resources/jquery/jquery.badge.js",
-               "../../resources/jquery/jquery.byteLimit.js",
-               "../../resources/jquery/jquery.localize.js",
-               "../../resources/jquery/jquery.spinner.js",
-               "../../resources/oojs",
-               "../../resources/oojs-ui"
+               "../../resources/src/mediawiki",
+               "../../resources/src/mediawiki.action/mediawiki.action.edit.js",
+               "../../resources/src/mediawiki.action/mediawiki.action.view.postEdit.js",
+               "../../resources/src/mediawiki.page/mediawiki.page.startup.js",
+               "../../resources/src/mediawiki.page/mediawiki.page.watch.ajax.js",
+               "../../resources/src/mediawiki.api",
+               "../../resources/src/mediawiki.language",
+               "../../resources/src/jquery/jquery.arrowSteps.js",
+               "../../resources/src/jquery/jquery.autoEllipsis.js",
+               "../../resources/src/jquery/jquery.badge.js",
+               "../../resources/src/jquery/jquery.byteLimit.js",
+               "../../resources/src/jquery/jquery.localize.js",
+               "../../resources/src/jquery/jquery.spinner.js",
+               "../../resources/lib/oojs",
+               "../../resources/lib/oojs-ui"
        ]
 }
index 66a78a9..31d753c 100644 (file)
@@ -1031,7 +1031,6 @@ $wgMessageStructure = array(
                'prefs-skin',
                'skin-preview',
                'datedefault',
-               'prefs-beta',
                'prefs-datetime',
                'prefs-labs',
                'prefs-user-pages',
diff --git a/maintenance/resources/update-oojs.sh b/maintenance/resources/update-oojs.sh
new file mode 100755 (executable)
index 0000000..f26350f
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+
+if [ "$2" != "" ]
+then
+       echo >&2 "Usage: $0 [<version>]"
+       exit 1
+fi
+
+MW_DIR=$(cd $(dirname $0)/../..; pwd) # e.g. mediawiki-core/
+NPM_DIR=`mktemp -d 2>/dev/null || mktemp -d -t 'mw-update-oojs'` # e.g. /tmp/mw-update-oojs.rI0I5Vir
+
+# Prepare MediaWiki working copy
+cd $MW_DIR
+git reset resources/lib/oojs/ && git checkout resources/lib/oojs/ && git fetch origin || exit 1
+
+git checkout -B upstream-oojs origin/master || exit 1
+
+# Fetch upstream version
+cd $NPM_DIR
+if [ "$1" != "" ]
+then
+       npm install oojs@$1 || exit 1
+else
+       npm install oojs || exit 1
+fi
+
+OOJS_VERSION=$(node -e 'console.log(JSON.parse(require("fs").readFileSync("./node_modules/oojs/package.json")).version);')
+if [ "$OOJS_VERSION" == "" ]
+then
+       echo 'Could not find OOjs version'
+       exit 1
+fi
+
+# Copy file(s)
+mv ./node_modules/oojs/dist/* $MW_DIR/resources/lib/oojs/ || exit 1
+
+# Generate commit
+cd $MW_DIR || exit 1
+
+# Clean up temporary area
+rm -rf $NPM_DIR
+
+COMMITMSG=$(cat <<END
+Update OOjs to v$OOJS_VERSION
+
+Release notes:
+ https://git.wikimedia.org/blob/oojs%2Fcore.git/v$OOJS_VERSION/History.md
+END
+)
+
+git commit resources/lib/oojs/ -m "$COMMITMSG" || exit 1
index f7d5fc0..cd657ac 100644 (file)
@@ -103,6 +103,7 @@ class RunJobs extends Maintenance {
                                        $status = $job->run();
                                        $error = $job->getLastError();
                                } catch ( MWException $e ) {
+                                       MWExceptionHandler::rollbackMasterChangesAndLog( $e );
                                        $status = false;
                                        $error = get_class( $e ) . ': ' . $e->getMessage();
                                        $e->report(); // write error to STDERR and the log
diff --git a/resources/Makefile b/resources/Makefile
deleted file mode 100644 (file)
index 1b7aeb1..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-MEDIAWIKI_LOAD_URL ?= http://localhost/w/load.php
-
-kss: nodecheck
-# FIXME: Use more up-to-date Ruby version
-
-# Generates CSS of mediawiki.ui and mediawiki.ui.button using ResourceLoader, then applies it to the
-# KSS style guide
-       $(eval KSS_RL_TMP := $(shell mktemp /tmp/tmp.XXXXXXXXXX))
-       @curl -sG "${MEDIAWIKI_LOAD_URL}?modules=mediawiki.ui|mediawiki.ui.button&only=styles" > $(KSS_RL_TMP)
-       @node_modules/.bin/kss-node mediawiki.ui mediawiki.ui/docs --css $(KSS_RL_TMP) -t styleguide-template
-       @rm $(KSS_RL_TMP)
-
-kssopen: kss
-       @echo Opening the generated style guide...
-       @command -v xdg-open >/dev/null 2>&1 || { open ${PWD}/mediawiki.ui/docs/index.html; exit 0; }
-       @xdg-open ${PWD}/mediawiki.ui/docs/index.html
-
-nodecheck:
-       @scripts/nodecheck.sh
diff --git a/resources/README.txt b/resources/README.txt
deleted file mode 100644 (file)
index d91bf2a..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-The Makefile, package.json, scripts, styleguide-template, and
-mediawiki.ui/styleguide.md files and directories in here support the automatic
-generation of CSS documentation from the source LESS files using kss for
-node.js, https://github.com/kneath/kss
index 5a255e6..00251ef 100644 (file)
@@ -55,27 +55,30 @@ return array(
         *
         * Level 1 "elements":
         *     The base level that only contains the most basic of common skin styles.
-        *     Only styles for single elements are included, no styling for complex structures like the TOC
-        *     is present. This level is for skins that want to implement the entire style of even content area
-        *     structures like the TOC themselves.
+        *     Only styles for single elements are included, no styling for complex structures like the
+        *     TOC is present. This level is for skins that want to implement the entire style of even
+        *     content area structures like the TOC themselves.
         *
         * Level 2 "content":
-        *     The most commonly used level for skins implemented from scratch. This level includes all the single
-        *     element styles from "elements" as well as styles for complex structures such as the TOC that are output
-        *     in the content area by MediaWiki rather than the skin. Essentially this is the common level that lets
-        *     skins leave the style of the content area as it is normally styled, while leaving the rest of the skin
-        *     up to the skin implementation.
+        *     The most commonly used level for skins implemented from scratch. This level includes all
+        *     the single element styles from "elements" as well as styles for complex structures such
+        *     as the TOC that are output in the content area by MediaWiki rather than the skin.
+        *     Essentially this is the common level that lets skins leave the style of the content area
+        *     as it is normally styled, while leaving the rest of the skin up to the skin
+        *     implementation.
         *
         * Level 3 "interface":
-        *     The highest level, this stylesheet contains extra common styles for classes like .firstHeading, #contentSub,
-        *     et cetera which are not outputted by MediaWiki but are common to skins like MonoBook, Vector, etc...
-        *     Essentially this level is for styles that are common to MonoBook clones. And since practically every skin
-        *     that currently exists within core is a MonoBook clone, all our core skins currently use this level.
+        *     The highest level, this stylesheet contains extra common styles for classes like
+        *     .firstHeading, #contentSub, et cetera which are not outputted by MediaWiki but are common
+        *     to skins like MonoBook, Vector, etc... Essentially this level is for styles that are
+        *     common to MonoBook clones. And since practically every skin that currently exists within
+        *     core is a MonoBook clone, all our core skins currently use this level.
         *
-        * These modules are typically loaded by addModuleStyles which has absolutely no concept of dependency
-        * management. As a result the skins.common.* modules contain duplicate stylesheet references instead of
-        * setting 'dependencies' to the lower level the module is based on. For this reason avoid including multiple
-        * skins.common.* modules into your skin as this will result in duplicate css.
+        * These modules are typically loaded by addModuleStyles which has absolutely no concept of
+        * dependency management. As a result, the skins.common.* modules contain duplicate stylesheet
+        * references instead of setting 'dependencies' to the lower level the module is based on. For
+        * this reason avoid including multiple skins.common.* modules into your skin as this will
+        * result in duplicate css.
         */
        'skins.common.elements' => array(
                'styles' => array(
@@ -174,7 +177,7 @@ return array(
        /* jQuery */
 
        'jquery' => array(
-               'scripts' => 'resources/jquery/jquery.js',
+               'scripts' => 'resources/lib/jquery/jquery.js',
                'debugRaw' => false,
                'targets' => array( 'desktop', 'mobile' ),
        ),
@@ -182,152 +185,152 @@ return array(
        /* jQuery Plugins */
 
        'jquery.appear' => array(
-               'scripts' => 'resources/jquery/jquery.appear.js',
+               'scripts' => 'resources/lib/jquery/jquery.appear.js',
        ),
        'jquery.arrowSteps' => array(
-               'scripts' => 'resources/jquery/jquery.arrowSteps.js',
-               'styles' => 'resources/jquery/jquery.arrowSteps.css',
+               'scripts' => 'resources/src/jquery/jquery.arrowSteps.js',
+               'styles' => 'resources/src/jquery/jquery.arrowSteps.css',
        ),
        'jquery.async' => array(
-               'scripts' => 'resources/jquery/jquery.async.js',
+               'scripts' => 'resources/lib/jquery/jquery.async.js',
        ),
        'jquery.autoEllipsis' => array(
-               'scripts' => 'resources/jquery/jquery.autoEllipsis.js',
+               'scripts' => 'resources/src/jquery/jquery.autoEllipsis.js',
                'dependencies' => 'jquery.highlightText',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.badge' => array(
-               'scripts' => 'resources/jquery/jquery.badge.js',
-               'styles' => 'resources/jquery/jquery.badge.css',
+               'scripts' => 'resources/src/jquery/jquery.badge.js',
+               'styles' => 'resources/src/jquery/jquery.badge.css',
                'dependencies' => 'mediawiki.language',
        ),
        'jquery.byteLength' => array(
-               'scripts' => 'resources/jquery/jquery.byteLength.js',
+               'scripts' => 'resources/src/jquery/jquery.byteLength.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.byteLimit' => array(
-               'scripts' => 'resources/jquery/jquery.byteLimit.js',
+               'scripts' => 'resources/src/jquery/jquery.byteLimit.js',
                'dependencies' => 'jquery.byteLength',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.checkboxShiftClick' => array(
-               'scripts' => 'resources/jquery/jquery.checkboxShiftClick.js',
+               'scripts' => 'resources/src/jquery/jquery.checkboxShiftClick.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.chosen' => array(
-               'scripts' => 'resources/jquery.chosen/chosen.jquery.js',
-               'styles' => 'resources/jquery.chosen/chosen.css',
+               'scripts' => 'resources/lib/jquery.chosen/chosen.jquery.js',
+               'styles' => 'resources/lib/jquery.chosen/chosen.css',
        ),
        'jquery.client' => array(
-               'scripts' => 'resources/jquery/jquery.client.js',
+               'scripts' => 'resources/src/jquery/jquery.client.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.color' => array(
-               'scripts' => 'resources/jquery/jquery.color.js',
+               'scripts' => 'resources/src/jquery/jquery.color.js',
                'dependencies' => 'jquery.colorUtil',
        ),
        'jquery.colorUtil' => array(
-               'scripts' => 'resources/jquery/jquery.colorUtil.js',
+               'scripts' => 'resources/src/jquery/jquery.colorUtil.js',
        ),
        'jquery.cookie' => array(
-               'scripts' => 'resources/jquery/jquery.cookie.js',
+               'scripts' => 'resources/lib/jquery/jquery.cookie.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.delayedBind' => array(
-               'scripts' => 'resources/jquery/jquery.delayedBind.js',
+               'scripts' => 'resources/src/jquery/jquery.delayedBind.js',
        ),
        'jquery.expandableField' => array(
-               'scripts' => 'resources/jquery/jquery.expandableField.js',
+               'scripts' => 'resources/src/jquery/jquery.expandableField.js',
        ),
        'jquery.farbtastic' => array(
-               'scripts' => 'resources/jquery/jquery.farbtastic.js',
-               'styles' => 'resources/jquery/jquery.farbtastic.css',
+               'scripts' => 'resources/src/jquery/jquery.farbtastic.js',
+               'styles' => 'resources/src/jquery/jquery.farbtastic.css',
                'dependencies' => 'jquery.colorUtil',
        ),
        'jquery.footHovzer' => array(
-               'scripts' => 'resources/jquery/jquery.footHovzer.js',
-               'styles' => 'resources/jquery/jquery.footHovzer.css',
+               'scripts' => 'resources/src/jquery/jquery.footHovzer.js',
+               'styles' => 'resources/src/jquery/jquery.footHovzer.css',
        ),
        'jquery.form' => array(
-               'scripts' => 'resources/jquery/jquery.form.js',
+               'scripts' => 'resources/lib/jquery/jquery.form.js',
        ),
        'jquery.fullscreen' => array(
-               'scripts' => 'resources/jquery/jquery.fullscreen.js',
+               'scripts' => 'resources/lib/jquery/jquery.fullscreen.js',
        ),
        'jquery.getAttrs' => array(
-               'scripts' => 'resources/jquery/jquery.getAttrs.js',
+               'scripts' => 'resources/src/jquery/jquery.getAttrs.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.hidpi' => array(
-               'scripts' => 'resources/jquery/jquery.hidpi.js',
+               'scripts' => 'resources/src/jquery/jquery.hidpi.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.highlightText' => array(
-               'scripts' => 'resources/jquery/jquery.highlightText.js',
+               'scripts' => 'resources/src/jquery/jquery.highlightText.js',
                'dependencies' => 'jquery.mwExtension',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.hoverIntent' => array(
-               'scripts' => 'resources/jquery/jquery.hoverIntent.js',
+               'scripts' => 'resources/lib/jquery/jquery.hoverIntent.js',
        ),
        'jquery.json' => array(
-               'scripts' => 'resources/jquery/jquery.json.js',
+               'scripts' => 'resources/lib/jquery/jquery.json.js',
                'targets' => array( 'mobile', 'desktop' ),
        ),
        'jquery.localize' => array(
-               'scripts' => 'resources/jquery/jquery.localize.js',
+               'scripts' => 'resources/src/jquery/jquery.localize.js',
        ),
        'jquery.makeCollapsible' => array(
-               'scripts' => 'resources/jquery/jquery.makeCollapsible.js',
-               'styles' => 'resources/jquery/jquery.makeCollapsible.css',
+               'scripts' => 'resources/src/jquery/jquery.makeCollapsible.js',
+               'styles' => 'resources/src/jquery/jquery.makeCollapsible.css',
                'messages' => array( 'collapsible-expand', 'collapsible-collapse' ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.mockjax' => array(
-               'scripts' => 'resources/jquery/jquery.mockjax.js',
+               'scripts' => 'resources/lib/jquery/jquery.mockjax.js',
        ),
        'jquery.mw-jump' => array(
-               'scripts' => 'resources/jquery/jquery.mw-jump.js',
+               'scripts' => 'resources/src/jquery/jquery.mw-jump.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.mwExtension' => array(
-               'scripts' => 'resources/jquery/jquery.mwExtension.js',
+               'scripts' => 'resources/src/jquery/jquery.mwExtension.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.placeholder' => array(
-               'scripts' => 'resources/jquery/jquery.placeholder.js',
+               'scripts' => 'resources/src/jquery/jquery.placeholder.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.qunit' => array(
-               'scripts' => 'resources/jquery/jquery.qunit.js',
-               'styles' => 'resources/jquery/jquery.qunit.css',
+               'scripts' => 'resources/lib/jquery/jquery.qunit.js',
+               'styles' => 'resources/lib/jquery/jquery.qunit.css',
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.qunit.completenessTest' => array(
-               'scripts' => 'resources/jquery/jquery.qunit.completenessTest.js',
+               'scripts' => 'resources/src/jquery/jquery.qunit.completenessTest.js',
                'dependencies' => 'jquery.qunit',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.spinner' => array(
-               'scripts' => 'resources/jquery/jquery.spinner.js',
-               'styles' => 'resources/jquery/jquery.spinner.css',
+               'scripts' => 'resources/src/jquery/jquery.spinner.js',
+               'styles' => 'resources/src/jquery/jquery.spinner.css',
        ),
        'jquery.jStorage' => array(
-               'scripts' => 'resources/jquery/jquery.jStorage.js',
+               'scripts' => 'resources/lib/jquery/jquery.jStorage.js',
                'dependencies' => 'jquery.json',
        ),
        'jquery.suggestions' => array(
-               'scripts' => 'resources/jquery/jquery.suggestions.js',
-               'styles' => 'resources/jquery/jquery.suggestions.css',
-               'dependencies' => 'jquery.autoEllipsis',
+               'scripts' => 'resources/src/jquery/jquery.suggestions.js',
+               'styles' => 'resources/src/jquery/jquery.suggestions.css',
+               'dependencies' => 'jquery.highlightText',
        ),
        'jquery.tabIndex' => array(
-               'scripts' => 'resources/jquery/jquery.tabIndex.js',
+               'scripts' => 'resources/src/jquery/jquery.tabIndex.js',
        ),
        'jquery.tablesorter' => array(
-               'scripts' => 'resources/jquery/jquery.tablesorter.js',
-               'styles' => 'resources/jquery/jquery.tablesorter.css',
+               'scripts' => 'resources/src/jquery/jquery.tablesorter.js',
+               'styles' => 'resources/src/jquery/jquery.tablesorter.css',
                'messages' => array( 'sort-descending', 'sort-ascending' ),
                'dependencies' => array(
                        'jquery.mwExtension',
@@ -335,195 +338,195 @@ return array(
                ),
        ),
        'jquery.textSelection' => array(
-               'scripts' => 'resources/jquery/jquery.textSelection.js',
+               'scripts' => 'resources/src/jquery/jquery.textSelection.js',
                'dependencies' => 'jquery.client',
        ),
        'jquery.throttle-debounce' => array(
-               'scripts' => 'resources/jquery/jquery.ba-throttle-debounce.js',
+               'scripts' => 'resources/lib/jquery/jquery.ba-throttle-debounce.js',
        ),
        'jquery.validate' => array(
-               'scripts' => 'resources/jquery/jquery.validate.js',
+               'scripts' => 'resources/lib/jquery/jquery.validate.js',
        ),
        'jquery.xmldom' => array(
-               'scripts' => 'resources/jquery/jquery.xmldom.js',
+               'scripts' => 'resources/lib/jquery/jquery.xmldom.js',
        ),
 
        /* jQuery Tipsy */
 
        'jquery.tipsy' => array(
-               'scripts' => 'resources/jquery.tipsy/jquery.tipsy.js',
-               'styles' => 'resources/jquery.tipsy/jquery.tipsy.css',
+               'scripts' => 'resources/src/jquery.tipsy/jquery.tipsy.js',
+               'styles' => 'resources/src/jquery.tipsy/jquery.tipsy.css',
        ),
 
        /* jQuery UI */
 
        // Core
        'jquery.ui.core' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.core.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.core.js',
                'skinStyles' => array(
                        'default' => array(
-                               'resources/jquery.ui/themes/default/jquery.ui.core.css',
-                               'resources/jquery.ui/themes/default/jquery.ui.theme.css',
+                               'resources/lib/jquery.ui/themes/default/jquery.ui.core.css',
+                               'resources/lib/jquery.ui/themes/default/jquery.ui.theme.css',
                        ),
                        'vector' => array(
-                               'resources/jquery.ui/themes/vector/jquery.ui.core.css',
-                               'resources/jquery.ui/themes/vector/jquery.ui.theme.css',
+                               'resources/src/jquery.ui-themes/vector/jquery.ui.core.css',
+                               'resources/src/jquery.ui-themes/vector/jquery.ui.theme.css',
                        ),
                ),
                'dependencies' => 'jquery',
                'group' => 'jquery.ui',
        ),
        'jquery.ui.widget' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.widget.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.widget.js',
                'group' => 'jquery.ui',
        ),
        'jquery.ui.mouse' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.mouse.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.mouse.js',
                'dependencies' => 'jquery.ui.widget',
                'group' => 'jquery.ui',
        ),
        'jquery.ui.position' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.position.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.position.js',
                'group' => 'jquery.ui',
        ),
        // Interactions
        'jquery.ui.draggable' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.draggable.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.draggable.js',
                'dependencies' => array( 'jquery.ui.core', 'jquery.ui.mouse', 'jquery.ui.widget' ),
                'group' => 'jquery.ui',
        ),
        'jquery.ui.droppable' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.droppable.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.droppable.js',
                'dependencies' => array(
                        'jquery.ui.core', 'jquery.ui.mouse', 'jquery.ui.widget', 'jquery.ui.draggable',
                ),
                'group' => 'jquery.ui',
        ),
        'jquery.ui.resizable' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.resizable.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.resizable.js',
                'skinStyles' => array(
-                       'default' => 'resources/jquery.ui/themes/default/jquery.ui.resizable.css',
-                       'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.resizable.css',
+                       'default' => 'resources/lib/jquery.ui/themes/default/jquery.ui.resizable.css',
+                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.resizable.css',
                ),
                'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
                'group' => 'jquery.ui',
        ),
        'jquery.ui.selectable' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.selectable.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.selectable.js',
                'skinStyles' => array(
-                       'default' => 'resources/jquery.ui/themes/default/jquery.ui.selectable.css',
-                       'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.selectable.css',
+                       'default' => 'resources/lib/jquery.ui/themes/default/jquery.ui.selectable.css',
+                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.selectable.css',
                ),
                'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
                'group' => 'jquery.ui',
        ),
        'jquery.ui.sortable' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.sortable.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.sortable.js',
                'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
                'group' => 'jquery.ui',
        ),
        // Widgets
        'jquery.ui.accordion' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.accordion.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.accordion.js',
                'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
                'skinStyles' => array(
-                       'default' => 'resources/jquery.ui/themes/default/jquery.ui.accordion.css',
-                       'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.accordion.css',
+                       'default' => 'resources/lib/jquery.ui/themes/default/jquery.ui.accordion.css',
+                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.accordion.css',
                ),
                'group' => 'jquery.ui',
        ),
        'jquery.ui.autocomplete' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.autocomplete.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.autocomplete.js',
                'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.position' ),
                'skinStyles' => array(
-                       'default' => 'resources/jquery.ui/themes/default/jquery.ui.autocomplete.css',
-                       'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.autocomplete.css',
+                       'default' => 'resources/lib/jquery.ui/themes/default/jquery.ui.autocomplete.css',
+                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.autocomplete.css',
                ),
                'group' => 'jquery.ui',
        ),
        'jquery.ui.button' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.button.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.button.js',
                'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
                'skinStyles' => array(
-                       'default' => 'resources/jquery.ui/themes/default/jquery.ui.button.css',
-                       'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.button.css',
+                       'default' => 'resources/lib/jquery.ui/themes/default/jquery.ui.button.css',
+                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.button.css',
                ),
                'group' => 'jquery.ui',
        ),
        'jquery.ui.datepicker' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.datepicker.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.datepicker.js',
                'dependencies' => 'jquery.ui.core',
                'skinStyles' => array(
-                       'default' => 'resources/jquery.ui/themes/default/jquery.ui.datepicker.css',
-                       'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.datepicker.css',
+                       'default' => 'resources/lib/jquery.ui/themes/default/jquery.ui.datepicker.css',
+                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.datepicker.css',
                ),
                'languageScripts' => array(
-                       'af' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-af.js',
-                       'ar' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ar.js',
-                       'az' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-az.js',
-                       'bg' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-bg.js',
-                       'bs' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-bs.js',
-                       'ca' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ca.js',
-                       'cs' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-cs.js',
-                       'da' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-da.js',
-                       'de' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-de.js',
-                       'el' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-el.js',
-                       'en-gb' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js',
-                       'eo' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-eo.js',
-                       'es' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-es.js',
-                       'et' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-et.js',
-                       'eu' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-eu.js',
-                       'fa' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fa.js',
-                       'fi' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fi.js',
-                       'fo' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fo.js',
-                       'fr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fr.js',
-                       'gl' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-gl.js',
-                       'he' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-he.js',
-                       'hi' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-hi.js',
-                       'hr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-hr.js',
-                       'hu' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-hu.js',
-                       'hy' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-hy.js',
-                       'id' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-id.js',
-                       'is' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-is.js',
-                       'it' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-it.js',
-                       'ja' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ja.js',
-                       'ka' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ka.js',
-                       'kk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-kk.js',
-                       'km' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-km.js',
-                       'ko' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ko.js',
-                       'lb' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-lb.js',
-                       'lt' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-lt.js',
-                       'lv' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-lv.js',
-                       'mk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-mk.js',
-                       'ml' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ml.js',
-                       'ms' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ms.js',
-                       'nl' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-nl.js',
-                       'no' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-no.js',
-                       'pl' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-pl.js',
-                       'pt' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-pt.js',
-                       'pt-br' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js',
-                       'rm' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-rm.js',
-                       'ro' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ro.js',
-                       'ru' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ru.js',
-                       'sk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sk.js',
-                       'sl' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sl.js',
-                       'sq' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sq.js',
-                       'sr-sr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js',
-                       'sr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sr.js',
-                       'sv' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sv.js',
-                       'ta' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ta.js',
-                       'th' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-th.js',
-                       'tr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-tr.js',
-                       'uk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-uk.js',
-                       'vi' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-vi.js',
-                       'zh-cn' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js',
-                       'zh-hk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js',
-                       'zh-tw' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js',
+                       'af' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-af.js',
+                       'ar' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar.js',
+                       'az' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-az.js',
+                       'bg' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bg.js',
+                       'bs' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bs.js',
+                       'ca' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ca.js',
+                       'cs' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cs.js',
+                       'da' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-da.js',
+                       'de' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de.js',
+                       'el' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-el.js',
+                       'en-gb' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js',
+                       'eo' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eo.js',
+                       'es' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-es.js',
+                       'et' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-et.js',
+                       'eu' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eu.js',
+                       'fa' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fa.js',
+                       'fi' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fi.js',
+                       'fo' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fo.js',
+                       'fr' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr.js',
+                       'gl' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-gl.js',
+                       'he' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-he.js',
+                       'hi' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hi.js',
+                       'hr' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hr.js',
+                       'hu' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hu.js',
+                       'hy' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hy.js',
+                       'id' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-id.js',
+                       'is' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-is.js',
+                       'it' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-it.js',
+                       'ja' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ja.js',
+                       'ka' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ka.js',
+                       'kk' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-kk.js',
+                       'km' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-km.js',
+                       'ko' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ko.js',
+                       'lb' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lb.js',
+                       'lt' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lt.js',
+                       'lv' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lv.js',
+                       'mk' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-mk.js',
+                       'ml' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ml.js',
+                       'ms' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ms.js',
+                       'nl' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl.js',
+                       'no' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-no.js',
+                       'pl' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pl.js',
+                       'pt' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt.js',
+                       'pt-br' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js',
+                       'rm' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-rm.js',
+                       'ro' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ro.js',
+                       'ru' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ru.js',
+                       'sk' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sk.js',
+                       'sl' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sl.js',
+                       'sq' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sq.js',
+                       'sr-sr' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js',
+                       'sr' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr.js',
+                       'sv' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sv.js',
+                       'ta' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ta.js',
+                       'th' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-th.js',
+                       'tr' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tr.js',
+                       'uk' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-uk.js',
+                       'vi' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-vi.js',
+                       'zh-cn' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js',
+                       'zh-hk' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js',
+                       'zh-tw' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js',
                ),
                'group' => 'jquery.ui',
        ),
        'jquery.ui.dialog' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.dialog.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.dialog.js',
                'dependencies' => array(
                        'jquery.ui.core',
                        'jquery.ui.widget',
@@ -534,106 +537,106 @@ return array(
                        'jquery.ui.resizable',
                ),
                'skinStyles' => array(
-                       'default' => 'resources/jquery.ui/themes/default/jquery.ui.dialog.css',
-                       'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.dialog.css',
+                       'default' => 'resources/lib/jquery.ui/themes/default/jquery.ui.dialog.css',
+                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.dialog.css',
                ),
                'group' => 'jquery.ui',
        ),
        'jquery.ui.progressbar' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.progressbar.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.progressbar.js',
                'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
                'skinStyles' => array(
-                       'default' => 'resources/jquery.ui/themes/default/jquery.ui.progressbar.css',
-                       'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.progressbar.css',
+                       'default' => 'resources/lib/jquery.ui/themes/default/jquery.ui.progressbar.css',
+                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.progressbar.css',
                ),
                'group' => 'jquery.ui',
        ),
        'jquery.ui.slider' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.slider.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.slider.js',
                'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
                'skinStyles' => array(
-                       'default' => 'resources/jquery.ui/themes/default/jquery.ui.slider.css',
-                       'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.slider.css',
+                       'default' => 'resources/lib/jquery.ui/themes/default/jquery.ui.slider.css',
+                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.slider.css',
                ),
                'group' => 'jquery.ui',
        ),
        'jquery.ui.tabs' => array(
-               'scripts' => 'resources/jquery.ui/jquery.ui.tabs.js',
+               'scripts' => 'resources/lib/jquery.ui/jquery.ui.tabs.js',
                'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
                'skinStyles' => array(
-                       'default' => 'resources/jquery.ui/themes/default/jquery.ui.tabs.css',
-                       'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.tabs.css',
+                       'default' => 'resources/lib/jquery.ui/themes/default/jquery.ui.tabs.css',
+                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.tabs.css',
                ),
                'group' => 'jquery.ui',
        ),
        // Effects
        'jquery.effects.core' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.core.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.core.js',
                'dependencies' => 'jquery',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.blind' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.blind.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.blind.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.bounce' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.bounce.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.bounce.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.clip' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.clip.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.clip.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.drop' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.drop.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.drop.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.explode' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.explode.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.explode.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.fade' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.fade.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.fade.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.fold' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.fold.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.fold.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.highlight' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.highlight.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.highlight.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.pulsate' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.pulsate.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.pulsate.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.scale' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.scale.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.scale.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.shake' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.shake.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.shake.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.slide' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.slide.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.slide.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
        'jquery.effects.transfer' => array(
-               'scripts' => 'resources/jquery.effects/jquery.effects.transfer.js',
+               'scripts' => 'resources/lib/jquery.effects/jquery.effects.transfer.js',
                'dependencies' => 'jquery.effects.core',
                'group' => 'jquery.ui',
        ),
@@ -641,117 +644,118 @@ return array(
        /* Moment.js */
 
        'moment' => array(
-               'scripts' => 'resources/moment/moment.js',
+               'scripts' => 'resources/lib/moment/moment.js',
                'languageScripts' => array(
-                       'ar-ma' => 'resources/moment/lang/ar-ma.js',
-                       'ar' => 'resources/moment/lang/ar.js',
-                       'bg' => 'resources/moment/lang/bg.js',
-                       'br' => 'resources/moment/lang/br.js',
-                       'bs' => 'resources/moment/lang/bs.js',
-                       'ca' => 'resources/moment/lang/ca.js',
-                       'cs' => 'resources/moment/lang/cs.js',
-                       'cv' => 'resources/moment/lang/cv.js',
-                       'cy' => 'resources/moment/lang/cy.js',
-                       'da' => 'resources/moment/lang/da.js',
-                       'de' => 'resources/moment/lang/de.js',
-                       'el' => 'resources/moment/lang/el.js',
-                       'en-au' => 'resources/moment/lang/en-au.js',
-                       'en-ca' => 'resources/moment/lang/en-ca.js',
-                       'en-gb' => 'resources/moment/lang/en-gb.js',
-                       'eo' => 'resources/moment/lang/eo.js',
-                       'es' => 'resources/moment/lang/es.js',
-                       'et' => 'resources/moment/lang/et.js',
-                       'eu' => 'resources/moment/lang/eu.js',
-                       'fa' => 'resources/moment/lang/fa.js',
-                       'fi' => 'resources/moment/lang/fi.js',
-                       'fo' => 'resources/moment/lang/fo.js',
-                       'fr-ca' => 'resources/moment/lang/fr-ca.js',
-                       'fr' => 'resources/moment/lang/fr.js',
-                       'gl' => 'resources/moment/lang/gl.js',
-                       'he' => 'resources/moment/lang/he.js',
-                       'hi' => 'resources/moment/lang/hi.js',
-                       'hr' => 'resources/moment/lang/hr.js',
-                       'hu' => 'resources/moment/lang/hu.js',
-                       'hy-am' => 'resources/moment/lang/hy-am.js',
-                       'id' => 'resources/moment/lang/id.js',
-                       'is' => 'resources/moment/lang/is.js',
-                       'it' => 'resources/moment/lang/it.js',
-                       'ja' => 'resources/moment/lang/ja.js',
-                       'ka' => 'resources/moment/lang/ka.js',
-                       'ko' => 'resources/moment/lang/ko.js',
-                       'lt' => 'resources/moment/lang/lt.js',
-                       'lv' => 'resources/moment/lang/lv.js',
-                       'mk' => 'resources/moment/lang/mk.js',
-                       'ml' => 'resources/moment/lang/ml.js',
-                       'mr' => 'resources/moment/lang/mr.js',
-                       'ms-my' => 'resources/moment/lang/ms-my.js',
-                       'nb' => 'resources/moment/lang/nb.js',
-                       'ne' => 'resources/moment/lang/ne.js',
-                       'nl' => 'resources/moment/lang/nl.js',
-                       'nn' => 'resources/moment/lang/nn.js',
-                       'pl' => 'resources/moment/lang/pl.js',
-                       'pt-br' => 'resources/moment/lang/pt-br.js',
-                       'pt' => 'resources/moment/lang/pt.js',
-                       'ro' => 'resources/moment/lang/ro.js',
-                       'rs' => 'resources/moment/lang/rs.js',
-                       'ru' => 'resources/moment/lang/ru.js',
-                       'sk' => 'resources/moment/lang/sk.js',
-                       'sl' => 'resources/moment/lang/sl.js',
-                       'sq' => 'resources/moment/lang/sq.js',
-                       'sv' => 'resources/moment/lang/sv.js',
-                       'ta' => 'resources/moment/lang/ta.js',
-                       'th' => 'resources/moment/lang/th.js',
-                       'tl-ph' => 'resources/moment/lang/tl-ph.js',
-                       'tr' => 'resources/moment/lang/tr.js',
-                       'tzm-la' => 'resources/moment/lang/tzm-la.js',
-                       'tzm' => 'resources/moment/lang/tzm.js',
-                       'uk' => 'resources/moment/lang/uk.js',
-                       'uz' => 'resources/moment/lang/uz.js',
-                       'vn' => 'resources/moment/lang/vn.js',
-                       'zh-cn' => 'resources/moment/lang/zh-cn.js',
-                       'zh-tw' => 'resources/moment/lang/zh-tw.js',
+                       'ar-ma' => 'resources/lib/moment/lang/ar-ma.js',
+                       'ar' => 'resources/lib/moment/lang/ar.js',
+                       'bg' => 'resources/lib/moment/lang/bg.js',
+                       'br' => 'resources/lib/moment/lang/br.js',
+                       'bs' => 'resources/lib/moment/lang/bs.js',
+                       'ca' => 'resources/lib/moment/lang/ca.js',
+                       'cs' => 'resources/lib/moment/lang/cs.js',
+                       'cv' => 'resources/lib/moment/lang/cv.js',
+                       'cy' => 'resources/lib/moment/lang/cy.js',
+                       'da' => 'resources/lib/moment/lang/da.js',
+                       'de' => 'resources/lib/moment/lang/de.js',
+                       'el' => 'resources/lib/moment/lang/el.js',
+                       'en-au' => 'resources/lib/moment/lang/en-au.js',
+                       'en-ca' => 'resources/lib/moment/lang/en-ca.js',
+                       'en-gb' => 'resources/lib/moment/lang/en-gb.js',
+                       'eo' => 'resources/lib/moment/lang/eo.js',
+                       'es' => 'resources/lib/moment/lang/es.js',
+                       'et' => 'resources/lib/moment/lang/et.js',
+                       'eu' => 'resources/lib/moment/lang/eu.js',
+                       'fa' => 'resources/lib/moment/lang/fa.js',
+                       'fi' => 'resources/lib/moment/lang/fi.js',
+                       'fo' => 'resources/lib/moment/lang/fo.js',
+                       'fr-ca' => 'resources/lib/moment/lang/fr-ca.js',
+                       'fr' => 'resources/lib/moment/lang/fr.js',
+                       'gl' => 'resources/lib/moment/lang/gl.js',
+                       'he' => 'resources/lib/moment/lang/he.js',
+                       'hi' => 'resources/lib/moment/lang/hi.js',
+                       'hr' => 'resources/lib/moment/lang/hr.js',
+                       'hu' => 'resources/lib/moment/lang/hu.js',
+                       'hy-am' => 'resources/lib/moment/lang/hy-am.js',
+                       'id' => 'resources/lib/moment/lang/id.js',
+                       'is' => 'resources/lib/moment/lang/is.js',
+                       'it' => 'resources/lib/moment/lang/it.js',
+                       'ja' => 'resources/lib/moment/lang/ja.js',
+                       'ka' => 'resources/lib/moment/lang/ka.js',
+                       'ko' => 'resources/lib/moment/lang/ko.js',
+                       'lt' => 'resources/lib/moment/lang/lt.js',
+                       'lv' => 'resources/lib/moment/lang/lv.js',
+                       'mk' => 'resources/lib/moment/lang/mk.js',
+                       'ml' => 'resources/lib/moment/lang/ml.js',
+                       'mr' => 'resources/lib/moment/lang/mr.js',
+                       'ms-my' => 'resources/lib/moment/lang/ms-my.js',
+                       'nb' => 'resources/lib/moment/lang/nb.js',
+                       'ne' => 'resources/lib/moment/lang/ne.js',
+                       'nl' => 'resources/lib/moment/lang/nl.js',
+                       'nn' => 'resources/lib/moment/lang/nn.js',
+                       'pl' => 'resources/lib/moment/lang/pl.js',
+                       'pt-br' => 'resources/lib/moment/lang/pt-br.js',
+                       'pt' => 'resources/lib/moment/lang/pt.js',
+                       'ro' => 'resources/lib/moment/lang/ro.js',
+                       'rs' => 'resources/lib/moment/lang/rs.js',
+                       'ru' => 'resources/lib/moment/lang/ru.js',
+                       'sk' => 'resources/lib/moment/lang/sk.js',
+                       'sl' => 'resources/lib/moment/lang/sl.js',
+                       'sq' => 'resources/lib/moment/lang/sq.js',
+                       'sv' => 'resources/lib/moment/lang/sv.js',
+                       'ta' => 'resources/lib/moment/lang/ta.js',
+                       'th' => 'resources/lib/moment/lang/th.js',
+                       'tl-ph' => 'resources/lib/moment/lang/tl-ph.js',
+                       'tr' => 'resources/lib/moment/lang/tr.js',
+                       'tzm-la' => 'resources/lib/moment/lang/tzm-la.js',
+                       'tzm' => 'resources/lib/moment/lang/tzm.js',
+                       'uk' => 'resources/lib/moment/lang/uk.js',
+                       'uz' => 'resources/lib/moment/lang/uz.js',
+                       'vn' => 'resources/lib/moment/lang/vn.js',
+                       'zh-cn' => 'resources/lib/moment/lang/zh-cn.js',
+                       'zh-tw' => 'resources/lib/moment/lang/zh-tw.js',
                ),
        ),
 
        /* MediaWiki */
 
        'mediawiki' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.js',
-               'debugScripts' => 'resources/mediawiki/mediawiki.log.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.js',
+               'debugScripts' => 'resources/src/mediawiki/mediawiki.log.js',
                'debugRaw' => false,
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.api' => array(
-               'scripts' => 'resources/mediawiki.api/mediawiki.api.js',
+               'scripts' => 'resources/src/mediawiki.api/mediawiki.api.js',
                'dependencies' => 'mediawiki.util',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.api.category' => array(
-               'scripts' => 'resources/mediawiki.api/mediawiki.api.category.js',
+               'scripts' => 'resources/src/mediawiki.api/mediawiki.api.category.js',
                'dependencies' => array(
                        'mediawiki.api',
                        'mediawiki.Title',
                ),
        ),
        'mediawiki.api.edit' => array(
-               'scripts' => 'resources/mediawiki.api/mediawiki.api.edit.js',
+               'scripts' => 'resources/src/mediawiki.api/mediawiki.api.edit.js',
                'dependencies' => array(
                        'mediawiki.api',
                        'mediawiki.Title',
+                       'user.tokens',
                ),
        ),
        'mediawiki.api.login' => array(
-               'scripts' => 'resources/mediawiki.api/mediawiki.api.login.js',
+               'scripts' => 'resources/src/mediawiki.api/mediawiki.api.login.js',
                'dependencies' => array(
                        'mediawiki.api',
                ),
        ),
        'mediawiki.api.parse' => array(
-               'scripts' => 'resources/mediawiki.api/mediawiki.api.parse.js',
+               'scripts' => 'resources/src/mediawiki.api/mediawiki.api.parse.js',
                'dependencies' => 'mediawiki.api',
        ),
        'mediawiki.api.watch' => array(
-               'scripts' => 'resources/mediawiki.api/mediawiki.api.watch.js',
+               'scripts' => 'resources/src/mediawiki.api/mediawiki.api.watch.js',
                'dependencies' => array(
                        'mediawiki.api',
                        'user.tokens',
@@ -759,12 +763,12 @@ return array(
        ),
        'mediawiki.debug' => array(
                'scripts' => array(
-                       'resources/mediawiki/mediawiki.debug.js',
-                       'resources/mediawiki/mediawiki.debug.profile.js'
+                       'resources/src/mediawiki/mediawiki.debug.js',
+                       'resources/src/mediawiki/mediawiki.debug.profile.js'
                ),
                'styles' => array(
-                       'resources/mediawiki/mediawiki.debug.less',
-                       'resources/mediawiki/mediawiki.debug.profile.css'
+                       'resources/src/mediawiki/mediawiki.debug.less',
+                       'resources/src/mediawiki/mediawiki.debug.profile.css'
                ),
                'dependencies' => array(
                        'jquery.footHovzer',
@@ -773,15 +777,15 @@ return array(
                'position' => 'bottom',
        ),
        'mediawiki.debug.init' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.debug.init.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.debug.init.js',
                'dependencies' => 'mediawiki.debug',
                // Uses a custom mw.config variable that is set in debughtml,
                // must be loaded on the bottom
                'position' => 'bottom',
        ),
        'mediawiki.feedback' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.feedback.js',
-               'styles' => 'resources/mediawiki/mediawiki.feedback.css',
+               'scripts' => 'resources/src/mediawiki/mediawiki.feedback.js',
+               'styles' => 'resources/src/mediawiki/mediawiki.feedback.css',
                'dependencies' => array(
                        'mediawiki.api.edit',
                        'mediawiki.Title',
@@ -805,28 +809,28 @@ return array(
                ),
        ),
        'mediawiki.hidpi' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.hidpi.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.hidpi.js',
                'dependencies' => array(
                        'jquery.hidpi',
                ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.hlist' => array(
-               'styles' => 'resources/mediawiki/mediawiki.hlist.css',
-               'scripts' => 'resources/mediawiki/mediawiki.hlist.js',
+               'styles' => 'resources/src/mediawiki/mediawiki.hlist.css',
+               'scripts' => 'resources/src/mediawiki/mediawiki.hlist.js',
                'dependencies' => array(
                        'jquery.client',
                ),
        ),
        'mediawiki.htmlform' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.htmlform.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.htmlform.js',
                'messages' => array( 'htmlform-chosen-placeholder' ),
        ),
        'mediawiki.icon' => array(
-               'styles' => 'resources/mediawiki/mediawiki.icon.less',
+               'styles' => 'resources/src/mediawiki/mediawiki.icon.less',
        ),
        'mediawiki.inspect' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.inspect.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.inspect.js',
                'dependencies' => array(
                        'jquery.byteLength',
                        'jquery.json',
@@ -835,28 +839,28 @@ return array(
        ),
        'mediawiki.notification' => array(
                'styles' => array(
-                       'resources/mediawiki/mediawiki.notification.css',
-                       'resources/mediawiki/mediawiki.notification.hideForPrint.css' => array( 'media' => 'print' ),
+                       'resources/src/mediawiki/mediawiki.notification.css',
+                       'resources/src/mediawiki/mediawiki.notification.hideForPrint.css'
+                               => array( 'media' => 'print' ),
                ),
-               'scripts' => 'resources/mediawiki/mediawiki.notification.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.notification.js',
                'dependencies' => array(
                        'mediawiki.page.startup',
                ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.notify' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.notify.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.notify.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.searchSuggest' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.searchSuggest.js',
-               'styles' => 'resources/mediawiki/mediawiki.searchSuggest.css',
+               'scripts' => 'resources/src/mediawiki/mediawiki.searchSuggest.js',
+               'styles' => 'resources/src/mediawiki/mediawiki.searchSuggest.css',
                'messages' => array(
                        'searchsuggest-search',
                        'searchsuggest-containing',
                ),
                'dependencies' => array(
-                       'jquery.autoEllipsis',
                        'jquery.client',
                        'jquery.placeholder',
                        'jquery.suggestions',
@@ -864,7 +868,7 @@ return array(
                ),
        ),
        'mediawiki.Title' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.Title.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.Title.js',
                'dependencies' => array(
                        'jquery.byteLength',
                        'mediawiki.util',
@@ -872,7 +876,7 @@ return array(
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.toc' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.toc.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.toc.js',
                'dependencies' => array(
                        'jquery.cookie',
                ),
@@ -880,11 +884,11 @@ return array(
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.Uri' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.Uri.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.Uri.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.user' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.user.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.user.js',
                'dependencies' => array(
                        'jquery.cookie',
                        'mediawiki.api',
@@ -894,7 +898,7 @@ return array(
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.util' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.util.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.util.js',
                'dependencies' => array(
                        'jquery.client',
                        'jquery.mwExtension',
@@ -908,7 +912,7 @@ return array(
        /* MediaWiki Action */
 
        'mediawiki.action.edit' => array(
-               'scripts' => 'resources/mediawiki.action/mediawiki.action.edit.js',
+               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.js',
                'dependencies' => array(
                        'mediawiki.action.edit.styles',
                        'jquery.textSelection',
@@ -917,12 +921,12 @@ return array(
                'position' => 'top',
        ),
        'mediawiki.action.edit.styles' => array(
-               'styles' => 'resources/mediawiki.action/mediawiki.action.edit.styles.css',
+               'styles' => 'resources/src/mediawiki.action/mediawiki.action.edit.styles.css',
                'position' => 'top',
        ),
        'mediawiki.action.edit.collapsibleFooter' => array(
-               'scripts' => 'resources/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js',
-               'styles' => 'resources/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css',
+               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js',
+               'styles' => 'resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css',
                'dependencies' => array(
                        'jquery.makeCollapsible',
                        'jquery.cookie',
@@ -930,7 +934,7 @@ return array(
                ),
        ),
        'mediawiki.action.edit.preview' => array(
-               'scripts' => 'resources/mediawiki.action/mediawiki.action.edit.preview.js',
+               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.preview.js',
                'dependencies' => array(
                        'jquery.form',
                        'jquery.spinner',
@@ -938,31 +942,31 @@ return array(
                ),
        ),
        'mediawiki.action.history' => array(
-               'scripts' => 'resources/mediawiki.action/mediawiki.action.history.js',
+               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.history.js',
                'group' => 'mediawiki.action.history',
        ),
        'mediawiki.action.history.diff' => array(
-               'styles' => 'resources/mediawiki.action/mediawiki.action.history.diff.css',
+               'styles' => 'resources/src/mediawiki.action/mediawiki.action.history.diff.css',
                'group' => 'mediawiki.action.history',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.action.view.dblClickEdit' => array(
-               'scripts' => 'resources/mediawiki.action/mediawiki.action.view.dblClickEdit.js',
+               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.dblClickEdit.js',
                'dependencies' => array(
                        'mediawiki.util',
                        'mediawiki.page.startup',
                ),
        ),
        'mediawiki.action.view.metadata' => array(
-               'scripts' => 'resources/mediawiki.action/mediawiki.action.view.metadata.js',
+               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.metadata.js',
                'messages' => array(
                        'metadata-expand',
                        'metadata-collapse',
                ),
        ),
        'mediawiki.action.view.postEdit' => array(
-               'scripts' => 'resources/mediawiki.action/mediawiki.action.view.postEdit.js',
-               'styles' => 'resources/mediawiki.action/mediawiki.action.view.postEdit.css',
+               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.postEdit.js',
+               'styles' => 'resources/src/mediawiki.action/mediawiki.action.view.postEdit.css',
                'dependencies' => array(
                        'jquery.cookie',
                        'mediawiki.jqueryMsg'
@@ -972,17 +976,17 @@ return array(
                ),
        ),
        'mediawiki.action.view.redirectToFragment' => array(
-               'scripts' => 'resources/mediawiki.action/mediawiki.action.view.redirectToFragment.js',
+               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.redirectToFragment.js',
                'dependencies' => array(
                        'jquery.client',
                ),
                'position' => 'top',
        ),
        'mediawiki.action.view.rightClickEdit' => array(
-               'scripts' => 'resources/mediawiki.action/mediawiki.action.view.rightClickEdit.js',
+               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.rightClickEdit.js',
        ),
        'mediawiki.action.edit.editWarning' => array(
-               'scripts' => 'resources/mediawiki.action/mediawiki.action.edit.editWarning.js',
+               'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js',
                'dependencies' => array(
                        'mediawiki.jqueryMsg'
                ),
@@ -1000,23 +1004,23 @@ return array(
 
        'mediawiki.language' => array(
                'scripts' => array(
-                       'resources/mediawiki.language/mediawiki.language.js',
-                       'resources/mediawiki.language/mediawiki.language.numbers.js'
+                       'resources/src/mediawiki.language/mediawiki.language.js',
+                       'resources/src/mediawiki.language/mediawiki.language.numbers.js'
                ),
                'languageScripts' => array(
-                       'bs' => 'resources/mediawiki.language/languages/bs.js',
-                       'dsb' => 'resources/mediawiki.language/languages/dsb.js',
-                       'fi' => 'resources/mediawiki.language/languages/fi.js',
-                       'ga' => 'resources/mediawiki.language/languages/ga.js',
-                       'he' => 'resources/mediawiki.language/languages/he.js',
-                       'hsb' => 'resources/mediawiki.language/languages/hsb.js',
-                       'hu' => 'resources/mediawiki.language/languages/hu.js',
-                       'hy' => 'resources/mediawiki.language/languages/hy.js',
-                       'la' => 'resources/mediawiki.language/languages/la.js',
-                       'os' => 'resources/mediawiki.language/languages/os.js',
-                       'ru' => 'resources/mediawiki.language/languages/ru.js',
-                       'sl' => 'resources/mediawiki.language/languages/sl.js',
-                       'uk' => 'resources/mediawiki.language/languages/uk.js',
+                       'bs' => 'resources/src/mediawiki.language/languages/bs.js',
+                       'dsb' => 'resources/src/mediawiki.language/languages/dsb.js',
+                       'fi' => 'resources/src/mediawiki.language/languages/fi.js',
+                       'ga' => 'resources/src/mediawiki.language/languages/ga.js',
+                       'he' => 'resources/src/mediawiki.language/languages/he.js',
+                       'hsb' => 'resources/src/mediawiki.language/languages/hsb.js',
+                       'hu' => 'resources/src/mediawiki.language/languages/hu.js',
+                       'hy' => 'resources/src/mediawiki.language/languages/hy.js',
+                       'la' => 'resources/src/mediawiki.language/languages/la.js',
+                       'os' => 'resources/src/mediawiki.language/languages/os.js',
+                       'ru' => 'resources/src/mediawiki.language/languages/ru.js',
+                       'sl' => 'resources/src/mediawiki.language/languages/sl.js',
+                       'uk' => 'resources/src/mediawiki.language/languages/uk.js',
                ),
                'dependencies' => array(
                                'mediawiki.language.data',
@@ -1026,7 +1030,7 @@ return array(
        ),
 
        'mediawiki.cldr' => array(
-               'scripts' => 'resources/mediawiki.language/mediawiki.cldr.js',
+               'scripts' => 'resources/src/mediawiki.language/mediawiki.cldr.js',
                'dependencies' => array(
                        'mediawiki.libs.pluralruleparser',
                ),
@@ -1034,17 +1038,17 @@ return array(
        ),
 
        'mediawiki.libs.pluralruleparser' => array(
-               'scripts' => 'resources/mediawiki.libs/CLDRPluralRuleParser.js',
+               'scripts' => 'resources/src/mediawiki.libs/CLDRPluralRuleParser.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
 
        'mediawiki.language.init' => array(
-               'scripts' => 'resources/mediawiki.language/mediawiki.language.init.js',
+               'scripts' => 'resources/src/mediawiki.language/mediawiki.language.init.js',
                'targets' => array( 'desktop', 'mobile' ),
        ),
 
        'mediawiki.jqueryMsg' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.jqueryMsg.js',
+               'scripts' => 'resources/src/mediawiki/mediawiki.jqueryMsg.js',
                'dependencies' => array(
                        'mediawiki.util',
                        'mediawiki.language',
@@ -1053,7 +1057,7 @@ return array(
        ),
 
        'mediawiki.language.months' => array(
-               'scripts' => 'resources/mediawiki.language/mediawiki.language.months.js',
+               'scripts' => 'resources/src/mediawiki.language/mediawiki.language.months.js',
                'dependencies' => 'mediawiki.language',
                'messages' => array_merge(
                        Language::$mMonthMsgs,
@@ -1065,16 +1069,16 @@ return array(
        /* MediaWiki Libs */
 
        'mediawiki.libs.jpegmeta' => array(
-               'scripts' => 'resources/mediawiki.libs/mediawiki.libs.jpegmeta.js',
+               'scripts' => 'resources/src/mediawiki.libs/mediawiki.libs.jpegmeta.js',
        ),
 
        /* MediaWiki Page */
 
        'mediawiki.page.gallery' => array(
-               'scripts' => 'resources/mediawiki.page/mediawiki.page.gallery.js',
+               'scripts' => 'resources/src/mediawiki.page/mediawiki.page.gallery.js',
        ),
        'mediawiki.page.ready' => array(
-               'scripts' => 'resources/mediawiki.page/mediawiki.page.ready.js',
+               'scripts' => 'resources/src/mediawiki.page/mediawiki.page.ready.js',
                'dependencies' => array(
                        'jquery.checkboxShiftClick',
                        'jquery.makeCollapsible',
@@ -1085,16 +1089,15 @@ return array(
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.page.startup' => array(
-               'scripts' => 'resources/mediawiki.page/mediawiki.page.startup.js',
+               'scripts' => 'resources/src/mediawiki.page/mediawiki.page.startup.js',
                'dependencies' => array(
-                       'jquery.client',
                        'mediawiki.util',
                ),
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.page.patrol.ajax' => array(
-               'scripts' => 'resources/mediawiki.page/mediawiki.page.patrol.ajax.js',
+               'scripts' => 'resources/src/mediawiki.page/mediawiki.page.patrol.ajax.js',
                'dependencies' => array(
                        'mediawiki.page.startup',
                        'mediawiki.api',
@@ -1111,7 +1114,7 @@ return array(
                ),
        ),
        'mediawiki.page.watch.ajax' => array(
-               'scripts' => 'resources/mediawiki.page/mediawiki.page.watch.ajax.js',
+               'scripts' => 'resources/src/mediawiki.page/mediawiki.page.watch.ajax.js',
                'dependencies' => array(
                        'mediawiki.page.startup',
                        'mediawiki.api.watch',
@@ -1130,29 +1133,29 @@ return array(
                ),
        ),
        'mediawiki.page.image.pagination' => array(
-               'scripts' => 'resources/mediawiki.page/mediawiki.page.image.pagination.js',
+               'scripts' => 'resources/src/mediawiki.page/mediawiki.page.image.pagination.js',
                'dependencies' => array( 'jquery.spinner' )
        ),
 
        /* MediaWiki Special pages */
 
        'mediawiki.special' => array(
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.js',
-               'styles' => 'resources/mediawiki.special/mediawiki.special.css',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.js',
+               'styles' => 'resources/src/mediawiki.special/mediawiki.special.css',
                'skinStyles' => array(
                        'vector' => 'skins/vector/special.less',
                ),
        ),
        'mediawiki.special.block' => array(
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.block.js',
-               'styles' => 'resources/mediawiki.special/mediawiki.special.block.css',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.block.js',
+               'styles' => 'resources/src/mediawiki.special/mediawiki.special.block.css',
                'dependencies' => array(
                        'mediawiki.util',
                ),
        ),
        'mediawiki.special.changeemail' => array(
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.changeemail.js',
-               'styles' => 'resources/mediawiki.special/mediawiki.special.changeemail.css',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changeemail.js',
+               'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeemail.css',
                'dependencies' => array(
                        'mediawiki.util',
                ),
@@ -1162,31 +1165,31 @@ return array(
                ),
        ),
        'mediawiki.special.changeslist' => array(
-               'styles' => 'resources/mediawiki.special/mediawiki.special.changeslist.css',
+               'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.css',
        ),
        'mediawiki.special.changeslist.legend' => array(
-               'styles' => 'resources/mediawiki.special/mediawiki.special.changeslist.legend.css',
+               'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css',
        ),
        'mediawiki.special.changeslist.legend.js' => array(
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.changeslist.legend.js',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.legend.js',
                'dependencies' => array(
                        'jquery.makeCollapsible',
                        'jquery.cookie',
                ),
        ),
        'mediawiki.special.changeslist.enhanced' => array(
-               'styles' => 'resources/mediawiki.special/mediawiki.special.changeslist.enhanced.css',
+               'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css',
        ),
        'mediawiki.special.movePage' => array(
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.movePage.js',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.movePage.js',
                'dependencies' => 'jquery.byteLimit',
        ),
        'mediawiki.special.pagesWithProp' => array(
-               'styles' => 'resources/mediawiki.special/mediawiki.special.pagesWithProp.css',
+               'styles' => 'resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css',
        ),
        'mediawiki.special.preferences' => array(
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.preferences.js',
-               'styles' => 'resources/mediawiki.special/mediawiki.special.preferences.css',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.preferences.js',
+               'styles' => 'resources/src/mediawiki.special/mediawiki.special.preferences.css',
                'position' => 'top',
                'skinStyles' => array(
                        'vector' => 'skins/vector/special.preferences.less',
@@ -1199,13 +1202,13 @@ return array(
                ),
        ),
        'mediawiki.special.recentchanges' => array(
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.recentchanges.js',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.recentchanges.js',
                'dependencies' => array( 'mediawiki.special' ),
                'position' => 'top',
        ),
        'mediawiki.special.search' => array(
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.search.js',
-               'styles' => 'resources/mediawiki.special/mediawiki.special.search.css',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.search.js',
+               'styles' => 'resources/src/mediawiki.special/mediawiki.special.search.css',
                'messages' => array(
                        'powersearch-togglelabel',
                        'powersearch-toggleall',
@@ -1213,11 +1216,11 @@ return array(
                ),
        ),
        'mediawiki.special.undelete' => array(
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.undelete.js',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.undelete.js',
        ),
        'mediawiki.special.upload' => array(
                // @todo merge in remainder of mediawiki.legacy.upload
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.upload.js',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.upload.js',
                'messages' => array(
                        'widthheight',
                        'size-bytes',
@@ -1233,25 +1236,25 @@ return array(
        ),
        'mediawiki.special.userlogin.common.styles' => array(
                'styles' => array(
-                       'resources/mediawiki.special/mediawiki.special.userlogin.common.css',
+                       'resources/src/mediawiki.special/mediawiki.special.userlogin.common.css',
                ),
                'position' => 'top',
        ),
        'mediawiki.special.userlogin.signup.styles' => array(
                'styles' => array(
-                       'resources/mediawiki.special/mediawiki.special.userlogin.signup.css',
+                       'resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css',
                ),
                'position' => 'top',
        ),
        'mediawiki.special.userlogin.login.styles' => array(
                'styles' => array(
-                       'resources/mediawiki.special/mediawiki.special.userlogin.login.css',
+                       'resources/src/mediawiki.special/mediawiki.special.userlogin.login.css',
                ),
                'position' => 'top',
        ),
        'mediawiki.special.userlogin.common.js' => array(
                'scripts' => array(
-                       'resources/mediawiki.special/mediawiki.special.userlogin.common.js',
+                       'resources/src/mediawiki.special/mediawiki.special.userlogin.common.js',
                ),
                'messages' => array(
                        'createacct-captcha',
@@ -1259,7 +1262,7 @@ return array(
                ),
        ),
        'mediawiki.special.userlogin.signup.js' => array(
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.userlogin.signup.js',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js',
                'messages' => array(
                        'createacct-error',
                        'createacct-emailrequired',
@@ -1273,7 +1276,7 @@ return array(
                ),
        ),
        'mediawiki.special.javaScriptTest' => array(
-               'scripts' => 'resources/mediawiki.special/mediawiki.special.javaScriptTest.js',
+               'scripts' => 'resources/src/mediawiki.special/mediawiki.special.javaScriptTest.js',
                'messages' => array_merge( Skin::getSkinNameMessages(), array(
                        'colon-separator',
                        'javascripttest-pagetext-skins',
@@ -1283,7 +1286,7 @@ return array(
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.special.version' => array(
-               'styles' => 'resources/mediawiki.special/mediawiki.special.version.css',
+               'styles' => 'resources/src/mediawiki.special/mediawiki.special.version.css',
        ),
 
        /* MediaWiki Legacy */
@@ -1356,8 +1359,8 @@ return array(
 
        'mediawiki.ui' => array(
                'skinStyles' => array(
-                       'default' => 'resources/mediawiki.ui/default.less',
-                       'vector' => 'resources/mediawiki.ui/vector.less',
+                       'default' => 'resources/src/mediawiki.ui/default.less',
+                       'vector' => 'resources/src/mediawiki.ui/vector.less',
                ),
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
@@ -1365,8 +1368,8 @@ return array(
        // Lightweight module for button styles
        'mediawiki.ui.button' => array(
                'skinStyles' => array(
-                       'default' => 'resources/mediawiki.ui/components/default/buttons.less',
-                       'vector' => 'resources/mediawiki.ui/components/vector/buttons.less',
+                       'default' => 'resources/src/mediawiki.ui/components/default/buttons.less',
+                       'vector' => 'resources/src/mediawiki.ui/components/vector/buttons.less',
                ),
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
@@ -1377,20 +1380,20 @@ return array(
        // WILL BREAK if loaded in browsers that don't support ES5
        'oojs' => array(
                'scripts' => array(
-                       'resources/oojs/oojs.js',
+                       'resources/lib/oojs/oojs.js',
                ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'oojs-ui' => array(
                'scripts' => array(
-                       'resources/oojs-ui/oojs-ui.js',
+                       'resources/lib/oojs-ui/oojs-ui.js',
                ),
                'styles' => array(
-                       'resources/oojs-ui/oojs-ui.svg.css',
+                       'resources/lib/oojs-ui/oojs-ui.svg.css',
                ),
                'skinStyles' => array(
-                       'default' => 'resources/oojs-ui/oojs-ui-apex.css',
-                       'minerva' => 'resources/oojs-ui/oojs-ui-agora.css',
+                       'default' => 'resources/lib/oojs-ui/oojs-ui-apex.css',
+                       'minerva' => 'resources/lib/oojs-ui/oojs-ui-agora.css',
                ),
                'messages' => array(
                        'ooui-dialog-action-close',
diff --git a/resources/jquery.chosen/LICENSE b/resources/jquery.chosen/LICENSE
deleted file mode 100644 (file)
index 0675dc5..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-# Chosen, a Select Box Enhancer for jQuery and Protoype
-## by Patrick Filler for [Harvest](http://getharvest.com)
-
-Available for use under the [MIT License](http://en.wikipedia.org/wiki/MIT_License)
-
-Copyright (c) 2011-2013 by Harvest
-
-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/resources/jquery.chosen/chosen-sprite.png b/resources/jquery.chosen/chosen-sprite.png
deleted file mode 100644 (file)
index 3611ae4..0000000
Binary files a/resources/jquery.chosen/chosen-sprite.png and /dev/null differ
diff --git a/resources/jquery.chosen/chosen-sprite@2x.png b/resources/jquery.chosen/chosen-sprite@2x.png
deleted file mode 100644 (file)
index bd61d96..0000000
Binary files a/resources/jquery.chosen/chosen-sprite@2x.png and /dev/null differ
diff --git a/resources/jquery.chosen/chosen.css b/resources/jquery.chosen/chosen.css
deleted file mode 100644 (file)
index 17793ed..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-/* @group Base */
-.chzn-container {
-  font-size: 13px;
-  position: relative;
-  display: inline-block;
-  vertical-align: middle;
-  zoom: 1;
-  *display: inline;
-}
-.chzn-container .chzn-drop {
-  background: #fff;
-  border: 1px solid #aaa;
-  border-top: 0;
-  position: absolute;
-  top: 100%;
-  left: -9999px;
-  -webkit-box-shadow: 0 4px 5px rgba(0,0,0,.15);
-  -moz-box-shadow   : 0 4px 5px rgba(0,0,0,.15);
-  box-shadow        : 0 4px 5px rgba(0,0,0,.15);
-  z-index: 1010;
-  width: 100%;
-  -moz-box-sizing   : border-box;
-  -ms-box-sizing    : border-box;
-  -webkit-box-sizing: border-box;
-  -khtml-box-sizing : border-box;
-  box-sizing        : border-box;
-}
-
-.chzn-container.chzn-with-drop .chzn-drop {
-  left: 0;
-}
-
-/* @end */
-
-/* @group Single Chosen */
-.chzn-container-single .chzn-single {
-  background-color: #ffffff;
-  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0 );   
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));
-  background-image: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
-  background-image: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
-  background-image: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
-  background-image: linear-gradient(#ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); 
-  -webkit-border-radius: 5px;
-  -moz-border-radius   : 5px;
-  border-radius        : 5px;
-  -moz-background-clip   : padding;
-  -webkit-background-clip: padding-box;
-  background-clip        : padding-box;
-  border: 1px solid #aaaaaa;
-  -webkit-box-shadow: 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
-  -moz-box-shadow   : 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
-  box-shadow        : 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
-  display: block;
-  overflow: hidden;
-  white-space: nowrap;
-  position: relative;
-  height: 23px;
-  line-height: 24px;
-  padding: 0 0 0 8px;
-  color: #444444;
-  text-decoration: none;
-}
-.chzn-container-single .chzn-default {
-  color: #999;
-}
-.chzn-container-single .chzn-single span {
-  margin-right: 26px;
-  display: block;
-  overflow: hidden;
-  white-space: nowrap;
-  -o-text-overflow: ellipsis;
-  -ms-text-overflow: ellipsis;
-  text-overflow: ellipsis;
-}
-.chzn-container-single .chzn-single abbr {
-  display: block;
-  position: absolute;
-  right: 26px;
-  top: 6px;
-  width: 12px;
-  height: 12px;
-  font-size: 1px;
-  background: url('chosen-sprite.png') -42px 1px no-repeat;
-}
-.chzn-container-single .chzn-single abbr:hover {
-  background-position: -42px -10px;
-}
-.chzn-container-single.chzn-disabled .chzn-single abbr:hover {
-  background-position: -42px -10px;
-}
-.chzn-container-single .chzn-single div {
-  position: absolute;
-  right: 0;
-  top: 0;
-  display: block;
-  height: 100%;
-  width: 18px;
-}
-.chzn-container-single .chzn-single div b {
-  background: url('chosen-sprite.png') no-repeat 0px 2px;
-  display: block;
-  width: 100%;
-  height: 100%;
-}
-.chzn-container-single .chzn-search {
-  padding: 3px 4px;
-  position: relative;
-  margin: 0;
-  white-space: nowrap;
-  z-index: 1010;
-}
-.chzn-container-single .chzn-search input {
-  background: #fff url('chosen-sprite.png') no-repeat 100% -20px;
-  background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
-  background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
-  background: url('chosen-sprite.png') no-repeat 100% -20px, -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
-  background: url('chosen-sprite.png') no-repeat 100% -20px, -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
-  background: url('chosen-sprite.png') no-repeat 100% -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
-  margin: 1px 0;
-  padding: 4px 20px 4px 5px;
-  outline: 0;
-  border: 1px solid #aaa;
-  font-family: sans-serif;
-  font-size: 1em;
-  width: 100%;
-  -moz-box-sizing   : border-box;
-  -ms-box-sizing    : border-box;
-  -webkit-box-sizing: border-box;
-  -khtml-box-sizing : border-box;
-  box-sizing        : border-box;
-}
-.chzn-container-single .chzn-drop {
-  margin-top: -1px;
-  -webkit-border-radius: 0 0 4px 4px;
-  -moz-border-radius   : 0 0 4px 4px;
-  border-radius        : 0 0 4px 4px;
-  -moz-background-clip   : padding;
-  -webkit-background-clip: padding-box;
-  background-clip        : padding-box;
-}
-.chzn-container-single-nosearch .chzn-search {
-  position: absolute;
-  left: -9999px;
-}
-/* @end */
-
-/* @group Multi Chosen */
-.chzn-container-multi .chzn-choices {
-  background-color: #fff;
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
-  background-image: -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
-  background-image: -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
-  background-image: -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
-  background-image: linear-gradient(#eeeeee 1%, #ffffff 15%);
-  border: 1px solid #aaa;
-  margin: 0;
-  padding: 0;
-  cursor: text;
-  overflow: hidden;
-  height: auto !important;
-  height: 1%;
-  position: relative;
-  width: 100%;
-  -moz-box-sizing   : border-box;
-  -ms-box-sizing    : border-box;
-  -webkit-box-sizing: border-box;
-  -khtml-box-sizing : border-box;
-  box-sizing        : border-box;
-}
-.chzn-container-multi .chzn-choices li {
-  float: left;
-  list-style: none;
-}
-.chzn-container-multi .chzn-choices .search-field {
-  white-space: nowrap;
-  margin: 0;
-  padding: 0;
-}
-.chzn-container-multi .chzn-choices .search-field input {
-  color: #666;
-  background: transparent !important;
-  border: 0 !important;
-  font-family: sans-serif;
-  font-size: 100%;
-  height: 15px;
-  padding: 5px;
-  margin: 1px 0;
-  outline: 0;
-  -webkit-box-shadow: none;
-  -moz-box-shadow   : none;
-  box-shadow        : none;
-}
-.chzn-container-multi .chzn-choices .search-field .default {
-  color: #999;
-}
-.chzn-container-multi .chzn-choices .search-choice {
-  -webkit-border-radius: 3px;
-  -moz-border-radius   : 3px;
-  border-radius        : 3px;
-  -moz-background-clip   : padding;
-  -webkit-background-clip: padding-box;
-  background-clip        : padding-box;
-  background-color: #e4e4e4;
-  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 ); 
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
-  background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
-  background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
-  background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
-  background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); 
-  -webkit-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
-  -moz-box-shadow   : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
-  box-shadow        : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
-  color: #333;
-  border: 1px solid #aaaaaa;
-  line-height: 13px;
-  padding: 3px 20px 3px 5px;
-  margin: 3px 0 3px 5px;
-  position: relative;
-  cursor: default;
-}
-.chzn-container-multi .chzn-choices .search-choice.search-choice-disabled {
-  background-color: #e4e4e4;
-  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 );
-  background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
-  background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
-  background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
-  background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
-  background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
-  background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
-  color: #666;
-  border: 1px solid #cccccc;
-  padding-right: 5px;
-}
-.chzn-container-multi .chzn-choices .search-choice-focus {
-  background: #d4d4d4;
-}
-.chzn-container-multi .chzn-choices .search-choice .search-choice-close {
-  display: block;
-  position: absolute;
-  right: 3px;
-  top: 4px;
-  width: 12px;
-  height: 12px;
-  font-size: 1px;
-  background: url('chosen-sprite.png') -42px 1px no-repeat;
-}
-.chzn-container-multi .chzn-choices .search-choice .search-choice-close:hover {
-  background-position: -42px -10px;
-}
-.chzn-container-multi .chzn-choices .search-choice-focus .search-choice-close {
-  background-position: -42px -10px;
-}
-/* @end */
-
-/* @group Results */
-.chzn-container .chzn-results {
-  margin: 0 4px 4px 0;
-  max-height: 240px;
-  padding: 0 0 0 4px;
-  position: relative;
-  overflow-x: hidden;
-  overflow-y: auto;
-  -webkit-overflow-scrolling: touch;
-}
-.chzn-container-multi .chzn-results {
-  margin: 0;
-  padding: 0;
-}
-.chzn-container .chzn-results li {
-  display: none;
-  line-height: 15px;
-  padding: 5px 6px;
-  margin: 0;
-  list-style: none;
-}
-.chzn-container .chzn-results .active-result {
-  cursor: pointer;
-  display: list-item;
-}
-.chzn-container .chzn-results .highlighted {
-  background-color: #3875d7;
-  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3875d7', endColorstr='#2a62bc', GradientType=0 );  
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
-  background-image: -webkit-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
-  background-image: -moz-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
-  background-image: -o-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
-  background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
-  color: #fff;
-}
-.chzn-container .chzn-results li em {
-  background: #feffde;
-  font-style: normal;
-}
-.chzn-container .chzn-results .highlighted em {
-  background: transparent;
-}
-.chzn-container .chzn-results .no-results {
-  background: #f4f4f4;
-  display: list-item;
-}
-.chzn-container .chzn-results .group-result {
-  cursor: default;
-  color: #999;
-  font-weight: bold;
-}
-.chzn-container .chzn-results .group-option {
-  padding-left: 15px;
-}
-.chzn-container-multi .chzn-drop .result-selected {
-  display: none;
-}
-.chzn-container .chzn-results-scroll {
-  background: white;
-  margin: 0 4px;
-  position: absolute;
-  text-align: center;
-  width: 321px; /* This should by dynamic with js */
-  z-index: 1;
-}
-.chzn-container .chzn-results-scroll span {
-  display: inline-block;
-  height: 17px;
-  text-indent: -5000px;
-  width: 9px;
-}
-.chzn-container .chzn-results-scroll-down {
-  bottom: 0;
-}
-.chzn-container .chzn-results-scroll-down span {
-  background: url('chosen-sprite.png') no-repeat -4px -3px;
-}
-.chzn-container .chzn-results-scroll-up span {
-  background: url('chosen-sprite.png') no-repeat -22px -3px;
-}
-/* @end */
-
-/* @group Active  */
-.chzn-container-active .chzn-single {
-  -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
-  -moz-box-shadow   : 0 0 5px rgba(0,0,0,.3);
-  box-shadow        : 0 0 5px rgba(0,0,0,.3);
-  border: 1px solid #5897fb;
-}
-.chzn-container-active.chzn-with-drop .chzn-single {
-  border: 1px solid #aaa;
-  -webkit-box-shadow: 0 1px 0 #fff inset;
-  -moz-box-shadow   : 0 1px 0 #fff inset;
-  box-shadow        : 0 1px 0 #fff inset;
-  background-color: #eee;
-  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0 );
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff));
-  background-image: -webkit-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
-  background-image: -moz-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
-  background-image: -o-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
-  background-image: linear-gradient(#eeeeee 20%, #ffffff 80%);
-  -webkit-border-bottom-left-radius : 0;
-  -webkit-border-bottom-right-radius: 0;
-  -moz-border-radius-bottomleft : 0;
-  -moz-border-radius-bottomright: 0;
-  border-bottom-left-radius : 0;
-  border-bottom-right-radius: 0;
-}
-.chzn-container-active.chzn-with-drop .chzn-single div {
-  background: transparent;
-  border-left: none;
-}
-.chzn-container-active.chzn-with-drop .chzn-single div b {
-  background-position: -18px 2px;
-}
-.chzn-container-active .chzn-choices {
-  -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
-  -moz-box-shadow   : 0 0 5px rgba(0,0,0,.3);
-  box-shadow        : 0 0 5px rgba(0,0,0,.3);
-  border: 1px solid #5897fb;
-}
-.chzn-container-active .chzn-choices .search-field input {
-  color: #111 !important;
-}
-/* @end */
-
-/* @group Disabled Support */
-.chzn-disabled {
-  cursor: default;
-  opacity:0.5 !important;
-}
-.chzn-disabled .chzn-single {
-  cursor: default;
-}
-.chzn-disabled .chzn-choices .search-choice .search-choice-close {
-  cursor: default;
-}
-
-/* @group Right to Left */
-.chzn-rtl { text-align: right; }
-.chzn-rtl .chzn-single { padding: 0 8px 0 0; overflow: visible; }
-.chzn-rtl .chzn-single span { margin-left: 26px; margin-right: 0; direction: rtl; }
-
-.chzn-rtl .chzn-single div { left: 3px; right: auto; }
-.chzn-rtl .chzn-single abbr {
-  left: 26px;
-  right: auto;
-}
-.chzn-rtl .chzn-choices .search-field input { direction: rtl; }
-.chzn-rtl .chzn-choices li { float: right; }
-.chzn-rtl .chzn-choices .search-choice { padding: 3px 5px 3px 19px; margin: 3px 5px 3px 0; }
-.chzn-rtl .chzn-choices .search-choice .search-choice-close { left: 4px; right: auto; }
-.chzn-rtl .chzn-search { left: 9999px; }
-.chzn-rtl.chzn-with-drop .chzn-search { left: 0px; }
-.chzn-rtl .chzn-drop { left: 9999px; }
-.chzn-rtl.chzn-container-single .chzn-results { margin: 0 0 4px 4px; padding: 0 4px 0 0; }
-.chzn-rtl .chzn-results .group-option { padding-left: 0; padding-right: 15px; }
-.chzn-rtl.chzn-container-active.chzn-with-drop .chzn-single div { border-right: none; }
-.chzn-rtl .chzn-search input {
-  background: #fff url('chosen-sprite.png') no-repeat -30px -20px;
-  background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
-  background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);  
-  background: url('chosen-sprite.png') no-repeat -30px -20px, -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
-  background: url('chosen-sprite.png') no-repeat -30px -20px, -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
-  background: url('chosen-sprite.png') no-repeat -30px -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
-  padding: 4px 5px 4px 20px;
-  direction: rtl;
-}
-.chzn-container-single.chzn-rtl .chzn-single div b {
-  background-position: 6px 2px;
-}
-.chzn-container-single.chzn-rtl.chzn-with-drop .chzn-single div b {
-  background-position: -12px 2px;
-}
-/* @end */
-
-/* @group Retina compatibility */
-@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi)  {
-  .chzn-rtl .chzn-search input, .chzn-container-single .chzn-single abbr, .chzn-container-single .chzn-single div b, .chzn-container-single .chzn-search input, .chzn-container-multi .chzn-choices .search-choice .search-choice-close, .chzn-container .chzn-results-scroll-down span, .chzn-container .chzn-results-scroll-up span {
-      background-image: url('chosen-sprite@2x.png') !important;
-      background-repeat: no-repeat !important;
-      background-size: 52px 37px !important;
-  }
-}
-/* @end */
diff --git a/resources/jquery.chosen/chosen.jquery.js b/resources/jquery.chosen/chosen.jquery.js
deleted file mode 100644 (file)
index 745174f..0000000
+++ /dev/null
@@ -1,1103 +0,0 @@
-// Chosen, a Select Box Enhancer for jQuery and Protoype
-// by Patrick Filler for Harvest, http://getharvest.com
-//
-// Version 0.9.14
-// Full source at https://github.com/harvesthq/chosen
-// Copyright (c) 2011 Harvest http://getharvest.com
-
-// MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
-// This file is generated by `cake build`, do not edit it by hand.
-(function() {
-  var SelectParser;
-
-  SelectParser = (function() {
-
-    function SelectParser() {
-      this.options_index = 0;
-      this.parsed = [];
-    }
-
-    SelectParser.prototype.add_node = function(child) {
-      if (child.nodeName.toUpperCase() === "OPTGROUP") {
-        return this.add_group(child);
-      } else {
-        return this.add_option(child);
-      }
-    };
-
-    SelectParser.prototype.add_group = function(group) {
-      var group_position, option, _i, _len, _ref, _results;
-      group_position = this.parsed.length;
-      this.parsed.push({
-        array_index: group_position,
-        group: true,
-        label: group.label,
-        children: 0,
-        disabled: group.disabled
-      });
-      _ref = group.childNodes;
-      _results = [];
-      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-        option = _ref[_i];
-        _results.push(this.add_option(option, group_position, group.disabled));
-      }
-      return _results;
-    };
-
-    SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
-      if (option.nodeName.toUpperCase() === "OPTION") {
-        if (option.text !== "") {
-          if (group_position != null) {
-            this.parsed[group_position].children += 1;
-          }
-          this.parsed.push({
-            array_index: this.parsed.length,
-            options_index: this.options_index,
-            value: option.value,
-            text: option.text,
-            html: option.innerHTML,
-            selected: option.selected,
-            disabled: group_disabled === true ? group_disabled : option.disabled,
-            group_array_index: group_position,
-            classes: option.className,
-            style: option.style.cssText
-          });
-        } else {
-          this.parsed.push({
-            array_index: this.parsed.length,
-            options_index: this.options_index,
-            empty: true
-          });
-        }
-        return this.options_index += 1;
-      }
-    };
-
-    return SelectParser;
-
-  })();
-
-  SelectParser.select_to_array = function(select) {
-    var child, parser, _i, _len, _ref;
-    parser = new SelectParser();
-    _ref = select.childNodes;
-    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-      child = _ref[_i];
-      parser.add_node(child);
-    }
-    return parser.parsed;
-  };
-
-  this.SelectParser = SelectParser;
-
-}).call(this);
-
-/*
-Chosen source: generate output using 'cake build'
-Copyright (c) 2011 by Harvest
-*/
-
-
-(function() {
-  var AbstractChosen, root;
-
-  root = this;
-
-  AbstractChosen = (function() {
-
-    function AbstractChosen(form_field, options) {
-      this.form_field = form_field;
-      this.options = options != null ? options : {};
-      if (!AbstractChosen.browser_is_supported()) {
-        return;
-      }
-      this.is_multiple = this.form_field.multiple;
-      this.set_default_text();
-      this.set_default_values();
-      this.setup();
-      this.set_up_html();
-      this.register_observers();
-      this.finish_setup();
-    }
-
-    AbstractChosen.prototype.set_default_values = function() {
-      var _this = this;
-      this.click_test_action = function(evt) {
-        return _this.test_active_click(evt);
-      };
-      this.activate_action = function(evt) {
-        return _this.activate_field(evt);
-      };
-      this.active_field = false;
-      this.mouse_on_container = false;
-      this.results_showing = false;
-      this.result_highlighted = null;
-      this.result_single_selected = null;
-      this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
-      this.disable_search_threshold = this.options.disable_search_threshold || 0;
-      this.disable_search = this.options.disable_search || false;
-      this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
-      this.search_contains = this.options.search_contains || false;
-      this.choices = 0;
-      this.single_backstroke_delete = this.options.single_backstroke_delete || false;
-      this.max_selected_options = this.options.max_selected_options || Infinity;
-      return this.inherit_select_classes = this.options.inherit_select_classes || false;
-    };
-
-    AbstractChosen.prototype.set_default_text = function() {
-      if (this.form_field.getAttribute("data-placeholder")) {
-        this.default_text = this.form_field.getAttribute("data-placeholder");
-      } else if (this.is_multiple) {
-        this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
-      } else {
-        this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
-      }
-      return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
-    };
-
-    AbstractChosen.prototype.mouse_enter = function() {
-      return this.mouse_on_container = true;
-    };
-
-    AbstractChosen.prototype.mouse_leave = function() {
-      return this.mouse_on_container = false;
-    };
-
-    AbstractChosen.prototype.input_focus = function(evt) {
-      var _this = this;
-      if (this.is_multiple) {
-        if (!this.active_field) {
-          return setTimeout((function() {
-            return _this.container_mousedown();
-          }), 50);
-        }
-      } else {
-        if (!this.active_field) {
-          return this.activate_field();
-        }
-      }
-    };
-
-    AbstractChosen.prototype.input_blur = function(evt) {
-      var _this = this;
-      if (!this.mouse_on_container) {
-        this.active_field = false;
-        return setTimeout((function() {
-          return _this.blur_test();
-        }), 100);
-      }
-    };
-
-    AbstractChosen.prototype.result_add_option = function(option) {
-      var classes, style;
-      if (!option.disabled) {
-        option.dom_id = this.container_id + "_o_" + option.array_index;
-        classes = option.selected && this.is_multiple ? [] : ["active-result"];
-        if (option.selected) {
-          classes.push("result-selected");
-        }
-        if (option.group_array_index != null) {
-          classes.push("group-option");
-        }
-        if (option.classes !== "") {
-          classes.push(option.classes);
-        }
-        style = option.style.cssText !== "" ? " style=\"" + option.style + "\"" : "";
-        return '<li id="' + option.dom_id + '" class="' + classes.join(' ') + '"' + style + '>' + option.html + '</li>';
-      } else {
-        return "";
-      }
-    };
-
-    AbstractChosen.prototype.results_update_field = function() {
-      this.set_default_text();
-      if (!this.is_multiple) {
-        this.results_reset_cleanup();
-      }
-      this.result_clear_highlight();
-      this.result_single_selected = null;
-      return this.results_build();
-    };
-
-    AbstractChosen.prototype.results_toggle = function() {
-      if (this.results_showing) {
-        return this.results_hide();
-      } else {
-        return this.results_show();
-      }
-    };
-
-    AbstractChosen.prototype.results_search = function(evt) {
-      if (this.results_showing) {
-        return this.winnow_results();
-      } else {
-        return this.results_show();
-      }
-    };
-
-    AbstractChosen.prototype.choices_click = function(evt) {
-      evt.preventDefault();
-      if (!this.results_showing) {
-        return this.results_show();
-      }
-    };
-
-    AbstractChosen.prototype.keyup_checker = function(evt) {
-      var stroke, _ref;
-      stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
-      this.search_field_scale();
-      switch (stroke) {
-        case 8:
-          if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) {
-            return this.keydown_backstroke();
-          } else if (!this.pending_backstroke) {
-            this.result_clear_highlight();
-            return this.results_search();
-          }
-          break;
-        case 13:
-          evt.preventDefault();
-          if (this.results_showing) {
-            return this.result_select(evt);
-          }
-          break;
-        case 27:
-          if (this.results_showing) {
-            this.results_hide();
-          }
-          return true;
-        case 9:
-        case 38:
-        case 40:
-        case 16:
-        case 91:
-        case 17:
-          break;
-        default:
-          return this.results_search();
-      }
-    };
-
-    AbstractChosen.prototype.generate_field_id = function() {
-      var new_id;
-      new_id = this.generate_random_id();
-      this.form_field.id = new_id;
-      return new_id;
-    };
-
-    AbstractChosen.prototype.generate_random_char = function() {
-      var chars, newchar, rand;
-      chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-      rand = Math.floor(Math.random() * chars.length);
-      return newchar = chars.substring(rand, rand + 1);
-    };
-
-    AbstractChosen.prototype.container_width = function() {
-      var width;
-      if (this.options.width != null) {
-        return this.options.width;
-      }
-      width = window.getComputedStyle != null ? parseFloat(window.getComputedStyle(this.form_field).getPropertyValue('width')) : (typeof jQuery !== "undefined" && jQuery !== null) && (this.form_field_jq != null) ? this.form_field_jq.outerWidth() : this.form_field.getWidth();
-      return width + "px";
-    };
-
-    AbstractChosen.browser_is_supported = function() {
-      var _ref;
-      if (window.navigator.appName === "Microsoft Internet Explorer") {
-        return (null !== (_ref = document.documentMode) && _ref >= 8);
-      }
-      return true;
-    };
-
-    AbstractChosen.default_multiple_text = "Select Some Options";
-
-    AbstractChosen.default_single_text = "Select an Option";
-
-    AbstractChosen.default_no_result_text = "No results match";
-
-    return AbstractChosen;
-
-  })();
-
-  root.AbstractChosen = AbstractChosen;
-
-}).call(this);
-
-/*
-Chosen source: generate output using 'cake build'
-Copyright (c) 2011 by Harvest
-*/
-
-
-(function() {
-  var $, Chosen, root,
-    __hasProp = {}.hasOwnProperty,
-    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
-
-  root = this;
-
-  $ = jQuery;
-
-  $.fn.extend({
-    chosen: function(options) {
-      if (!AbstractChosen.browser_is_supported()) {
-        return this;
-      }
-      return this.each(function(input_field) {
-        var $this;
-        $this = $(this);
-        if (!$this.hasClass("chzn-done")) {
-          return $this.data('chosen', new Chosen(this, options));
-        }
-      });
-    }
-  });
-
-  Chosen = (function(_super) {
-
-    __extends(Chosen, _super);
-
-    function Chosen() {
-      return Chosen.__super__.constructor.apply(this, arguments);
-    }
-
-    Chosen.prototype.setup = function() {
-      this.form_field_jq = $(this.form_field);
-      this.current_selectedIndex = this.form_field.selectedIndex;
-      return this.is_rtl = this.form_field_jq.hasClass("chzn-rtl");
-    };
-
-    Chosen.prototype.finish_setup = function() {
-      return this.form_field_jq.addClass("chzn-done");
-    };
-
-    Chosen.prototype.set_up_html = function() {
-      var container_classes, container_props;
-      this.container_id = this.form_field.id.length ? this.form_field.id.replace(/[^\w]/g, '_') : this.generate_field_id();
-      this.container_id += "_chzn";
-      container_classes = ["chzn-container"];
-      container_classes.push("chzn-container-" + (this.is_multiple ? "multi" : "single"));
-      if (this.inherit_select_classes && this.form_field.className) {
-        container_classes.push(this.form_field.className);
-      }
-      if (this.is_rtl) {
-        container_classes.push("chzn-rtl");
-      }
-      container_props = {
-        'id': this.container_id,
-        'class': container_classes.join(' '),
-        'style': "width: " + (this.container_width()) + ";",
-        'title': this.form_field.title
-      };
-      this.container = $("<div />", container_props);
-      if (this.is_multiple) {
-        this.container.html('<ul class="chzn-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:auto;" /></li></ul><div class="chzn-drop"><ul class="chzn-results"></ul></div>');
-      } else {
-        this.container.html('<a href="javascript:void(0)" class="chzn-single chzn-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chzn-drop"><div class="chzn-search"><input type="text" autocomplete="off" /></div><ul class="chzn-results"></ul></div>');
-      }
-      this.form_field_jq.hide().after(this.container);
-      this.dropdown = this.container.find('div.chzn-drop').first();
-      this.search_field = this.container.find('input').first();
-      this.search_results = this.container.find('ul.chzn-results').first();
-      this.search_field_scale();
-      this.search_no_results = this.container.find('li.no-results').first();
-      if (this.is_multiple) {
-        this.search_choices = this.container.find('ul.chzn-choices').first();
-        this.search_container = this.container.find('li.search-field').first();
-      } else {
-        this.search_container = this.container.find('div.chzn-search').first();
-        this.selected_item = this.container.find('.chzn-single').first();
-      }
-      this.results_build();
-      this.set_tab_index();
-      this.set_label_behavior();
-      return this.form_field_jq.trigger("liszt:ready", {
-        chosen: this
-      });
-    };
-
-    Chosen.prototype.register_observers = function() {
-      var _this = this;
-      this.container.mousedown(function(evt) {
-        _this.container_mousedown(evt);
-      });
-      this.container.mouseup(function(evt) {
-        _this.container_mouseup(evt);
-      });
-      this.container.mouseenter(function(evt) {
-        _this.mouse_enter(evt);
-      });
-      this.container.mouseleave(function(evt) {
-        _this.mouse_leave(evt);
-      });
-      this.search_results.mouseup(function(evt) {
-        _this.search_results_mouseup(evt);
-      });
-      this.search_results.mouseover(function(evt) {
-        _this.search_results_mouseover(evt);
-      });
-      this.search_results.mouseout(function(evt) {
-        _this.search_results_mouseout(evt);
-      });
-      this.search_results.bind('mousewheel DOMMouseScroll', function(evt) {
-        _this.search_results_mousewheel(evt);
-      });
-      this.form_field_jq.bind("liszt:updated", function(evt) {
-        _this.results_update_field(evt);
-      });
-      this.form_field_jq.bind("liszt:activate", function(evt) {
-        _this.activate_field(evt);
-      });
-      this.form_field_jq.bind("liszt:open", function(evt) {
-        _this.container_mousedown(evt);
-      });
-      this.search_field.blur(function(evt) {
-        _this.input_blur(evt);
-      });
-      this.search_field.keyup(function(evt) {
-        _this.keyup_checker(evt);
-      });
-      this.search_field.keydown(function(evt) {
-        _this.keydown_checker(evt);
-      });
-      this.search_field.focus(function(evt) {
-        _this.input_focus(evt);
-      });
-      if (this.is_multiple) {
-        return this.search_choices.click(function(evt) {
-          _this.choices_click(evt);
-        });
-      } else {
-        return this.container.click(function(evt) {
-          evt.preventDefault();
-        });
-      }
-    };
-
-    Chosen.prototype.search_field_disabled = function() {
-      this.is_disabled = this.form_field_jq[0].disabled;
-      if (this.is_disabled) {
-        this.container.addClass('chzn-disabled');
-        this.search_field[0].disabled = true;
-        if (!this.is_multiple) {
-          this.selected_item.unbind("focus", this.activate_action);
-        }
-        return this.close_field();
-      } else {
-        this.container.removeClass('chzn-disabled');
-        this.search_field[0].disabled = false;
-        if (!this.is_multiple) {
-          return this.selected_item.bind("focus", this.activate_action);
-        }
-      }
-    };
-
-    Chosen.prototype.container_mousedown = function(evt) {
-      if (!this.is_disabled) {
-        if (evt && evt.type === "mousedown" && !this.results_showing) {
-          evt.preventDefault();
-        }
-        if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
-          if (!this.active_field) {
-            if (this.is_multiple) {
-              this.search_field.val("");
-            }
-            $(document).click(this.click_test_action);
-            this.results_show();
-          } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chzn-single").length)) {
-            evt.preventDefault();
-            this.results_toggle();
-          }
-          return this.activate_field();
-        }
-      }
-    };
-
-    Chosen.prototype.container_mouseup = function(evt) {
-      if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
-        return this.results_reset(evt);
-      }
-    };
-
-    Chosen.prototype.search_results_mousewheel = function(evt) {
-      var delta, _ref, _ref1;
-      delta = -((_ref = evt.originalEvent) != null ? _ref.wheelDelta : void 0) || ((_ref1 = evt.originialEvent) != null ? _ref1.detail : void 0);
-      if (delta != null) {
-        evt.preventDefault();
-        if (evt.type === 'DOMMouseScroll') {
-          delta = delta * 40;
-        }
-        return this.search_results.scrollTop(delta + this.search_results.scrollTop());
-      }
-    };
-
-    Chosen.prototype.blur_test = function(evt) {
-      if (!this.active_field && this.container.hasClass("chzn-container-active")) {
-        return this.close_field();
-      }
-    };
-
-    Chosen.prototype.close_field = function() {
-      $(document).unbind("click", this.click_test_action);
-      this.active_field = false;
-      this.results_hide();
-      this.container.removeClass("chzn-container-active");
-      this.winnow_results_clear();
-      this.clear_backstroke();
-      this.show_search_field_default();
-      return this.search_field_scale();
-    };
-
-    Chosen.prototype.activate_field = function() {
-      this.container.addClass("chzn-container-active");
-      this.active_field = true;
-      this.search_field.val(this.search_field.val());
-      return this.search_field.focus();
-    };
-
-    Chosen.prototype.test_active_click = function(evt) {
-      if ($(evt.target).parents('#' + this.container_id).length) {
-        return this.active_field = true;
-      } else {
-        return this.close_field();
-      }
-    };
-
-    Chosen.prototype.results_build = function() {
-      var content, data, _i, _len, _ref;
-      this.parsing = true;
-      this.results_data = root.SelectParser.select_to_array(this.form_field);
-      if (this.is_multiple && this.choices > 0) {
-        this.search_choices.find("li.search-choice").remove();
-        this.choices = 0;
-      } else if (!this.is_multiple) {
-        this.selected_item.addClass("chzn-default").find("span").text(this.default_text);
-        if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
-          this.container.addClass("chzn-container-single-nosearch");
-        } else {
-          this.container.removeClass("chzn-container-single-nosearch");
-        }
-      }
-      content = '';
-      _ref = this.results_data;
-      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-        data = _ref[_i];
-        if (data.group) {
-          content += this.result_add_group(data);
-        } else if (!data.empty) {
-          content += this.result_add_option(data);
-          if (data.selected && this.is_multiple) {
-            this.choice_build(data);
-          } else if (data.selected && !this.is_multiple) {
-            this.selected_item.removeClass("chzn-default").find("span").text(data.text);
-            if (this.allow_single_deselect) {
-              this.single_deselect_control_build();
-            }
-          }
-        }
-      }
-      this.search_field_disabled();
-      this.show_search_field_default();
-      this.search_field_scale();
-      this.search_results.html(content);
-      return this.parsing = false;
-    };
-
-    Chosen.prototype.result_add_group = function(group) {
-      if (!group.disabled) {
-        group.dom_id = this.container_id + "_g_" + group.array_index;
-        return '<li id="' + group.dom_id + '" class="group-result">' + $("<div />").text(group.label).html() + '</li>';
-      } else {
-        return "";
-      }
-    };
-
-    Chosen.prototype.result_do_highlight = function(el) {
-      var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
-      if (el.length) {
-        this.result_clear_highlight();
-        this.result_highlight = el;
-        this.result_highlight.addClass("highlighted");
-        maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
-        visible_top = this.search_results.scrollTop();
-        visible_bottom = maxHeight + visible_top;
-        high_top = this.result_highlight.position().top + this.search_results.scrollTop();
-        high_bottom = high_top + this.result_highlight.outerHeight();
-        if (high_bottom >= visible_bottom) {
-          return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
-        } else if (high_top < visible_top) {
-          return this.search_results.scrollTop(high_top);
-        }
-      }
-    };
-
-    Chosen.prototype.result_clear_highlight = function() {
-      if (this.result_highlight) {
-        this.result_highlight.removeClass("highlighted");
-      }
-      return this.result_highlight = null;
-    };
-
-    Chosen.prototype.results_show = function() {
-      if (this.result_single_selected != null) {
-        this.result_do_highlight(this.result_single_selected);
-      } else if (this.is_multiple && this.max_selected_options <= this.choices) {
-        this.form_field_jq.trigger("liszt:maxselected", {
-          chosen: this
-        });
-        return false;
-      }
-      this.container.addClass("chzn-with-drop");
-      this.form_field_jq.trigger("liszt:showing_dropdown", {
-        chosen: this
-      });
-      this.results_showing = true;
-      this.search_field.focus();
-      this.search_field.val(this.search_field.val());
-      return this.winnow_results();
-    };
-
-    Chosen.prototype.results_hide = function() {
-      this.result_clear_highlight();
-      this.container.removeClass("chzn-with-drop");
-      this.form_field_jq.trigger("liszt:hiding_dropdown", {
-        chosen: this
-      });
-      return this.results_showing = false;
-    };
-
-    Chosen.prototype.set_tab_index = function(el) {
-      var ti;
-      if (this.form_field_jq.attr("tabindex")) {
-        ti = this.form_field_jq.attr("tabindex");
-        this.form_field_jq.attr("tabindex", -1);
-        return this.search_field.attr("tabindex", ti);
-      }
-    };
-
-    Chosen.prototype.set_label_behavior = function() {
-      var _this = this;
-      this.form_field_label = this.form_field_jq.parents("label");
-      if (!this.form_field_label.length && this.form_field.id.length) {
-        this.form_field_label = $("label[for=" + this.form_field.id + "]");
-      }
-      if (this.form_field_label.length > 0) {
-        return this.form_field_label.click(function(evt) {
-          if (_this.is_multiple) {
-            return _this.container_mousedown(evt);
-          } else {
-            return _this.activate_field();
-          }
-        });
-      }
-    };
-
-    Chosen.prototype.show_search_field_default = function() {
-      if (this.is_multiple && this.choices < 1 && !this.active_field) {
-        this.search_field.val(this.default_text);
-        return this.search_field.addClass("default");
-      } else {
-        this.search_field.val("");
-        return this.search_field.removeClass("default");
-      }
-    };
-
-    Chosen.prototype.search_results_mouseup = function(evt) {
-      var target;
-      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
-      if (target.length) {
-        this.result_highlight = target;
-        this.result_select(evt);
-        return this.search_field.focus();
-      }
-    };
-
-    Chosen.prototype.search_results_mouseover = function(evt) {
-      var target;
-      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
-      if (target) {
-        return this.result_do_highlight(target);
-      }
-    };
-
-    Chosen.prototype.search_results_mouseout = function(evt) {
-      if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
-        return this.result_clear_highlight();
-      }
-    };
-
-    Chosen.prototype.choice_build = function(item) {
-      var choice_id, html, link,
-        _this = this;
-      if (this.is_multiple && this.max_selected_options <= this.choices) {
-        this.form_field_jq.trigger("liszt:maxselected", {
-          chosen: this
-        });
-        return false;
-      }
-      choice_id = this.container_id + "_c_" + item.array_index;
-      this.choices += 1;
-      if (item.disabled) {
-        html = '<li class="search-choice search-choice-disabled" id="' + choice_id + '"><span>' + item.html + '</span></li>';
-      } else {
-        html = '<li class="search-choice" id="' + choice_id + '"><span>' + item.html + '</span><a href="javascript:void(0)" class="search-choice-close" rel="' + item.array_index + '"></a></li>';
-      }
-      this.search_container.before(html);
-      link = $('#' + choice_id).find("a").first();
-      return link.click(function(evt) {
-        return _this.choice_destroy_link_click(evt);
-      });
-    };
-
-    Chosen.prototype.choice_destroy_link_click = function(evt) {
-      evt.preventDefault();
-      evt.stopPropagation();
-      if (!this.is_disabled) {
-        return this.choice_destroy($(evt.target));
-      }
-    };
-
-    Chosen.prototype.choice_destroy = function(link) {
-      if (this.result_deselect(link.attr("rel"))) {
-        this.choices -= 1;
-        this.show_search_field_default();
-        if (this.is_multiple && this.choices > 0 && this.search_field.val().length < 1) {
-          this.results_hide();
-        }
-        link.parents('li').first().remove();
-        return this.search_field_scale();
-      }
-    };
-
-    Chosen.prototype.results_reset = function() {
-      this.form_field.options[0].selected = true;
-      this.selected_item.find("span").text(this.default_text);
-      if (!this.is_multiple) {
-        this.selected_item.addClass("chzn-default");
-      }
-      this.show_search_field_default();
-      this.results_reset_cleanup();
-      this.form_field_jq.trigger("change");
-      if (this.active_field) {
-        return this.results_hide();
-      }
-    };
-
-    Chosen.prototype.results_reset_cleanup = function() {
-      this.current_selectedIndex = this.form_field.selectedIndex;
-      return this.selected_item.find("abbr").remove();
-    };
-
-    Chosen.prototype.result_select = function(evt) {
-      var high, high_id, item, position;
-      if (this.result_highlight) {
-        high = this.result_highlight;
-        high_id = high.attr("id");
-        this.result_clear_highlight();
-        if (this.is_multiple) {
-          this.result_deactivate(high);
-        } else {
-          this.search_results.find(".result-selected").removeClass("result-selected");
-          this.result_single_selected = high;
-          this.selected_item.removeClass("chzn-default");
-        }
-        high.addClass("result-selected");
-        position = high_id.substr(high_id.lastIndexOf("_") + 1);
-        item = this.results_data[position];
-        item.selected = true;
-        this.form_field.options[item.options_index].selected = true;
-        if (this.is_multiple) {
-          this.choice_build(item);
-        } else {
-          this.selected_item.find("span").first().text(item.text);
-          if (this.allow_single_deselect) {
-            this.single_deselect_control_build();
-          }
-        }
-        if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
-          this.results_hide();
-        }
-        this.search_field.val("");
-        if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
-          this.form_field_jq.trigger("change", {
-            'selected': this.form_field.options[item.options_index].value
-          });
-        }
-        this.current_selectedIndex = this.form_field.selectedIndex;
-        return this.search_field_scale();
-      }
-    };
-
-    Chosen.prototype.result_activate = function(el) {
-      return el.addClass("active-result");
-    };
-
-    Chosen.prototype.result_deactivate = function(el) {
-      return el.removeClass("active-result");
-    };
-
-    Chosen.prototype.result_deselect = function(pos) {
-      var result, result_data;
-      result_data = this.results_data[pos];
-      if (!this.form_field.options[result_data.options_index].disabled) {
-        result_data.selected = false;
-        this.form_field.options[result_data.options_index].selected = false;
-        result = $("#" + this.container_id + "_o_" + pos);
-        result.removeClass("result-selected").addClass("active-result").show();
-        this.result_clear_highlight();
-        this.winnow_results();
-        this.form_field_jq.trigger("change", {
-          deselected: this.form_field.options[result_data.options_index].value
-        });
-        this.search_field_scale();
-        return true;
-      } else {
-        return false;
-      }
-    };
-
-    Chosen.prototype.single_deselect_control_build = function() {
-      if (this.allow_single_deselect && this.selected_item.find("abbr").length < 1) {
-        return this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
-      }
-    };
-
-    Chosen.prototype.winnow_results = function() {
-      var found, option, part, parts, regex, regexAnchor, result, result_id, results, searchText, startpos, text, zregex, _i, _j, _len, _len1, _ref;
-      this.no_results_clear();
-      results = 0;
-      searchText = this.search_field.val() === this.default_text ? "" : $('<div/>').text($.trim(this.search_field.val())).html();
-      regexAnchor = this.search_contains ? "" : "^";
-      regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
-      zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
-      _ref = this.results_data;
-      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-        option = _ref[_i];
-        if (!option.disabled && !option.empty) {
-          if (option.group) {
-            $('#' + option.dom_id).css('display', 'none');
-          } else if (!(this.is_multiple && option.selected)) {
-            found = false;
-            result_id = option.dom_id;
-            result = $("#" + result_id);
-            if (regex.test(option.html)) {
-              found = true;
-              results += 1;
-            } else if (this.enable_split_word_search && (option.html.indexOf(" ") >= 0 || option.html.indexOf("[") === 0)) {
-              parts = option.html.replace(/\[|\]/g, "").split(" ");
-              if (parts.length) {
-                for (_j = 0, _len1 = parts.length; _j < _len1; _j++) {
-                  part = parts[_j];
-                  if (regex.test(part)) {
-                    found = true;
-                    results += 1;
-                  }
-                }
-              }
-            }
-            if (found) {
-              if (searchText.length) {
-                startpos = option.html.search(zregex);
-                text = option.html.substr(0, startpos + searchText.length) + '</em>' + option.html.substr(startpos + searchText.length);
-                text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
-              } else {
-                text = option.html;
-              }
-              result.html(text);
-              this.result_activate(result);
-              if (option.group_array_index != null) {
-                $("#" + this.results_data[option.group_array_index].dom_id).css('display', 'list-item');
-              }
-            } else {
-              if (this.result_highlight && result_id === this.result_highlight.attr('id')) {
-                this.result_clear_highlight();
-              }
-              this.result_deactivate(result);
-            }
-          }
-        }
-      }
-      if (results < 1 && searchText.length) {
-        return this.no_results(searchText);
-      } else {
-        return this.winnow_results_set_highlight();
-      }
-    };
-
-    Chosen.prototype.winnow_results_clear = function() {
-      var li, lis, _i, _len, _results;
-      this.search_field.val("");
-      lis = this.search_results.find("li");
-      _results = [];
-      for (_i = 0, _len = lis.length; _i < _len; _i++) {
-        li = lis[_i];
-        li = $(li);
-        if (li.hasClass("group-result")) {
-          _results.push(li.css('display', 'auto'));
-        } else if (!this.is_multiple || !li.hasClass("result-selected")) {
-          _results.push(this.result_activate(li));
-        } else {
-          _results.push(void 0);
-        }
-      }
-      return _results;
-    };
-
-    Chosen.prototype.winnow_results_set_highlight = function() {
-      var do_high, selected_results;
-      if (!this.result_highlight) {
-        selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
-        do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
-        if (do_high != null) {
-          return this.result_do_highlight(do_high);
-        }
-      }
-    };
-
-    Chosen.prototype.no_results = function(terms) {
-      var no_results_html;
-      no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
-      no_results_html.find("span").first().html(terms);
-      return this.search_results.append(no_results_html);
-    };
-
-    Chosen.prototype.no_results_clear = function() {
-      return this.search_results.find(".no-results").remove();
-    };
-
-    Chosen.prototype.keydown_arrow = function() {
-      var first_active, next_sib;
-      if (!this.result_highlight) {
-        first_active = this.search_results.find("li.active-result").first();
-        if (first_active) {
-          this.result_do_highlight($(first_active));
-        }
-      } else if (this.results_showing) {
-        next_sib = this.result_highlight.nextAll("li.active-result").first();
-        if (next_sib) {
-          this.result_do_highlight(next_sib);
-        }
-      }
-      if (!this.results_showing) {
-        return this.results_show();
-      }
-    };
-
-    Chosen.prototype.keyup_arrow = function() {
-      var prev_sibs;
-      if (!this.results_showing && !this.is_multiple) {
-        return this.results_show();
-      } else if (this.result_highlight) {
-        prev_sibs = this.result_highlight.prevAll("li.active-result");
-        if (prev_sibs.length) {
-          return this.result_do_highlight(prev_sibs.first());
-        } else {
-          if (this.choices > 0) {
-            this.results_hide();
-          }
-          return this.result_clear_highlight();
-        }
-      }
-    };
-
-    Chosen.prototype.keydown_backstroke = function() {
-      var next_available_destroy;
-      if (this.pending_backstroke) {
-        this.choice_destroy(this.pending_backstroke.find("a").first());
-        return this.clear_backstroke();
-      } else {
-        next_available_destroy = this.search_container.siblings("li.search-choice").last();
-        if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
-          this.pending_backstroke = next_available_destroy;
-          if (this.single_backstroke_delete) {
-            return this.keydown_backstroke();
-          } else {
-            return this.pending_backstroke.addClass("search-choice-focus");
-          }
-        }
-      }
-    };
-
-    Chosen.prototype.clear_backstroke = function() {
-      if (this.pending_backstroke) {
-        this.pending_backstroke.removeClass("search-choice-focus");
-      }
-      return this.pending_backstroke = null;
-    };
-
-    Chosen.prototype.keydown_checker = function(evt) {
-      var stroke, _ref;
-      stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
-      this.search_field_scale();
-      if (stroke !== 8 && this.pending_backstroke) {
-        this.clear_backstroke();
-      }
-      switch (stroke) {
-        case 8:
-          this.backstroke_length = this.search_field.val().length;
-          break;
-        case 9:
-          if (this.results_showing && !this.is_multiple) {
-            this.result_select(evt);
-          }
-          this.mouse_on_container = false;
-          break;
-        case 13:
-          evt.preventDefault();
-          break;
-        case 38:
-          evt.preventDefault();
-          this.keyup_arrow();
-          break;
-        case 40:
-          this.keydown_arrow();
-          break;
-      }
-    };
-
-    Chosen.prototype.search_field_scale = function() {
-      var div, h, style, style_block, styles, w, _i, _len;
-      if (this.is_multiple) {
-        h = 0;
-        w = 0;
-        style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
-        styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
-        for (_i = 0, _len = styles.length; _i < _len; _i++) {
-          style = styles[_i];
-          style_block += style + ":" + this.search_field.css(style) + ";";
-        }
-        div = $('<div />', {
-          'style': style_block
-        });
-        div.text(this.search_field.val());
-        $('body').append(div);
-        w = div.width() + 25;
-        div.remove();
-        if (!this.f_width) {
-          this.f_width = this.container.outerWidth();
-        }
-        if (w > this.f_width - 10) {
-          w = this.f_width - 10;
-        }
-        return this.search_field.css({
-          'width': w + 'px'
-        });
-      }
-    };
-
-    Chosen.prototype.generate_random_id = function() {
-      var string;
-      string = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char();
-      while ($("#" + string).length > 0) {
-        string += this.generate_random_char();
-      }
-      return string;
-    };
-
-    return Chosen;
-
-  })(AbstractChosen);
-
-  root.Chosen = Chosen;
-
-}).call(this);
diff --git a/resources/jquery.effects/jquery.effects.blind.js b/resources/jquery.effects/jquery.effects.blind.js
deleted file mode 100644 (file)
index ac25bbd..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*!
- * jQuery UI Effects Blind 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Blind
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.blind = function(o) {
-
-       return this.queue(function() {
-
-               // Create element
-               var el = $(this), props = ['position','top','bottom','left','right'];
-
-               // Set options
-               var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
-               var direction = o.options.direction || 'vertical'; // Default direction
-
-               // Adjust
-               $.effects.save(el, props); el.show(); // Save & Show
-               var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
-               var ref = (direction == 'vertical') ? 'height' : 'width';
-               var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
-               if(mode == 'show') wrapper.css(ref, 0); // Shift
-
-               // Animation
-               var animation = {};
-               animation[ref] = mode == 'show' ? distance : 0;
-
-               // Animate
-               wrapper.animate(animation, o.duration, o.options.easing, function() {
-                       if(mode == 'hide') el.hide(); // Hide
-                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
-                       if(o.callback) o.callback.apply(el[0], arguments); // Callback
-                       el.dequeue();
-               });
-
-       });
-
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.bounce.js b/resources/jquery.effects/jquery.effects.bounce.js
deleted file mode 100644 (file)
index 1169d77..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*!
- * jQuery UI Effects Bounce 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Bounce
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.bounce = function(o) {
-
-       return this.queue(function() {
-
-               // Create element
-               var el = $(this), props = ['position','top','bottom','left','right'];
-
-               // Set options
-               var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
-               var direction = o.options.direction || 'up'; // Default direction
-               var distance = o.options.distance || 20; // Default distance
-               var times = o.options.times || 5; // Default # of times
-               var speed = o.duration || 250; // Default speed per bounce
-               if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
-
-               // Adjust
-               $.effects.save(el, props); el.show(); // Save & Show
-               $.effects.createWrapper(el); // Create Wrapper
-               var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
-               var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
-               var distance = o.options.distance || (ref == 'top' ? el.outerHeight(true) / 3 : el.outerWidth(true) / 3);
-               if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
-               if (mode == 'hide') distance = distance / (times * 2);
-               if (mode != 'hide') times--;
-
-               // Animate
-               if (mode == 'show') { // Show Bounce
-                       var animation = {opacity: 1};
-                       animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
-                       el.animate(animation, speed / 2, o.options.easing);
-                       distance = distance / 2;
-                       times--;
-               };
-               for (var i = 0; i < times; i++) { // Bounces
-                       var animation1 = {}, animation2 = {};
-                       animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
-                       animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
-                       el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
-                       distance = (mode == 'hide') ? distance * 2 : distance / 2;
-               };
-               if (mode == 'hide') { // Last Bounce
-                       var animation = {opacity: 0};
-                       animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
-                       el.animate(animation, speed / 2, o.options.easing, function(){
-                               el.hide(); // Hide
-                               $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
-                               if(o.callback) o.callback.apply(this, arguments); // Callback
-                       });
-               } else {
-                       var animation1 = {}, animation2 = {};
-                       animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
-                       animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
-                       el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
-                               $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
-                               if(o.callback) o.callback.apply(this, arguments); // Callback
-                       });
-               };
-               el.queue('fx', function() { el.dequeue(); });
-               el.dequeue();
-       });
-
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.clip.js b/resources/jquery.effects/jquery.effects.clip.js
deleted file mode 100644 (file)
index edd51a6..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*!
- * jQuery UI Effects Clip 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Clip
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.clip = function(o) {
-
-       return this.queue(function() {
-
-               // Create element
-               var el = $(this), props = ['position','top','bottom','left','right','height','width'];
-
-               // Set options
-               var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
-               var direction = o.options.direction || 'vertical'; // Default direction
-
-               // Adjust
-               $.effects.save(el, props); el.show(); // Save & Show
-               var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
-               var animate = el[0].tagName == 'IMG' ? wrapper : el;
-               var ref = {
-                       size: (direction == 'vertical') ? 'height' : 'width',
-                       position: (direction == 'vertical') ? 'top' : 'left'
-               };
-               var distance = (direction == 'vertical') ? animate.height() : animate.width();
-               if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
-
-               // Animation
-               var animation = {};
-               animation[ref.size] = mode == 'show' ? distance : 0;
-               animation[ref.position] = mode == 'show' ? 0 : distance / 2;
-
-               // Animate
-               animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
-                       if(mode == 'hide') el.hide(); // Hide
-                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
-                       if(o.callback) o.callback.apply(el[0], arguments); // Callback
-                       el.dequeue();
-               }});
-
-       });
-
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.core.js b/resources/jquery.effects/jquery.effects.core.js
deleted file mode 100644 (file)
index 7fd946f..0000000
+++ /dev/null
@@ -1,612 +0,0 @@
-/*!
- * jQuery UI Effects 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/
- */
-;jQuery.effects || (function($, undefined) {
-
-$.effects = {};
-
-
-
-/******************************************************************************/
-/****************************** COLOR ANIMATIONS ******************************/
-/******************************************************************************/
-
-// override the animation for color styles
-$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
-       'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
-function(i, attr) {
-       $.fx.step[attr] = function(fx) {
-               if (!fx.colorInit) {
-                       fx.start = getColor(fx.elem, attr);
-                       fx.end = getRGB(fx.end);
-                       fx.colorInit = true;
-               }
-
-               fx.elem.style[attr] = 'rgb(' +
-                       Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
-                       Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
-                       Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
-       };
-});
-
-// Color Conversion functions from highlightFade
-// By Blair Mitchelmore
-// http://jquery.offput.ca/highlightFade/
-
-// Parse strings looking for color tuples [255,255,255]
-function getRGB(color) {
-               var result;
-
-               // Check if we're already dealing with an array of colors
-               if ( color && color.constructor == Array && color.length == 3 )
-                               return color;
-
-               // Look for rgb(num,num,num)
-               if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
-                               return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
-
-               // Look for rgb(num%,num%,num%)
-               if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
-                               return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
-
-               // Look for #a0b1c2
-               if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
-                               return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
-
-               // Look for #fff
-               if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
-                               return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
-
-               // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
-               if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
-                               return colors['transparent'];
-
-               // Otherwise, we're most likely dealing with a named color
-               return colors[$.trim(color).toLowerCase()];
-}
-
-function getColor(elem, attr) {
-               var color;
-
-               do {
-                               // jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
-                               color = ($.curCSS || $.css)(elem, attr);
-
-                               // Keep going until we find an element that has color, or we hit the body
-                               if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
-                                               break;
-
-                               attr = "backgroundColor";
-               } while ( elem = elem.parentNode );
-
-               return getRGB(color);
-};
-
-// Some named colors to work with
-// From Interface by Stefan Petre
-// http://interface.eyecon.ro/
-
-var colors = {
-       aqua:[0,255,255],
-       azure:[240,255,255],
-       beige:[245,245,220],
-       black:[0,0,0],
-       blue:[0,0,255],
-       brown:[165,42,42],
-       cyan:[0,255,255],
-       darkblue:[0,0,139],
-       darkcyan:[0,139,139],
-       darkgrey:[169,169,169],
-       darkgreen:[0,100,0],
-       darkkhaki:[189,183,107],
-       darkmagenta:[139,0,139],
-       darkolivegreen:[85,107,47],
-       darkorange:[255,140,0],
-       darkorchid:[153,50,204],
-       darkred:[139,0,0],
-       darksalmon:[233,150,122],
-       darkviolet:[148,0,211],
-       fuchsia:[255,0,255],
-       gold:[255,215,0],
-       green:[0,128,0],
-       indigo:[75,0,130],
-       khaki:[240,230,140],
-       lightblue:[173,216,230],
-       lightcyan:[224,255,255],
-       lightgreen:[144,238,144],
-       lightgrey:[211,211,211],
-       lightpink:[255,182,193],
-       lightyellow:[255,255,224],
-       lime:[0,255,0],
-       magenta:[255,0,255],
-       maroon:[128,0,0],
-       navy:[0,0,128],
-       olive:[128,128,0],
-       orange:[255,165,0],
-       pink:[255,192,203],
-       purple:[128,0,128],
-       violet:[128,0,128],
-       red:[255,0,0],
-       silver:[192,192,192],
-       white:[255,255,255],
-       yellow:[255,255,0],
-       transparent: [255,255,255]
-};
-
-
-
-/******************************************************************************/
-/****************************** CLASS ANIMATIONS ******************************/
-/******************************************************************************/
-
-var classAnimationActions = ['add', 'remove', 'toggle'],
-       shorthandStyles = {
-               border: 1,
-               borderBottom: 1,
-               borderColor: 1,
-               borderLeft: 1,
-               borderRight: 1,
-               borderTop: 1,
-               borderWidth: 1,
-               margin: 1,
-               padding: 1
-       };
-
-function getElementStyles() {
-       var style = document.defaultView
-                       ? document.defaultView.getComputedStyle(this, null)
-                       : this.currentStyle,
-               newStyle = {},
-               key,
-               camelCase;
-
-       // webkit enumerates style porperties
-       if (style && style.length && style[0] && style[style[0]]) {
-               var len = style.length;
-               while (len--) {
-                       key = style[len];
-                       if (typeof style[key] == 'string') {
-                               camelCase = key.replace(/\-(\w)/g, function(all, letter){
-                                       return letter.toUpperCase();
-                               });
-                               newStyle[camelCase] = style[key];
-                       }
-               }
-       } else {
-               for (key in style) {
-                       if (typeof style[key] === 'string') {
-                               newStyle[key] = style[key];
-                       }
-               }
-       }
-       
-       return newStyle;
-}
-
-function filterStyles(styles) {
-       var name, value;
-       for (name in styles) {
-               value = styles[name];
-               if (
-                       // ignore null and undefined values
-                       value == null ||
-                       // ignore functions (when does this occur?)
-                       $.isFunction(value) ||
-                       // shorthand styles that need to be expanded
-                       name in shorthandStyles ||
-                       // ignore scrollbars (break in IE)
-                       (/scrollbar/).test(name) ||
-
-                       // only colors or values that can be converted to numbers
-                       (!(/color/i).test(name) && isNaN(parseFloat(value)))
-               ) {
-                       delete styles[name];
-               }
-       }
-       
-       return styles;
-}
-
-function styleDifference(oldStyle, newStyle) {
-       var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
-               name;
-
-       for (name in newStyle) {
-               if (oldStyle[name] != newStyle[name]) {
-                       diff[name] = newStyle[name];
-               }
-       }
-
-       return diff;
-}
-
-$.effects.animateClass = function(value, duration, easing, callback) {
-       if ($.isFunction(easing)) {
-               callback = easing;
-               easing = null;
-       }
-
-       return this.queue(function() {
-               var that = $(this),
-                       originalStyleAttr = that.attr('style') || ' ',
-                       originalStyle = filterStyles(getElementStyles.call(this)),
-                       newStyle,
-                       className = that.attr('class') || "";
-
-               $.each(classAnimationActions, function(i, action) {
-                       if (value[action]) {
-                               that[action + 'Class'](value[action]);
-                       }
-               });
-               newStyle = filterStyles(getElementStyles.call(this));
-               that.attr('class', className);
-
-               that.animate(styleDifference(originalStyle, newStyle), {
-                       queue: false,
-                       duration: duration,
-                       easing: easing,
-                       complete: function() {
-                               $.each(classAnimationActions, function(i, action) {
-                                       if (value[action]) { that[action + 'Class'](value[action]); }
-                               });
-                               // work around bug in IE by clearing the cssText before setting it
-                               if (typeof that.attr('style') == 'object') {
-                                       that.attr('style').cssText = '';
-                                       that.attr('style').cssText = originalStyleAttr;
-                               } else {
-                                       that.attr('style', originalStyleAttr);
-                               }
-                               if (callback) { callback.apply(this, arguments); }
-                               $.dequeue( this );
-                       }
-               });
-       });
-};
-
-$.fn.extend({
-       _addClass: $.fn.addClass,
-       addClass: function(classNames, speed, easing, callback) {
-               return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
-       },
-
-       _removeClass: $.fn.removeClass,
-       removeClass: function(classNames,speed,easing,callback) {
-               return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
-       },
-
-       _toggleClass: $.fn.toggleClass,
-       toggleClass: function(classNames, force, speed, easing, callback) {
-               if ( typeof force == "boolean" || force === undefined ) {
-                       if ( !speed ) {
-                               // without speed parameter;
-                               return this._toggleClass(classNames, force);
-                       } else {
-                               return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
-                       }
-               } else {
-                       // without switch parameter;
-                       return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
-               }
-       },
-
-       switchClass: function(remove,add,speed,easing,callback) {
-               return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
-       }
-});
-
-
-
-/******************************************************************************/
-/*********************************** EFFECTS **********************************/
-/******************************************************************************/
-
-$.extend($.effects, {
-       version: "1.8.24",
-
-       // Saves a set of properties in a data storage
-       save: function(element, set) {
-               for(var i=0; i < set.length; i++) {
-                       if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
-               }
-       },
-
-       // Restores a set of previously saved properties from a data storage
-       restore: function(element, set) {
-               for(var i=0; i < set.length; i++) {
-                       if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
-               }
-       },
-
-       setMode: function(el, mode) {
-               if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
-               return mode;
-       },
-
-       getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
-               // this should be a little more flexible in the future to handle a string & hash
-               var y, x;
-               switch (origin[0]) {
-                       case 'top': y = 0; break;
-                       case 'middle': y = 0.5; break;
-                       case 'bottom': y = 1; break;
-                       default: y = origin[0] / original.height;
-               };
-               switch (origin[1]) {
-                       case 'left': x = 0; break;
-                       case 'center': x = 0.5; break;
-                       case 'right': x = 1; break;
-                       default: x = origin[1] / original.width;
-               };
-               return {x: x, y: y};
-       },
-
-       // Wraps the element around a wrapper that copies position properties
-       createWrapper: function(element) {
-
-               // if the element is already wrapped, return it
-               if (element.parent().is('.ui-effects-wrapper')) {
-                       return element.parent();
-               }
-
-               // wrap the element
-               var props = {
-                               width: element.outerWidth(true),
-                               height: element.outerHeight(true),
-                               'float': element.css('float')
-                       },
-                       wrapper = $('<div></div>')
-                               .addClass('ui-effects-wrapper')
-                               .css({
-                                       fontSize: '100%',
-                                       background: 'transparent',
-                                       border: 'none',
-                                       margin: 0,
-                                       padding: 0
-                               }),
-                       active = document.activeElement;
-
-               // support: Firefox
-               // Firefox incorrectly exposes anonymous content
-               // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
-               try {
-                       active.id;
-               } catch( e ) {
-                       active = document.body;
-               }
-
-               element.wrap( wrapper );
-
-               // Fixes #7595 - Elements lose focus when wrapped.
-               if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
-                       $( active ).focus();
-               }
-               
-               wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
-
-               // transfer positioning properties to the wrapper
-               if (element.css('position') == 'static') {
-                       wrapper.css({ position: 'relative' });
-                       element.css({ position: 'relative' });
-               } else {
-                       $.extend(props, {
-                               position: element.css('position'),
-                               zIndex: element.css('z-index')
-                       });
-                       $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
-                               props[pos] = element.css(pos);
-                               if (isNaN(parseInt(props[pos], 10))) {
-                                       props[pos] = 'auto';
-                               }
-                       });
-                       element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
-               }
-
-               return wrapper.css(props).show();
-       },
-
-       removeWrapper: function(element) {
-               var parent,
-                       active = document.activeElement;
-               
-               if (element.parent().is('.ui-effects-wrapper')) {
-                       parent = element.parent().replaceWith(element);
-                       // Fixes #7595 - Elements lose focus when wrapped.
-                       if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
-                               $( active ).focus();
-                       }
-                       return parent;
-               }
-                       
-               return element;
-       },
-
-       setTransition: function(element, list, factor, value) {
-               value = value || {};
-               $.each(list, function(i, x){
-                       var unit = element.cssUnit(x);
-                       if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
-               });
-               return value;
-       }
-});
-
-
-function _normalizeArguments(effect, options, speed, callback) {
-       // shift params for method overloading
-       if (typeof effect == 'object') {
-               callback = options;
-               speed = null;
-               options = effect;
-               effect = options.effect;
-       }
-       if ($.isFunction(options)) {
-               callback = options;
-               speed = null;
-               options = {};
-       }
-        if (typeof options == 'number' || $.fx.speeds[options]) {
-               callback = speed;
-               speed = options;
-               options = {};
-       }
-       if ($.isFunction(speed)) {
-               callback = speed;
-               speed = null;
-       }
-
-       options = options || {};
-
-       speed = speed || options.duration;
-       speed = $.fx.off ? 0 : typeof speed == 'number'
-               ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
-
-       callback = callback || options.complete;
-
-       return [effect, options, speed, callback];
-}
-
-function standardSpeed( speed ) {
-       // valid standard speeds
-       if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
-               return true;
-       }
-       
-       // invalid strings - treat as "normal" speed
-       if ( typeof speed === "string" && !$.effects[ speed ] ) {
-               return true;
-       }
-       
-       return false;
-}
-
-$.fn.extend({
-       effect: function(effect, options, speed, callback) {
-               var args = _normalizeArguments.apply(this, arguments),
-                       // TODO: make effects take actual parameters instead of a hash
-                       args2 = {
-                               options: args[1],
-                               duration: args[2],
-                               callback: args[3]
-                       },
-                       mode = args2.options.mode,
-                       effectMethod = $.effects[effect];
-               
-               if ( $.fx.off || !effectMethod ) {
-                       // delegate to the original method (e.g., .show()) if possible
-                       if ( mode ) {
-                               return this[ mode ]( args2.duration, args2.callback );
-                       } else {
-                               return this.each(function() {
-                                       if ( args2.callback ) {
-                                               args2.callback.call( this );
-                                       }
-                               });
-                       }
-               }
-               
-               return effectMethod.call(this, args2);
-       },
-
-       _show: $.fn.show,
-       show: function(speed) {
-               if ( standardSpeed( speed ) ) {
-                       return this._show.apply(this, arguments);
-               } else {
-                       var args = _normalizeArguments.apply(this, arguments);
-                       args[1].mode = 'show';
-                       return this.effect.apply(this, args);
-               }
-       },
-
-       _hide: $.fn.hide,
-       hide: function(speed) {
-               if ( standardSpeed( speed ) ) {
-                       return this._hide.apply(this, arguments);
-               } else {
-                       var args = _normalizeArguments.apply(this, arguments);
-                       args[1].mode = 'hide';
-                       return this.effect.apply(this, args);
-               }
-       },
-
-       // jQuery core overloads toggle and creates _toggle
-       __toggle: $.fn.toggle,
-       toggle: function(speed) {
-               if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
-                       return this.__toggle.apply(this, arguments);
-               } else {
-                       var args = _normalizeArguments.apply(this, arguments);
-                       args[1].mode = 'toggle';
-                       return this.effect.apply(this, args);
-               }
-       },
-
-       // helper functions
-       cssUnit: function(key) {
-               var style = this.css(key), val = [];
-               $.each( ['em','px','%','pt'], function(i, unit){
-                       if(style.indexOf(unit) > 0)
-                               val = [parseFloat(style), unit];
-               });
-               return val;
-       }
-});
-
-
-
-/******************************************************************************/
-/*********************************** EASING ***********************************/
-/******************************************************************************/
-
-// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
-
-var baseEasings = {};
-
-$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
-       baseEasings[ name ] = function( p ) {
-               return Math.pow( p, i + 2 );
-       };
-});
-
-$.extend( baseEasings, {
-       Sine: function ( p ) {
-               return 1 - Math.cos( p * Math.PI / 2 );
-       },
-       Circ: function ( p ) {
-               return 1 - Math.sqrt( 1 - p * p );
-       },
-       Elastic: function( p ) {
-               return p === 0 || p === 1 ? p :
-                       -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
-       },
-       Back: function( p ) {
-               return p * p * ( 3 * p - 2 );
-       },
-       Bounce: function ( p ) {
-               var pow2,
-                       bounce = 4;
-
-               while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
-               return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
-       }
-});
-
-$.each( baseEasings, function( name, easeIn ) {
-       $.easing[ "easeIn" + name ] = easeIn;
-       $.easing[ "easeOut" + name ] = function( p ) {
-               return 1 - easeIn( 1 - p );
-       };
-       $.easing[ "easeInOut" + name ] = function( p ) {
-               return p < .5 ?
-                       easeIn( p * 2 ) / 2 :
-                       easeIn( p * -2 + 2 ) / -2 + 1;
-       };
-});
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.drop.js b/resources/jquery.effects/jquery.effects.drop.js
deleted file mode 100644 (file)
index 97e5abd..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*!
- * jQuery UI Effects Drop 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Drop
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.drop = function(o) {
-
-       return this.queue(function() {
-
-               // Create element
-               var el = $(this), props = ['position','top','bottom','left','right','opacity'];
-
-               // Set options
-               var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
-               var direction = o.options.direction || 'left'; // Default Direction
-
-               // Adjust
-               $.effects.save(el, props); el.show(); // Save & Show
-               $.effects.createWrapper(el); // Create Wrapper
-               var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
-               var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
-               var distance = o.options.distance || (ref == 'top' ? el.outerHeight( true ) / 2 : el.outerWidth( true ) / 2);
-               if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
-
-               // Animation
-               var animation = {opacity: mode == 'show' ? 1 : 0};
-               animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
-
-               // Animate
-               el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
-                       if(mode == 'hide') el.hide(); // Hide
-                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
-                       if(o.callback) o.callback.apply(this, arguments); // Callback
-                       el.dequeue();
-               }});
-
-       });
-
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.explode.js b/resources/jquery.effects/jquery.effects.explode.js
deleted file mode 100644 (file)
index f63e47a..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*!
- * jQuery UI Effects Explode 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Explode
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.explode = function(o) {
-
-       return this.queue(function() {
-
-       var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
-       var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
-
-       o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
-       var el = $(this).show().css('visibility', 'hidden');
-       var offset = el.offset();
-
-       //Substract the margins - not fixing the problem yet.
-       offset.top -= parseInt(el.css("marginTop"),10) || 0;
-       offset.left -= parseInt(el.css("marginLeft"),10) || 0;
-
-       var width = el.outerWidth(true);
-       var height = el.outerHeight(true);
-
-       for(var i=0;i<rows;i++) { // =
-               for(var j=0;j<cells;j++) { // ||
-                       el
-                               .clone()
-                               .appendTo('body')
-                               .wrap('<div></div>')
-                               .css({
-                                       position: 'absolute',
-                                       visibility: 'visible',
-                                       left: -j*(width/cells),
-                                       top: -i*(height/rows)
-                               })
-                               .parent()
-                               .addClass('ui-effects-explode')
-                               .css({
-                                       position: 'absolute',
-                                       overflow: 'hidden',
-                                       width: width/cells,
-                                       height: height/rows,
-                                       left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
-                                       top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
-                                       opacity: o.options.mode == 'show' ? 0 : 1
-                               }).animate({
-                                       left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
-                                       top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
-                                       opacity: o.options.mode == 'show' ? 1 : 0
-                               }, o.duration || 500);
-               }
-       }
-
-       // Set a timeout, to call the callback approx. when the other animations have finished
-       setTimeout(function() {
-
-               o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
-                               if(o.callback) o.callback.apply(el[0]); // Callback
-                               el.dequeue();
-
-                               $('div.ui-effects-explode').remove();
-
-       }, o.duration || 500);
-
-
-       });
-
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.fade.js b/resources/jquery.effects/jquery.effects.fade.js
deleted file mode 100644 (file)
index 7aa37b1..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*!
- * jQuery UI Effects Fade 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Fade
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.fade = function(o) {
-       return this.queue(function() {
-               var elem = $(this),
-                       mode = $.effects.setMode(elem, o.options.mode || 'hide');
-
-               elem.animate({ opacity: mode }, {
-                       queue: false,
-                       duration: o.duration,
-                       easing: o.options.easing,
-                       complete: function() {
-                               (o.callback && o.callback.apply(this, arguments));
-                               elem.dequeue();
-                       }
-               });
-       });
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.fold.js b/resources/jquery.effects/jquery.effects.fold.js
deleted file mode 100644 (file)
index 06cc553..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*!
- * jQuery UI Effects Fold 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Fold
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.fold = function(o) {
-
-       return this.queue(function() {
-
-               // Create element
-               var el = $(this), props = ['position','top','bottom','left','right'];
-
-               // Set options
-               var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
-               var size = o.options.size || 15; // Default fold size
-               var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
-               var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
-
-               // Adjust
-               $.effects.save(el, props); el.show(); // Save & Show
-               var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
-               var widthFirst = ((mode == 'show') != horizFirst);
-               var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
-               var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
-               var percent = /([0-9]+)%/.exec(size);
-               if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
-               if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
-
-               // Animation
-               var animation1 = {}, animation2 = {};
-               animation1[ref[0]] = mode == 'show' ? distance[0] : size;
-               animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
-
-               // Animate
-               wrapper.animate(animation1, duration, o.options.easing)
-               .animate(animation2, duration, o.options.easing, function() {
-                       if(mode == 'hide') el.hide(); // Hide
-                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
-                       if(o.callback) o.callback.apply(el[0], arguments); // Callback
-                       el.dequeue();
-               });
-
-       });
-
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.highlight.js b/resources/jquery.effects/jquery.effects.highlight.js
deleted file mode 100644 (file)
index ad9e7bd..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*!
- * jQuery UI Effects Highlight 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Highlight
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.highlight = function(o) {
-       return this.queue(function() {
-               var elem = $(this),
-                       props = ['backgroundImage', 'backgroundColor', 'opacity'],
-                       mode = $.effects.setMode(elem, o.options.mode || 'show'),
-                       animation = {
-                               backgroundColor: elem.css('backgroundColor')
-                       };
-
-               if (mode == 'hide') {
-                       animation.opacity = 0;
-               }
-
-               $.effects.save(elem, props);
-               elem
-                       .show()
-                       .css({
-                               backgroundImage: 'none',
-                               backgroundColor: o.options.color || '#ffff99'
-                       })
-                       .animate(animation, {
-                               queue: false,
-                               duration: o.duration,
-                               easing: o.options.easing,
-                               complete: function() {
-                                       (mode == 'hide' && elem.hide());
-                                       $.effects.restore(elem, props);
-                                       (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
-                                       (o.callback && o.callback.apply(this, arguments));
-                                       elem.dequeue();
-                               }
-                       });
-       });
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.pulsate.js b/resources/jquery.effects/jquery.effects.pulsate.js
deleted file mode 100644 (file)
index d730bee..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*!
- * jQuery UI Effects Pulsate 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Pulsate
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.pulsate = function(o) {
-       return this.queue(function() {
-               var elem = $(this),
-                       mode = $.effects.setMode(elem, o.options.mode || 'show'),
-                       times = ((o.options.times || 5) * 2) - 1,
-                       duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
-                       isVisible = elem.is(':visible'),
-                       animateTo = 0;
-
-               if (!isVisible) {
-                       elem.css('opacity', 0).show();
-                       animateTo = 1;
-               }
-
-               if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
-                       times--;
-               }
-
-               for (var i = 0; i < times; i++) {
-                       elem.animate({ opacity: animateTo }, duration, o.options.easing);
-                       animateTo = (animateTo + 1) % 2;
-               }
-
-               elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
-                       if (animateTo == 0) {
-                               elem.hide();
-                       }
-                       (o.callback && o.callback.apply(this, arguments));
-               });
-
-               elem
-                       .queue('fx', function() { elem.dequeue(); })
-                       .dequeue();
-       });
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.scale.js b/resources/jquery.effects/jquery.effects.scale.js
deleted file mode 100644 (file)
index 52d1871..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*!
- * jQuery UI Effects Scale 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Scale
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.puff = function(o) {
-       return this.queue(function() {
-               var elem = $(this),
-                       mode = $.effects.setMode(elem, o.options.mode || 'hide'),
-                       percent = parseInt(o.options.percent, 10) || 150,
-                       factor = percent / 100,
-                       original = { height: elem.height(), width: elem.width() };
-
-               $.extend(o.options, {
-                       fade: true,
-                       mode: mode,
-                       percent: mode == 'hide' ? percent : 100,
-                       from: mode == 'hide'
-                               ? original
-                               : {
-                                       height: original.height * factor,
-                                       width: original.width * factor
-                               }
-               });
-
-               elem.effect('scale', o.options, o.duration, o.callback);
-               elem.dequeue();
-       });
-};
-
-$.effects.scale = function(o) {
-
-       return this.queue(function() {
-
-               // Create element
-               var el = $(this);
-
-               // Set options
-               var options = $.extend(true, {}, o.options);
-               var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
-               var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
-               var direction = o.options.direction || 'both'; // Set default axis
-               var origin = o.options.origin; // The origin of the scaling
-               if (mode != 'effect') { // Set default origin and restore for show/hide
-                       options.origin = origin || ['middle','center'];
-                       options.restore = true;
-               }
-               var original = {height: el.height(), width: el.width()}; // Save original
-               el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
-
-               // Adjust
-               var factor = { // Set scaling factor
-                       y: direction != 'horizontal' ? (percent / 100) : 1,
-                       x: direction != 'vertical' ? (percent / 100) : 1
-               };
-               el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
-
-               if (o.options.fade) { // Fade option to support puff
-                       if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
-                       if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
-               };
-
-               // Animation
-               options.from = el.from; options.to = el.to; options.mode = mode;
-
-               // Animate
-               el.effect('size', options, o.duration, o.callback);
-               el.dequeue();
-       });
-
-};
-
-$.effects.size = function(o) {
-
-       return this.queue(function() {
-
-               // Create element
-               var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity'];
-               var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore
-               var props2 = ['width','height','overflow']; // Copy for children
-               var cProps = ['fontSize'];
-               var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
-               var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
-
-               // Set options
-               var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
-               var restore = o.options.restore || false; // Default restore
-               var scale = o.options.scale || 'both'; // Default scale mode
-               var origin = o.options.origin; // The origin of the sizing
-               var original = {height: el.height(), width: el.width()}; // Save original
-               el.from = o.options.from || original; // Default from state
-               el.to = o.options.to || original; // Default to state
-               // Adjust
-               if (origin) { // Calculate baseline shifts
-                       var baseline = $.effects.getBaseline(origin, original);
-                       el.from.top = (original.height - el.from.height) * baseline.y;
-                       el.from.left = (original.width - el.from.width) * baseline.x;
-                       el.to.top = (original.height - el.to.height) * baseline.y;
-                       el.to.left = (original.width - el.to.width) * baseline.x;
-               };
-               var factor = { // Set scaling factor
-                       from: {y: el.from.height / original.height, x: el.from.width / original.width},
-                       to: {y: el.to.height / original.height, x: el.to.width / original.width}
-               };
-               if (scale == 'box' || scale == 'both') { // Scale the css box
-                       if (factor.from.y != factor.to.y) { // Vertical props scaling
-                               props = props.concat(vProps);
-                               el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
-                               el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
-                       };
-                       if (factor.from.x != factor.to.x) { // Horizontal props scaling
-                               props = props.concat(hProps);
-                               el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
-                               el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
-                       };
-               };
-               if (scale == 'content' || scale == 'both') { // Scale the content
-                       if (factor.from.y != factor.to.y) { // Vertical props scaling
-                               props = props.concat(cProps);
-                               el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
-                               el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
-                       };
-               };
-               $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
-               $.effects.createWrapper(el); // Create Wrapper
-               el.css('overflow','hidden').css(el.from); // Shift
-
-               // Animate
-               if (scale == 'content' || scale == 'both') { // Scale the children
-                       vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
-                       hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
-                       props2 = props.concat(vProps).concat(hProps); // Concat
-                       el.find("*[width]").each(function(){
-                               var child = $(this);
-                               if (restore) $.effects.save(child, props2);
-                               var c_original = {height: child.height(), width: child.width()}; // Save original
-                               child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
-                               child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
-                               if (factor.from.y != factor.to.y) { // Vertical props scaling
-                                       child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
-                                       child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
-                               };
-                               if (factor.from.x != factor.to.x) { // Horizontal props scaling
-                                       child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
-                                       child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
-                               };
-                               child.css(child.from); // Shift children
-                               child.animate(child.to, o.duration, o.options.easing, function(){
-                                       if (restore) $.effects.restore(child, props2); // Restore children
-                               }); // Animate children
-                       });
-               };
-
-               // Animate
-               el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
-                       if (el.to.opacity === 0) {
-                               el.css('opacity', el.from.opacity);
-                       }
-                       if(mode == 'hide') el.hide(); // Hide
-                       $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
-                       if(o.callback) o.callback.apply(this, arguments); // Callback
-                       el.dequeue();
-               }});
-
-       });
-
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.shake.js b/resources/jquery.effects/jquery.effects.shake.js
deleted file mode 100644 (file)
index 44b8ea4..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*!
- * jQuery UI Effects Shake 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Shake
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.shake = function(o) {
-
-       return this.queue(function() {
-
-               // Create element
-               var el = $(this), props = ['position','top','bottom','left','right'];
-
-               // Set options
-               var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
-               var direction = o.options.direction || 'left'; // Default direction
-               var distance = o.options.distance || 20; // Default distance
-               var times = o.options.times || 3; // Default # of times
-               var speed = o.duration || o.options.duration || 140; // Default speed per shake
-
-               // Adjust
-               $.effects.save(el, props); el.show(); // Save & Show
-               $.effects.createWrapper(el); // Create Wrapper
-               var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
-               var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
-
-               // Animation
-               var animation = {}, animation1 = {}, animation2 = {};
-               animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
-               animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
-               animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
-
-               // Animate
-               el.animate(animation, speed, o.options.easing);
-               for (var i = 1; i < times; i++) { // Shakes
-                       el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
-               };
-               el.animate(animation1, speed, o.options.easing).
-               animate(animation, speed / 2, o.options.easing, function(){ // Last shake
-                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
-                       if(o.callback) o.callback.apply(this, arguments); // Callback
-               });
-               el.queue('fx', function() { el.dequeue(); });
-               el.dequeue();
-       });
-
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.slide.js b/resources/jquery.effects/jquery.effects.slide.js
deleted file mode 100644 (file)
index 502e6c9..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*!
- * jQuery UI Effects Slide 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Slide
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.slide = function(o) {
-
-       return this.queue(function() {
-
-               // Create element
-               var el = $(this), props = ['position','top','bottom','left','right'];
-
-               // Set options
-               var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
-               var direction = o.options.direction || 'left'; // Default Direction
-
-               // Adjust
-               $.effects.save(el, props); el.show(); // Save & Show
-               $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
-               var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
-               var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
-               var distance = o.options.distance || (ref == 'top' ? el.outerHeight( true ) : el.outerWidth( true ));
-               if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift
-
-               // Animation
-               var animation = {};
-               animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
-
-               // Animate
-               el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
-                       if(mode == 'hide') el.hide(); // Hide
-                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
-                       if(o.callback) o.callback.apply(this, arguments); // Callback
-                       el.dequeue();
-               }});
-
-       });
-
-};
-
-})(jQuery);
diff --git a/resources/jquery.effects/jquery.effects.transfer.js b/resources/jquery.effects/jquery.effects.transfer.js
deleted file mode 100644 (file)
index 4ee4ae8..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*!
- * jQuery UI Effects Transfer 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Effects/Transfer
- *
- * Depends:
- *     jquery.effects.core.js
- */
-(function( $, undefined ) {
-
-$.effects.transfer = function(o) {
-       return this.queue(function() {
-               var elem = $(this),
-                       target = $(o.options.to),
-                       endPosition = target.offset(),
-                       animation = {
-                               top: endPosition.top,
-                               left: endPosition.left,
-                               height: target.innerHeight(),
-                               width: target.innerWidth()
-                       },
-                       startPosition = elem.offset(),
-                       transfer = $('<div class="ui-effects-transfer"></div>')
-                               .appendTo(document.body)
-                               .addClass(o.options.className)
-                               .css({
-                                       top: startPosition.top,
-                                       left: startPosition.left,
-                                       height: elem.innerHeight(),
-                                       width: elem.innerWidth(),
-                                       position: 'absolute'
-                               })
-                               .animate(animation, o.duration, o.options.easing, function() {
-                                       transfer.remove();
-                                       (o.callback && o.callback.apply(elem[0], arguments));
-                                       elem.dequeue();
-                               });
-       });
-};
-
-})(jQuery);
diff --git a/resources/jquery.tipsy/images/tipsy.png b/resources/jquery.tipsy/images/tipsy.png
deleted file mode 100644 (file)
index ef17cc3..0000000
Binary files a/resources/jquery.tipsy/images/tipsy.png and /dev/null differ
diff --git a/resources/jquery.tipsy/jquery.tipsy.css b/resources/jquery.tipsy/jquery.tipsy.css
deleted file mode 100644 (file)
index 3680fbe..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-.tipsy {
-       padding: 5px;
-       position: absolute;
-       z-index: 100000;
-       cursor: default;
-}
-.tipsy-inner {
-       padding: 5px 8px 4px 8px;
-       /*background-color: #e8f2f8;*/
-       background-color: #ffffff;
-       border: solid 1px #a7d7f9;
-       color: black;
-       max-width: 15em;
-       border-radius: 4px;
-       -moz-border-radius: 4px;
-       -webkit-border-radius: 4px;
-       /*
-       -moz-box-shadow: 0px 2px 8px #cccccc;
-       -webkit-box-shadow: 0px 2px 8px #cccccc;
-       box-shadow: 0px 2px 8px #cccccc;
-       -ms-filter: "progid:DXImageTransform.Microsoft.DropShadow(OffX=0, OffY=2, Strength=6, Direction=90, Color='#cccccc')";
-       filter: progid:DXImageTransform.Microsoft.DropShadow(OffX=0, OffY=2, Strength=6, Direction=90, Color='#cccccc');
-       */
-}
-.tipsy-arrow {
-       position: absolute;
-       /* @embed */
-       background: url('images/tipsy.png') no-repeat top left;
-       width: 11px;
-       height: 6px;
-}
-/* @noflip */ .tipsy-n .tipsy-arrow {
-       top: 0px;
-       left: 50%;
-       margin-left: -5px;
-}
-/* @noflip */ .tipsy-nw .tipsy-arrow {
-       top: 1px;
-       left: 10px;
-}
-/* @noflip */ .tipsy-ne .tipsy-arrow {
-       top: 1px;
-       right: 10px;
-}
-/* @noflip */ .tipsy-s .tipsy-arrow {
-       bottom: 0px;
-       left: 50%;
-       margin-left: -5px;
-       background-position: bottom left;
-}
-/* @noflip */ .tipsy-sw .tipsy-arrow {
-       bottom: 0px;
-       left: 10px;
-       background-position: bottom left;
-}
-/* @noflip */ .tipsy-se .tipsy-arrow {
-       bottom: 0px;
-       right: 10px;
-       background-position: bottom left;
-}
-/* @noflip */ .tipsy-e .tipsy-arrow {
-       top: 50%;
-       margin-top: -5px;
-       right: 1px;
-       width: 5px;
-       height: 11px;
-       background-position: top right;
-}
-/* @noflip */ .tipsy-w .tipsy-arrow {
-       top: 50%;
-       margin-top: -5px;
-       left: 0px;
-       width: 6px;
-       height: 11px;
-}
\ No newline at end of file
diff --git a/resources/jquery.tipsy/jquery.tipsy.js b/resources/jquery.tipsy/jquery.tipsy.js
deleted file mode 100644 (file)
index f920e8b..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-// tipsy, facebook style tooltips for jquery
-// version 1.0.0a*
-// (c) 2008-2010 jason frame [jason@onehackoranother.com]
-// released under the MIT license
-
-// * This installation of tipsy includes several local modifications to both Javascript and CSS.
-//   Please be careful when upgrading.
-
-(function($) {
-
-    function maybeCall(thing, ctx) {
-        return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
-    }
-
-    function fixTitle($ele) {
-        if ($ele.attr('title') || typeof($ele.attr('original-title')) != 'string') {
-            $ele.attr('original-title', $ele.attr('title') || '').removeAttr('title');
-        }
-    }
-
-    function Tipsy(element, options) {
-        this.$element = $(element);
-        this.options = options;
-        this.enabled = true;
-        fixTitle(this.$element);
-    }
-
-    Tipsy.prototype = {
-        show: function() {
-            var title = this.getTitle();
-            if (title && this.enabled) {
-                var $tip = this.tip();
-
-                $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
-                $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
-                if (this.options.className) {
-                    $tip.addClass(maybeCall(this.options.className, this.$element[0]));
-                }
-                $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);
-
-                var pos = $.extend({}, this.$element.offset(), {
-                    width: this.$element[0].offsetWidth,
-                    height: this.$element[0].offsetHeight
-                });
-
-                var gravity = (typeof this.options.gravity == 'function')
-                                ? this.options.gravity.call(this.$element[0])
-                                : this.options.gravity;
-
-                // Attach css classes before checking height/width so they
-                // can be applied.
-                $tip.addClass('tipsy-' + gravity);
-                if (this.options.className) {
-                    $tip.addClass(maybeCall(this.options.className, this.$element[0]));
-                }
-
-                var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight;
-                var tp;
-                switch (gravity.charAt(0)) {
-                    case 'n':
-                        tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
-                        break;
-                    case 's':
-                        tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
-                        break;
-                    case 'e':
-                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
-                        break;
-                    case 'w':
-                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
-                        break;
-                }
-
-                if (gravity.length == 2) {
-                    if (gravity.charAt(1) == 'w') {
-                        if (this.options.center) {
-                            tp.left = pos.left + pos.width / 2 - 15;
-                        } else {
-                            tp.left = pos.left;
-                        }
-                    } else {
-                        if (this.options.center) {
-                            tp.left = pos.left + pos.width / 2 - actualWidth + 15;
-                        } else {
-                            tp.left = pos.left + pos.width;
-                        }
-                    }
-                }
-                $tip.css(tp);
-
-                if (this.options.fade) {
-                    $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity}, 100);
-                } else {
-                    $tip.css({visibility: 'visible', opacity: this.options.opacity});
-                }
-            }
-        },
-
-        hide: function() {
-            if (this.options.fade) {
-                this.tip().stop().fadeOut(100, function() { $(this).remove(); });
-            } else {
-                this.tip().remove();
-            }
-        },
-
-        getTitle: function() {
-            var title, $e = this.$element, o = this.options;
-            fixTitle($e);
-            if (typeof o.title == 'string') {
-                title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
-            } else if (typeof o.title == 'function') {
-                title = o.title.call($e[0]);
-            }
-            title = ('' + title).replace(/(^\s*|\s*$)/, "");
-            return title || o.fallback;
-        },
-
-        tip: function() {
-            if (!this.$tip) {
-                this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"/></div>');
-            }
-            return this.$tip;
-        },
-
-        validate: function() {
-            if (!this.$element[0].parentNode) {
-                this.hide();
-                this.$element = null;
-                this.options = null;
-            }
-        },
-
-        enable: function() { this.enabled = true; },
-        disable: function() { this.enabled = false; },
-        toggleEnabled: function() { this.enabled = !this.enabled; }
-    };
-
-    $.fn.tipsy = function(options) {
-
-        if (options === true) {
-            return this.data('tipsy');
-        } else if (typeof options == 'string') {
-            return this.data('tipsy')[options]();
-        }
-
-        options = $.extend({}, $.fn.tipsy.defaults, options);
-
-        function get(ele) {
-            var tipsy = $.data(ele, 'tipsy');
-            if (!tipsy) {
-                tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
-                $.data(ele, 'tipsy', tipsy);
-            }
-            return tipsy;
-        }
-
-        function enter() {
-            var tipsy = get(this);
-            tipsy.hoverState = 'in';
-            if (options.delayIn == 0) {
-                tipsy.show();
-            } else {
-                setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
-            }
-        };
-
-        function leave() {
-            var tipsy = get(this);
-            tipsy.hoverState = 'out';
-            if (options.delayOut == 0) {
-                tipsy.hide();
-            } else {
-                setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
-            }
-        };
-
-        if (!options.live) this.each(function() { get(this); });
-
-        if (options.trigger != 'manual') {
-            var binder   = options.live ? 'live' : 'bind',
-                eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus',
-                eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
-            this[binder](eventIn, enter)[binder](eventOut, leave);
-        }
-
-        return this;
-
-    };
-
-    $.fn.tipsy.defaults = {
-        className: null,
-        delayIn: 0,
-        delayOut: 0,
-        fade: true,
-        fallback: '',
-        gravity: 'n',
-        center: true,
-        html: false,
-        live: false,
-        offset: 0,
-        opacity: 1.0,
-        title: 'title',
-        trigger: 'hover'
-    };
-
-    // Overwrite this method to provide options on a per-element basis.
-    // For example, you could store the gravity in a 'tipsy-gravity' attribute:
-    // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
-    // (remember - do not modify 'options' in place!)
-    $.fn.tipsy.elementOptions = function(ele, options) {
-        return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
-    };
-
-    $.fn.tipsy.autoNS = function() {
-        return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
-    };
-
-    $.fn.tipsy.autoWE = function() {
-        return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
-    };
-
-})(jQuery);
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-af.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-af.js
deleted file mode 100644 (file)
index 0922ef7..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Afrikaans initialisation for the jQuery UI date picker plugin. */
-/* Written by Renier Pretorius. */
-jQuery(function($){
-       $.datepicker.regional['af'] = {
-               closeText: 'Selekteer',
-               prevText: 'Vorige',
-               nextText: 'Volgende',
-               currentText: 'Vandag',
-               monthNames: ['Januarie','Februarie','Maart','April','Mei','Junie',
-               'Julie','Augustus','September','Oktober','November','Desember'],
-               monthNamesShort: ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun',
-               'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
-               dayNames: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],
-               dayNamesShort: ['Son', 'Maa', 'Din', 'Woe', 'Don', 'Vry', 'Sat'],
-               dayNamesMin: ['So','Ma','Di','Wo','Do','Vr','Sa'],
-               weekHeader: 'Wk',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['af']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-ar.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-ar.js
deleted file mode 100644 (file)
index 8a9218d..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Arabic Translation for jQuery UI date picker plugin. */
-/* Khaled Alhourani -- me@khaledalhourani.com */
-/* NOTE: monthNames are the original months names and they are the Arabic names, not the new months name فبراير - يناير and there isn't any Arabic roots for these months */
-jQuery(function($){
-       $.datepicker.regional['ar'] = {
-               closeText: 'إغلاق',
-               prevText: '&#x3c;السابق',
-               nextText: 'التالي&#x3e;',
-               currentText: 'اليوم',
-               monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'مايو', 'حزيران',
-               'تموز', 'آب', 'أيلول',       'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
-               monthNamesShort: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
-               dayNames: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
-               dayNamesShort: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
-               dayNamesMin: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
-               weekHeader: 'أسبوع',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 6,
-               isRTL: true,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['ar']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-az.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-az.js
deleted file mode 100644 (file)
index 57802a4..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Azerbaijani (UTF-8) initialisation for the jQuery UI date picker plugin. */
-/* Written by Jamil Najafov (necefov33@gmail.com). */
-jQuery(function($) {
-       $.datepicker.regional['az'] = {
-               closeText: 'Bağla',
-               prevText: '&#x3c;Geri',
-               nextText: 'İrəli&#x3e;',
-               currentText: 'Bugün',
-               monthNames: ['Yanvar','Fevral','Mart','Aprel','May','İyun',
-               'İyul','Avqust','Sentyabr','Oktyabr','Noyabr','Dekabr'],
-               monthNamesShort: ['Yan','Fev','Mar','Apr','May','İyun',
-               'İyul','Avq','Sen','Okt','Noy','Dek'],
-               dayNames: ['Bazar','Bazar ertəsi','Çərşənbə axşamı','Çərşənbə','Cümə axşamı','Cümə','Şənbə'],
-               dayNamesShort: ['B','Be','Ça','Ç','Ca','C','Ş'],
-               dayNamesMin: ['B','B','Ç','С','Ç','C','Ş'],
-               weekHeader: 'Hf',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['az']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-bg.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-bg.js
deleted file mode 100644 (file)
index c19d20f..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Bulgarian initialisation for the jQuery UI date picker plugin. */
-/* Written by Stoyan Kyosev (http://svest.org). */
-jQuery(function($){
-    $.datepicker.regional['bg'] = {
-        closeText: 'затвори',
-        prevText: '&#x3c;назад',
-        nextText: 'напред&#x3e;',
-               nextBigText: '&#x3e;&#x3e;',
-        currentText: 'днес',
-        monthNames: ['Януари','Февруари','Март','Април','Май','Юни',
-        'Юли','Август','Септември','Октомври','Ноември','Декември'],
-        monthNamesShort: ['Яну','Фев','Мар','Апр','Май','Юни',
-        'Юли','Авг','Сеп','Окт','Нов','Дек'],
-        dayNames: ['Неделя','Понеделник','Вторник','Сряда','Четвъртък','Петък','Събота'],
-        dayNamesShort: ['Нед','Пон','Вто','Сря','Чет','Пет','Съб'],
-        dayNamesMin: ['Не','По','Вт','Ср','Че','Пе','Съ'],
-               weekHeader: 'Wk',
-        dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-        isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-    $.datepicker.setDefaults($.datepicker.regional['bg']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-bs.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-bs.js
deleted file mode 100644 (file)
index d4dc8b0..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Bosnian i18n for the jQuery UI date picker plugin. */
-/* Written by Kenan Konjo. */
-jQuery(function($){
-       $.datepicker.regional['bs'] = {
-               closeText: 'Zatvori', 
-               prevText: '&#x3c;', 
-               nextText: '&#x3e;', 
-               currentText: 'Danas', 
-               monthNames: ['Januar','Februar','Mart','April','Maj','Juni',
-               'Juli','August','Septembar','Oktobar','Novembar','Decembar'],
-               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
-               'Jul','Aug','Sep','Okt','Nov','Dec'],
-               dayNames: ['Nedelja','Ponedeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],
-               dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],
-               dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
-               weekHeader: 'Wk',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['bs']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-ca.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-ca.js
deleted file mode 100644 (file)
index b128e69..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Inicialització en català per a l'extenció 'calendar' per jQuery. */
-/* Writers: (joan.leon@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['ca'] = {
-               closeText: 'Tancar',
-               prevText: '&#x3c;Ant',
-               nextText: 'Seg&#x3e;',
-               currentText: 'Avui',
-               monthNames: ['Gener','Febrer','Mar&ccedil;','Abril','Maig','Juny',
-               'Juliol','Agost','Setembre','Octubre','Novembre','Desembre'],
-               monthNamesShort: ['Gen','Feb','Mar','Abr','Mai','Jun',
-               'Jul','Ago','Set','Oct','Nov','Des'],
-               dayNames: ['Diumenge','Dilluns','Dimarts','Dimecres','Dijous','Divendres','Dissabte'],
-               dayNamesShort: ['Dug','Dln','Dmt','Dmc','Djs','Dvn','Dsb'],
-               dayNamesMin: ['Dg','Dl','Dt','Dc','Dj','Dv','Ds'],
-               weekHeader: 'Sm',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['ca']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-cs.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-cs.js
deleted file mode 100644 (file)
index 9805bcd..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Czech initialisation for the jQuery UI date picker plugin. */
-/* Written by Tomas Muller (tomas@tomas-muller.net). */
-jQuery(function($){
-       $.datepicker.regional['cs'] = {
-               closeText: 'Zavřít',
-               prevText: '&#x3c;Dříve',
-               nextText: 'Později&#x3e;',
-               currentText: 'Nyní',
-               monthNames: ['leden','únor','březen','duben','květen','červen',
-        'červenec','srpen','září','říjen','listopad','prosinec'],
-               monthNamesShort: ['led','úno','bře','dub','kvě','čer',
-               'čvc','srp','zář','říj','lis','pro'],
-               dayNames: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'],
-               dayNamesShort: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
-               dayNamesMin: ['ne','po','út','st','čt','pá','so'],
-               weekHeader: 'Týd',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['cs']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-da.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-da.js
deleted file mode 100644 (file)
index 176044e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Danish initialisation for the jQuery UI date picker plugin. */
-/* Written by Jan Christensen ( deletestuff@gmail.com). */
-jQuery(function($){
-    $.datepicker.regional['da'] = {
-               closeText: 'Luk',
-        prevText: '&#x3c;Forrige',
-               nextText: 'Næste&#x3e;',
-               currentText: 'Idag',
-        monthNames: ['Januar','Februar','Marts','April','Maj','Juni',
-        'Juli','August','September','Oktober','November','December'],
-        monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
-        'Jul','Aug','Sep','Okt','Nov','Dec'],
-               dayNames: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],
-               dayNamesShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'],
-               dayNamesMin: ['Sø','Ma','Ti','On','To','Fr','Lø'],
-               weekHeader: 'Uge',
-        dateFormat: 'dd-mm-yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-    $.datepicker.setDefaults($.datepicker.regional['da']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-de.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-de.js
deleted file mode 100644 (file)
index f3ef9e8..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* German initialisation for the jQuery UI date picker plugin. */
-/* Written by Milian Wolff (mail@milianw.de). */
-jQuery(function($){
-       $.datepicker.regional['de'] = {
-               closeText: 'schließen',
-               prevText: '&#x3c;zurück',
-               nextText: 'Vor&#x3e;',
-               currentText: 'heute',
-               monthNames: ['Januar','Februar','März','April','Mai','Juni',
-               'Juli','August','September','Oktober','November','Dezember'],
-               monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun',
-               'Jul','Aug','Sep','Okt','Nov','Dez'],
-               dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
-               dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
-               dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],
-               weekHeader: 'KW',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['de']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-el.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-el.js
deleted file mode 100644 (file)
index 6d775f9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Greek (el) initialisation for the jQuery UI date picker plugin. */
-/* Written by Alex Cicovic (http://www.alexcicovic.com) */
-jQuery(function($){
-       $.datepicker.regional['el'] = {
-               closeText: 'Κλείσιμο',
-               prevText: 'Προηγούμενος',
-               nextText: 'Επόμενος',
-               currentText: 'Τρέχων Μήνας',
-               monthNames: ['Ιανουάριος','Φεβρουάριος','Μάρτιος','Απρίλιος','Μάιος','Ιούνιος',
-               'Ιούλιος','Αύγουστος','Σεπτέμβριος','Οκτώβριος','Νοέμβριος','Δεκέμβριος'],
-               monthNamesShort: ['Ιαν','Φεβ','Μαρ','Απρ','Μαι','Ιουν',
-               'Ιουλ','Αυγ','Σεπ','Οκτ','Νοε','Δεκ'],
-               dayNames: ['Κυριακή','Δευτέρα','Τρίτη','Τετάρτη','Πέμπτη','Παρασκευή','Σάββατο'],
-               dayNamesShort: ['Κυρ','Δευ','Τρι','Τετ','Πεμ','Παρ','Σαβ'],
-               dayNamesMin: ['Κυ','Δε','Τρ','Τε','Πε','Πα','Σα'],
-               weekHeader: 'Εβδ',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['el']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js
deleted file mode 100644 (file)
index 16a096e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* English/UK initialisation for the jQuery UI date picker plugin. */
-/* Written by Stuart. */
-jQuery(function($){
-       $.datepicker.regional['en-GB'] = {
-               closeText: 'Done',
-               prevText: 'Prev',
-               nextText: 'Next',
-               currentText: 'Today',
-               monthNames: ['January','February','March','April','May','June',
-               'July','August','September','October','November','December'],
-               monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
-               'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
-               dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
-               dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
-               dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'],
-               weekHeader: 'Wk',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['en-GB']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-eo.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-eo.js
deleted file mode 100644 (file)
index 6cabc2c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Esperanto initialisation for the jQuery UI date picker plugin. */
-/* Written by Olivier M. (olivierweb@ifrance.com). */
-jQuery(function($){
-       $.datepicker.regional['eo'] = {
-               closeText: 'Fermi',
-               prevText: '&lt;Anta',
-               nextText: 'Sekv&gt;',
-               currentText: 'Nuna',
-               monthNames: ['Januaro','Februaro','Marto','Aprilo','Majo','Junio',
-               'Julio','Aŭgusto','Septembro','Oktobro','Novembro','Decembro'],
-               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
-               'Jul','Aŭg','Sep','Okt','Nov','Dec'],
-               dayNames: ['Dimanĉo','Lundo','Mardo','Merkredo','Ĵaŭdo','Vendredo','Sabato'],
-               dayNamesShort: ['Dim','Lun','Mar','Mer','Ĵaŭ','Ven','Sab'],
-               dayNamesMin: ['Di','Lu','Ma','Me','Ĵa','Ve','Sa'],
-               weekHeader: 'Sb',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['eo']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-es.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-es.js
deleted file mode 100644 (file)
index a02133d..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Inicialización en español para la extensión 'UI date picker' para jQuery. */
-/* Traducido por Vester (xvester@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['es'] = {
-               closeText: 'Cerrar',
-               prevText: '&#x3c;Ant',
-               nextText: 'Sig&#x3e;',
-               currentText: 'Hoy',
-               monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio',
-               'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
-               monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun',
-               'Jul','Ago','Sep','Oct','Nov','Dic'],
-               dayNames: ['Domingo','Lunes','Martes','Mi&eacute;rcoles','Jueves','Viernes','S&aacute;bado'],
-               dayNamesShort: ['Dom','Lun','Mar','Mi&eacute;','Juv','Vie','S&aacute;b'],
-               dayNamesMin: ['Do','Lu','Ma','Mi','Ju','Vi','S&aacute;'],
-               weekHeader: 'Sm',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['es']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-et.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-et.js
deleted file mode 100644 (file)
index 32702b2..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Estonian initialisation for the jQuery UI date picker plugin. */
-/* Written by Mart Sõmermaa (mrts.pydev at gmail com). */
-jQuery(function($){
-       $.datepicker.regional['et'] = {
-               closeText: 'Sulge',
-               prevText: 'Eelnev',
-               nextText: 'Järgnev',
-               currentText: 'Täna',
-               monthNames: ['Jaanuar','Veebruar','Märts','Aprill','Mai','Juuni',
-               'Juuli','August','September','Oktoober','November','Detsember'],
-               monthNamesShort: ['Jaan', 'Veebr', 'Märts', 'Apr', 'Mai', 'Juuni',
-               'Juuli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dets'],
-               dayNames: ['Pühapäev', 'Esmaspäev', 'Teisipäev', 'Kolmapäev', 'Neljapäev', 'Reede', 'Laupäev'],
-               dayNamesShort: ['Pühap', 'Esmasp', 'Teisip', 'Kolmap', 'Neljap', 'Reede', 'Laup'],
-               dayNamesMin: ['P','E','T','K','N','R','L'],
-               weekHeader: 'näd',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['et']);
-}); 
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-eu.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-eu.js
deleted file mode 100644 (file)
index ff66e49..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Euskarako oinarria 'UI date picker' jquery-ko extentsioarentzat */
-/* Karrikas-ek itzulia (karrikas@karrikas.com) */
-jQuery(function($){
-       $.datepicker.regional['eu'] = {
-               closeText: 'Egina',
-               prevText: '&#x3c;Aur',
-               nextText: 'Hur&#x3e;',
-               currentText: 'Gaur',
-               monthNames: ['urtarrila','otsaila','martxoa','apirila','maiatza','ekaina',
-                       'uztaila','abuztua','iraila','urria','azaroa','abendua'],
-               monthNamesShort: ['urt.','ots.','mar.','api.','mai.','eka.',
-                       'uzt.','abu.','ira.','urr.','aza.','abe.'],
-               dayNames: ['igandea','astelehena','asteartea','asteazkena','osteguna','ostirala','larunbata'],
-               dayNamesShort: ['ig.','al.','ar.','az.','og.','ol.','lr.'],
-               dayNamesMin: ['ig','al','ar','az','og','ol','lr'],
-               weekHeader: 'As',
-               dateFormat: 'yy-mm-dd',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['eu']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-fa.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-fa.js
deleted file mode 100644 (file)
index be8acd2..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Persian (Farsi) Translation for the jQuery UI date picker plugin. */
-/* Javad Mowlanezhad -- jmowla@gmail.com */
-/* Jalali calendar should supported soon! (Its implemented but I have to test it) */
-jQuery(function($) {
-       $.datepicker.regional['fa'] = {
-               closeText: 'بستن',
-               prevText: '&#x3C;قبلی',
-               nextText: 'بعدی&#x3E;',
-               currentText: 'امروز',
-               monthNames: [
-                       'فروردين',
-                       'ارديبهشت',
-                       'خرداد',
-                       'تير',
-                       'مرداد',
-                       'شهريور',
-                       'مهر',
-                       'آبان',
-                       'آذر',
-                       'دی',
-                       'بهمن',
-                       'اسفند'
-               ],
-               monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],
-               dayNames: [
-                       'يکشنبه',
-                       'دوشنبه',
-                       'سه‌شنبه',
-                       'چهارشنبه',
-                       'پنجشنبه',
-                       'جمعه',
-                       'شنبه'
-               ],
-               dayNamesShort: [
-                       'ی',
-                       'د',
-                       'س',
-                       'چ',
-                       'پ',
-                       'ج', 
-                       'ش'
-               ],
-               dayNamesMin: [
-                       'ی',
-                       'د',
-                       'س',
-                       'چ',
-                       'پ',
-                       'ج', 
-                       'ش'
-               ],
-               weekHeader: 'هف',
-               dateFormat: 'yy/mm/dd',
-               firstDay: 6,
-               isRTL: true,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['fa']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-fi.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-fi.js
deleted file mode 100644 (file)
index 4c5adda..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Finnish initialisation for the jQuery UI date picker plugin. */
-/* Written by Harri Kilpiö (harrikilpio@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['fi'] = {
-               closeText: 'Sulje',
-               prevText: '&#xAB;Edellinen',
-               nextText: 'Seuraava&#xBB;',
-               currentText: 'T&#xE4;n&#xE4;&#xE4;n',
-               monthNames: ['Tammikuu','Helmikuu','Maaliskuu','Huhtikuu','Toukokuu','Kes&#xE4;kuu',
-               'Hein&#xE4;kuu','Elokuu','Syyskuu','Lokakuu','Marraskuu','Joulukuu'],
-               monthNamesShort: ['Tammi','Helmi','Maalis','Huhti','Touko','Kes&#xE4;',
-               'Hein&#xE4;','Elo','Syys','Loka','Marras','Joulu'],
-               dayNamesShort: ['Su','Ma','Ti','Ke','To','Pe','La'],
-               dayNames: ['Sunnuntai','Maanantai','Tiistai','Keskiviikko','Torstai','Perjantai','Lauantai'],
-               dayNamesMin: ['Su','Ma','Ti','Ke','To','Pe','La'],
-               weekHeader: 'Vk',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['fi']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-fo.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-fo.js
deleted file mode 100644 (file)
index 8a6cb99..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Faroese initialisation for the jQuery UI date picker plugin */
-/* Written by Sverri Mohr Olsen, sverrimo@gmail.com */
-jQuery(function($){
-       $.datepicker.regional['fo'] = {
-               closeText: 'Lat aftur',
-               prevText: '&#x3c;Fyrra',
-               nextText: 'Næsta&#x3e;',
-               currentText: 'Í dag',
-               monthNames: ['Januar','Februar','Mars','Apríl','Mei','Juni',
-               'Juli','August','September','Oktober','November','Desember'],
-               monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',
-               'Jul','Aug','Sep','Okt','Nov','Des'],
-               dayNames: ['Sunnudagur','Mánadagur','Týsdagur','Mikudagur','Hósdagur','Fríggjadagur','Leyardagur'],
-               dayNamesShort: ['Sun','Mán','Týs','Mik','Hós','Frí','Ley'],
-               dayNamesMin: ['Su','Má','Tý','Mi','Hó','Fr','Le'],
-               weekHeader: 'Vk',
-               dateFormat: 'dd-mm-yy',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['fo']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-fr.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-fr.js
deleted file mode 100644 (file)
index 7e79363..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* French initialisation for the jQuery UI date picker plugin. */
-/* Written by Keith Wood (kbwood{at}iinet.com.au),
-              Stéphane Nahmani (sholby@sholby.net),
-              Stéphane Raimbault <stephane.raimbault@gmail.com> */
-jQuery(function($){
-       $.datepicker.regional['fr'] = {
-               closeText: 'Fermer',
-               prevText: 'Précédent',
-               nextText: 'Suivant',
-               currentText: 'Aujourd\'hui',
-               monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',
-               'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
-               monthNamesShort: ['Janv.','Févr.','Mars','Avril','Mai','Juin',
-               'Juil.','Août','Sept.','Oct.','Nov.','Déc.'],
-               dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
-               dayNamesShort: ['Dim.','Lun.','Mar.','Mer.','Jeu.','Ven.','Sam.'],
-               dayNamesMin: ['D','L','M','M','J','V','S'],
-               weekHeader: 'Sem.',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['fr']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-gl.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-gl.js
deleted file mode 100644 (file)
index 278403e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Galician localization for 'UI date picker' jQuery extension. */
-/* Translated by Jorge Barreiro <yortx.barry@gmail.com>. */
-jQuery(function($){
-       $.datepicker.regional['gl'] = {
-               closeText: 'Pechar',
-               prevText: '&#x3c;Ant',
-               nextText: 'Seg&#x3e;',
-               currentText: 'Hoxe',
-               monthNames: ['Xaneiro','Febreiro','Marzo','Abril','Maio','Xuño',
-               'Xullo','Agosto','Setembro','Outubro','Novembro','Decembro'],
-               monthNamesShort: ['Xan','Feb','Mar','Abr','Mai','Xuñ',
-               'Xul','Ago','Set','Out','Nov','Dec'],
-               dayNames: ['Domingo','Luns','Martes','M&eacute;rcores','Xoves','Venres','S&aacute;bado'],
-               dayNamesShort: ['Dom','Lun','Mar','M&eacute;r','Xov','Ven','S&aacute;b'],
-               dayNamesMin: ['Do','Lu','Ma','M&eacute;','Xo','Ve','S&aacute;'],
-               weekHeader: 'Sm',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['gl']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-he.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-he.js
deleted file mode 100644 (file)
index 135cdec..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Hebrew initialisation for the UI Datepicker extension. */
-/* Written by Amir Hardon (ahardon at gmail dot com). */
-jQuery(function($){
-       $.datepicker.regional['he'] = {
-               closeText: 'סגור',
-               prevText: '&#x3c;הקודם',
-               nextText: 'הבא&#x3e;',
-               currentText: 'היום',
-               monthNames: ['ינואר','פברואר','מרץ','אפריל','מאי','יוני',
-               'יולי','אוגוסט','ספטמבר','אוקטובר','נובמבר','דצמבר'],
-               monthNamesShort: ['ינו','פבר','מרץ','אפר','מאי','יוני',
-               'יולי','אוג','ספט','אוק','נוב','דצמ'],
-               dayNames: ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת'],
-               dayNamesShort: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
-               dayNamesMin: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
-               weekHeader: 'Wk',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 0,
-               isRTL: true,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['he']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-hi.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-hi.js
deleted file mode 100644 (file)
index 6c563b9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Hindi initialisation for the jQuery UI date picker plugin. */
-/* Written by Michael Dawart. */
-jQuery(function($){
-       $.datepicker.regional['hi'] = {
-               closeText: 'बंद',
-               prevText: 'पिछला',
-               nextText: 'अगला',
-               currentText: 'आज',
-               monthNames: ['जनवरी ','फरवरी','मार्च','अप्रेल','मई','जून',
-               'जूलाई','अगस्त ','सितम्बर','अक्टूबर','नवम्बर','दिसम्बर'],
-               monthNamesShort: ['जन', 'फर', 'मार्च', 'अप्रेल', 'मई', 'जून',
-               'जूलाई', 'अग', 'सित', 'अक्ट', 'नव', 'दि'],
-               dayNames: ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरुवार', 'शुक्रवार', 'शनिवार'],
-               dayNamesShort: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
-               dayNamesMin: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
-               weekHeader: 'हफ्ता',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['hi']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-hr.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-hr.js
deleted file mode 100644 (file)
index 1eb3dd9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Croatian i18n for the jQuery UI date picker plugin. */
-/* Written by Vjekoslav Nesek. */
-jQuery(function($){
-       $.datepicker.regional['hr'] = {
-               closeText: 'Zatvori',
-               prevText: '&#x3c;',
-               nextText: '&#x3e;',
-               currentText: 'Danas',
-               monthNames: ['Siječanj','Veljača','Ožujak','Travanj','Svibanj','Lipanj',
-               'Srpanj','Kolovoz','Rujan','Listopad','Studeni','Prosinac'],
-               monthNamesShort: ['Sij','Velj','Ožu','Tra','Svi','Lip',
-               'Srp','Kol','Ruj','Lis','Stu','Pro'],
-               dayNames: ['Nedjelja','Ponedjeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],
-               dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],
-               dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
-               weekHeader: 'Tje',
-               dateFormat: 'dd.mm.yy.',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['hr']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-hu.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-hu.js
deleted file mode 100644 (file)
index b28c268..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Hungarian initialisation for the jQuery UI date picker plugin. */
-/* Written by Istvan Karaszi (jquery@spam.raszi.hu). */
-jQuery(function($){
-       $.datepicker.regional['hu'] = {
-               closeText: 'bezár',
-               prevText: 'vissza',
-               nextText: 'előre',
-               currentText: 'ma',
-               monthNames: ['Január', 'Február', 'Március', 'Április', 'Május', 'Június',
-               'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'],
-               monthNamesShort: ['Jan', 'Feb', 'Már', 'Ápr', 'Máj', 'Jún',
-               'Júl', 'Aug', 'Szep', 'Okt', 'Nov', 'Dec'],
-               dayNames: ['Vasárnap', 'Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'],
-               dayNamesShort: ['Vas', 'Hét', 'Ked', 'Sze', 'Csü', 'Pén', 'Szo'],
-               dayNamesMin: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],
-               weekHeader: 'Hét',
-               dateFormat: 'yy.mm.dd.',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: true,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['hu']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-hy.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-hy.js
deleted file mode 100644 (file)
index c6cc194..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Armenian(UTF-8) initialisation for the jQuery UI date picker plugin. */
-/* Written by Levon Zakaryan (levon.zakaryan@gmail.com)*/
-jQuery(function($){
-       $.datepicker.regional['hy'] = {
-               closeText: 'Փակել',
-               prevText: '&#x3c;Նախ.',
-               nextText: 'Հաջ.&#x3e;',
-               currentText: 'Այսօր',
-               monthNames: ['Հունվար','Փետրվար','Մարտ','Ապրիլ','Մայիս','Հունիս',
-               'Հուլիս','Օգոստոս','Սեպտեմբեր','Հոկտեմբեր','Նոյեմբեր','Դեկտեմբեր'],
-               monthNamesShort: ['Հունվ','Փետր','Մարտ','Ապր','Մայիս','Հունիս',
-               'Հուլ','Օգս','Սեպ','Հոկ','Նոյ','Դեկ'],
-               dayNames: ['կիրակի','եկուշաբթի','երեքշաբթի','չորեքշաբթի','հինգշաբթի','ուրբաթ','շաբաթ'],
-               dayNamesShort: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],
-               dayNamesMin: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],
-               weekHeader: 'ՇԲՏ',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['hy']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-id.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-id.js
deleted file mode 100644 (file)
index c626fbb..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Indonesian initialisation for the jQuery UI date picker plugin. */
-/* Written by Deden Fathurahman (dedenf@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['id'] = {
-               closeText: 'Tutup',
-               prevText: '&#x3c;mundur',
-               nextText: 'maju&#x3e;',
-               currentText: 'hari ini',
-               monthNames: ['Januari','Februari','Maret','April','Mei','Juni',
-               'Juli','Agustus','September','Oktober','Nopember','Desember'],
-               monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',
-               'Jul','Agus','Sep','Okt','Nop','Des'],
-               dayNames: ['Minggu','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'],
-               dayNamesShort: ['Min','Sen','Sel','Rab','kam','Jum','Sab'],
-               dayNamesMin: ['Mg','Sn','Sl','Rb','Km','jm','Sb'],
-               weekHeader: 'Mg',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['id']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-is.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-is.js
deleted file mode 100644 (file)
index c53235a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Icelandic initialisation for the jQuery UI date picker plugin. */
-/* Written by Haukur H. Thorsson (haukur@eskill.is). */
-jQuery(function($){
-       $.datepicker.regional['is'] = {
-               closeText: 'Loka',
-               prevText: '&#x3c; Fyrri',
-               nextText: 'N&aelig;sti &#x3e;',
-               currentText: '&Iacute; dag',
-               monthNames: ['Jan&uacute;ar','Febr&uacute;ar','Mars','Apr&iacute;l','Ma&iacute','J&uacute;n&iacute;',
-               'J&uacute;l&iacute;','&Aacute;g&uacute;st','September','Okt&oacute;ber','N&oacute;vember','Desember'],
-               monthNamesShort: ['Jan','Feb','Mar','Apr','Ma&iacute;','J&uacute;n',
-               'J&uacute;l','&Aacute;g&uacute;','Sep','Okt','N&oacute;v','Des'],
-               dayNames: ['Sunnudagur','M&aacute;nudagur','&THORN;ri&eth;judagur','Mi&eth;vikudagur','Fimmtudagur','F&ouml;studagur','Laugardagur'],
-               dayNamesShort: ['Sun','M&aacute;n','&THORN;ri','Mi&eth;','Fim','F&ouml;s','Lau'],
-               dayNamesMin: ['Su','M&aacute;','&THORN;r','Mi','Fi','F&ouml;','La'],
-               weekHeader: 'Vika',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['is']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-it.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-it.js
deleted file mode 100644 (file)
index 59da2df..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Italian initialisation for the jQuery UI date picker plugin. */
-/* Written by Antonello Pasella (antonello.pasella@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['it'] = {
-               closeText: 'Chiudi',
-               prevText: '&#x3c;Prec',
-               nextText: 'Succ&#x3e;',
-               currentText: 'Oggi',
-               monthNames: ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno',
-                       'Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],
-               monthNamesShort: ['Gen','Feb','Mar','Apr','Mag','Giu',
-                       'Lug','Ago','Set','Ott','Nov','Dic'],
-               dayNames: ['Domenica','Luned&#236','Marted&#236','Mercoled&#236','Gioved&#236','Venerd&#236','Sabato'],
-               dayNamesShort: ['Dom','Lun','Mar','Mer','Gio','Ven','Sab'],
-               dayNamesMin: ['Do','Lu','Ma','Me','Gi','Ve','Sa'],
-               weekHeader: 'Sm',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['it']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-ja.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-ja.js
deleted file mode 100644 (file)
index 7eb4268..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Japanese initialisation for the jQuery UI date picker plugin. */
-/* Written by Kentaro SATO (kentaro@ranvis.com). */
-jQuery(function($){
-       $.datepicker.regional['ja'] = {
-               closeText: '閉じる',
-               prevText: '&#x3c;前',
-               nextText: '次&#x3e;',
-               currentText: '今日',
-               monthNames: ['1月','2月','3月','4月','5月','6月',
-               '7月','8月','9月','10月','11月','12月'],
-               monthNamesShort: ['1月','2月','3月','4月','5月','6月',
-               '7月','8月','9月','10月','11月','12月'],
-               dayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],
-               dayNamesShort: ['日','月','火','水','木','金','土'],
-               dayNamesMin: ['日','月','火','水','木','金','土'],
-               weekHeader: '週',
-               dateFormat: 'yy/mm/dd',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: true,
-               yearSuffix: '年'};
-       $.datepicker.setDefaults($.datepicker.regional['ja']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-ka.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-ka.js
deleted file mode 100644 (file)
index c10658d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Georgian (UTF-8) initialisation for the jQuery UI date picker plugin. */
-/* Written by Lado Lomidze (lado.lomidze@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['ka'] = {
-               closeText: 'დახურვა',
-               prevText: '&#x3c; წინა',
-               nextText: 'შემდეგი &#x3e;',
-               currentText: 'დღეს',
-               monthNames: ['იანვარი','თებერვალი','მარტი','აპრილი','მაისი','ივნისი', 'ივლისი','აგვისტო','სექტემბერი','ოქტომბერი','ნოემბერი','დეკემბერი'],
-               monthNamesShort: ['იან','თებ','მარ','აპრ','მაი','ივნ', 'ივლ','აგვ','სექ','ოქტ','ნოე','დეკ'],
-               dayNames: ['კვირა','ორშაბათი','სამშაბათი','ოთხშაბათი','ხუთშაბათი','პარასკევი','შაბათი'],
-               dayNamesShort: ['კვ','ორშ','სამ','ოთხ','ხუთ','პარ','შაბ'],
-               dayNamesMin: ['კვ','ორშ','სამ','ოთხ','ხუთ','პარ','შაბ'],
-               weekHeader: 'კვირა',
-               dateFormat: 'dd-mm-yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['ka']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-kk.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-kk.js
deleted file mode 100644 (file)
index 79e3f24..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Kazakh (UTF-8) initialisation for the jQuery UI date picker plugin. */
-/* Written by Dmitriy Karasyov (dmitriy.karasyov@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['kk'] = {
-               closeText: 'Жабу',
-               prevText: '&#x3c;Алдыңғы',
-               nextText: 'Келесі&#x3e;',
-               currentText: 'Бүгін',
-               monthNames: ['Қаңтар','Ақпан','Наурыз','Сәуір','Мамыр','Маусым',
-               'Шілде','Тамыз','Қыркүйек','Қазан','Қараша','Желтоқсан'],
-               monthNamesShort: ['Қаң','Ақп','Нау','Сәу','Мам','Мау',
-               'Шіл','Там','Қыр','Қаз','Қар','Жел'],
-               dayNames: ['Жексенбі','Дүйсенбі','Сейсенбі','Сәрсенбі','Бейсенбі','Жұма','Сенбі'],
-               dayNamesShort: ['жкс','дсн','ссн','срс','бсн','жма','снб'],
-               dayNamesMin: ['Жк','Дс','Сс','Ср','Бс','Жм','Сн'],
-               weekHeader: 'Не',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['kk']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-km.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-km.js
deleted file mode 100644 (file)
index f9c4e3a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Khmer initialisation for the jQuery calendar extension. */
-/* Written by Chandara Om (chandara.teacher@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['km'] = {
-               closeText: 'ធ្វើ​រួច',
-               prevText: 'មុន',
-               nextText: 'បន្ទាប់',
-               currentText: 'ថ្ងៃ​នេះ',
-               monthNames: ['មករា','កុម្ភៈ','មីនា','មេសា','ឧសភា','មិថុនា',
-               'កក្កដា','សីហា','កញ្ញា','តុលា','វិច្ឆិកា','ធ្នូ'],
-               monthNamesShort: ['មករា','កុម្ភៈ','មីនា','មេសា','ឧសភា','មិថុនា',
-               'កក្កដា','សីហា','កញ្ញា','តុលា','វិច្ឆិកា','ធ្នូ'],
-               dayNames: ['អាទិត្យ', 'ចន្ទ', 'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ', 'សៅរ៍'],
-               dayNamesShort: ['អា', 'ច', 'អ', 'ពុ', 'ព្រហ', 'សុ', 'សៅ'],
-               dayNamesMin: ['អា', 'ច', 'អ', 'ពុ', 'ព្រហ', 'សុ', 'សៅ'],
-               weekHeader: 'សប្ដាហ៍',
-               dateFormat: 'dd-mm-yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['km']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-ko.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-ko.js
deleted file mode 100644 (file)
index 0411242..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Korean initialisation for the jQuery calendar extension. */
-/* Written by DaeKwon Kang (ncrash.dk@gmail.com), Edited by Genie. */
-jQuery(function($){
-       $.datepicker.regional['ko'] = {
-               closeText: '닫기',
-               prevText: '이전달',
-               nextText: '다음달',
-               currentText: '오늘',
-               monthNames: ['1월','2월','3월','4월','5월','6월',
-               '7월','8월','9월','10월','11월','12월'],
-               monthNamesShort: ['1월','2월','3월','4월','5월','6월',
-               '7월','8월','9월','10월','11월','12월'],
-               dayNames: ['일요일','월요일','화요일','수요일','목요일','금요일','토요일'],
-               dayNamesShort: ['일','월','화','수','목','금','토'],
-               dayNamesMin: ['일','월','화','수','목','금','토'],
-               weekHeader: 'Wk',
-               dateFormat: 'yy-mm-dd',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: true,
-               yearSuffix: '년'};
-       $.datepicker.setDefaults($.datepicker.regional['ko']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-lb.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-lb.js
deleted file mode 100644 (file)
index 87c79d5..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Luxembourgish initialisation for the jQuery UI date picker plugin. */
-/* Written by Michel Weimerskirch <michel@weimerskirch.net> */
-jQuery(function($){
-       $.datepicker.regional['lb'] = {
-               closeText: 'Fäerdeg',
-               prevText: 'Zréck',
-               nextText: 'Weider',
-               currentText: 'Haut',
-               monthNames: ['Januar','Februar','Mäerz','Abrëll','Mee','Juni',
-               'Juli','August','September','Oktober','November','Dezember'],
-               monthNamesShort: ['Jan', 'Feb', 'Mäe', 'Abr', 'Mee', 'Jun',
-               'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
-               dayNames: ['Sonndeg', 'Méindeg', 'Dënschdeg', 'Mëttwoch', 'Donneschdeg', 'Freideg', 'Samschdeg'],
-               dayNamesShort: ['Son', 'Méi', 'Dën', 'Mët', 'Don', 'Fre', 'Sam'],
-               dayNamesMin: ['So','Mé','Dë','Më','Do','Fr','Sa'],
-               weekHeader: 'W',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['lb']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-lt.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-lt.js
deleted file mode 100644 (file)
index 67d5119..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Lithuanian (UTF-8) initialisation for the jQuery UI date picker plugin. */
-/* @author Arturas Paleicikas <arturas@avalon.lt> */
-jQuery(function($){
-       $.datepicker.regional['lt'] = {
-               closeText: 'Uždaryti',
-               prevText: '&#x3c;Atgal',
-               nextText: 'Pirmyn&#x3e;',
-               currentText: 'Šiandien',
-               monthNames: ['Sausis','Vasaris','Kovas','Balandis','Gegužė','Birželis',
-               'Liepa','Rugpjūtis','Rugsėjis','Spalis','Lapkritis','Gruodis'],
-               monthNamesShort: ['Sau','Vas','Kov','Bal','Geg','Bir',
-               'Lie','Rugp','Rugs','Spa','Lap','Gru'],
-               dayNames: ['sekmadienis','pirmadienis','antradienis','trečiadienis','ketvirtadienis','penktadienis','šeštadienis'],
-               dayNamesShort: ['sek','pir','ant','tre','ket','pen','šeš'],
-               dayNamesMin: ['Se','Pr','An','Tr','Ke','Pe','Še'],
-               weekHeader: 'Wk',
-               dateFormat: 'yy-mm-dd',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['lt']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-lv.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-lv.js
deleted file mode 100644 (file)
index 003934e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Latvian (UTF-8) initialisation for the jQuery UI date picker plugin. */
-/* @author Arturas Paleicikas <arturas.paleicikas@metasite.net> */
-jQuery(function($){
-       $.datepicker.regional['lv'] = {
-               closeText: 'Aizvērt',
-               prevText: 'Iepr',
-               nextText: 'Nāka',
-               currentText: 'Šodien',
-               monthNames: ['Janvāris','Februāris','Marts','Aprīlis','Maijs','Jūnijs',
-               'Jūlijs','Augusts','Septembris','Oktobris','Novembris','Decembris'],
-               monthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jūn',
-               'Jūl','Aug','Sep','Okt','Nov','Dec'],
-               dayNames: ['svētdiena','pirmdiena','otrdiena','trešdiena','ceturtdiena','piektdiena','sestdiena'],
-               dayNamesShort: ['svt','prm','otr','tre','ctr','pkt','sst'],
-               dayNamesMin: ['Sv','Pr','Ot','Tr','Ct','Pk','Ss'],
-               weekHeader: 'Nav',
-               dateFormat: 'dd-mm-yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['lv']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-mk.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-mk.js
deleted file mode 100644 (file)
index 0285325..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Macedonian i18n for the jQuery UI date picker plugin. */
-/* Written by Stojce Slavkovski. */
-jQuery(function($){
-       $.datepicker.regional['mk'] = {
-               closeText: 'Затвори',
-               prevText: '&#x3C;',
-               nextText: '&#x3E;',
-               currentText: 'Денес',
-               monthNames: ['Јануари','Февруари','Март','Април','Мај','Јуни',
-               'Јули','Август','Септември','Октомври','Ноември','Декември'],
-               monthNamesShort: ['Јан','Фев','Мар','Апр','Мај','Јун',
-               'Јул','Авг','Сеп','Окт','Ное','Дек'],
-               dayNames: ['Недела','Понеделник','Вторник','Среда','Четврток','Петок','Сабота'],
-               dayNamesShort: ['Нед','Пон','Вто','Сре','Чет','Пет','Саб'],
-               dayNamesMin: ['Не','По','Вт','Ср','Че','Пе','Са'],
-               weekHeader: 'Сед',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['mk']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-ml.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-ml.js
deleted file mode 100644 (file)
index 1e3432c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Malayalam (UTF-8) initialisation for the jQuery UI date picker plugin. */
-/* Written by Saji Nediyanchath (saji89@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['ml'] = {
-               closeText: 'ശരി',
-               prevText: 'മുന്നത്തെ',  
-               nextText: 'അടുത്തത് ',
-               currentText: 'ഇന്ന്',
-               monthNames: ['ജനുവരി','ഫെബ്രുവരി','മാര്‍ച്ച്','ഏപ്രില്‍','മേയ്','ജൂണ്‍',
-               'ജൂലൈ','ആഗസ്റ്റ്','സെപ്റ്റംബര്‍','ഒക്ടോബര്‍','നവംബര്‍','ഡിസംബര്‍'],
-               monthNamesShort: ['ജനു', 'ഫെബ്', 'മാര്‍', 'ഏപ്രി', 'മേയ്', 'ജൂണ്‍',
-               'ജൂലാ', 'ആഗ', 'സെപ്', 'ഒക്ടോ', 'നവം', 'ഡിസ'],
-               dayNames: ['ഞായര്‍', 'തിങ്കള്‍', 'ചൊവ്വ', 'ബുധന്‍', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],
-               dayNamesShort: ['ഞായ', 'തിങ്ക', 'ചൊവ്വ', 'ബുധ', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],
-               dayNamesMin: ['ഞാ','തി','ചൊ','ബു','വ്യാ','വെ','ശ'],
-               weekHeader: 'ആ',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['ml']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-ms.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-ms.js
deleted file mode 100644 (file)
index e953ac0..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Malaysian initialisation for the jQuery UI date picker plugin. */
-/* Written by Mohd Nawawi Mohamad Jamili (nawawi@ronggeng.net). */
-jQuery(function($){
-       $.datepicker.regional['ms'] = {
-               closeText: 'Tutup',
-               prevText: '&#x3c;Sebelum',
-               nextText: 'Selepas&#x3e;',
-               currentText: 'hari ini',
-               monthNames: ['Januari','Februari','Mac','April','Mei','Jun',
-               'Julai','Ogos','September','Oktober','November','Disember'],
-               monthNamesShort: ['Jan','Feb','Mac','Apr','Mei','Jun',
-               'Jul','Ogo','Sep','Okt','Nov','Dis'],
-               dayNames: ['Ahad','Isnin','Selasa','Rabu','Khamis','Jumaat','Sabtu'],
-               dayNamesShort: ['Aha','Isn','Sel','Rab','kha','Jum','Sab'],
-               dayNamesMin: ['Ah','Is','Se','Ra','Kh','Ju','Sa'],
-               weekHeader: 'Mg',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['ms']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-nl.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-nl.js
deleted file mode 100644 (file)
index 781fe61..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */
-/* Written by Mathias Bynens <http://mathiasbynens.be/> */
-jQuery(function($){
-       $.datepicker.regional.nl = {
-               closeText: 'Sluiten',
-               prevText: '←',
-               nextText: '→',
-               currentText: 'Vandaag',
-               monthNames: ['januari', 'februari', 'maart', 'april', 'mei', 'juni',
-               'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
-               monthNamesShort: ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun',
-               'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
-               dayNames: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
-               dayNamesShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'],
-               dayNamesMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
-               weekHeader: 'Wk',
-               dateFormat: 'dd-mm-yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional.nl);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-no.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-no.js
deleted file mode 100644 (file)
index 2507043..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Norwegian initialisation for the jQuery UI date picker plugin. */
-/* Written by Naimdjon Takhirov (naimdjon@gmail.com). */
-
-jQuery(function($){
-  $.datepicker.regional['no'] = {
-    closeText: 'Lukk',
-    prevText: '&laquo;Forrige',
-    nextText: 'Neste&raquo;',
-    currentText: 'I dag',
-    monthNames: ['januar','februar','mars','april','mai','juni','juli','august','september','oktober','november','desember'],
-    monthNamesShort: ['jan','feb','mar','apr','mai','jun','jul','aug','sep','okt','nov','des'],
-    dayNamesShort: ['søn','man','tir','ons','tor','fre','lør'],
-    dayNames: ['søndag','mandag','tirsdag','onsdag','torsdag','fredag','lørdag'],
-    dayNamesMin: ['sø','ma','ti','on','to','fr','lø'],
-    weekHeader: 'Uke',
-    dateFormat: 'dd.mm.yy',
-    firstDay: 1,
-    isRTL: false,
-    showMonthAfterYear: false,
-    yearSuffix: ''
-  };
-  $.datepicker.setDefaults($.datepicker.regional['no']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-pl.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-pl.js
deleted file mode 100644 (file)
index 61fa29c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Polish initialisation for the jQuery UI date picker plugin. */
-/* Written by Jacek Wysocki (jacek.wysocki@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['pl'] = {
-               closeText: 'Zamknij',
-               prevText: '&#x3c;Poprzedni',
-               nextText: 'Następny&#x3e;',
-               currentText: 'Dziś',
-               monthNames: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec',
-               'Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],
-               monthNamesShort: ['Sty','Lu','Mar','Kw','Maj','Cze',
-               'Lip','Sie','Wrz','Pa','Lis','Gru'],
-               dayNames: ['Niedziela','Poniedziałek','Wtorek','Środa','Czwartek','Piątek','Sobota'],
-               dayNamesShort: ['Nie','Pn','Wt','Śr','Czw','Pt','So'],
-               dayNamesMin: ['N','Pn','Wt','Śr','Cz','Pt','So'],
-               weekHeader: 'Tydz',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['pl']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js
deleted file mode 100644 (file)
index 3cc8c79..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Brazilian initialisation for the jQuery UI date picker plugin. */
-/* Written by Leonildo Costa Silva (leocsilva@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['pt-BR'] = {
-               closeText: 'Fechar',
-               prevText: '&#x3c;Anterior',
-               nextText: 'Pr&oacute;ximo&#x3e;',
-               currentText: 'Hoje',
-               monthNames: ['Janeiro','Fevereiro','Mar&ccedil;o','Abril','Maio','Junho',
-               'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
-               monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',
-               'Jul','Ago','Set','Out','Nov','Dez'],
-               dayNames: ['Domingo','Segunda-feira','Ter&ccedil;a-feira','Quarta-feira','Quinta-feira','Sexta-feira','S&aacute;bado'],
-               dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
-               dayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
-               weekHeader: 'Sm',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['pt-BR']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-pt.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-pt.js
deleted file mode 100644 (file)
index f09f5ae..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Portuguese initialisation for the jQuery UI date picker plugin. */
-jQuery(function($){
-       $.datepicker.regional['pt'] = {
-               closeText: 'Fechar',
-               prevText: '&#x3c;Anterior',
-               nextText: 'Seguinte',
-               currentText: 'Hoje',
-               monthNames: ['Janeiro','Fevereiro','Mar&ccedil;o','Abril','Maio','Junho',
-               'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
-               monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',
-               'Jul','Ago','Set','Out','Nov','Dez'],
-               dayNames: ['Domingo','Segunda-feira','Ter&ccedil;a-feira','Quarta-feira','Quinta-feira','Sexta-feira','S&aacute;bado'],
-               dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
-               dayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
-               weekHeader: 'Sem',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['pt']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-rm.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-rm.js
deleted file mode 100644 (file)
index cf03cd4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Romansh initialisation for the jQuery UI date picker plugin. */
-/* Written by Yvonne Gienal (yvonne.gienal@educa.ch). */
-jQuery(function($){
-       $.datepicker.regional['rm'] = {
-               closeText: 'Serrar',
-               prevText: '&#x3c;Suandant',
-               nextText: 'Precedent&#x3e;',
-               currentText: 'Actual',
-               monthNames: ['Schaner','Favrer','Mars','Avrigl','Matg','Zercladur', 'Fanadur','Avust','Settember','October','November','December'],
-               monthNamesShort: ['Scha','Fev','Mar','Avr','Matg','Zer', 'Fan','Avu','Sett','Oct','Nov','Dec'],
-               dayNames: ['Dumengia','Glindesdi','Mardi','Mesemna','Gievgia','Venderdi','Sonda'],
-               dayNamesShort: ['Dum','Gli','Mar','Mes','Gie','Ven','Som'],
-               dayNamesMin: ['Du','Gl','Ma','Me','Gi','Ve','So'],
-               weekHeader: 'emna',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['rm']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-ro.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-ro.js
deleted file mode 100644 (file)
index 6b140af..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Romanian initialisation for the jQuery UI date picker plugin.
- *
- * Written by Edmond L. (ll_edmond@walla.com)
- * and Ionut G. Stan (ionut.g.stan@gmail.com)
- */
-jQuery(function($){
-       $.datepicker.regional['ro'] = {
-               closeText: 'Închide',
-               prevText: '&laquo; Luna precedentă',
-               nextText: 'Luna următoare &raquo;',
-               currentText: 'Azi',
-               monthNames: ['Ianuarie','Februarie','Martie','Aprilie','Mai','Iunie',
-               'Iulie','August','Septembrie','Octombrie','Noiembrie','Decembrie'],
-               monthNamesShort: ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun',
-               'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
-               dayNames: ['Duminică', 'Luni', 'Marţi', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'],
-               dayNamesShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
-               dayNamesMin: ['Du','Lu','Ma','Mi','Jo','Vi','Sâ'],
-               weekHeader: 'Săpt',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['ro']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-ru.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-ru.js
deleted file mode 100644 (file)
index 50a4613..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Russian (UTF-8) initialisation for the jQuery UI date picker plugin. */
-/* Written by Andrew Stromnov (stromnov@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['ru'] = {
-               closeText: 'Закрыть',
-               prevText: '&#x3c;Пред',
-               nextText: 'След&#x3e;',
-               currentText: 'Сегодня',
-               monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь',
-               'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],
-               monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн',
-               'Июл','Авг','Сен','Окт','Ноя','Дек'],
-               dayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'],
-               dayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'],
-               dayNamesMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'],
-               weekHeader: 'Нед',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['ru']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-sk.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-sk.js
deleted file mode 100644 (file)
index 078d1b0..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Slovak initialisation for the jQuery UI date picker plugin. */
-/* Written by Vojtech Rinik (vojto@hmm.sk). */
-jQuery(function($){
-       $.datepicker.regional['sk'] = {
-               closeText: 'Zavrieť',
-               prevText: '&#x3c;Predchádzajúci',
-               nextText: 'Nasledujúci&#x3e;',
-               currentText: 'Dnes',
-               monthNames: ['Január','Február','Marec','Apríl','Máj','Jún',
-               'Júl','August','September','Október','November','December'],
-               monthNamesShort: ['Jan','Feb','Mar','Apr','Máj','Jún',
-               'Júl','Aug','Sep','Okt','Nov','Dec'],
-               dayNames: ['Nedeľa','Pondelok','Utorok','Streda','Štvrtok','Piatok','Sobota'],
-               dayNamesShort: ['Ned','Pon','Uto','Str','Štv','Pia','Sob'],
-               dayNamesMin: ['Ne','Po','Ut','St','Št','Pia','So'],
-               weekHeader: 'Ty',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['sk']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-sl.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-sl.js
deleted file mode 100644 (file)
index 5165501..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Slovenian initialisation for the jQuery UI date picker plugin. */
-/* Written by Jaka Jancar (jaka@kubje.org). */
-/* c = &#x10D;, s = &#x161; z = &#x17E; C = &#x10C; S = &#x160; Z = &#x17D; */
-jQuery(function($){
-       $.datepicker.regional['sl'] = {
-               closeText: 'Zapri',
-               prevText: '&lt;Prej&#x161;nji',
-               nextText: 'Naslednji&gt;',
-               currentText: 'Trenutni',
-               monthNames: ['Januar','Februar','Marec','April','Maj','Junij',
-               'Julij','Avgust','September','Oktober','November','December'],
-               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
-               'Jul','Avg','Sep','Okt','Nov','Dec'],
-               dayNames: ['Nedelja','Ponedeljek','Torek','Sreda','&#x10C;etrtek','Petek','Sobota'],
-               dayNamesShort: ['Ned','Pon','Tor','Sre','&#x10C;et','Pet','Sob'],
-               dayNamesMin: ['Ne','Po','To','Sr','&#x10C;e','Pe','So'],
-               weekHeader: 'Teden',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['sl']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-sq.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-sq.js
deleted file mode 100644 (file)
index 21974c5..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Albanian initialisation for the jQuery UI date picker plugin. */
-/* Written by Flakron Bytyqi (flakron@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['sq'] = {
-               closeText: 'mbylle',
-               prevText: '&#x3c;mbrapa',
-               nextText: 'Përpara&#x3e;',
-               currentText: 'sot',
-               monthNames: ['Janar','Shkurt','Mars','Prill','Maj','Qershor',
-               'Korrik','Gusht','Shtator','Tetor','Nëntor','Dhjetor'],
-               monthNamesShort: ['Jan','Shk','Mar','Pri','Maj','Qer',
-               'Kor','Gus','Sht','Tet','Nën','Dhj'],
-               dayNames: ['E Diel','E Hënë','E Martë','E Mërkurë','E Enjte','E Premte','E Shtune'],
-               dayNamesShort: ['Di','Hë','Ma','Më','En','Pr','Sh'],
-               dayNamesMin: ['Di','Hë','Ma','Më','En','Pr','Sh'],
-               weekHeader: 'Ja',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['sq']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js
deleted file mode 100644 (file)
index e7a8683..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Serbian i18n for the jQuery UI date picker plugin. */
-/* Written by Dejan Dimić. */
-jQuery(function($){
-       $.datepicker.regional['sr-SR'] = {
-               closeText: 'Zatvori',
-               prevText: '&#x3c;',
-               nextText: '&#x3e;',
-               currentText: 'Danas',
-               monthNames: ['Januar','Februar','Mart','April','Maj','Jun',
-               'Jul','Avgust','Septembar','Oktobar','Novembar','Decembar'],
-               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
-               'Jul','Avg','Sep','Okt','Nov','Dec'],
-               dayNames: ['Nedelja','Ponedeljak','Utorak','Sreda','Četvrtak','Petak','Subota'],
-               dayNamesShort: ['Ned','Pon','Uto','Sre','Čet','Pet','Sub'],
-               dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
-               weekHeader: 'Sed',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['sr-SR']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-sr.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-sr.js
deleted file mode 100644 (file)
index 0bd240e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Serbian i18n for the jQuery UI date picker plugin. */
-/* Written by Dejan Dimić. */
-jQuery(function($){
-       $.datepicker.regional['sr'] = {
-               closeText: 'Затвори',
-               prevText: '&#x3c;',
-               nextText: '&#x3e;',
-               currentText: 'Данас',
-               monthNames: ['Јануар','Фебруар','Март','Април','Мај','Јун',
-               'Јул','Август','Септембар','Октобар','Новембар','Децембар'],
-               monthNamesShort: ['Јан','Феб','Мар','Апр','Мај','Јун',
-               'Јул','Авг','Сеп','Окт','Нов','Дец'],
-               dayNames: ['Недеља','Понедељак','Уторак','Среда','Четвртак','Петак','Субота'],
-               dayNamesShort: ['Нед','Пон','Уто','Сре','Чет','Пет','Суб'],
-               dayNamesMin: ['Не','По','Ут','Ср','Че','Пе','Су'],
-               weekHeader: 'Сед',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['sr']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-sv.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-sv.js
deleted file mode 100644 (file)
index e5f549f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Swedish initialisation for the jQuery UI date picker plugin. */
-/* Written by Anders Ekdahl ( anders@nomadiz.se). */
-jQuery(function($){
-    $.datepicker.regional['sv'] = {
-               closeText: 'Stäng',
-        prevText: '&laquo;Förra',
-               nextText: 'Nästa&raquo;',
-               currentText: 'Idag',
-        monthNames: ['Januari','Februari','Mars','April','Maj','Juni',
-        'Juli','Augusti','September','Oktober','November','December'],
-        monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
-        'Jul','Aug','Sep','Okt','Nov','Dec'],
-               dayNamesShort: ['Sön','Mån','Tis','Ons','Tor','Fre','Lör'],
-               dayNames: ['Söndag','Måndag','Tisdag','Onsdag','Torsdag','Fredag','Lördag'],
-               dayNamesMin: ['Sö','Må','Ti','On','To','Fr','Lö'],
-               weekHeader: 'Ve',
-        dateFormat: 'yy-mm-dd',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-    $.datepicker.setDefaults($.datepicker.regional['sv']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-ta.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-ta.js
deleted file mode 100644 (file)
index 40431ed..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Tamil (UTF-8) initialisation for the jQuery UI date picker plugin. */
-/* Written by S A Sureshkumar (saskumar@live.com). */
-jQuery(function($){
-       $.datepicker.regional['ta'] = {
-               closeText: 'மூடு',
-               prevText: 'முன்னையது',
-               nextText: 'அடுத்தது',
-               currentText: 'இன்று',
-               monthNames: ['தை','மாசி','பங்குனி','சித்திரை','வைகாசி','ஆனி',
-               'ஆடி','ஆவணி','புரட்டாசி','ஐப்பசி','கார்த்திகை','மார்கழி'],
-               monthNamesShort: ['தை','மாசி','பங்','சித்','வைகா','ஆனி',
-               'ஆடி','ஆவ','புர','ஐப்','கார்','மார்'],
-               dayNames: ['ஞாயிற்றுக்கிழமை','திங்கட்கிழமை','செவ்வாய்க்கிழமை','புதன்கிழமை','வியாழக்கிழமை','வெள்ளிக்கிழமை','சனிக்கிழமை'],
-               dayNamesShort: ['ஞாயிறு','திங்கள்','செவ்வாய்','புதன்','வியாழன்','வெள்ளி','சனி'],
-               dayNamesMin: ['ஞா','தி','செ','பு','வி','வெ','ச'],
-               weekHeader: 'Не',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['ta']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-th.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-th.js
deleted file mode 100644 (file)
index 2e5300c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Thai initialisation for the jQuery UI date picker plugin. */
-/* Written by pipo (pipo@sixhead.com). */
-jQuery(function($){
-       $.datepicker.regional['th'] = {
-               closeText: 'ปิด',
-               prevText: '&laquo;&nbsp;ย้อน',
-               nextText: 'ถัดไป&nbsp;&raquo;',
-               currentText: 'วันนี้',
-               monthNames: ['มกราคม','กุมภาพันธ์','มีนาคม','เมษายน','พฤษภาคม','มิถุนายน',
-               'กรกฎาคม','สิงหาคม','กันยายน','ตุลาคม','พฤศจิกายน','ธันวาคม'],
-               monthNamesShort: ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.',
-               'ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'],
-               dayNames: ['อาทิตย์','จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์','เสาร์'],
-               dayNamesShort: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],
-               dayNamesMin: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],
-               weekHeader: 'Wk',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['th']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-tr.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-tr.js
deleted file mode 100644 (file)
index dedfc7f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Turkish initialisation for the jQuery UI date picker plugin. */
-/* Written by Izzet Emre Erkan (kara@karalamalar.net). */
-jQuery(function($){
-       $.datepicker.regional['tr'] = {
-               closeText: 'kapat',
-               prevText: '&#x3c;geri',
-               nextText: 'ileri&#x3e',
-               currentText: 'bugün',
-               monthNames: ['Ocak','Şubat','Mart','Nisan','Mayıs','Haziran',
-               'Temmuz','Ağustos','Eylül','Ekim','Kasım','Aralık'],
-               monthNamesShort: ['Oca','Şub','Mar','Nis','May','Haz',
-               'Tem','Ağu','Eyl','Eki','Kas','Ara'],
-               dayNames: ['Pazar','Pazartesi','Salı','Çarşamba','Perşembe','Cuma','Cumartesi'],
-               dayNamesShort: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],
-               dayNamesMin: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],
-               weekHeader: 'Hf',
-               dateFormat: 'dd.mm.yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['tr']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-uk.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-uk.js
deleted file mode 100644 (file)
index 2718f5d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Ukrainian (UTF-8) initialisation for the jQuery UI date picker plugin. */
-/* Written by Maxim Drogobitskiy (maxdao@gmail.com). */
-/* Corrected by Igor Milla (igor.fsp.milla@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['uk'] = {
-               closeText: 'Закрити',
-               prevText: '&#x3c;',
-               nextText: '&#x3e;',
-               currentText: 'Сьогодні',
-               monthNames: ['Січень','Лютий','Березень','Квітень','Травень','Червень',
-               'Липень','Серпень','Вересень','Жовтень','Листопад','Грудень'],
-               monthNamesShort: ['Січ','Лют','Бер','Кві','Тра','Чер',
-               'Лип','Сер','Вер','Жов','Лис','Гру'],
-               dayNames: ['неділя','понеділок','вівторок','середа','четвер','п’ятниця','субота'],
-               dayNamesShort: ['нед','пнд','вів','срд','чтв','птн','сбт'],
-               dayNamesMin: ['Нд','Пн','Вт','Ср','Чт','Пт','Сб'],
-               weekHeader: 'Тиж',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['uk']);
-});
\ No newline at end of file
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-vi.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-vi.js
deleted file mode 100644 (file)
index 1d8f7bb..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Vietnamese initialisation for the jQuery UI date picker plugin. */
-/* Translated by Le Thanh Huy (lthanhhuy@cit.ctu.edu.vn). */
-jQuery(function($){
-       $.datepicker.regional['vi'] = {
-               closeText: 'Đóng',
-               prevText: '&#x3c;Trước',
-               nextText: 'Tiếp&#x3e;',
-               currentText: 'Hôm nay',
-               monthNames: ['Tháng Một', 'Tháng Hai', 'Tháng Ba', 'Tháng Tư', 'Tháng Năm', 'Tháng Sáu',
-               'Tháng Bảy', 'Tháng Tám', 'Tháng Chín', 'Tháng Mười', 'Tháng Mười Một', 'Tháng Mười Hai'],
-               monthNamesShort: ['Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5', 'Tháng 6',
-               'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11', 'Tháng 12'],
-               dayNames: ['Chủ Nhật', 'Thứ Hai', 'Thứ Ba', 'Thứ Tư', 'Thứ Năm', 'Thứ Sáu', 'Thứ Bảy'],
-               dayNamesShort: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
-               dayNamesMin: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
-               weekHeader: 'Tu',
-               dateFormat: 'dd/mm/yy',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: false,
-               yearSuffix: ''};
-       $.datepicker.setDefaults($.datepicker.regional['vi']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js
deleted file mode 100644 (file)
index 83f2825..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Chinese initialisation for the jQuery UI date picker plugin. */
-/* Written by Cloudream (cloudream@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['zh-CN'] = {
-               closeText: '关闭',
-               prevText: '&#x3c;上月',
-               nextText: '下月&#x3e;',
-               currentText: '今天',
-               monthNames: ['一月','二月','三月','四月','五月','六月',
-               '七月','八月','九月','十月','十一月','十二月'],
-               monthNamesShort: ['一月','二月','三月','四月','五月','六月',
-               '七月','八月','九月','十月','十一月','十二月'],
-               dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
-               dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
-               dayNamesMin: ['日','一','二','三','四','五','六'],
-               weekHeader: '周',
-               dateFormat: 'yy-mm-dd',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: true,
-               yearSuffix: '年'};
-       $.datepicker.setDefaults($.datepicker.regional['zh-CN']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js
deleted file mode 100644 (file)
index 11189d3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Chinese initialisation for the jQuery UI date picker plugin. */
-/* Written by SCCY (samuelcychan@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['zh-HK'] = {
-               closeText: '關閉',
-               prevText: '&#x3c;上月',
-               nextText: '下月&#x3e;',
-               currentText: '今天',
-               monthNames: ['一月','二月','三月','四月','五月','六月',
-               '七月','八月','九月','十月','十一月','十二月'],
-               monthNamesShort: ['一月','二月','三月','四月','五月','六月',
-               '七月','八月','九月','十月','十一月','十二月'],
-               dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
-               dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
-               dayNamesMin: ['日','一','二','三','四','五','六'],
-               weekHeader: '周',
-               dateFormat: 'dd-mm-yy',
-               firstDay: 0,
-               isRTL: false,
-               showMonthAfterYear: true,
-               yearSuffix: '年'};
-       $.datepicker.setDefaults($.datepicker.regional['zh-HK']);
-});
diff --git a/resources/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js b/resources/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js
deleted file mode 100644 (file)
index 089498b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Chinese initialisation for the jQuery UI date picker plugin. */
-/* Written by Ressol (ressol@gmail.com). */
-jQuery(function($){
-       $.datepicker.regional['zh-TW'] = {
-               closeText: '關閉',
-               prevText: '&#x3c;上月',
-               nextText: '下月&#x3e;',
-               currentText: '今天',
-               monthNames: ['一月','二月','三月','四月','五月','六月',
-               '七月','八月','九月','十月','十一月','十二月'],
-               monthNamesShort: ['一月','二月','三月','四月','五月','六月',
-               '七月','八月','九月','十月','十一月','十二月'],
-               dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
-               dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
-               dayNamesMin: ['日','一','二','三','四','五','六'],
-               weekHeader: '周',
-               dateFormat: 'yy/mm/dd',
-               firstDay: 1,
-               isRTL: false,
-               showMonthAfterYear: true,
-               yearSuffix: '年'};
-       $.datepicker.setDefaults($.datepicker.regional['zh-TW']);
-});
diff --git a/resources/jquery.ui/jquery.ui.accordion.js b/resources/jquery.ui/jquery.ui.accordion.js
deleted file mode 100644 (file)
index dc1ba60..0000000
+++ /dev/null
@@ -1,611 +0,0 @@
-/*!
- * jQuery UI Accordion 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Accordion
- *
- * Depends:
- *     jquery.ui.core.js
- *     jquery.ui.widget.js
- */
-(function( $, undefined ) {
-
-$.widget( "ui.accordion", {
-       options: {
-               active: 0,
-               animated: "slide",
-               autoHeight: true,
-               clearStyle: false,
-               collapsible: false,
-               event: "click",
-               fillSpace: false,
-               header: "> li > :first-child,> :not(li):even",
-               icons: {
-                       header: "ui-icon-triangle-1-e",
-                       headerSelected: "ui-icon-triangle-1-s"
-               },
-               navigation: false,
-               navigationFilter: function() {
-                       return this.href.toLowerCase() === location.href.toLowerCase();
-               }
-       },
-
-       _create: function() {
-               var self = this,
-                       options = self.options;
-
-               self.running = 0;
-
-               self.element
-                       .addClass( "ui-accordion ui-widget ui-helper-reset" )
-                       // in lack of child-selectors in CSS
-                       // we need to mark top-LIs in a UL-accordion for some IE-fix
-                       .children( "li" )
-                               .addClass( "ui-accordion-li-fix" );
-
-               self.headers = self.element.find( options.header )
-                       .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
-                       .bind( "mouseenter.accordion", function() {
-                               if ( options.disabled ) {
-                                       return;
-                               }
-                               $( this ).addClass( "ui-state-hover" );
-                       })
-                       .bind( "mouseleave.accordion", function() {
-                               if ( options.disabled ) {
-                                       return;
-                               }
-                               $( this ).removeClass( "ui-state-hover" );
-                       })
-                       .bind( "focus.accordion", function() {
-                               if ( options.disabled ) {
-                                       return;
-                               }
-                               $( this ).addClass( "ui-state-focus" );
-                       })
-                       .bind( "blur.accordion", function() {
-                               if ( options.disabled ) {
-                                       return;
-                               }
-                               $( this ).removeClass( "ui-state-focus" );
-                       });
-
-               self.headers.next()
-                       .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
-
-               if ( options.navigation ) {
-                       var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
-                       if ( current.length ) {
-                               var header = current.closest( ".ui-accordion-header" );
-                               if ( header.length ) {
-                                       // anchor within header
-                                       self.active = header;
-                               } else {
-                                       // anchor within content
-                                       self.active = current.closest( ".ui-accordion-content" ).prev();
-                               }
-                       }
-               }
-
-               self.active = self._findActive( self.active || options.active )
-                       .addClass( "ui-state-default ui-state-active" )
-                       .toggleClass( "ui-corner-all" )
-                       .toggleClass( "ui-corner-top" );
-               self.active.next().addClass( "ui-accordion-content-active" );
-
-               self._createIcons();
-               self.resize();
-               
-               // ARIA
-               self.element.attr( "role", "tablist" );
-
-               self.headers
-                       .attr( "role", "tab" )
-                       .bind( "keydown.accordion", function( event ) {
-                               return self._keydown( event );
-                       })
-                       .next()
-                               .attr( "role", "tabpanel" );
-
-               self.headers
-                       .not( self.active || "" )
-                       .attr({
-                               "aria-expanded": "false",
-                               "aria-selected": "false",
-                               tabIndex: -1
-                       })
-                       .next()
-                               .hide();
-
-               // make sure at least one header is in the tab order
-               if ( !self.active.length ) {
-                       self.headers.eq( 0 ).attr( "tabIndex", 0 );
-               } else {
-                       self.active
-                               .attr({
-                                       "aria-expanded": "true",
-                                       "aria-selected": "true",
-                                       tabIndex: 0
-                               });
-               }
-
-               // only need links in tab order for Safari
-               if ( !$.browser.safari ) {
-                       self.headers.find( "a" ).attr( "tabIndex", -1 );
-               }
-
-               if ( options.event ) {
-                       self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
-                               self._clickHandler.call( self, event, this );
-                               event.preventDefault();
-                       });
-               }
-       },
-
-       _createIcons: function() {
-               var options = this.options;
-               if ( options.icons ) {
-                       $( "<span></span>" )
-                               .addClass( "ui-icon " + options.icons.header )
-                               .prependTo( this.headers );
-                       this.active.children( ".ui-icon" )
-                               .toggleClass(options.icons.header)
-                               .toggleClass(options.icons.headerSelected);
-                       this.element.addClass( "ui-accordion-icons" );
-               }
-       },
-
-       _destroyIcons: function() {
-               this.headers.children( ".ui-icon" ).remove();
-               this.element.removeClass( "ui-accordion-icons" );
-       },
-
-       destroy: function() {
-               var options = this.options;
-
-               this.element
-                       .removeClass( "ui-accordion ui-widget ui-helper-reset" )
-                       .removeAttr( "role" );
-
-               this.headers
-                       .unbind( ".accordion" )
-                       .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
-                       .removeAttr( "role" )
-                       .removeAttr( "aria-expanded" )
-                       .removeAttr( "aria-selected" )
-                       .removeAttr( "tabIndex" );
-
-               this.headers.find( "a" ).removeAttr( "tabIndex" );
-               this._destroyIcons();
-               var contents = this.headers.next()
-                       .css( "display", "" )
-                       .removeAttr( "role" )
-                       .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
-               if ( options.autoHeight || options.fillHeight ) {
-                       contents.css( "height", "" );
-               }
-
-               return $.Widget.prototype.destroy.call( this );
-       },
-
-       _setOption: function( key, value ) {
-               $.Widget.prototype._setOption.apply( this, arguments );
-                       
-               if ( key == "active" ) {
-                       this.activate( value );
-               }
-               if ( key == "icons" ) {
-                       this._destroyIcons();
-                       if ( value ) {
-                               this._createIcons();
-                       }
-               }
-               // #5332 - opacity doesn't cascade to positioned elements in IE
-               // so we need to add the disabled class to the headers and panels
-               if ( key == "disabled" ) {
-                       this.headers.add(this.headers.next())
-                               [ value ? "addClass" : "removeClass" ](
-                                       "ui-accordion-disabled ui-state-disabled" );
-               }
-       },
-
-       _keydown: function( event ) {
-               if ( this.options.disabled || event.altKey || event.ctrlKey ) {
-                       return;
-               }
-
-               var keyCode = $.ui.keyCode,
-                       length = this.headers.length,
-                       currentIndex = this.headers.index( event.target ),
-                       toFocus = false;
-
-               switch ( event.keyCode ) {
-                       case keyCode.RIGHT:
-                       case keyCode.DOWN:
-                               toFocus = this.headers[ ( currentIndex + 1 ) % length ];
-                               break;
-                       case keyCode.LEFT:
-                       case keyCode.UP:
-                               toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
-                               break;
-                       case keyCode.SPACE:
-                       case keyCode.ENTER:
-                               this._clickHandler( { target: event.target }, event.target );
-                               event.preventDefault();
-               }
-
-               if ( toFocus ) {
-                       $( event.target ).attr( "tabIndex", -1 );
-                       $( toFocus ).attr( "tabIndex", 0 );
-                       toFocus.focus();
-                       return false;
-               }
-
-               return true;
-       },
-
-       resize: function() {
-               var options = this.options,
-                       maxHeight;
-
-               if ( options.fillSpace ) {
-                       if ( $.browser.msie ) {
-                               var defOverflow = this.element.parent().css( "overflow" );
-                               this.element.parent().css( "overflow", "hidden");
-                       }
-                       maxHeight = this.element.parent().height();
-                       if ($.browser.msie) {
-                               this.element.parent().css( "overflow", defOverflow );
-                       }
-
-                       this.headers.each(function() {
-                               maxHeight -= $( this ).outerHeight( true );
-                       });
-
-                       this.headers.next()
-                               .each(function() {
-                                       $( this ).height( Math.max( 0, maxHeight -
-                                               $( this ).innerHeight() + $( this ).height() ) );
-                               })
-                               .css( "overflow", "auto" );
-               } else if ( options.autoHeight ) {
-                       maxHeight = 0;
-                       this.headers.next()
-                               .each(function() {
-                                       maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
-                               })
-                               .height( maxHeight );
-               }
-
-               return this;
-       },
-
-       activate: function( index ) {
-               // TODO this gets called on init, changing the option without an explicit call for that
-               this.options.active = index;
-               // call clickHandler with custom event
-               var active = this._findActive( index )[ 0 ];
-               this._clickHandler( { target: active }, active );
-
-               return this;
-       },
-
-       _findActive: function( selector ) {
-               return selector
-                       ? typeof selector === "number"
-                               ? this.headers.filter( ":eq(" + selector + ")" )
-                               : this.headers.not( this.headers.not( selector ) )
-                       : selector === false
-                               ? $( [] )
-                               : this.headers.filter( ":eq(0)" );
-       },
-
-       // TODO isn't event.target enough? why the separate target argument?
-       _clickHandler: function( event, target ) {
-               var options = this.options;
-               if ( options.disabled ) {
-                       return;
-               }
-
-               // called only when using activate(false) to close all parts programmatically
-               if ( !event.target ) {
-                       if ( !options.collapsible ) {
-                               return;
-                       }
-                       this.active
-                               .removeClass( "ui-state-active ui-corner-top" )
-                               .addClass( "ui-state-default ui-corner-all" )
-                               .children( ".ui-icon" )
-                                       .removeClass( options.icons.headerSelected )
-                                       .addClass( options.icons.header );
-                       this.active.next().addClass( "ui-accordion-content-active" );
-                       var toHide = this.active.next(),
-                               data = {
-                                       options: options,
-                                       newHeader: $( [] ),
-                                       oldHeader: options.active,
-                                       newContent: $( [] ),
-                                       oldContent: toHide
-                               },
-                               toShow = ( this.active = $( [] ) );
-                       this._toggle( toShow, toHide, data );
-                       return;
-               }
-
-               // get the click target
-               var clicked = $( event.currentTarget || target ),
-                       clickedIsActive = clicked[0] === this.active[0];
-
-               // TODO the option is changed, is that correct?
-               // TODO if it is correct, shouldn't that happen after determining that the click is valid?
-               options.active = options.collapsible && clickedIsActive ?
-                       false :
-                       this.headers.index( clicked );
-
-               // if animations are still active, or the active header is the target, ignore click
-               if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
-                       return;
-               }
-
-               // find elements to show and hide
-               var active = this.active,
-                       toShow = clicked.next(),
-                       toHide = this.active.next(),
-                       data = {
-                               options: options,
-                               newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
-                               oldHeader: this.active,
-                               newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
-                               oldContent: toHide
-                       },
-                       down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
-
-               // when the call to ._toggle() comes after the class changes
-               // it causes a very odd bug in IE 8 (see #6720)
-               this.active = clickedIsActive ? $([]) : clicked;
-               this._toggle( toShow, toHide, data, clickedIsActive, down );
-
-               // switch classes
-               active
-                       .removeClass( "ui-state-active ui-corner-top" )
-                       .addClass( "ui-state-default ui-corner-all" )
-                       .children( ".ui-icon" )
-                               .removeClass( options.icons.headerSelected )
-                               .addClass( options.icons.header );
-               if ( !clickedIsActive ) {
-                       clicked
-                               .removeClass( "ui-state-default ui-corner-all" )
-                               .addClass( "ui-state-active ui-corner-top" )
-                               .children( ".ui-icon" )
-                                       .removeClass( options.icons.header )
-                                       .addClass( options.icons.headerSelected );
-                       clicked
-                               .next()
-                               .addClass( "ui-accordion-content-active" );
-               }
-
-               return;
-       },
-
-       _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
-               var self = this,
-                       options = self.options;
-
-               self.toShow = toShow;
-               self.toHide = toHide;
-               self.data = data;
-
-               var complete = function() {
-                       if ( !self ) {
-                               return;
-                       }
-                       return self._completed.apply( self, arguments );
-               };
-
-               // trigger changestart event
-               self._trigger( "changestart", null, self.data );
-
-               // count elements to animate
-               self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
-
-               if ( options.animated ) {
-                       var animOptions = {};
-
-                       if ( options.collapsible && clickedIsActive ) {
-                               animOptions = {
-                                       toShow: $( [] ),
-                                       toHide: toHide,
-                                       complete: complete,
-                                       down: down,
-                                       autoHeight: options.autoHeight || options.fillSpace
-                               };
-                       } else {
-                               animOptions = {
-                                       toShow: toShow,
-                                       toHide: toHide,
-                                       complete: complete,
-                                       down: down,
-                                       autoHeight: options.autoHeight || options.fillSpace
-                               };
-                       }
-
-                       if ( !options.proxied ) {
-                               options.proxied = options.animated;
-                       }
-
-                       if ( !options.proxiedDuration ) {
-                               options.proxiedDuration = options.duration;
-                       }
-
-                       options.animated = $.isFunction( options.proxied ) ?
-                               options.proxied( animOptions ) :
-                               options.proxied;
-
-                       options.duration = $.isFunction( options.proxiedDuration ) ?
-                               options.proxiedDuration( animOptions ) :
-                               options.proxiedDuration;
-
-                       var animations = $.ui.accordion.animations,
-                               duration = options.duration,
-                               easing = options.animated;
-
-                       if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
-                               easing = "slide";
-                       }
-                       if ( !animations[ easing ] ) {
-                               animations[ easing ] = function( options ) {
-                                       this.slide( options, {
-                                               easing: easing,
-                                               duration: duration || 700
-                                       });
-                               };
-                       }
-
-                       animations[ easing ]( animOptions );
-               } else {
-                       if ( options.collapsible && clickedIsActive ) {
-                               toShow.toggle();
-                       } else {
-                               toHide.hide();
-                               toShow.show();
-                       }
-
-                       complete( true );
-               }
-
-               // TODO assert that the blur and focus triggers are really necessary, remove otherwise
-               toHide.prev()
-                       .attr({
-                               "aria-expanded": "false",
-                               "aria-selected": "false",
-                               tabIndex: -1
-                       })
-                       .blur();
-               toShow.prev()
-                       .attr({
-                               "aria-expanded": "true",
-                               "aria-selected": "true",
-                               tabIndex: 0
-                       })
-                       .focus();
-       },
-
-       _completed: function( cancel ) {
-               this.running = cancel ? 0 : --this.running;
-               if ( this.running ) {
-                       return;
-               }
-
-               if ( this.options.clearStyle ) {
-                       this.toShow.add( this.toHide ).css({
-                               height: "",
-                               overflow: ""
-                       });
-               }
-
-               // other classes are removed before the animation; this one needs to stay until completed
-               this.toHide.removeClass( "ui-accordion-content-active" );
-               // Work around for rendering bug in IE (#5421)
-               if ( this.toHide.length ) {
-                       this.toHide.parent()[0].className = this.toHide.parent()[0].className;
-               }
-
-               this._trigger( "change", null, this.data );
-       }
-});
-
-$.extend( $.ui.accordion, {
-       version: "1.8.24",
-       animations: {
-               slide: function( options, additions ) {
-                       options = $.extend({
-                               easing: "swing",
-                               duration: 300
-                       }, options, additions );
-                       if ( !options.toHide.size() ) {
-                               options.toShow.animate({
-                                       height: "show",
-                                       paddingTop: "show",
-                                       paddingBottom: "show"
-                               }, options );
-                               return;
-                       }
-                       if ( !options.toShow.size() ) {
-                               options.toHide.animate({
-                                       height: "hide",
-                                       paddingTop: "hide",
-                                       paddingBottom: "hide"
-                               }, options );
-                               return;
-                       }
-                       var overflow = options.toShow.css( "overflow" ),
-                               percentDone = 0,
-                               showProps = {},
-                               hideProps = {},
-                               fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
-                               originalWidth;
-                       // fix width before calculating height of hidden element
-                       var s = options.toShow;
-                       originalWidth = s[0].style.width;
-                       s.width( s.parent().width()
-                               - parseFloat( s.css( "paddingLeft" ) )
-                               - parseFloat( s.css( "paddingRight" ) )
-                               - ( parseFloat( s.css( "borderLeftWidth" ) ) || 0 )
-                               - ( parseFloat( s.css( "borderRightWidth" ) ) || 0 ) );
-
-                       $.each( fxAttrs, function( i, prop ) {
-                               hideProps[ prop ] = "hide";
-
-                               var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
-                               showProps[ prop ] = {
-                                       value: parts[ 1 ],
-                                       unit: parts[ 2 ] || "px"
-                               };
-                       });
-                       options.toShow.css({ height: 0, overflow: "hidden" }).show();
-                       options.toHide
-                               .filter( ":hidden" )
-                                       .each( options.complete )
-                               .end()
-                               .filter( ":visible" )
-                               .animate( hideProps, {
-                               step: function( now, settings ) {
-                                       // only calculate the percent when animating height
-                                       // IE gets very inconsistent results when animating elements
-                                       // with small values, which is common for padding
-                                       if ( settings.prop == "height" ) {
-                                               percentDone = ( settings.end - settings.start === 0 ) ? 0 :
-                                                       ( settings.now - settings.start ) / ( settings.end - settings.start );
-                                       }
-
-                                       options.toShow[ 0 ].style[ settings.prop ] =
-                                               ( percentDone * showProps[ settings.prop ].value )
-                                               + showProps[ settings.prop ].unit;
-                               },
-                               duration: options.duration,
-                               easing: options.easing,
-                               complete: function() {
-                                       if ( !options.autoHeight ) {
-                                               options.toShow.css( "height", "" );
-                                       }
-                                       options.toShow.css({
-                                               width: originalWidth,
-                                               overflow: overflow
-                                       });
-                                       options.complete();
-                               }
-                       });
-               },
-               bounceslide: function( options ) {
-                       this.slide( options, {
-                               easing: options.down ? "easeOutBounce" : "swing",
-                               duration: options.down ? 1000 : 200
-                       });
-               }
-       }
-});
-
-})( jQuery );
diff --git a/resources/jquery.ui/jquery.ui.autocomplete.js b/resources/jquery.ui/jquery.ui.autocomplete.js
deleted file mode 100644 (file)
index 8d69be2..0000000
+++ /dev/null
@@ -1,631 +0,0 @@
-/*!
- * jQuery UI Autocomplete 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Autocomplete
- *
- * Depends:
- *     jquery.ui.core.js
- *     jquery.ui.widget.js
- *     jquery.ui.position.js
- */
-(function( $, undefined ) {
-
-// used to prevent race conditions with remote data sources
-var requestIndex = 0;
-
-$.widget( "ui.autocomplete", {
-       options: {
-               appendTo: "body",
-               autoFocus: false,
-               delay: 300,
-               minLength: 1,
-               position: {
-                       my: "left top",
-                       at: "left bottom",
-                       collision: "none"
-               },
-               source: null
-       },
-
-       pending: 0,
-
-       _create: function() {
-               var self = this,
-                       doc = this.element[ 0 ].ownerDocument,
-                       suppressKeyPress;
-               this.isMultiLine = this.element.is( "textarea" );
-
-               this.element
-                       .addClass( "ui-autocomplete-input" )
-                       .attr( "autocomplete", "off" )
-                       // TODO verify these actually work as intended
-                       .attr({
-                               role: "textbox",
-                               "aria-autocomplete": "list",
-                               "aria-haspopup": "true"
-                       })
-                       .bind( "keydown.autocomplete", function( event ) {
-                               if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) {
-                                       return;
-                               }
-
-                               suppressKeyPress = false;
-                               var keyCode = $.ui.keyCode;
-                               switch( event.keyCode ) {
-                               case keyCode.PAGE_UP:
-                                       self._move( "previousPage", event );
-                                       break;
-                               case keyCode.PAGE_DOWN:
-                                       self._move( "nextPage", event );
-                                       break;
-                               case keyCode.UP:
-                                       self._keyEvent( "previous", event );
-                                       break;
-                               case keyCode.DOWN:
-                                       self._keyEvent( "next", event );
-                                       break;
-                               case keyCode.ENTER:
-                               case keyCode.NUMPAD_ENTER:
-                                       // when menu is open and has focus
-                                       if ( self.menu.active ) {
-                                               // #6055 - Opera still allows the keypress to occur
-                                               // which causes forms to submit
-                                               suppressKeyPress = true;
-                                               event.preventDefault();
-                                       }
-                                       //passthrough - ENTER and TAB both select the current element
-                               case keyCode.TAB:
-                                       if ( !self.menu.active ) {
-                                               return;
-                                       }
-                                       self.menu.select( event );
-                                       break;
-                               case keyCode.ESCAPE:
-                                       self.element.val( self.term );
-                                       self.close( event );
-                                       break;
-                               default:
-                                       // keypress is triggered before the input value is changed
-                                       clearTimeout( self.searching );
-                                       self.searching = setTimeout(function() {
-                                               // only search if the value has changed
-                                               if ( self.term != self.element.val() ) {
-                                                       self.selectedItem = null;
-                                                       self.search( null, event );
-                                               }
-                                       }, self.options.delay );
-                                       break;
-                               }
-                       })
-                       .bind( "keypress.autocomplete", function( event ) {
-                               if ( suppressKeyPress ) {
-                                       suppressKeyPress = false;
-                                       event.preventDefault();
-                               }
-                       })
-                       .bind( "focus.autocomplete", function() {
-                               if ( self.options.disabled ) {
-                                       return;
-                               }
-
-                               self.selectedItem = null;
-                               self.previous = self.element.val();
-                       })
-                       .bind( "blur.autocomplete", function( event ) {
-                               if ( self.options.disabled ) {
-                                       return;
-                               }
-
-                               clearTimeout( self.searching );
-                               // clicks on the menu (or a button to trigger a search) will cause a blur event
-                               self.closing = setTimeout(function() {
-                                       self.close( event );
-                                       self._change( event );
-                               }, 150 );
-                       });
-               this._initSource();
-               this.menu = $( "<ul></ul>" )
-                       .addClass( "ui-autocomplete" )
-                       .appendTo( $( this.options.appendTo || "body", doc )[0] )
-                       // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
-                       .mousedown(function( event ) {
-                               // clicking on the scrollbar causes focus to shift to the body
-                               // but we can't detect a mouseup or a click immediately afterward
-                               // so we have to track the next mousedown and close the menu if
-                               // the user clicks somewhere outside of the autocomplete
-                               var menuElement = self.menu.element[ 0 ];
-                               if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
-                                       setTimeout(function() {
-                                               $( document ).one( 'mousedown', function( event ) {
-                                                       if ( event.target !== self.element[ 0 ] &&
-                                                               event.target !== menuElement &&
-                                                               !$.ui.contains( menuElement, event.target ) ) {
-                                                               self.close();
-                                                       }
-                                               });
-                                       }, 1 );
-                               }
-
-                               // use another timeout to make sure the blur-event-handler on the input was already triggered
-                               setTimeout(function() {
-                                       clearTimeout( self.closing );
-                               }, 13);
-                       })
-                       .menu({
-                               focus: function( event, ui ) {
-                                       var item = ui.item.data( "item.autocomplete" );
-                                       if ( false !== self._trigger( "focus", event, { item: item } ) ) {
-                                               // use value to match what will end up in the input, if it was a key event
-                                               if ( /^key/.test(event.originalEvent.type) ) {
-                                                       self.element.val( item.value );
-                                               }
-                                       }
-                               },
-                               selected: function( event, ui ) {
-                                       var item = ui.item.data( "item.autocomplete" ),
-                                               previous = self.previous;
-
-                                       // only trigger when focus was lost (click on menu)
-                                       if ( self.element[0] !== doc.activeElement ) {
-                                               self.element.focus();
-                                               self.previous = previous;
-                                               // #6109 - IE triggers two focus events and the second
-                                               // is asynchronous, so we need to reset the previous
-                                               // term synchronously and asynchronously :-(
-                                               setTimeout(function() {
-                                                       self.previous = previous;
-                                                       self.selectedItem = item;
-                                               }, 1);
-                                       }
-
-                                       if ( false !== self._trigger( "select", event, { item: item } ) ) {
-                                               self.element.val( item.value );
-                                       }
-                                       // reset the term after the select event
-                                       // this allows custom select handling to work properly
-                                       self.term = self.element.val();
-
-                                       self.close( event );
-                                       self.selectedItem = item;
-                               },
-                               blur: function( event, ui ) {
-                                       // don't set the value of the text field if it's already correct
-                                       // this prevents moving the cursor unnecessarily
-                                       if ( self.menu.element.is(":visible") &&
-                                               ( self.element.val() !== self.term ) ) {
-                                               self.element.val( self.term );
-                                       }
-                               }
-                       })
-                       .zIndex( this.element.zIndex() + 1 )
-                       // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
-                       .css({ top: 0, left: 0 })
-                       .hide()
-                       .data( "menu" );
-               if ( $.fn.bgiframe ) {
-                        this.menu.element.bgiframe();
-               }
-               // turning off autocomplete prevents the browser from remembering the
-               // value when navigating through history, so we re-enable autocomplete
-               // if the page is unloaded before the widget is destroyed. #7790
-               self.beforeunloadHandler = function() {
-                       self.element.removeAttr( "autocomplete" );
-               };
-               $( window ).bind( "beforeunload", self.beforeunloadHandler );
-       },
-
-       destroy: function() {
-               this.element
-                       .removeClass( "ui-autocomplete-input" )
-                       .removeAttr( "autocomplete" )
-                       .removeAttr( "role" )
-                       .removeAttr( "aria-autocomplete" )
-                       .removeAttr( "aria-haspopup" );
-               this.menu.element.remove();
-               $( window ).unbind( "beforeunload", this.beforeunloadHandler );
-               $.Widget.prototype.destroy.call( this );
-       },
-
-       _setOption: function( key, value ) {
-               $.Widget.prototype._setOption.apply( this, arguments );
-               if ( key === "source" ) {
-                       this._initSource();
-               }
-               if ( key === "appendTo" ) {
-                       this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
-               }
-               if ( key === "disabled" && value && this.xhr ) {
-                       this.xhr.abort();
-               }
-       },
-
-       _initSource: function() {
-               var self = this,
-                       array,
-                       url;
-               if ( $.isArray(this.options.source) ) {
-                       array = this.options.source;
-                       this.source = function( request, response ) {
-                               response( $.ui.autocomplete.filter(array, request.term) );
-                       };
-               } else if ( typeof this.options.source === "string" ) {
-                       url = this.options.source;
-                       this.source = function( request, response ) {
-                               if ( self.xhr ) {
-                                       self.xhr.abort();
-                               }
-                               self.xhr = $.ajax({
-                                       url: url,
-                                       data: request,
-                                       dataType: "json",
-                                       success: function( data, status ) {
-                                               response( data );
-                                       },
-                                       error: function() {
-                                               response( [] );
-                                       }
-                               });
-                       };
-               } else {
-                       this.source = this.options.source;
-               }
-       },
-
-       search: function( value, event ) {
-               value = value != null ? value : this.element.val();
-
-               // always save the actual value, not the one passed as an argument
-               this.term = this.element.val();
-
-               if ( value.length < this.options.minLength ) {
-                       return this.close( event );
-               }
-
-               clearTimeout( this.closing );
-               if ( this._trigger( "search", event ) === false ) {
-                       return;
-               }
-
-               return this._search( value );
-       },
-
-       _search: function( value ) {
-               this.pending++;
-               this.element.addClass( "ui-autocomplete-loading" );
-
-               this.source( { term: value }, this._response() );
-       },
-
-       _response: function() {
-               var that = this,
-                       index = ++requestIndex;
-
-               return function( content ) {
-                       if ( index === requestIndex ) {
-                               that.__response( content );
-                       }
-
-                       that.pending--;
-                       if ( !that.pending ) {
-                               that.element.removeClass( "ui-autocomplete-loading" );
-                       }
-               };
-       },
-
-       __response: function( content ) {
-               if ( !this.options.disabled && content && content.length ) {
-                       content = this._normalize( content );
-                       this._suggest( content );
-                       this._trigger( "open" );
-               } else {
-                       this.close();
-               }
-       },
-
-       close: function( event ) {
-               clearTimeout( this.closing );
-               if ( this.menu.element.is(":visible") ) {
-                       this.menu.element.hide();
-                       this.menu.deactivate();
-                       this._trigger( "close", event );
-               }
-       },
-       
-       _change: function( event ) {
-               if ( this.previous !== this.element.val() ) {
-                       this._trigger( "change", event, { item: this.selectedItem } );
-               }
-       },
-
-       _normalize: function( items ) {
-               // assume all items have the right format when the first item is complete
-               if ( items.length && items[0].label && items[0].value ) {
-                       return items;
-               }
-               return $.map( items, function(item) {
-                       if ( typeof item === "string" ) {
-                               return {
-                                       label: item,
-                                       value: item
-                               };
-                       }
-                       return $.extend({
-                               label: item.label || item.value,
-                               value: item.value || item.label
-                       }, item );
-               });
-       },
-
-       _suggest: function( items ) {
-               var ul = this.menu.element
-                       .empty()
-                       .zIndex( this.element.zIndex() + 1 );
-               this._renderMenu( ul, items );
-               // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
-               this.menu.deactivate();
-               this.menu.refresh();
-
-               // size and position menu
-               ul.show();
-               this._resizeMenu();
-               ul.position( $.extend({
-                       of: this.element
-               }, this.options.position ));
-
-               if ( this.options.autoFocus ) {
-                       this.menu.next( new $.Event("mouseover") );
-               }
-       },
-
-       _resizeMenu: function() {
-               var ul = this.menu.element;
-               ul.outerWidth( Math.max(
-                       // Firefox wraps long text (possibly a rounding bug)
-                       // so we add 1px to avoid the wrapping (#7513)
-                       ul.width( "" ).outerWidth() + 1,
-                       this.element.outerWidth()
-               ) );
-       },
-
-       _renderMenu: function( ul, items ) {
-               var self = this;
-               $.each( items, function( index, item ) {
-                       self._renderItem( ul, item );
-               });
-       },
-
-       _renderItem: function( ul, item) {
-               return $( "<li></li>" )
-                       .data( "item.autocomplete", item )
-                       .append( $( "<a></a>" ).text( item.label ) )
-                       .appendTo( ul );
-       },
-
-       _move: function( direction, event ) {
-               if ( !this.menu.element.is(":visible") ) {
-                       this.search( null, event );
-                       return;
-               }
-               if ( this.menu.first() && /^previous/.test(direction) ||
-                               this.menu.last() && /^next/.test(direction) ) {
-                       this.element.val( this.term );
-                       this.menu.deactivate();
-                       return;
-               }
-               this.menu[ direction ]( event );
-       },
-
-       widget: function() {
-               return this.menu.element;
-       },
-       _keyEvent: function( keyEvent, event ) {
-               if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
-                       this._move( keyEvent, event );
-
-                       // prevents moving cursor to beginning/end of the text field in some browsers
-                       event.preventDefault();
-               }
-       }
-});
-
-$.extend( $.ui.autocomplete, {
-       escapeRegex: function( value ) {
-               return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
-       },
-       filter: function(array, term) {
-               var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
-               return $.grep( array, function(value) {
-                       return matcher.test( value.label || value.value || value );
-               });
-       }
-});
-
-}( jQuery ));
-
-/*
- * jQuery UI Menu (not officially released)
- * 
- * This widget isn't yet finished and the API is subject to change. We plan to finish
- * it for the next release. You're welcome to give it a try anyway and give us feedback,
- * as long as you're okay with migrating your code later on. We can help with that, too.
- *
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Menu
- *
- * Depends:
- *     jquery.ui.core.js
- *  jquery.ui.widget.js
- */
-(function($) {
-
-$.widget("ui.menu", {
-       _create: function() {
-               var self = this;
-               this.element
-                       .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
-                       .attr({
-                               role: "listbox",
-                               "aria-activedescendant": "ui-active-menuitem"
-                       })
-                       .click(function( event ) {
-                               if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
-                                       return;
-                               }
-                               // temporary
-                               event.preventDefault();
-                               self.select( event );
-                       });
-               this.refresh();
-       },
-       
-       refresh: function() {
-               var self = this;
-
-               // don't refresh list items that are already adapted
-               var items = this.element.children("li:not(.ui-menu-item):has(a)")
-                       .addClass("ui-menu-item")
-                       .attr("role", "menuitem");
-               
-               items.children("a")
-                       .addClass("ui-corner-all")
-                       .attr("tabindex", -1)
-                       // mouseenter doesn't work with event delegation
-                       .mouseenter(function( event ) {
-                               self.activate( event, $(this).parent() );
-                       })
-                       .mouseleave(function() {
-                               self.deactivate();
-                       });
-       },
-
-       activate: function( event, item ) {
-               this.deactivate();
-               if (this.hasScroll()) {
-                       var offset = item.offset().top - this.element.offset().top,
-                               scroll = this.element.scrollTop(),
-                               elementHeight = this.element.height();
-                       if (offset < 0) {
-                               this.element.scrollTop( scroll + offset);
-                       } else if (offset >= elementHeight) {
-                               this.element.scrollTop( scroll + offset - elementHeight + item.height());
-                       }
-               }
-               this.active = item.eq(0)
-                       .children("a")
-                               .addClass("ui-state-hover")
-                               .attr("id", "ui-active-menuitem")
-                       .end();
-               this._trigger("focus", event, { item: item });
-       },
-
-       deactivate: function() {
-               if (!this.active) { return; }
-
-               this.active.children("a")
-                       .removeClass("ui-state-hover")
-                       .removeAttr("id");
-               this._trigger("blur");
-               this.active = null;
-       },
-
-       next: function(event) {
-               this.move("next", ".ui-menu-item:first", event);
-       },
-
-       previous: function(event) {
-               this.move("prev", ".ui-menu-item:last", event);
-       },
-
-       first: function() {
-               return this.active && !this.active.prevAll(".ui-menu-item").length;
-       },
-
-       last: function() {
-               return this.active && !this.active.nextAll(".ui-menu-item").length;
-       },
-
-       move: function(direction, edge, event) {
-               if (!this.active) {
-                       this.activate(event, this.element.children(edge));
-                       return;
-               }
-               var next = this.active[direction + "All"](".ui-menu-item").eq(0);
-               if (next.length) {
-                       this.activate(event, next);
-               } else {
-                       this.activate(event, this.element.children(edge));
-               }
-       },
-
-       // TODO merge with previousPage
-       nextPage: function(event) {
-               if (this.hasScroll()) {
-                       // TODO merge with no-scroll-else
-                       if (!this.active || this.last()) {
-                               this.activate(event, this.element.children(".ui-menu-item:first"));
-                               return;
-                       }
-                       var base = this.active.offset().top,
-                               height = this.element.height(),
-                               result = this.element.children(".ui-menu-item").filter(function() {
-                                       var close = $(this).offset().top - base - height + $(this).height();
-                                       // TODO improve approximation
-                                       return close < 10 && close > -10;
-                               });
-
-                       // TODO try to catch this earlier when scrollTop indicates the last page anyway
-                       if (!result.length) {
-                               result = this.element.children(".ui-menu-item:last");
-                       }
-                       this.activate(event, result);
-               } else {
-                       this.activate(event, this.element.children(".ui-menu-item")
-                               .filter(!this.active || this.last() ? ":first" : ":last"));
-               }
-       },
-
-       // TODO merge with nextPage
-       previousPage: function(event) {
-               if (this.hasScroll()) {
-                       // TODO merge with no-scroll-else
-                       if (!this.active || this.first()) {
-                               this.activate(event, this.element.children(".ui-menu-item:last"));
-                               return;
-                       }
-
-                       var base = this.active.offset().top,
-                               height = this.element.height(),
-                               result = this.element.children(".ui-menu-item").filter(function() {
-                                       var close = $(this).offset().top - base + height - $(this).height();
-                                       // TODO improve approximation
-                                       return close < 10 && close > -10;
-                               });
-
-                       // TODO try to catch this earlier when scrollTop indicates the last page anyway
-                       if (!result.length) {
-                               result = this.element.children(".ui-menu-item:first");
-                       }
-                       this.activate(event, result);
-               } else {
-                       this.activate(event, this.element.children(".ui-menu-item")
-                               .filter(!this.active || this.first() ? ":last" : ":first"));
-               }
-       },
-
-       hasScroll: function() {
-               return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
-       },
-
-       select: function( event ) {
-               this._trigger("selected", event, { item: this.active });
-       }
-});
-
-}(jQuery));
diff --git a/resources/jquery.ui/jquery.ui.button.js b/resources/jquery.ui/jquery.ui.button.js
deleted file mode 100644 (file)
index 8326262..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-/*!
- * jQuery UI Button 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Button
- *
- * Depends:
- *     jquery.ui.core.js
- *     jquery.ui.widget.js
- */
-(function( $, undefined ) {
-
-var lastActive, startXPos, startYPos, clickDragged,
-       baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
-       stateClasses = "ui-state-hover ui-state-active ",
-       typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
-       formResetHandler = function() {
-               var buttons = $( this ).find( ":ui-button" );
-               setTimeout(function() {
-                       buttons.button( "refresh" );
-               }, 1 );
-       },
-       radioGroup = function( radio ) {
-               var name = radio.name,
-                       form = radio.form,
-                       radios = $( [] );
-               if ( name ) {
-                       if ( form ) {
-                               radios = $( form ).find( "[name='" + name + "']" );
-                       } else {
-                               radios = $( "[name='" + name + "']", radio.ownerDocument )
-                                       .filter(function() {
-                                               return !this.form;
-                                       });
-                       }
-               }
-               return radios;
-       };
-
-$.widget( "ui.button", {
-       options: {
-               disabled: null,
-               text: true,
-               label: null,
-               icons: {
-                       primary: null,
-                       secondary: null
-               }
-       },
-       _create: function() {
-               this.element.closest( "form" )
-                       .unbind( "reset.button" )
-                       .bind( "reset.button", formResetHandler );
-
-               if ( typeof this.options.disabled !== "boolean" ) {
-                       this.options.disabled = !!this.element.propAttr( "disabled" );
-               } else {
-                       this.element.propAttr( "disabled", this.options.disabled );
-               }
-
-               this._determineButtonType();
-               this.hasTitle = !!this.buttonElement.attr( "title" );
-
-               var self = this,
-                       options = this.options,
-                       toggleButton = this.type === "checkbox" || this.type === "radio",
-                       hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
-                       focusClass = "ui-state-focus";
-
-               if ( options.label === null ) {
-                       options.label = this.buttonElement.html();
-               }
-
-               this.buttonElement
-                       .addClass( baseClasses )
-                       .attr( "role", "button" )
-                       .bind( "mouseenter.button", function() {
-                               if ( options.disabled ) {
-                                       return;
-                               }
-                               $( this ).addClass( "ui-state-hover" );
-                               if ( this === lastActive ) {
-                                       $( this ).addClass( "ui-state-active" );
-                               }
-                       })
-                       .bind( "mouseleave.button", function() {
-                               if ( options.disabled ) {
-                                       return;
-                               }
-                               $( this ).removeClass( hoverClass );
-                       })
-                       .bind( "click.button", function( event ) {
-                               if ( options.disabled ) {
-                                       event.preventDefault();
-                                       event.stopImmediatePropagation();
-                               }
-                       });
-
-               this.element
-                       .bind( "focus.button", function() {
-                               // no need to check disabled, focus won't be triggered anyway
-                               self.buttonElement.addClass( focusClass );
-                       })
-                       .bind( "blur.button", function() {
-                               self.buttonElement.removeClass( focusClass );
-                       });
-
-               if ( toggleButton ) {
-                       this.element.bind( "change.button", function() {
-                               if ( clickDragged ) {
-                                       return;
-                               }
-                               self.refresh();
-                       });
-                       // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
-                       // prevents issue where button state changes but checkbox/radio checked state
-                       // does not in Firefox (see ticket #6970)
-                       this.buttonElement
-                               .bind( "mousedown.button", function( event ) {
-                                       if ( options.disabled ) {
-                                               return;
-                                       }
-                                       clickDragged = false;
-                                       startXPos = event.pageX;
-                                       startYPos = event.pageY;
-                               })
-                               .bind( "mouseup.button", function( event ) {
-                                       if ( options.disabled ) {
-                                               return;
-                                       }
-                                       if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
-                                               clickDragged = true;
-                                       }
-                       });
-               }
-
-               if ( this.type === "checkbox" ) {
-                       this.buttonElement.bind( "click.button", function() {
-                               if ( options.disabled || clickDragged ) {
-                                       return false;
-                               }
-                               $( this ).toggleClass( "ui-state-active" );
-                               self.buttonElement.attr( "aria-pressed", self.element[0].checked );
-                       });
-               } else if ( this.type === "radio" ) {
-                       this.buttonElement.bind( "click.button", function() {
-                               if ( options.disabled || clickDragged ) {
-                                       return false;
-                               }
-                               $( this ).addClass( "ui-state-active" );
-                               self.buttonElement.attr( "aria-pressed", "true" );
-
-                               var radio = self.element[ 0 ];
-                               radioGroup( radio )
-                                       .not( radio )
-                                       .map(function() {
-                                               return $( this ).button( "widget" )[ 0 ];
-                                       })
-                                       .removeClass( "ui-state-active" )
-                                       .attr( "aria-pressed", "false" );
-                       });
-               } else {
-                       this.buttonElement
-                               .bind( "mousedown.button", function() {
-                                       if ( options.disabled ) {
-                                               return false;
-                                       }
-                                       $( this ).addClass( "ui-state-active" );
-                                       lastActive = this;
-                                       $( document ).one( "mouseup", function() {
-                                               lastActive = null;
-                                       });
-                               })
-                               .bind( "mouseup.button", function() {
-                                       if ( options.disabled ) {
-                                               return false;
-                                       }
-                                       $( this ).removeClass( "ui-state-active" );
-                               })
-                               .bind( "keydown.button", function(event) {
-                                       if ( options.disabled ) {
-                                               return false;
-                                       }
-                                       if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
-                                               $( this ).addClass( "ui-state-active" );
-                                       }
-                               })
-                               .bind( "keyup.button", function() {
-                                       $( this ).removeClass( "ui-state-active" );
-                               });
-
-                       if ( this.buttonElement.is("a") ) {
-                               this.buttonElement.keyup(function(event) {
-                                       if ( event.keyCode === $.ui.keyCode.SPACE ) {
-                                               // TODO pass through original event correctly (just as 2nd argument doesn't work)
-                                               $( this ).click();
-                                       }
-                               });
-                       }
-               }
-
-               // TODO: pull out $.Widget's handling for the disabled option into
-               // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
-               // be overridden by individual plugins
-               this._setOption( "disabled", options.disabled );
-               this._resetButton();
-       },
-
-       _determineButtonType: function() {
-
-               if ( this.element.is(":checkbox") ) {
-                       this.type = "checkbox";
-               } else if ( this.element.is(":radio") ) {
-                       this.type = "radio";
-               } else if ( this.element.is("input") ) {
-                       this.type = "input";
-               } else {
-                       this.type = "button";
-               }
-
-               if ( this.type === "checkbox" || this.type === "radio" ) {
-                       // we don't search against the document in case the element
-                       // is disconnected from the DOM
-                       var ancestor = this.element.parents().filter(":last"),
-                               labelSelector = "label[for='" + this.element.attr("id") + "']";
-                       this.buttonElement = ancestor.find( labelSelector );
-                       if ( !this.buttonElement.length ) {
-                               ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
-                               this.buttonElement = ancestor.filter( labelSelector );
-                               if ( !this.buttonElement.length ) {
-                                       this.buttonElement = ancestor.find( labelSelector );
-                               }
-                       }
-                       this.element.addClass( "ui-helper-hidden-accessible" );
-
-                       var checked = this.element.is( ":checked" );
-                       if ( checked ) {
-                               this.buttonElement.addClass( "ui-state-active" );
-                       }
-                       this.buttonElement.attr( "aria-pressed", checked );
-               } else {
-                       this.buttonElement = this.element;
-               }
-       },
-
-       widget: function() {
-               return this.buttonElement;
-       },
-
-       destroy: function() {
-               this.element
-                       .removeClass( "ui-helper-hidden-accessible" );
-               this.buttonElement
-                       .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
-                       .removeAttr( "role" )
-                       .removeAttr( "aria-pressed" )
-                       .html( this.buttonElement.find(".ui-button-text").html() );
-
-               if ( !this.hasTitle ) {
-                       this.buttonElement.removeAttr( "title" );
-               }
-
-               $.Widget.prototype.destroy.call( this );
-       },
-
-       _setOption: function( key, value ) {
-               $.Widget.prototype._setOption.apply( this, arguments );
-               if ( key === "disabled" ) {
-                       if ( value ) {
-                               this.element.propAttr( "disabled", true );
-                       } else {
-                               this.element.propAttr( "disabled", false );
-                       }
-                       return;
-               }
-               this._resetButton();
-       },
-
-       refresh: function() {
-               var isDisabled = this.element.is( ":disabled" );
-               if ( isDisabled !== this.options.disabled ) {
-                       this._setOption( "disabled", isDisabled );
-               }
-               if ( this.type === "radio" ) {
-                       radioGroup( this.element[0] ).each(function() {
-                               if ( $( this ).is( ":checked" ) ) {
-                                       $( this ).button( "widget" )
-                                               .addClass( "ui-state-active" )
-                                               .attr( "aria-pressed", "true" );
-                               } else {
-                                       $( this ).button( "widget" )
-                                               .removeClass( "ui-state-active" )
-                                               .attr( "aria-pressed", "false" );
-                               }
-                       });
-               } else if ( this.type === "checkbox" ) {
-                       if ( this.element.is( ":checked" ) ) {
-                               this.buttonElement
-                                       .addClass( "ui-state-active" )
-                                       .attr( "aria-pressed", "true" );
-                       } else {
-                               this.buttonElement
-                                       .removeClass( "ui-state-active" )
-                                       .attr( "aria-pressed", "false" );
-                       }
-               }
-       },
-
-       _resetButton: function() {
-               if ( this.type === "input" ) {
-                       if ( this.options.label ) {
-                               this.element.val( this.options.label );
-                       }
-                       return;
-               }
-               var buttonElement = this.buttonElement.removeClass( typeClasses ),
-                       buttonText = $( "<span></span>", this.element[0].ownerDocument )
-                               .addClass( "ui-button-text" )
-                               .html( this.options.label )
-                               .appendTo( buttonElement.empty() )
-                               .text(),
-                       icons = this.options.icons,
-                       multipleIcons = icons.primary && icons.secondary,
-                       buttonClasses = [];  
-
-               if ( icons.primary || icons.secondary ) {
-                       if ( this.options.text ) {
-                               buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
-                       }
-
-                       if ( icons.primary ) {
-                               buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
-                       }
-
-                       if ( icons.secondary ) {
-                               buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
-                       }
-
-                       if ( !this.options.text ) {
-                               buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
-
-                               if ( !this.hasTitle ) {
-                                       buttonElement.attr( "title", buttonText );
-                               }
-                       }
-               } else {
-                       buttonClasses.push( "ui-button-text-only" );
-               }
-               buttonElement.addClass( buttonClasses.join( " " ) );
-       }
-});
-
-$.widget( "ui.buttonset", {
-       options: {
-               items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
-       },
-
-       _create: function() {
-               this.element.addClass( "ui-buttonset" );
-       },
-       
-       _init: function() {
-               this.refresh();
-       },
-
-       _setOption: function( key, value ) {
-               if ( key === "disabled" ) {
-                       this.buttons.button( "option", key, value );
-               }
-
-               $.Widget.prototype._setOption.apply( this, arguments );
-       },
-       
-       refresh: function() {
-               var rtl = this.element.css( "direction" ) === "rtl";
-               
-               this.buttons = this.element.find( this.options.items )
-                       .filter( ":ui-button" )
-                               .button( "refresh" )
-                       .end()
-                       .not( ":ui-button" )
-                               .button()
-                       .end()
-                       .map(function() {
-                               return $( this ).button( "widget" )[ 0 ];
-                       })
-                               .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
-                               .filter( ":first" )
-                                       .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
-                               .end()
-                               .filter( ":last" )
-                                       .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
-                               .end()
-                       .end();
-       },
-
-       destroy: function() {
-               this.element.removeClass( "ui-buttonset" );
-               this.buttons
-                       .map(function() {
-                               return $( this ).button( "widget" )[ 0 ];
-                       })
-                               .removeClass( "ui-corner-left ui-corner-right" )
-                       .end()
-                       .button( "destroy" );
-
-               $.Widget.prototype.destroy.call( this );
-       }
-});
-
-}( jQuery ) );
diff --git a/resources/jquery.ui/jquery.ui.core.js b/resources/jquery.ui/jquery.ui.core.js
deleted file mode 100644 (file)
index b36c1ac..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-/*!
- * jQuery UI 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI
- */
-(function( $, undefined ) {
-
-// prevent duplicate loading
-// this is only a problem because we proxy existing functions
-// and we don't want to double proxy them
-$.ui = $.ui || {};
-if ( $.ui.version ) {
-       return;
-}
-
-$.extend( $.ui, {
-       version: "1.8.24",
-
-       keyCode: {
-               ALT: 18,
-               BACKSPACE: 8,
-               CAPS_LOCK: 20,
-               COMMA: 188,
-               COMMAND: 91,
-               COMMAND_LEFT: 91, // COMMAND
-               COMMAND_RIGHT: 93,
-               CONTROL: 17,
-               DELETE: 46,
-               DOWN: 40,
-               END: 35,
-               ENTER: 13,
-               ESCAPE: 27,
-               HOME: 36,
-               INSERT: 45,
-               LEFT: 37,
-               MENU: 93, // COMMAND_RIGHT
-               NUMPAD_ADD: 107,
-               NUMPAD_DECIMAL: 110,
-               NUMPAD_DIVIDE: 111,
-               NUMPAD_ENTER: 108,
-               NUMPAD_MULTIPLY: 106,
-               NUMPAD_SUBTRACT: 109,
-               PAGE_DOWN: 34,
-               PAGE_UP: 33,
-               PERIOD: 190,
-               RIGHT: 39,
-               SHIFT: 16,
-               SPACE: 32,
-               TAB: 9,
-               UP: 38,
-               WINDOWS: 91 // COMMAND
-       }
-});
-
-// plugins
-$.fn.extend({
-       propAttr: $.fn.prop || $.fn.attr,
-
-       _focus: $.fn.focus,
-       focus: function( delay, fn ) {
-               return typeof delay === "number" ?
-                       this.each(function() {
-                               var elem = this;
-                               setTimeout(function() {
-                                       $( elem ).focus();
-                                       if ( fn ) {
-                                               fn.call( elem );
-                                       }
-                               }, delay );
-                       }) :
-                       this._focus.apply( this, arguments );
-       },
-
-       scrollParent: function() {
-               var scrollParent;
-               if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
-                       scrollParent = this.parents().filter(function() {
-                               return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
-                       }).eq(0);
-               } else {
-                       scrollParent = this.parents().filter(function() {
-                               return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
-                       }).eq(0);
-               }
-
-               return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
-       },
-
-       zIndex: function( zIndex ) {
-               if ( zIndex !== undefined ) {
-                       return this.css( "zIndex", zIndex );
-               }
-
-               if ( this.length ) {
-                       var elem = $( this[ 0 ] ), position, value;
-                       while ( elem.length && elem[ 0 ] !== document ) {
-                               // Ignore z-index if position is set to a value where z-index is ignored by the browser
-                               // This makes behavior of this function consistent across browsers
-                               // WebKit always returns auto if the element is positioned
-                               position = elem.css( "position" );
-                               if ( position === "absolute" || position === "relative" || position === "fixed" ) {
-                                       // IE returns 0 when zIndex is not specified
-                                       // other browsers return a string
-                                       // we ignore the case of nested elements with an explicit value of 0
-                                       // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
-                                       value = parseInt( elem.css( "zIndex" ), 10 );
-                                       if ( !isNaN( value ) && value !== 0 ) {
-                                               return value;
-                                       }
-                               }
-                               elem = elem.parent();
-                       }
-               }
-
-               return 0;
-       },
-
-       disableSelection: function() {
-               return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
-                       ".ui-disableSelection", function( event ) {
-                               event.preventDefault();
-                       });
-       },
-
-       enableSelection: function() {
-               return this.unbind( ".ui-disableSelection" );
-       }
-});
-
-// support: jQuery <1.8
-if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
-       $.each( [ "Width", "Height" ], function( i, name ) {
-               var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
-                       type = name.toLowerCase(),
-                       orig = {
-                               innerWidth: $.fn.innerWidth,
-                               innerHeight: $.fn.innerHeight,
-                               outerWidth: $.fn.outerWidth,
-                               outerHeight: $.fn.outerHeight
-                       };
-
-               function reduce( elem, size, border, margin ) {
-                       $.each( side, function() {
-                               size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
-                               if ( border ) {
-                                       size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
-                               }
-                               if ( margin ) {
-                                       size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
-                               }
-                       });
-                       return size;
-               }
-
-               $.fn[ "inner" + name ] = function( size ) {
-                       if ( size === undefined ) {
-                               return orig[ "inner" + name ].call( this );
-                       }
-
-                       return this.each(function() {
-                               $( this ).css( type, reduce( this, size ) + "px" );
-                       });
-               };
-
-               $.fn[ "outer" + name] = function( size, margin ) {
-                       if ( typeof size !== "number" ) {
-                               return orig[ "outer" + name ].call( this, size );
-                       }
-
-                       return this.each(function() {
-                               $( this).css( type, reduce( this, size, true, margin ) + "px" );
-                       });
-               };
-       });
-}
-
-// selectors
-function focusable( element, isTabIndexNotNaN ) {
-       var nodeName = element.nodeName.toLowerCase();
-       if ( "area" === nodeName ) {
-               var map = element.parentNode,
-                       mapName = map.name,
-                       img;
-               if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
-                       return false;
-               }
-               img = $( "img[usemap=#" + mapName + "]" )[0];
-               return !!img && visible( img );
-       }
-       return ( /input|select|textarea|button|object/.test( nodeName )
-               ? !element.disabled
-               : "a" == nodeName
-                       ? element.href || isTabIndexNotNaN
-                       : isTabIndexNotNaN)
-               // the element and all of its ancestors must be visible
-               && visible( element );
-}
-
-function visible( element ) {
-       return !$( element ).parents().andSelf().filter(function() {
-               return $.curCSS( this, "visibility" ) === "hidden" ||
-                       $.expr.filters.hidden( this );
-       }).length;
-}
-
-$.extend( $.expr[ ":" ], {
-       data: $.expr.createPseudo ?
-               $.expr.createPseudo(function( dataName ) {
-                       return function( elem ) {
-                               return !!$.data( elem, dataName );
-                       };
-               }) :
-               // support: jQuery <1.8
-               function( elem, i, match ) {
-                       return !!$.data( elem, match[ 3 ] );
-               },
-
-       focusable: function( element ) {
-               return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
-       },
-
-       tabbable: function( element ) {
-               var tabIndex = $.attr( element, "tabindex" ),
-                       isTabIndexNaN = isNaN( tabIndex );
-               return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
-       }
-});
-
-// support
-$(function() {
-       var body = document.body,
-               div = body.appendChild( div = document.createElement( "div" ) );
-
-       // access offsetHeight before setting the style to prevent a layout bug
-       // in IE 9 which causes the elemnt to continue to take up space even
-       // after it is removed from the DOM (#8026)
-       div.offsetHeight;
-
-       $.extend( div.style, {
-               minHeight: "100px",
-               height: "auto",
-               padding: 0,
-               borderWidth: 0
-       });
-
-       $.support.minHeight = div.offsetHeight === 100;
-       $.support.selectstart = "onselectstart" in div;
-
-       // set display to none to avoid a layout bug in IE
-       // http://dev.jquery.com/ticket/4014
-       body.removeChild( div ).style.display = "none";
-});
-
-// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
-if ( !$.curCSS ) {
-       $.curCSS = $.css;
-}
-
-
-
-
-
-// deprecated
-$.extend( $.ui, {
-       // $.ui.plugin is deprecated.  Use the proxy pattern instead.
-       plugin: {
-               add: function( module, option, set ) {
-                       var proto = $.ui[ module ].prototype;
-                       for ( var i in set ) {
-                               proto.plugins[ i ] = proto.plugins[ i ] || [];
-                               proto.plugins[ i ].push( [ option, set[ i ] ] );
-                       }
-               },
-               call: function( instance, name, args ) {
-                       var set = instance.plugins[ name ];
-                       if ( !set || !instance.element[ 0 ].parentNode ) {
-                               return;
-                       }
-       
-                       for ( var i = 0; i < set.length; i++ ) {
-                               if ( instance.options[ set[ i ][ 0 ] ] ) {
-                                       set[ i ][ 1 ].apply( instance.element, args );
-                               }
-                       }
-               }
-       },
-       
-       // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
-       contains: function( a, b ) {
-               return document.compareDocumentPosition ?
-                       a.compareDocumentPosition( b ) & 16 :
-                       a !== b && a.contains( b );
-       },
-       
-       // only used by resizable
-       hasScroll: function( el, a ) {
-       
-               //If overflow is hidden, the element might have extra content, but the user wants to hide it
-               if ( $( el ).css( "overflow" ) === "hidden") {
-                       return false;
-               }
-       
-               var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
-                       has = false;
-       
-               if ( el[ scroll ] > 0 ) {
-                       return true;
-               }
-       
-               // TODO: determine which cases actually cause this to happen
-               // if the element doesn't have the scroll set, see if it's possible to
-               // set the scroll
-               el[ scroll ] = 1;
-               has = ( el[ scroll ] > 0 );
-               el[ scroll ] = 0;
-               return has;
-       },
-       
-       // these are odd functions, fix the API or move into individual plugins
-       isOverAxis: function( x, reference, size ) {
-               //Determines when x coordinate is over "b" element axis
-               return ( x > reference ) && ( x < ( reference + size ) );
-       },
-       isOver: function( y, x, top, left, height, width ) {
-               //Determines when x, y coordinates is over "b" element
-               return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
-       }
-});
-
-})( jQuery );
diff --git a/resources/jquery.ui/jquery.ui.datepicker.js b/resources/jquery.ui/jquery.ui.datepicker.js
deleted file mode 100644 (file)
index 1fcea12..0000000
+++ /dev/null
@@ -1,1854 +0,0 @@
-/*!
- * jQuery UI Datepicker 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Datepicker
- *
- * Depends:
- *     jquery.ui.core.js
- */
-(function( $, undefined ) {
-
-$.extend($.ui, { datepicker: { version: "1.8.24" } });
-
-var PROP_NAME = 'datepicker';
-var dpuuid = new Date().getTime();
-var instActive;
-
-/* Date picker manager.
-   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
-   Settings for (groups of) date pickers are maintained in an instance object,
-   allowing multiple different settings on the same page. */
-
-function Datepicker() {
-       this.debug = false; // Change this to true to start debugging
-       this._curInst = null; // The current instance in use
-       this._keyEvent = false; // If the last event was a key event
-       this._disabledInputs = []; // List of date picker inputs that have been disabled
-       this._datepickerShowing = false; // True if the popup picker is showing , false if not
-       this._inDialog = false; // True if showing within a "dialog", false if not
-       this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
-       this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
-       this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
-       this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
-       this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
-       this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
-       this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
-       this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
-       this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
-       this.regional = []; // Available regional settings, indexed by language code
-       this.regional[''] = { // Default regional settings
-               closeText: 'Done', // Display text for close link
-               prevText: 'Prev', // Display text for previous month link
-               nextText: 'Next', // Display text for next month link
-               currentText: 'Today', // Display text for current month link
-               monthNames: ['January','February','March','April','May','June',
-                       'July','August','September','October','November','December'], // Names of months for drop-down and formatting
-               monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
-               dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
-               dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
-               dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
-               weekHeader: 'Wk', // Column header for week of the year
-               dateFormat: 'mm/dd/yy', // See format options on parseDate
-               firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
-               isRTL: false, // True if right-to-left language, false if left-to-right
-               showMonthAfterYear: false, // True if the year select precedes month, false for month then year
-               yearSuffix: '' // Additional text to append to the year in the month headers
-       };
-       this._defaults = { // Global defaults for all the date picker instances
-               showOn: 'focus', // 'focus' for popup on focus,
-                       // 'button' for trigger button, or 'both' for either
-               showAnim: 'fadeIn', // Name of jQuery animation for popup
-               showOptions: {}, // Options for enhanced animations
-               defaultDate: null, // Used when field is blank: actual date,
-                       // +/-number for offset from today, null for today
-               appendText: '', // Display text following the input box, e.g. showing the format
-               buttonText: '...', // Text for trigger button
-               buttonImage: '', // URL for trigger button image
-               buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
-               hideIfNoPrevNext: false, // True to hide next/previous month links
-                       // if not applicable, false to just disable them
-               navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
-               gotoCurrent: false, // True if today link goes back to current selection instead
-               changeMonth: false, // True if month can be selected directly, false if only prev/next
-               changeYear: false, // True if year can be selected directly, false if only prev/next
-               yearRange: 'c-10:c+10', // Range of years to display in drop-down,
-                       // either relative to today's year (-nn:+nn), relative to currently displayed year
-                       // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
-               showOtherMonths: false, // True to show dates in other months, false to leave blank
-               selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
-               showWeek: false, // True to show week of the year, false to not show it
-               calculateWeek: this.iso8601Week, // How to calculate the week of the year,
-                       // takes a Date and returns the number of the week for it
-               shortYearCutoff: '+10', // Short year values < this are in the current century,
-                       // > this are in the previous century,
-                       // string value starting with '+' for current year + value
-               minDate: null, // The earliest selectable date, or null for no limit
-               maxDate: null, // The latest selectable date, or null for no limit
-               duration: 'fast', // Duration of display/closure
-               beforeShowDay: null, // Function that takes a date and returns an array with
-                       // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
-                       // [2] = cell title (optional), e.g. $.datepicker.noWeekends
-               beforeShow: null, // Function that takes an input field and
-                       // returns a set of custom settings for the date picker
-               onSelect: null, // Define a callback function when a date is selected
-               onChangeMonthYear: null, // Define a callback function when the month or year is changed
-               onClose: null, // Define a callback function when the datepicker is closed
-               numberOfMonths: 1, // Number of months to show at a time
-               showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
-               stepMonths: 1, // Number of months to step back/forward
-               stepBigMonths: 12, // Number of months to step back/forward for the big links
-               altField: '', // Selector for an alternate field to store selected dates into
-               altFormat: '', // The date format to use for the alternate field
-               constrainInput: true, // The input is constrained by the current date format
-               showButtonPanel: false, // True to show button panel, false to not show it
-               autoSize: false, // True to size the input for the date format, false to leave as is
-               disabled: false // The initial disabled state
-       };
-       $.extend(this._defaults, this.regional['']);
-       this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
-}
-
-$.extend(Datepicker.prototype, {
-       /* Class name added to elements to indicate already configured with a date picker. */
-       markerClassName: 'hasDatepicker',
-       
-       //Keep track of the maximum number of rows displayed (see #7043)
-       maxRows: 4,
-
-       /* Debug logging (if enabled). */
-       log: function () {
-               if (this.debug)
-                       console.log.apply('', arguments);
-       },
-       
-       // TODO rename to "widget" when switching to widget factory
-       _widgetDatepicker: function() {
-               return this.dpDiv;
-       },
-
-       /* Override the default settings for all instances of the date picker.
-          @param  settings  object - the new settings to use as defaults (anonymous object)
-          @return the manager object */
-       setDefaults: function(settings) {
-               extendRemove(this._defaults, settings || {});
-               return this;
-       },
-
-       /* Attach the date picker to a jQuery selection.
-          @param  target    element - the target input field or division or span
-          @param  settings  object - the new settings to use for this date picker instance (anonymous) */
-       _attachDatepicker: function(target, settings) {
-               // check for settings on the control itself - in namespace 'date:'
-               var inlineSettings = null;
-               for (var attrName in this._defaults) {
-                       var attrValue = target.getAttribute('date:' + attrName);
-                       if (attrValue) {
-                               inlineSettings = inlineSettings || {};
-                               try {
-                                       inlineSettings[attrName] = eval(attrValue);
-                               } catch (err) {
-                                       inlineSettings[attrName] = attrValue;
-                               }
-                       }
-               }
-               var nodeName = target.nodeName.toLowerCase();
-               var inline = (nodeName == 'div' || nodeName == 'span');
-               if (!target.id) {
-                       this.uuid += 1;
-                       target.id = 'dp' + this.uuid;
-               }
-               var inst = this._newInst($(target), inline);
-               inst.settings = $.extend({}, settings || {}, inlineSettings || {});
-               if (nodeName == 'input') {
-                       this._connectDatepicker(target, inst);
-               } else if (inline) {
-                       this._inlineDatepicker(target, inst);
-               }
-       },
-
-       /* Create a new instance object. */
-       _newInst: function(target, inline) {
-               var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
-               return {id: id, input: target, // associated target
-                       selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
-                       drawMonth: 0, drawYear: 0, // month being drawn
-                       inline: inline, // is datepicker inline or not
-                       dpDiv: (!inline ? this.dpDiv : // presentation div
-                       bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
-       },
-
-       /* Attach the date picker to an input field. */
-       _connectDatepicker: function(target, inst) {
-               var input = $(target);
-               inst.append = $([]);
-               inst.trigger = $([]);
-               if (input.hasClass(this.markerClassName))
-                       return;
-               this._attachments(input, inst);
-               input.addClass(this.markerClassName).keydown(this._doKeyDown).
-                       keypress(this._doKeyPress).keyup(this._doKeyUp).
-                       bind("setData.datepicker", function(event, key, value) {
-                               inst.settings[key] = value;
-                       }).bind("getData.datepicker", function(event, key) {
-                               return this._get(inst, key);
-                       });
-               this._autoSize(inst);
-               $.data(target, PROP_NAME, inst);
-               //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
-               if( inst.settings.disabled ) {
-                       this._disableDatepicker( target );
-               }
-       },
-
-       /* Make attachments based on settings. */
-       _attachments: function(input, inst) {
-               var appendText = this._get(inst, 'appendText');
-               var isRTL = this._get(inst, 'isRTL');
-               if (inst.append)
-                       inst.append.remove();
-               if (appendText) {
-                       inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
-                       input[isRTL ? 'before' : 'after'](inst.append);
-               }
-               input.unbind('focus', this._showDatepicker);
-               if (inst.trigger)
-                       inst.trigger.remove();
-               var showOn = this._get(inst, 'showOn');
-               if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
-                       input.focus(this._showDatepicker);
-               if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
-                       var buttonText = this._get(inst, 'buttonText');
-                       var buttonImage = this._get(inst, 'buttonImage');
-                       inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
-                               $('<img/>').addClass(this._triggerClass).
-                                       attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
-                               $('<button type="button"></button>').addClass(this._triggerClass).
-                                       html(buttonImage == '' ? buttonText : $('<img/>').attr(
-                                       { src:buttonImage, alt:buttonText, title:buttonText })));
-                       input[isRTL ? 'before' : 'after'](inst.trigger);
-                       inst.trigger.click(function() {
-                               if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
-                                       $.datepicker._hideDatepicker();
-                               else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) {
-                                       $.datepicker._hideDatepicker(); 
-                                       $.datepicker._showDatepicker(input[0]);
-                               } else
-                                       $.datepicker._showDatepicker(input[0]);
-                               return false;
-                       });
-               }
-       },
-
-       /* Apply the maximum length for the date format. */
-       _autoSize: function(inst) {
-               if (this._get(inst, 'autoSize') && !inst.inline) {
-                       var date = new Date(2009, 12 - 1, 20); // Ensure double digits
-                       var dateFormat = this._get(inst, 'dateFormat');
-                       if (dateFormat.match(/[DM]/)) {
-                               var findMax = function(names) {
-                                       var max = 0;
-                                       var maxI = 0;
-                                       for (var i = 0; i < names.length; i++) {
-                                               if (names[i].length > max) {
-                                                       max = names[i].length;
-                                                       maxI = i;
-                                               }
-                                       }
-                                       return maxI;
-                               };
-                               date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
-                                       'monthNames' : 'monthNamesShort'))));
-                               date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
-                                       'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
-                       }
-                       inst.input.attr('size', this._formatDate(inst, date).length);
-               }
-       },
-
-       /* Attach an inline date picker to a div. */
-       _inlineDatepicker: function(target, inst) {
-               var divSpan = $(target);
-               if (divSpan.hasClass(this.markerClassName))
-                       return;
-               divSpan.addClass(this.markerClassName).append(inst.dpDiv).
-                       bind("setData.datepicker", function(event, key, value){
-                               inst.settings[key] = value;
-                       }).bind("getData.datepicker", function(event, key){
-                               return this._get(inst, key);
-                       });
-               $.data(target, PROP_NAME, inst);
-               this._setDate(inst, this._getDefaultDate(inst), true);
-               this._updateDatepicker(inst);
-               this._updateAlternate(inst);
-               //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
-               if( inst.settings.disabled ) {
-                       this._disableDatepicker( target );
-               }
-               // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
-               // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
-               inst.dpDiv.css( "display", "block" );
-       },
-
-       /* Pop-up the date picker in a "dialog" box.
-          @param  input     element - ignored
-          @param  date      string or Date - the initial date to display
-          @param  onSelect  function - the function to call when a date is selected
-          @param  settings  object - update the dialog date picker instance's settings (anonymous object)
-          @param  pos       int[2] - coordinates for the dialog's position within the screen or
-                            event - with x/y coordinates or
-                            leave empty for default (screen centre)
-          @return the manager object */
-       _dialogDatepicker: function(input, date, onSelect, settings, pos) {
-               var inst = this._dialogInst; // internal instance
-               if (!inst) {
-                       this.uuid += 1;
-                       var id = 'dp' + this.uuid;
-                       this._dialogInput = $('<input type="text" id="' + id +
-                               '" style="position: absolute; top: -100px; width: 0px;"/>');
-                       this._dialogInput.keydown(this._doKeyDown);
-                       $('body').append(this._dialogInput);
-                       inst = this._dialogInst = this._newInst(this._dialogInput, false);
-                       inst.settings = {};
-                       $.data(this._dialogInput[0], PROP_NAME, inst);
-               }
-               extendRemove(inst.settings, settings || {});
-               date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
-               this._dialogInput.val(date);
-
-               this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
-               if (!this._pos) {
-                       var browserWidth = document.documentElement.clientWidth;
-                       var browserHeight = document.documentElement.clientHeight;
-                       var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
-                       var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
-                       this._pos = // should use actual width/height below
-                               [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
-               }
-
-               // move input on screen for focus, but hidden behind dialog
-               this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
-               inst.settings.onSelect = onSelect;
-               this._inDialog = true;
-               this.dpDiv.addClass(this._dialogClass);
-               this._showDatepicker(this._dialogInput[0]);
-               if ($.blockUI)
-                       $.blockUI(this.dpDiv);
-               $.data(this._dialogInput[0], PROP_NAME, inst);
-               return this;
-       },
-
-       /* Detach a datepicker from its control.
-          @param  target    element - the target input field or division or span */
-       _destroyDatepicker: function(target) {
-               var $target = $(target);
-               var inst = $.data(target, PROP_NAME);
-               if (!$target.hasClass(this.markerClassName)) {
-                       return;
-               }
-               var nodeName = target.nodeName.toLowerCase();
-               $.removeData(target, PROP_NAME);
-               if (nodeName == 'input') {
-                       inst.append.remove();
-                       inst.trigger.remove();
-                       $target.removeClass(this.markerClassName).
-                               unbind('focus', this._showDatepicker).
-                               unbind('keydown', this._doKeyDown).
-                               unbind('keypress', this._doKeyPress).
-                               unbind('keyup', this._doKeyUp);
-               } else if (nodeName == 'div' || nodeName == 'span')
-                       $target.removeClass(this.markerClassName).empty();
-       },
-
-       /* Enable the date picker to a jQuery selection.
-          @param  target    element - the target input field or division or span */
-       _enableDatepicker: function(target) {
-               var $target = $(target);
-               var inst = $.data(target, PROP_NAME);
-               if (!$target.hasClass(this.markerClassName)) {
-                       return;
-               }
-               var nodeName = target.nodeName.toLowerCase();
-               if (nodeName == 'input') {
-                       target.disabled = false;
-                       inst.trigger.filter('button').
-                               each(function() { this.disabled = false; }).end().
-                               filter('img').css({opacity: '1.0', cursor: ''});
-               }
-               else if (nodeName == 'div' || nodeName == 'span') {
-                       var inline = $target.children('.' + this._inlineClass);
-                       inline.children().removeClass('ui-state-disabled');
-                       inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
-                               removeAttr("disabled");
-               }
-               this._disabledInputs = $.map(this._disabledInputs,
-                       function(value) { return (value == target ? null : value); }); // delete entry
-       },
-
-       /* Disable the date picker to a jQuery selection.
-          @param  target    element - the target input field or division or span */
-       _disableDatepicker: function(target) {
-               var $target = $(target);
-               var inst = $.data(target, PROP_NAME);
-               if (!$target.hasClass(this.markerClassName)) {
-                       return;
-               }
-               var nodeName = target.nodeName.toLowerCase();
-               if (nodeName == 'input') {
-                       target.disabled = true;
-                       inst.trigger.filter('button').
-                               each(function() { this.disabled = true; }).end().
-                               filter('img').css({opacity: '0.5', cursor: 'default'});
-               }
-               else if (nodeName == 'div' || nodeName == 'span') {
-                       var inline = $target.children('.' + this._inlineClass);
-                       inline.children().addClass('ui-state-disabled');
-                       inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
-                               attr("disabled", "disabled");
-               }
-               this._disabledInputs = $.map(this._disabledInputs,
-                       function(value) { return (value == target ? null : value); }); // delete entry
-               this._disabledInputs[this._disabledInputs.length] = target;
-       },
-
-       /* Is the first field in a jQuery collection disabled as a datepicker?
-          @param  target    element - the target input field or division or span
-          @return boolean - true if disabled, false if enabled */
-       _isDisabledDatepicker: function(target) {
-               if (!target) {
-                       return false;
-               }
-               for (var i = 0; i < this._disabledInputs.length; i++) {
-                       if (this._disabledInputs[i] == target)
-                               return true;
-               }
-               return false;
-       },
-
-       /* Retrieve the instance data for the target control.
-          @param  target  element - the target input field or division or span
-          @return  object - the associated instance data
-          @throws  error if a jQuery problem getting data */
-       _getInst: function(target) {
-               try {
-                       return $.data(target, PROP_NAME);
-               }
-               catch (err) {
-                       throw 'Missing instance data for this datepicker';
-               }
-       },
-
-       /* Update or retrieve the settings for a date picker attached to an input field or division.
-          @param  target  element - the target input field or division or span
-          @param  name    object - the new settings to update or
-                          string - the name of the setting to change or retrieve,
-                          when retrieving also 'all' for all instance settings or
-                          'defaults' for all global defaults
-          @param  value   any - the new value for the setting
-                          (omit if above is an object or to retrieve a value) */
-       _optionDatepicker: function(target, name, value) {
-               var inst = this._getInst(target);
-               if (arguments.length == 2 && typeof name == 'string') {
-                       return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
-                               (inst ? (name == 'all' ? $.extend({}, inst.settings) :
-                               this._get(inst, name)) : null));
-               }
-               var settings = name || {};
-               if (typeof name == 'string') {
-                       settings = {};
-                       settings[name] = value;
-               }
-               if (inst) {
-                       if (this._curInst == inst) {
-                               this._hideDatepicker();
-                       }
-                       var date = this._getDateDatepicker(target, true);
-                       var minDate = this._getMinMaxDate(inst, 'min');
-                       var maxDate = this._getMinMaxDate(inst, 'max');
-                       extendRemove(inst.settings, settings);
-                       // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
-                       if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
-                               inst.settings.minDate = this._formatDate(inst, minDate);
-                       if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
-                               inst.settings.maxDate = this._formatDate(inst, maxDate);
-                       this._attachments($(target), inst);
-                       this._autoSize(inst);
-                       this._setDate(inst, date);
-                       this._updateAlternate(inst);
-                       this._updateDatepicker(inst);
-               }
-       },
-
-       // change method deprecated
-       _changeDatepicker: function(target, name, value) {
-               this._optionDatepicker(target, name, value);
-       },
-
-       /* Redraw the date picker attached to an input field or division.
-          @param  target  element - the target input field or division or span */
-       _refreshDatepicker: function(target) {
-               var inst = this._getInst(target);
-               if (inst) {
-                       this._updateDatepicker(inst);
-               }
-       },
-
-       /* Set the dates for a jQuery selection.
-          @param  target   element - the target input field or division or span
-          @param  date     Date - the new date */
-       _setDateDatepicker: function(target, date) {
-               var inst = this._getInst(target);
-               if (inst) {
-                       this._setDate(inst, date);
-                       this._updateDatepicker(inst);
-                       this._updateAlternate(inst);
-               }
-       },
-
-       /* Get the date(s) for the first entry in a jQuery selection.
-          @param  target     element - the target input field or division or span
-          @param  noDefault  boolean - true if no default date is to be used
-          @return Date - the current date */
-       _getDateDatepicker: function(target, noDefault) {
-               var inst = this._getInst(target);
-               if (inst && !inst.inline)
-                       this._setDateFromField(inst, noDefault);
-               return (inst ? this._getDate(inst) : null);
-       },
-
-       /* Handle keystrokes. */
-       _doKeyDown: function(event) {
-               var inst = $.datepicker._getInst(event.target);
-               var handled = true;
-               var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
-               inst._keyEvent = true;
-               if ($.datepicker._datepickerShowing)
-                       switch (event.keyCode) {
-                               case 9: $.datepicker._hideDatepicker();
-                                               handled = false;
-                                               break; // hide on tab out
-                               case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + 
-                                                                       $.datepicker._currentClass + ')', inst.dpDiv);
-                                               if (sel[0])
-                                                       $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
-                                                       var onSelect = $.datepicker._get(inst, 'onSelect');
-                                                       if (onSelect) {
-                                                               var dateStr = $.datepicker._formatDate(inst);
-
-                                                               // trigger custom callback
-                                                               onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
-                                                       }
-                                               else
-                                                       $.datepicker._hideDatepicker();
-                                               return false; // don't submit the form
-                                               break; // select the value on enter
-                               case 27: $.datepicker._hideDatepicker();
-                                               break; // hide on escape
-                               case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-                                                       -$.datepicker._get(inst, 'stepBigMonths') :
-                                                       -$.datepicker._get(inst, 'stepMonths')), 'M');
-                                               break; // previous month/year on page up/+ ctrl
-                               case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-                                                       +$.datepicker._get(inst, 'stepBigMonths') :
-                                                       +$.datepicker._get(inst, 'stepMonths')), 'M');
-                                               break; // next month/year on page down/+ ctrl
-                               case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
-                                               handled = event.ctrlKey || event.metaKey;
-                                               break; // clear on ctrl or command +end
-                               case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
-                                               handled = event.ctrlKey || event.metaKey;
-                                               break; // current on ctrl or command +home
-                               case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
-                                               handled = event.ctrlKey || event.metaKey;
-                                               // -1 day on ctrl or command +left
-                                               if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-                                                                       -$.datepicker._get(inst, 'stepBigMonths') :
-                                                                       -$.datepicker._get(inst, 'stepMonths')), 'M');
-                                               // next month/year on alt +left on Mac
-                                               break;
-                               case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
-                                               handled = event.ctrlKey || event.metaKey;
-                                               break; // -1 week on ctrl or command +up
-                               case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
-                                               handled = event.ctrlKey || event.metaKey;
-                                               // +1 day on ctrl or command +right
-                                               if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-                                                                       +$.datepicker._get(inst, 'stepBigMonths') :
-                                                                       +$.datepicker._get(inst, 'stepMonths')), 'M');
-                                               // next month/year on alt +right
-                                               break;
-                               case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
-                                               handled = event.ctrlKey || event.metaKey;
-                                               break; // +1 week on ctrl or command +down
-                               default: handled = false;
-                       }
-               else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
-                       $.datepicker._showDatepicker(this);
-               else {
-                       handled = false;
-               }
-               if (handled) {
-                       event.preventDefault();
-                       event.stopPropagation();
-               }
-       },
-
-       /* Filter entered characters - based on date format. */
-       _doKeyPress: function(event) {
-               var inst = $.datepicker._getInst(event.target);
-               if ($.datepicker._get(inst, 'constrainInput')) {
-                       var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
-                       var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
-                       return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
-               }
-       },
-
-       /* Synchronise manual entry and field/alternate field. */
-       _doKeyUp: function(event) {
-               var inst = $.datepicker._getInst(event.target);
-               if (inst.input.val() != inst.lastVal) {
-                       try {
-                               var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
-                                       (inst.input ? inst.input.val() : null),
-                                       $.datepicker._getFormatConfig(inst));
-                               if (date) { // only if valid
-                                       $.datepicker._setDateFromField(inst);
-                                       $.datepicker._updateAlternate(inst);
-                                       $.datepicker._updateDatepicker(inst);
-                               }
-                       }
-                       catch (err) {
-                               $.datepicker.log(err);
-                       }
-               }
-               return true;
-       },
-
-       /* Pop-up the date picker for a given input field.
-       If false returned from beforeShow event handler do not show. 
-          @param  input  element - the input field attached to the date picker or
-                         event - if triggered by focus */
-       _showDatepicker: function(input) {
-               input = input.target || input;
-               if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
-                       input = $('input', input.parentNode)[0];
-               if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
-                       return;
-               var inst = $.datepicker._getInst(input);
-               if ($.datepicker._curInst && $.datepicker._curInst != inst) {
-                       $.datepicker._curInst.dpDiv.stop(true, true);
-                       if ( inst && $.datepicker._datepickerShowing ) {
-                               $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
-                       }
-               }
-               var beforeShow = $.datepicker._get(inst, 'beforeShow');
-               var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
-               if(beforeShowSettings === false){
-            //false
-                       return;
-               }
-               extendRemove(inst.settings, beforeShowSettings);
-               inst.lastVal = null;
-               $.datepicker._lastInput = input;
-               $.datepicker._setDateFromField(inst);
-               if ($.datepicker._inDialog) // hide cursor
-                       input.value = '';
-               if (!$.datepicker._pos) { // position below input
-                       $.datepicker._pos = $.datepicker._findPos(input);
-                       $.datepicker._pos[1] += input.offsetHeight; // add the height
-               }
-               var isFixed = false;
-               $(input).parents().each(function() {
-                       isFixed |= $(this).css('position') == 'fixed';
-                       return !isFixed;
-               });
-               if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
-                       $.datepicker._pos[0] -= document.documentElement.scrollLeft;
-                       $.datepicker._pos[1] -= document.documentElement.scrollTop;
-               }
-               var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
-               $.datepicker._pos = null;
-               //to avoid flashes on Firefox
-               inst.dpDiv.empty();
-               // determine sizing offscreen
-               inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
-               $.datepicker._updateDatepicker(inst);
-               // fix width for dynamic number of date pickers
-               // and adjust position before showing
-               offset = $.datepicker._checkOffset(inst, offset, isFixed);
-               inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
-                       'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
-                       left: offset.left + 'px', top: offset.top + 'px'});
-               if (!inst.inline) {
-                       var showAnim = $.datepicker._get(inst, 'showAnim');
-                       var duration = $.datepicker._get(inst, 'duration');
-                       var postProcess = function() {
-                               var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
-                               if( !! cover.length ){
-                                       var borders = $.datepicker._getBorders(inst.dpDiv);
-                                       cover.css({left: -borders[0], top: -borders[1],
-                                               width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
-                               }
-                       };
-                       inst.dpDiv.zIndex($(input).zIndex()+1);
-                       $.datepicker._datepickerShowing = true;
-                       if ($.effects && $.effects[showAnim])
-                               inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
-                       else
-                               inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
-                       if (!showAnim || !duration)
-                               postProcess();
-                       if (inst.input.is(':visible') && !inst.input.is(':disabled'))
-                               inst.input.focus();
-                       $.datepicker._curInst = inst;
-               }
-       },
-
-       /* Generate the date picker content. */
-       _updateDatepicker: function(inst) {
-               var self = this;
-               self.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
-               var borders = $.datepicker._getBorders(inst.dpDiv);
-               instActive = inst; // for delegate hover events
-               inst.dpDiv.empty().append(this._generateHTML(inst));
-               this._attachHandlers(inst);
-               var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
-               if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
-                       cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
-               }
-               inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
-               var numMonths = this._getNumberOfMonths(inst);
-               var cols = numMonths[1];
-               var width = 17;
-               inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
-               if (cols > 1)
-                       inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
-               inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
-                       'Class']('ui-datepicker-multi');
-               inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
-                       'Class']('ui-datepicker-rtl');
-               if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
-                               // #6694 - don't focus the input if it's already focused
-                               // this breaks the change event in IE
-                               inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
-                       inst.input.focus();
-               // deffered render of the years select (to avoid flashes on Firefox) 
-               if( inst.yearshtml ){
-                       var origyearshtml = inst.yearshtml;
-                       setTimeout(function(){
-                               //assure that inst.yearshtml didn't change.
-                               if( origyearshtml === inst.yearshtml && inst.yearshtml ){
-                                       inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
-                               }
-                               origyearshtml = inst.yearshtml = null;
-                       }, 0);
-               }
-       },
-
-       /* Retrieve the size of left and top borders for an element.
-          @param  elem  (jQuery object) the element of interest
-          @return  (number[2]) the left and top borders */
-       _getBorders: function(elem) {
-               var convert = function(value) {
-                       return {thin: 1, medium: 2, thick: 3}[value] || value;
-               };
-               return [parseFloat(convert(elem.css('border-left-width'))),
-                       parseFloat(convert(elem.css('border-top-width')))];
-       },
-
-       /* Check positioning to remain on screen. */
-       _checkOffset: function(inst, offset, isFixed) {
-               var dpWidth = inst.dpDiv.outerWidth();
-               var dpHeight = inst.dpDiv.outerHeight();
-               var inputWidth = inst.input ? inst.input.outerWidth() : 0;
-               var inputHeight = inst.input ? inst.input.outerHeight() : 0;
-               var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft());
-               var viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
-
-               offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
-               offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
-               offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
-
-               // now check if datepicker is showing outside window viewport - move to a better place if so.
-               offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
-                       Math.abs(offset.left + dpWidth - viewWidth) : 0);
-               offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
-                       Math.abs(dpHeight + inputHeight) : 0);
-
-               return offset;
-       },
-
-       /* Find an object's position on the screen. */
-       _findPos: function(obj) {
-               var inst = this._getInst(obj);
-               var isRTL = this._get(inst, 'isRTL');
-        while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
-            obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
-        }
-        var position = $(obj).offset();
-           return [position.left, position.top];
-       },
-
-       /* Hide the date picker from view.
-          @param  input  element - the input field attached to the date picker */
-       _hideDatepicker: function(input) {
-               var inst = this._curInst;
-               if (!inst || (input && inst != $.data(input, PROP_NAME)))
-                       return;
-               if (this._datepickerShowing) {
-                       var showAnim = this._get(inst, 'showAnim');
-                       var duration = this._get(inst, 'duration');
-                       var postProcess = function() {
-                               $.datepicker._tidyDialog(inst);
-                       };
-                       if ($.effects && $.effects[showAnim])
-                               inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
-                       else
-                               inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
-                                       (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
-                       if (!showAnim)
-                               postProcess();
-                       this._datepickerShowing = false;
-                       var onClose = this._get(inst, 'onClose');
-                       if (onClose)
-                               onClose.apply((inst.input ? inst.input[0] : null),
-                                       [(inst.input ? inst.input.val() : ''), inst]);
-                       this._lastInput = null;
-                       if (this._inDialog) {
-                               this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
-                               if ($.blockUI) {
-                                       $.unblockUI();
-                                       $('body').append(this.dpDiv);
-                               }
-                       }
-                       this._inDialog = false;
-               }
-       },
-
-       /* Tidy up after a dialog display. */
-       _tidyDialog: function(inst) {
-               inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
-       },
-
-       /* Close date picker if clicked elsewhere. */
-       _checkExternalClick: function(event) {
-               if (!$.datepicker._curInst)
-                       return;
-
-               var $target = $(event.target),
-                       inst = $.datepicker._getInst($target[0]);
-
-               if ( ( ( $target[0].id != $.datepicker._mainDivId &&
-                               $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
-                               !$target.hasClass($.datepicker.markerClassName) &&
-                               !$target.closest("." + $.datepicker._triggerClass).length &&
-                               $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
-                       ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) )
-                       $.datepicker._hideDatepicker();
-       },
-
-       /* Adjust one of the date sub-fields. */
-       _adjustDate: function(id, offset, period) {
-               var target = $(id);
-               var inst = this._getInst(target[0]);
-               if (this._isDisabledDatepicker(target[0])) {
-                       return;
-               }
-               this._adjustInstDate(inst, offset +
-                       (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
-                       period);
-               this._updateDatepicker(inst);
-       },
-
-       /* Action for current link. */
-       _gotoToday: function(id) {
-               var target = $(id);
-               var inst = this._getInst(target[0]);
-               if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
-                       inst.selectedDay = inst.currentDay;
-                       inst.drawMonth = inst.selectedMonth = inst.currentMonth;
-                       inst.drawYear = inst.selectedYear = inst.currentYear;
-               }
-               else {
-                       var date = new Date();
-                       inst.selectedDay = date.getDate();
-                       inst.drawMonth = inst.selectedMonth = date.getMonth();
-                       inst.drawYear = inst.selectedYear = date.getFullYear();
-               }
-               this._notifyChange(inst);
-               this._adjustDate(target);
-       },
-
-       /* Action for selecting a new month/year. */
-       _selectMonthYear: function(id, select, period) {
-               var target = $(id);
-               var inst = this._getInst(target[0]);
-               inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
-               inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
-                       parseInt(select.options[select.selectedIndex].value,10);
-               this._notifyChange(inst);
-               this._adjustDate(target);
-       },
-
-       /* Action for selecting a day. */
-       _selectDay: function(id, month, year, td) {
-               var target = $(id);
-               if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
-                       return;
-               }
-               var inst = this._getInst(target[0]);
-               inst.selectedDay = inst.currentDay = $('a', td).html();
-               inst.selectedMonth = inst.currentMonth = month;
-               inst.selectedYear = inst.currentYear = year;
-               this._selectDate(id, this._formatDate(inst,
-                       inst.currentDay, inst.currentMonth, inst.currentYear));
-       },
-
-       /* Erase the input field and hide the date picker. */
-       _clearDate: function(id) {
-               var target = $(id);
-               var inst = this._getInst(target[0]);
-               this._selectDate(target, '');
-       },
-
-       /* Update the input field with the selected date. */
-       _selectDate: function(id, dateStr) {
-               var target = $(id);
-               var inst = this._getInst(target[0]);
-               dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
-               if (inst.input)
-                       inst.input.val(dateStr);
-               this._updateAlternate(inst);
-               var onSelect = this._get(inst, 'onSelect');
-               if (onSelect)
-                       onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
-               else if (inst.input)
-                       inst.input.trigger('change'); // fire the change event
-               if (inst.inline)
-                       this._updateDatepicker(inst);
-               else {
-                       this._hideDatepicker();
-                       this._lastInput = inst.input[0];
-                       if (typeof(inst.input[0]) != 'object')
-                               inst.input.focus(); // restore focus
-                       this._lastInput = null;
-               }
-       },
-
-       /* Update any alternate field to synchronise with the main field. */
-       _updateAlternate: function(inst) {
-               var altField = this._get(inst, 'altField');
-               if (altField) { // update alternate field too
-                       var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
-                       var date = this._getDate(inst);
-                       var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
-                       $(altField).each(function() { $(this).val(dateStr); });
-               }
-       },
-
-       /* Set as beforeShowDay function to prevent selection of weekends.
-          @param  date  Date - the date to customise
-          @return [boolean, string] - is this date selectable?, what is its CSS class? */
-       noWeekends: function(date) {
-               var day = date.getDay();
-               return [(day > 0 && day < 6), ''];
-       },
-
-       /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
-          @param  date  Date - the date to get the week for
-          @return  number - the number of the week within the year that contains this date */
-       iso8601Week: function(date) {
-               var checkDate = new Date(date.getTime());
-               // Find Thursday of this week starting on Monday
-               checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
-               var time = checkDate.getTime();
-               checkDate.setMonth(0); // Compare with Jan 1
-               checkDate.setDate(1);
-               return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
-       },
-
-       /* Parse a string value into a date object.
-          See formatDate below for the possible formats.
-
-          @param  format    string - the expected format of the date
-          @param  value     string - the date in the above format
-          @param  settings  Object - attributes include:
-                            shortYearCutoff  number - the cutoff year for determining the century (optional)
-                            dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
-                            dayNames         string[7] - names of the days from Sunday (optional)
-                            monthNamesShort  string[12] - abbreviated names of the months (optional)
-                            monthNames       string[12] - names of the months (optional)
-          @return  Date - the extracted date value or null if value is blank */
-       parseDate: function (format, value, settings) {
-               if (format == null || value == null)
-                       throw 'Invalid arguments';
-               value = (typeof value == 'object' ? value.toString() : value + '');
-               if (value == '')
-                       return null;
-               var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
-               shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
-                               new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
-               var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
-               var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
-               var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
-               var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
-               var year = -1;
-               var month = -1;
-               var day = -1;
-               var doy = -1;
-               var literal = false;
-               // Check whether a format character is doubled
-               var lookAhead = function(match) {
-                       var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
-                       if (matches)
-                               iFormat++;
-                       return matches;
-               };
-               // Extract a number from the string value
-               var getNumber = function(match) {
-                       var isDoubled = lookAhead(match);
-                       var size = (match == '@' ? 14 : (match == '!' ? 20 :
-                               (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
-                       var digits = new RegExp('^\\d{1,' + size + '}');
-                       var num = value.substring(iValue).match(digits);
-                       if (!num)
-                               throw 'Missing number at position ' + iValue;
-                       iValue += num[0].length;
-                       return parseInt(num[0], 10);
-               };
-               // Extract a name from the string value and convert to an index
-               var getName = function(match, shortNames, longNames) {
-                       var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
-                               return [ [k, v] ];
-                       }).sort(function (a, b) {
-                               return -(a[1].length - b[1].length);
-                       });
-                       var index = -1;
-                       $.each(names, function (i, pair) {
-                               var name = pair[1];
-                               if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
-                                       index = pair[0];
-                                       iValue += name.length;
-                                       return false;
-                               }
-                       });
-                       if (index != -1)
-                               return index + 1;
-                       else
-                               throw 'Unknown name at position ' + iValue;
-               };
-               // Confirm that a literal character matches the string value
-               var checkLiteral = function() {
-                       if (value.charAt(iValue) != format.charAt(iFormat))
-                               throw 'Unexpected literal at position ' + iValue;
-                       iValue++;
-               };
-               var iValue = 0;
-               for (var iFormat = 0; iFormat < format.length; iFormat++) {
-                       if (literal)
-                               if (format.charAt(iFormat) == "'" && !lookAhead("'"))
-                                       literal = false;
-                               else
-                                       checkLiteral();
-                       else
-                               switch (format.charAt(iFormat)) {
-                                       case 'd':
-                                               day = getNumber('d');
-                                               break;
-                                       case 'D':
-                                               getName('D', dayNamesShort, dayNames);
-                                               break;
-                                       case 'o':
-                                               doy = getNumber('o');
-                                               break;
-                                       case 'm':
-                                               month = getNumber('m');
-                                               break;
-                                       case 'M':
-                                               month = getName('M', monthNamesShort, monthNames);
-                                               break;
-                                       case 'y':
-                                               year = getNumber('y');
-                                               break;
-                                       case '@':
-                                               var date = new Date(getNumber('@'));
-                                               year = date.getFullYear();
-                                               month = date.getMonth() + 1;
-                                               day = date.getDate();
-                                               break;
-                                       case '!':
-                                               var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
-                                               year = date.getFullYear();
-                                               month = date.getMonth() + 1;
-                                               day = date.getDate();
-                                               break;
-                                       case "'":
-                                               if (lookAhead("'"))
-                                                       checkLiteral();
-                                               else
-                                                       literal = true;
-                                               break;
-                                       default:
-                                               checkLiteral();
-                               }
-               }
-               if (iValue < value.length){
-                       throw "Extra/unparsed characters found in date: " + value.substring(iValue);
-               }
-               if (year == -1)
-                       year = new Date().getFullYear();
-               else if (year < 100)
-                       year += new Date().getFullYear() - new Date().getFullYear() % 100 +
-                               (year <= shortYearCutoff ? 0 : -100);
-               if (doy > -1) {
-                       month = 1;
-                       day = doy;
-                       do {
-                               var dim = this._getDaysInMonth(year, month - 1);
-                               if (day <= dim)
-                                       break;
-                               month++;
-                               day -= dim;
-                       } while (true);
-               }
-               var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
-               if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
-                       throw 'Invalid date'; // E.g. 31/02/00
-               return date;
-       },
-
-       /* Standard date formats. */
-       ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
-       COOKIE: 'D, dd M yy',
-       ISO_8601: 'yy-mm-dd',
-       RFC_822: 'D, d M y',
-       RFC_850: 'DD, dd-M-y',
-       RFC_1036: 'D, d M y',
-       RFC_1123: 'D, d M yy',
-       RFC_2822: 'D, d M yy',
-       RSS: 'D, d M y', // RFC 822
-       TICKS: '!',
-       TIMESTAMP: '@',
-       W3C: 'yy-mm-dd', // ISO 8601
-
-       _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
-               Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
-
-       /* Format a date object into a string value.
-          The format can be combinations of the following:
-          d  - day of month (no leading zero)
-          dd - day of month (two digit)
-          o  - day of year (no leading zeros)
-          oo - day of year (three digit)
-          D  - day name short
-          DD - day name long
-          m  - month of year (no leading zero)
-          mm - month of year (two digit)
-          M  - month name short
-          MM - month name long
-          y  - year (two digit)
-          yy - year (four digit)
-          @ - Unix timestamp (ms since 01/01/1970)
-          ! - Windows ticks (100ns since 01/01/0001)
-          '...' - literal text
-          '' - single quote
-
-          @param  format    string - the desired format of the date
-          @param  date      Date - the date value to format
-          @param  settings  Object - attributes include:
-                            dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
-                            dayNames         string[7] - names of the days from Sunday (optional)
-                            monthNamesShort  string[12] - abbreviated names of the months (optional)
-                            monthNames       string[12] - names of the months (optional)
-          @return  string - the date in the above format */
-       formatDate: function (format, date, settings) {
-               if (!date)
-                       return '';
-               var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
-               var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
-               var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
-               var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
-               // Check whether a format character is doubled
-               var lookAhead = function(match) {
-                       var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
-                       if (matches)
-                               iFormat++;
-                       return matches;
-               };
-               // Format a number, with leading zero if necessary
-               var formatNumber = function(match, value, len) {
-                       var num = '' + value;
-                       if (lookAhead(match))
-                               while (num.length < len)
-                                       num = '0' + num;
-                       return num;
-               };
-               // Format a name, short or long as requested
-               var formatName = function(match, value, shortNames, longNames) {
-                       return (lookAhead(match) ? longNames[value] : shortNames[value]);
-               };
-               var output = '';
-               var literal = false;
-               if (date)
-                       for (var iFormat = 0; iFormat < format.length; iFormat++) {
-                               if (literal)
-                                       if (format.charAt(iFormat) == "'" && !lookAhead("'"))
-                                               literal = false;
-                                       else
-                                               output += format.charAt(iFormat);
-                               else
-                                       switch (format.charAt(iFormat)) {
-                                               case 'd':
-                                                       output += formatNumber('d', date.getDate(), 2);
-                                                       break;
-                                               case 'D':
-                                                       output += formatName('D', date.getDay(), dayNamesShort, dayNames);
-                                                       break;
-                                               case 'o':
-                                                       output += formatNumber('o',
-                                                               Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
-                                                       break;
-                                               case 'm':
-                                                       output += formatNumber('m', date.getMonth() + 1, 2);
-                                                       break;
-                                               case 'M':
-                                                       output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
-                                                       break;
-                                               case 'y':
-                                                       output += (lookAhead('y') ? date.getFullYear() :
-                                                               (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
-                                                       break;
-                                               case '@':
-                                                       output += date.getTime();
-                                                       break;
-                                               case '!':
-                                                       output += date.getTime() * 10000 + this._ticksTo1970;
-                                                       break;
-                                               case "'":
-                                                       if (lookAhead("'"))
-                                                               output += "'";
-                                                       else
-                                                               literal = true;
-                                                       break;
-                                               default:
-                                                       output += format.charAt(iFormat);
-                                       }
-                       }
-               return output;
-       },
-
-       /* Extract all possible characters from the date format. */
-       _possibleChars: function (format) {
-               var chars = '';
-               var literal = false;
-               // Check whether a format character is doubled
-               var lookAhead = function(match) {
-                       var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
-                       if (matches)
-                               iFormat++;
-                       return matches;
-               };
-               for (var iFormat = 0; iFormat < format.length; iFormat++)
-                       if (literal)
-                               if (format.charAt(iFormat) == "'" && !lookAhead("'"))
-                                       literal = false;
-                               else
-                                       chars += format.charAt(iFormat);
-                       else
-                               switch (format.charAt(iFormat)) {
-                                       case 'd': case 'm': case 'y': case '@':
-                                               chars += '0123456789';
-                                               break;
-                                       case 'D': case 'M':
-                                               return null; // Accept anything
-                                       case "'":
-                                               if (lookAhead("'"))
-                                                       chars += "'";
-                                               else
-                                                       literal = true;
-                                               break;
-                                       default:
-                                               chars += format.charAt(iFormat);
-                               }
-               return chars;
-       },
-
-       /* Get a setting value, defaulting if necessary. */
-       _get: function(inst, name) {
-               return inst.settings[name] !== undefined ?
-                       inst.settings[name] : this._defaults[name];
-       },
-
-       /* Parse existing date and initialise date picker. */
-       _setDateFromField: function(inst, noDefault) {
-               if (inst.input.val() == inst.lastVal) {
-                       return;
-               }
-               var dateFormat = this._get(inst, 'dateFormat');
-               var dates = inst.lastVal = inst.input ? inst.input.val() : null;
-               var date, defaultDate;
-               date = defaultDate = this._getDefaultDate(inst);
-               var settings = this._getFormatConfig(inst);
-               try {
-                       date = this.parseDate(dateFormat, dates, settings) || defaultDate;
-               } catch (event) {
-                       this.log(event);
-                       dates = (noDefault ? '' : dates);
-               }
-               inst.selectedDay = date.getDate();
-               inst.drawMonth = inst.selectedMonth = date.getMonth();
-               inst.drawYear = inst.selectedYear = date.getFullYear();
-               inst.currentDay = (dates ? date.getDate() : 0);
-               inst.currentMonth = (dates ? date.getMonth() : 0);
-               inst.currentYear = (dates ? date.getFullYear() : 0);
-               this._adjustInstDate(inst);
-       },
-
-       /* Retrieve the default date shown on opening. */
-       _getDefaultDate: function(inst) {
-               return this._restrictMinMax(inst,
-                       this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
-       },
-
-       /* A date may be specified as an exact value or a relative one. */
-       _determineDate: function(inst, date, defaultDate) {
-               var offsetNumeric = function(offset) {
-                       var date = new Date();
-                       date.setDate(date.getDate() + offset);
-                       return date;
-               };
-               var offsetString = function(offset) {
-                       try {
-                               return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
-                                       offset, $.datepicker._getFormatConfig(inst));
-                       }
-                       catch (e) {
-                               // Ignore
-                       }
-                       var date = (offset.toLowerCase().match(/^c/) ?
-                               $.datepicker._getDate(inst) : null) || new Date();
-                       var year = date.getFullYear();
-                       var month = date.getMonth();
-                       var day = date.getDate();
-                       var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
-                       var matches = pattern.exec(offset);
-                       while (matches) {
-                               switch (matches[2] || 'd') {
-                                       case 'd' : case 'D' :
-                                               day += parseInt(matches[1],10); break;
-                                       case 'w' : case 'W' :
-                                               day += parseInt(matches[1],10) * 7; break;
-                                       case 'm' : case 'M' :
-                                               month += parseInt(matches[1],10);
-                                               day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
-                                               break;
-                                       case 'y': case 'Y' :
-                                               year += parseInt(matches[1],10);
-                                               day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
-                                               break;
-                               }
-                               matches = pattern.exec(offset);
-                       }
-                       return new Date(year, month, day);
-               };
-               var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
-                       (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
-               newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
-               if (newDate) {
-                       newDate.setHours(0);
-                       newDate.setMinutes(0);
-                       newDate.setSeconds(0);
-                       newDate.setMilliseconds(0);
-               }
-               return this._daylightSavingAdjust(newDate);
-       },
-
-       /* Handle switch to/from daylight saving.
-          Hours may be non-zero on daylight saving cut-over:
-          > 12 when midnight changeover, but then cannot generate
-          midnight datetime, so jump to 1AM, otherwise reset.
-          @param  date  (Date) the date to check
-          @return  (Date) the corrected date */
-       _daylightSavingAdjust: function(date) {
-               if (!date) return null;
-               date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
-               return date;
-       },
-
-       /* Set the date(s) directly. */
-       _setDate: function(inst, date, noChange) {
-               var clear = !date;
-               var origMonth = inst.selectedMonth;
-               var origYear = inst.selectedYear;
-               var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
-               inst.selectedDay = inst.currentDay = newDate.getDate();
-               inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
-               inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
-               if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
-                       this._notifyChange(inst);
-               this._adjustInstDate(inst);
-               if (inst.input) {
-                       inst.input.val(clear ? '' : this._formatDate(inst));
-               }
-       },
-
-       /* Retrieve the date(s) directly. */
-       _getDate: function(inst) {
-               var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
-                       this._daylightSavingAdjust(new Date(
-                       inst.currentYear, inst.currentMonth, inst.currentDay)));
-                       return startDate;
-       },
-
-       /* Attach the onxxx handlers.  These are declared statically so
-        * they work with static code transformers like Caja.
-        */
-       _attachHandlers: function(inst) {
-               var stepMonths = this._get(inst, 'stepMonths');
-               var id = '#' + inst.id.replace( /\\\\/g, "\\" );
-               inst.dpDiv.find('[data-handler]').map(function () {
-                       var handler = {
-                               prev: function () {
-                                       window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M');
-                               },
-                               next: function () {
-                                       window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M');
-                               },
-                               hide: function () {
-                                       window['DP_jQuery_' + dpuuid].datepicker._hideDatepicker();
-                               },
-                               today: function () {
-                                       window['DP_jQuery_' + dpuuid].datepicker._gotoToday(id);
-                               },
-                               selectDay: function () {
-                                       window['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this);
-                                       return false;
-                               },
-                               selectMonth: function () {
-                                       window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M');
-                                       return false;
-                               },
-                               selectYear: function () {
-                                       window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y');
-                                       return false;
-                               }
-                       };
-                       $(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]);
-               });
-       },
-       
-       /* Generate the HTML for the current state of the date picker. */
-       _generateHTML: function(inst) {
-               var today = new Date();
-               today = this._daylightSavingAdjust(
-                       new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
-               var isRTL = this._get(inst, 'isRTL');
-               var showButtonPanel = this._get(inst, 'showButtonPanel');
-               var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
-               var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
-               var numMonths = this._getNumberOfMonths(inst);
-               var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
-               var stepMonths = this._get(inst, 'stepMonths');
-               var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
-               var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
-                       new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
-               var minDate = this._getMinMaxDate(inst, 'min');
-               var maxDate = this._getMinMaxDate(inst, 'max');
-               var drawMonth = inst.drawMonth - showCurrentAtPos;
-               var drawYear = inst.drawYear;
-               if (drawMonth < 0) {
-                       drawMonth += 12;
-                       drawYear--;
-               }
-               if (maxDate) {
-                       var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
-                               maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
-                       maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
-                       while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
-                               drawMonth--;
-                               if (drawMonth < 0) {
-                                       drawMonth = 11;
-                                       drawYear--;
-                               }
-                       }
-               }
-               inst.drawMonth = drawMonth;
-               inst.drawYear = drawYear;
-               var prevText = this._get(inst, 'prevText');
-               prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
-                       this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
-                       this._getFormatConfig(inst)));
-               var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
-                       '<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click"' +
-                       ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
-                       (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
-               var nextText = this._get(inst, 'nextText');
-               nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
-                       this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
-                       this._getFormatConfig(inst)));
-               var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
-                       '<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click"' +
-                       ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
-                       (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
-               var currentText = this._get(inst, 'currentText');
-               var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
-               currentText = (!navigationAsDateFormat ? currentText :
-                       this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
-               var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">' +
-                       this._get(inst, 'closeText') + '</button>' : '');
-               var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
-                       (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click"' +
-                       '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
-               var firstDay = parseInt(this._get(inst, 'firstDay'),10);
-               firstDay = (isNaN(firstDay) ? 0 : firstDay);
-               var showWeek = this._get(inst, 'showWeek');
-               var dayNames = this._get(inst, 'dayNames');
-               var dayNamesShort = this._get(inst, 'dayNamesShort');
-               var dayNamesMin = this._get(inst, 'dayNamesMin');
-               var monthNames = this._get(inst, 'monthNames');
-               var monthNamesShort = this._get(inst, 'monthNamesShort');
-               var beforeShowDay = this._get(inst, 'beforeShowDay');
-               var showOtherMonths = this._get(inst, 'showOtherMonths');
-               var selectOtherMonths = this._get(inst, 'selectOtherMonths');
-               var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
-               var defaultDate = this._getDefaultDate(inst);
-               var html = '';
-               for (var row = 0; row < numMonths[0]; row++) {
-                       var group = '';
-                       this.maxRows = 4;
-                       for (var col = 0; col < numMonths[1]; col++) {
-                               var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
-                               var cornerClass = ' ui-corner-all';
-                               var calender = '';
-                               if (isMultiMonth) {
-                                       calender += '<div class="ui-datepicker-group';
-                                       if (numMonths[1] > 1)
-                                               switch (col) {
-                                                       case 0: calender += ' ui-datepicker-group-first';
-                                                               cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
-                                                       case numMonths[1]-1: calender += ' ui-datepicker-group-last';
-                                                               cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
-                                                       default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
-                                               }
-                                       calender += '">';
-                               }
-                               calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
-                                       (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
-                                       (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
-                                       this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
-                                       row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
-                                       '</div><table class="ui-datepicker-calendar"><thead>' +
-                                       '<tr>';
-                               var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
-                               for (var dow = 0; dow < 7; dow++) { // days of the week
-                                       var day = (dow + firstDay) % 7;
-                                       thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
-                                               '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
-                               }
-                               calender += thead + '</tr></thead><tbody>';
-                               var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
-                               if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
-                                       inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
-                               var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
-                               var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
-                               var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
-                               this.maxRows = numRows;
-                               var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
-                               for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
-                                       calender += '<tr>';
-                                       var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
-                                               this._get(inst, 'calculateWeek')(printDate) + '</td>');
-                                       for (var dow = 0; dow < 7; dow++) { // create date picker days
-                                               var daySettings = (beforeShowDay ?
-                                                       beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
-                                               var otherMonth = (printDate.getMonth() != drawMonth);
-                                               var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
-                                                       (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
-                                               tbody += '<td class="' +
-                                                       ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
-                                                       (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
-                                                       ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
-                                                       (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
-                                                       // or defaultDate is current printedDate and defaultDate is selectedDate
-                                                       ' ' + this._dayOverClass : '') + // highlight selected day
-                                                       (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
-                                                       (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
-                                                       (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
-                                                       (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
-                                                       ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
-                                                       (unselectable ? '' : ' data-handler="selectDay" data-event="click" data-month="' + printDate.getMonth() + '" data-year="' + printDate.getFullYear() + '"') + '>' + // actions
-                                                       (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
-                                                       (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
-                                                       (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
-                                                       (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
-                                                       (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
-                                                       '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
-                                               printDate.setDate(printDate.getDate() + 1);
-                                               printDate = this._daylightSavingAdjust(printDate);
-                                       }
-                                       calender += tbody + '</tr>';
-                               }
-                               drawMonth++;
-                               if (drawMonth > 11) {
-                                       drawMonth = 0;
-                                       drawYear++;
-                               }
-                               calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
-                                                       ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
-                               group += calender;
-                       }
-                       html += group;
-               }
-               html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
-                       '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
-               inst._keyEvent = false;
-               return html;
-       },
-
-       /* Generate the month and year header. */
-       _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
-                       secondary, monthNames, monthNamesShort) {
-               var changeMonth = this._get(inst, 'changeMonth');
-               var changeYear = this._get(inst, 'changeYear');
-               var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
-               var html = '<div class="ui-datepicker-title">';
-               var monthHtml = '';
-               // month selection
-               if (secondary || !changeMonth)
-                       monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
-               else {
-                       var inMinYear = (minDate && minDate.getFullYear() == drawYear);
-                       var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
-                       monthHtml += '<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';
-                       for (var month = 0; month < 12; month++) {
-                               if ((!inMinYear || month >= minDate.getMonth()) &&
-                                               (!inMaxYear || month <= maxDate.getMonth()))
-                                       monthHtml += '<option value="' + month + '"' +
-                                               (month == drawMonth ? ' selected="selected"' : '') +
-                                               '>' + monthNamesShort[month] + '</option>';
-                       }
-                       monthHtml += '</select>';
-               }
-               if (!showMonthAfterYear)
-                       html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
-               // year selection
-               if ( !inst.yearshtml ) {
-                       inst.yearshtml = '';
-                       if (secondary || !changeYear)
-                               html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
-                       else {
-                               // determine range of years to display
-                               var years = this._get(inst, 'yearRange').split(':');
-                               var thisYear = new Date().getFullYear();
-                               var determineYear = function(value) {
-                                       var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
-                                               (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
-                                               parseInt(value, 10)));
-                                       return (isNaN(year) ? thisYear : year);
-                               };
-                               var year = determineYear(years[0]);
-                               var endYear = Math.max(year, determineYear(years[1] || ''));
-                               year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
-                               endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
-                               inst.yearshtml += '<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';
-                               for (; year <= endYear; year++) {
-                                       inst.yearshtml += '<option value="' + year + '"' +
-                                               (year == drawYear ? ' selected="selected"' : '') +
-                                               '>' + year + '</option>';
-                               }
-                               inst.yearshtml += '</select>';
-                               
-                               html += inst.yearshtml;
-                               inst.yearshtml = null;
-                       }
-               }
-               html += this._get(inst, 'yearSuffix');
-               if (showMonthAfterYear)
-                       html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
-               html += '</div>'; // Close datepicker_header
-               return html;
-       },
-
-       /* Adjust one of the date sub-fields. */
-       _adjustInstDate: function(inst, offset, period) {
-               var year = inst.drawYear + (period == 'Y' ? offset : 0);
-               var month = inst.drawMonth + (period == 'M' ? offset : 0);
-               var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
-                       (period == 'D' ? offset : 0);
-               var date = this._restrictMinMax(inst,
-                       this._daylightSavingAdjust(new Date(year, month, day)));
-               inst.selectedDay = date.getDate();
-               inst.drawMonth = inst.selectedMonth = date.getMonth();
-               inst.drawYear = inst.selectedYear = date.getFullYear();
-               if (period == 'M' || period == 'Y')
-                       this._notifyChange(inst);
-       },
-
-       /* Ensure a date is within any min/max bounds. */
-       _restrictMinMax: function(inst, date) {
-               var minDate = this._getMinMaxDate(inst, 'min');
-               var maxDate = this._getMinMaxDate(inst, 'max');
-               var newDate = (minDate && date < minDate ? minDate : date);
-               newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
-               return newDate;
-       },
-
-       /* Notify change of month/year. */
-       _notifyChange: function(inst) {
-               var onChange = this._get(inst, 'onChangeMonthYear');
-               if (onChange)
-                       onChange.apply((inst.input ? inst.input[0] : null),
-                               [inst.selectedYear, inst.selectedMonth + 1, inst]);
-       },
-
-       /* Determine the number of months to show. */
-       _getNumberOfMonths: function(inst) {
-               var numMonths = this._get(inst, 'numberOfMonths');
-               return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
-       },
-
-       /* Determine the current maximum date - ensure no time components are set. */
-       _getMinMaxDate: function(inst, minMax) {
-               return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
-       },
-
-       /* Find the number of days in a given month. */
-       _getDaysInMonth: function(year, month) {
-               return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
-       },
-
-       /* Find the day of the week of the first of a month. */
-       _getFirstDayOfMonth: function(year, month) {
-               return new Date(year, month, 1).getDay();
-       },
-
-       /* Determines if we should allow a "next/prev" month display change. */
-       _canAdjustMonth: function(inst, offset, curYear, curMonth) {
-               var numMonths = this._getNumberOfMonths(inst);
-               var date = this._daylightSavingAdjust(new Date(curYear,
-                       curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
-               if (offset < 0)
-                       date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
-               return this._isInRange(inst, date);
-       },
-
-       /* Is the given date in the accepted range? */
-       _isInRange: function(inst, date) {
-               var minDate = this._getMinMaxDate(inst, 'min');
-               var maxDate = this._getMinMaxDate(inst, 'max');
-               return ((!minDate || date.getTime() >= minDate.getTime()) &&
-                       (!maxDate || date.getTime() <= maxDate.getTime()));
-       },
-
-       /* Provide the configuration settings for formatting/parsing. */
-       _getFormatConfig: function(inst) {
-               var shortYearCutoff = this._get(inst, 'shortYearCutoff');
-               shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
-                       new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
-               return {shortYearCutoff: shortYearCutoff,
-                       dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
-                       monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
-       },
-
-       /* Format the given date for display. */
-       _formatDate: function(inst, day, month, year) {
-               if (!day) {
-                       inst.currentDay = inst.selectedDay;
-                       inst.currentMonth = inst.selectedMonth;
-                       inst.currentYear = inst.selectedYear;
-               }
-               var date = (day ? (typeof day == 'object' ? day :
-                       this._daylightSavingAdjust(new Date(year, month, day))) :
-                       this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
-               return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
-       }
-});
-
-/*
- * Bind hover events for datepicker elements.
- * Done via delegate so the binding only occurs once in the lifetime of the parent div.
- * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
- */ 
-function bindHover(dpDiv) {
-       var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
-       return dpDiv.bind('mouseout', function(event) {
-                       var elem = $( event.target ).closest( selector );
-                       if ( !elem.length ) {
-                               return;
-                       }
-                       elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
-               })
-               .bind('mouseover', function(event) {
-                       var elem = $( event.target ).closest( selector );
-                       if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) ||
-                                       !elem.length ) {
-                               return;
-                       }
-                       elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
-                       elem.addClass('ui-state-hover');
-                       if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover');
-                       if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover');
-               });
-}
-
-/* jQuery extend now ignores nulls! */
-function extendRemove(target, props) {
-       $.extend(target, props);
-       for (var name in props)
-               if (props[name] == null || props[name] == undefined)
-                       target[name] = props[name];
-       return target;
-};
-
-/* Determine whether an object is an array. */
-function isArray(a) {
-       return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
-               (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
-};
-
-/* Invoke the datepicker functionality.
-   @param  options  string - a command, optionally followed by additional parameters or
-                    Object - settings for attaching new datepicker functionality
-   @return  jQuery object */
-$.fn.datepicker = function(options){
-       
-       /* Verify an empty collection wasn't passed - Fixes #6976 */
-       if ( !this.length ) {
-               return this;
-       }
-       
-       /* Initialise the date picker. */
-       if (!$.datepicker.initialized) {
-               $(document).mousedown($.datepicker._checkExternalClick).
-                       find('body').append($.datepicker.dpDiv);
-               $.datepicker.initialized = true;
-       }
-
-       var otherArgs = Array.prototype.slice.call(arguments, 1);
-       if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
-               return $.datepicker['_' + options + 'Datepicker'].
-                       apply($.datepicker, [this[0]].concat(otherArgs));
-       if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
-               return $.datepicker['_' + options + 'Datepicker'].
-                       apply($.datepicker, [this[0]].concat(otherArgs));
-       return this.each(function() {
-               typeof options == 'string' ?
-                       $.datepicker['_' + options + 'Datepicker'].
-                               apply($.datepicker, [this].concat(otherArgs)) :
-                       $.datepicker._attachDatepicker(this, options);
-       });
-};
-
-$.datepicker = new Datepicker(); // singleton instance
-$.datepicker.initialized = false;
-$.datepicker.uuid = new Date().getTime();
-$.datepicker.version = "1.8.24";
-
-// Workaround for #4055
-// Add another global to avoid noConflict issues with inline event handlers
-window['DP_jQuery_' + dpuuid] = $;
-
-})(jQuery);
diff --git a/resources/jquery.ui/jquery.ui.dialog.js b/resources/jquery.ui/jquery.ui.dialog.js
deleted file mode 100644 (file)
index 06b85f2..0000000
+++ /dev/null
@@ -1,866 +0,0 @@
-/*!
- * jQuery UI Dialog 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Dialog
- *
- * Depends:
- *     jquery.ui.core.js
- *     jquery.ui.widget.js
- *  jquery.ui.button.js
- *     jquery.ui.draggable.js
- *     jquery.ui.mouse.js
- *     jquery.ui.position.js
- *     jquery.ui.resizable.js
- */
-(function( $, undefined ) {
-
-var uiDialogClasses =
-               'ui-dialog ' +
-               'ui-widget ' +
-               'ui-widget-content ' +
-               'ui-corner-all ',
-       sizeRelatedOptions = {
-               buttons: true,
-               height: true,
-               maxHeight: true,
-               maxWidth: true,
-               minHeight: true,
-               minWidth: true,
-               width: true
-       },
-       resizableRelatedOptions = {
-               maxHeight: true,
-               maxWidth: true,
-               minHeight: true,
-               minWidth: true
-       };
-
-$.widget("ui.dialog", {
-       options: {
-               autoOpen: true,
-               buttons: {},
-               closeOnEscape: true,
-               closeText: 'close',
-               dialogClass: '',
-               draggable: true,
-               hide: null,
-               height: 'auto',
-               maxHeight: false,
-               maxWidth: false,
-               minHeight: 150,
-               minWidth: 150,
-               modal: false,
-               position: {
-                       my: 'center',
-                       at: 'center',
-                       collision: 'fit',
-                       // ensure that the titlebar is never outside the document
-                       using: function(pos) {
-                               var topOffset = $(this).css(pos).offset().top;
-                               if (topOffset < 0) {
-                                       $(this).css('top', pos.top - topOffset);
-                               }
-                       }
-               },
-               resizable: true,
-               show: null,
-               stack: true,
-               title: '',
-               width: 300,
-               zIndex: 1000
-       },
-
-       _create: function() {
-               this.originalTitle = this.element.attr('title');
-               // #5742 - .attr() might return a DOMElement
-               if ( typeof this.originalTitle !== "string" ) {
-                       this.originalTitle = "";
-               }
-
-               this.options.title = this.options.title || this.originalTitle;
-               var self = this,
-                       options = self.options,
-
-                       title = options.title || '&#160;',
-                       titleId = $.ui.dialog.getTitleId(self.element),
-
-                       uiDialog = (self.uiDialog = $('<div></div>'))
-                               .appendTo(document.body)
-                               .hide()
-                               .addClass(uiDialogClasses + options.dialogClass)
-                               .css({
-                                       zIndex: options.zIndex
-                               })
-                               // setting tabIndex makes the div focusable
-                               // setting outline to 0 prevents a border on focus in Mozilla
-                               .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
-                                       if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
-                                               event.keyCode === $.ui.keyCode.ESCAPE) {
-                                               
-                                               self.close(event);
-                                               event.preventDefault();
-                                       }
-                               })
-                               .attr({
-                                       role: 'dialog',
-                                       'aria-labelledby': titleId
-                               })
-                               .mousedown(function(event) {
-                                       self.moveToTop(false, event);
-                               }),
-
-                       uiDialogContent = self.element
-                               .show()
-                               .removeAttr('title')
-                               .addClass(
-                                       'ui-dialog-content ' +
-                                       'ui-widget-content')
-                               .appendTo(uiDialog),
-
-                       uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
-                               .addClass(
-                                       'ui-dialog-titlebar ' +
-                                       'ui-widget-header ' +
-                                       'ui-corner-all ' +
-                                       'ui-helper-clearfix'
-                               )
-                               .prependTo(uiDialog),
-
-                       uiDialogTitlebarClose = $('<a href="#"></a>')
-                               .addClass(
-                                       'ui-dialog-titlebar-close ' +
-                                       'ui-corner-all'
-                               )
-                               .attr('role', 'button')
-                               .hover(
-                                       function() {
-                                               uiDialogTitlebarClose.addClass('ui-state-hover');
-                                       },
-                                       function() {
-                                               uiDialogTitlebarClose.removeClass('ui-state-hover');
-                                       }
-                               )
-                               .focus(function() {
-                                       uiDialogTitlebarClose.addClass('ui-state-focus');
-                               })
-                               .blur(function() {
-                                       uiDialogTitlebarClose.removeClass('ui-state-focus');
-                               })
-                               .click(function(event) {
-                                       self.close(event);
-                                       return false;
-                               })
-                               .appendTo(uiDialogTitlebar),
-
-                       uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
-                               .addClass(
-                                       'ui-icon ' +
-                                       'ui-icon-closethick'
-                               )
-                               .text(options.closeText)
-                               .appendTo(uiDialogTitlebarClose),
-
-                       uiDialogTitle = $('<span></span>')
-                               .addClass('ui-dialog-title')
-                               .attr('id', titleId)
-                               .html(title)
-                               .prependTo(uiDialogTitlebar);
-
-               //handling of deprecated beforeclose (vs beforeClose) option
-               //Ticket #4669 http://dev.jqueryui.com/ticket/4669
-               //TODO: remove in 1.9pre
-               if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
-                       options.beforeClose = options.beforeclose;
-               }
-
-               uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
-
-               if (options.draggable && $.fn.draggable) {
-                       self._makeDraggable();
-               }
-               if (options.resizable && $.fn.resizable) {
-                       self._makeResizable();
-               }
-
-               self._createButtons(options.buttons);
-               self._isOpen = false;
-
-               if ($.fn.bgiframe) {
-                       uiDialog.bgiframe();
-               }
-       },
-
-       _init: function() {
-               if ( this.options.autoOpen ) {
-                       this.open();
-               }
-       },
-
-       destroy: function() {
-               var self = this;
-               
-               if (self.overlay) {
-                       self.overlay.destroy();
-               }
-               self.uiDialog.hide();
-               self.element
-                       .unbind('.dialog')
-                       .removeData('dialog')
-                       .removeClass('ui-dialog-content ui-widget-content')
-                       .hide().appendTo('body');
-               self.uiDialog.remove();
-
-               if (self.originalTitle) {
-                       self.element.attr('title', self.originalTitle);
-               }
-
-               return self;
-       },
-
-       widget: function() {
-               return this.uiDialog;
-       },
-
-       close: function(event) {
-               var self = this,
-                       maxZ, thisZ;
-               
-               if (false === self._trigger('beforeClose', event)) {
-                       return;
-               }
-
-               if (self.overlay) {
-                       self.overlay.destroy();
-               }
-               self.uiDialog.unbind('keypress.ui-dialog');
-
-               self._isOpen = false;
-
-               if (self.options.hide) {
-                       self.uiDialog.hide(self.options.hide, function() {
-                               self._trigger('close', event);
-                       });
-               } else {
-                       self.uiDialog.hide();
-                       self._trigger('close', event);
-               }
-
-               $.ui.dialog.overlay.resize();
-
-               // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
-               if (self.options.modal) {
-                       maxZ = 0;
-                       $('.ui-dialog').each(function() {
-                               if (this !== self.uiDialog[0]) {
-                                       thisZ = $(this).css('z-index');
-                                       if(!isNaN(thisZ)) {
-                                               maxZ = Math.max(maxZ, thisZ);
-                                       }
-                               }
-                       });
-                       $.ui.dialog.maxZ = maxZ;
-               }
-
-               return self;
-       },
-
-       isOpen: function() {
-               return this._isOpen;
-       },
-
-       // the force parameter allows us to move modal dialogs to their correct
-       // position on open
-       moveToTop: function(force, event) {
-               var self = this,
-                       options = self.options,
-                       saveScroll;
-
-               if ((options.modal && !force) ||
-                       (!options.stack && !options.modal)) {
-                       return self._trigger('focus', event);
-               }
-
-               if (options.zIndex > $.ui.dialog.maxZ) {
-                       $.ui.dialog.maxZ = options.zIndex;
-               }
-               if (self.overlay) {
-                       $.ui.dialog.maxZ += 1;
-                       self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
-               }
-
-               //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
-               //  http://ui.jquery.com/bugs/ticket/3193
-               saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() };
-               $.ui.dialog.maxZ += 1;
-               self.uiDialog.css('z-index', $.ui.dialog.maxZ);
-               self.element.attr(saveScroll);
-               self._trigger('focus', event);
-
-               return self;
-       },
-
-       open: function() {
-               if (this._isOpen) { return; }
-
-               var self = this,
-                       options = self.options,
-                       uiDialog = self.uiDialog;
-
-               self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
-               self._size();
-               self._position(options.position);
-               uiDialog.show(options.show);
-               self.moveToTop(true);
-
-               // prevent tabbing out of modal dialogs
-               if ( options.modal ) {
-                       uiDialog.bind( "keydown.ui-dialog", function( event ) {
-                               if ( event.keyCode !== $.ui.keyCode.TAB ) {
-                                       return;
-                               }
-
-                               var tabbables = $(':tabbable', this),
-                                       first = tabbables.filter(':first'),
-                                       last  = tabbables.filter(':last');
-
-                               if (event.target === last[0] && !event.shiftKey) {
-                                       first.focus(1);
-                                       return false;
-                               } else if (event.target === first[0] && event.shiftKey) {
-                                       last.focus(1);
-                                       return false;
-                               }
-                       });
-               }
-
-               // set focus to the first tabbable element in the content area or the first button
-               // if there are no tabbable elements, set focus on the dialog itself
-               $(self.element.find(':tabbable').get().concat(
-                       uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
-                               uiDialog.get()))).eq(0).focus();
-
-               self._isOpen = true;
-               self._trigger('open');
-
-               return self;
-       },
-
-       _createButtons: function(buttons) {
-               var self = this,
-                       hasButtons = false,
-                       uiDialogButtonPane = $('<div></div>')
-                               .addClass(
-                                       'ui-dialog-buttonpane ' +
-                                       'ui-widget-content ' +
-                                       'ui-helper-clearfix'
-                               ),
-                       uiButtonSet = $( "<div></div>" )
-                               .addClass( "ui-dialog-buttonset" )
-                               .appendTo( uiDialogButtonPane );
-
-               // if we already have a button pane, remove it
-               self.uiDialog.find('.ui-dialog-buttonpane').remove();
-
-               if (typeof buttons === 'object' && buttons !== null) {
-                       $.each(buttons, function() {
-                               return !(hasButtons = true);
-                       });
-               }
-               if (hasButtons) {
-                       $.each(buttons, function(name, props) {
-                               props = $.isFunction( props ) ?
-                                       { click: props, text: name } :
-                                       props;
-                               var button = $('<button type="button"></button>')
-                                       .click(function() {
-                                               props.click.apply(self.element[0], arguments);
-                                       })
-                                       .appendTo(uiButtonSet);
-                               // can't use .attr( props, true ) with jQuery 1.3.2.
-                               $.each( props, function( key, value ) {
-                                       if ( key === "click" ) {
-                                               return;
-                                       }
-                                       if ( key in button ) {
-                                               button[ key ]( value );
-                                       } else {
-                                               button.attr( key, value );
-                                       }
-                               });
-                               if ($.fn.button) {
-                                       button.button();
-                               }
-                       });
-                       uiDialogButtonPane.appendTo(self.uiDialog);
-               }
-       },
-
-       _makeDraggable: function() {
-               var self = this,
-                       options = self.options,
-                       doc = $(document),
-                       heightBeforeDrag;
-
-               function filteredUi(ui) {
-                       return {
-                               position: ui.position,
-                               offset: ui.offset
-                       };
-               }
-
-               self.uiDialog.draggable({
-                       cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
-                       handle: '.ui-dialog-titlebar',
-                       containment: 'document',
-                       start: function(event, ui) {
-                               heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
-                               $(this).height($(this).height()).addClass("ui-dialog-dragging");
-                               self._trigger('dragStart', event, filteredUi(ui));
-                       },
-                       drag: function(event, ui) {
-                               self._trigger('drag', event, filteredUi(ui));
-                       },
-                       stop: function(event, ui) {
-                               options.position = [ui.position.left - doc.scrollLeft(),
-                                       ui.position.top - doc.scrollTop()];
-                               $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
-                               self._trigger('dragStop', event, filteredUi(ui));
-                               $.ui.dialog.overlay.resize();
-                       }
-               });
-       },
-
-       _makeResizable: function(handles) {
-               handles = (handles === undefined ? this.options.resizable : handles);
-               var self = this,
-                       options = self.options,
-                       // .ui-resizable has position: relative defined in the stylesheet
-                       // but dialogs have to use absolute or fixed positioning
-                       position = self.uiDialog.css('position'),
-                       resizeHandles = (typeof handles === 'string' ?
-                               handles :
-                               'n,e,s,w,se,sw,ne,nw'
-                       );
-
-               function filteredUi(ui) {
-                       return {
-                               originalPosition: ui.originalPosition,
-                               originalSize: ui.originalSize,
-                               position: ui.position,
-                               size: ui.size
-                       };
-               }
-
-               self.uiDialog.resizable({
-                       cancel: '.ui-dialog-content',
-                       containment: 'document',
-                       alsoResize: self.element,
-                       maxWidth: options.maxWidth,
-                       maxHeight: options.maxHeight,
-                       minWidth: options.minWidth,
-                       minHeight: self._minHeight(),
-                       handles: resizeHandles,
-                       start: function(event, ui) {
-                               $(this).addClass("ui-dialog-resizing");
-                               self._trigger('resizeStart', event, filteredUi(ui));
-                       },
-                       resize: function(event, ui) {
-                               self._trigger('resize', event, filteredUi(ui));
-                       },
-                       stop: function(event, ui) {
-                               $(this).removeClass("ui-dialog-resizing");
-                               options.height = $(this).height();
-                               options.width = $(this).width();
-                               self._trigger('resizeStop', event, filteredUi(ui));
-                               $.ui.dialog.overlay.resize();
-                       }
-               })
-               .css('position', position)
-               .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
-       },
-
-       _minHeight: function() {
-               var options = this.options;
-
-               if (options.height === 'auto') {
-                       return options.minHeight;
-               } else {
-                       return Math.min(options.minHeight, options.height);
-               }
-       },
-
-       _position: function(position) {
-               var myAt = [],
-                       offset = [0, 0],
-                       isVisible;
-
-               if (position) {
-                       // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
-       //              if (typeof position == 'string' || $.isArray(position)) {
-       //                      myAt = $.isArray(position) ? position : position.split(' ');
-
-                       if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
-                               myAt = position.split ? position.split(' ') : [position[0], position[1]];
-                               if (myAt.length === 1) {
-                                       myAt[1] = myAt[0];
-                               }
-
-                               $.each(['left', 'top'], function(i, offsetPosition) {
-                                       if (+myAt[i] === myAt[i]) {
-                                               offset[i] = myAt[i];
-                                               myAt[i] = offsetPosition;
-                                       }
-                               });
-
-                               position = {
-                                       my: myAt.join(" "),
-                                       at: myAt.join(" "),
-                                       offset: offset.join(" ")
-                               };
-                       } 
-
-                       position = $.extend({}, $.ui.dialog.prototype.options.position, position);
-               } else {
-                       position = $.ui.dialog.prototype.options.position;
-               }
-
-               // need to show the dialog to get the actual offset in the position plugin
-               isVisible = this.uiDialog.is(':visible');
-               if (!isVisible) {
-                       this.uiDialog.show();
-               }
-               this.uiDialog
-                       // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
-                       .css({ top: 0, left: 0 })
-                       .position($.extend({ of: window }, position));
-               if (!isVisible) {
-                       this.uiDialog.hide();
-               }
-       },
-
-       _setOptions: function( options ) {
-               var self = this,
-                       resizableOptions = {},
-                       resize = false;
-
-               $.each( options, function( key, value ) {
-                       self._setOption( key, value );
-                       
-                       if ( key in sizeRelatedOptions ) {
-                               resize = true;
-                       }
-                       if ( key in resizableRelatedOptions ) {
-                               resizableOptions[ key ] = value;
-                       }
-               });
-
-               if ( resize ) {
-                       this._size();
-               }
-               if ( this.uiDialog.is( ":data(resizable)" ) ) {
-                       this.uiDialog.resizable( "option", resizableOptions );
-               }
-       },
-
-       _setOption: function(key, value){
-               var self = this,
-                       uiDialog = self.uiDialog;
-
-               switch (key) {
-                       //handling of deprecated beforeclose (vs beforeClose) option
-                       //Ticket #4669 http://dev.jqueryui.com/ticket/4669
-                       //TODO: remove in 1.9pre
-                       case "beforeclose":
-                               key = "beforeClose";
-                               break;
-                       case "buttons":
-                               self._createButtons(value);
-                               break;
-                       case "closeText":
-                               // ensure that we always pass a string
-                               self.uiDialogTitlebarCloseText.text("" + value);
-                               break;
-                       case "dialogClass":
-                               uiDialog
-                                       .removeClass(self.options.dialogClass)
-                                       .addClass(uiDialogClasses + value);
-                               break;
-                       case "disabled":
-                               if (value) {
-                                       uiDialog.addClass('ui-dialog-disabled');
-                               } else {
-                                       uiDialog.removeClass('ui-dialog-disabled');
-                               }
-                               break;
-                       case "draggable":
-                               var isDraggable = uiDialog.is( ":data(draggable)" );
-                               if ( isDraggable && !value ) {
-                                       uiDialog.draggable( "destroy" );
-                               }
-                               
-                               if ( !isDraggable && value ) {
-                                       self._makeDraggable();
-                               }
-                               break;
-                       case "position":
-                               self._position(value);
-                               break;
-                       case "resizable":
-                               // currently resizable, becoming non-resizable
-                               var isResizable = uiDialog.is( ":data(resizable)" );
-                               if (isResizable && !value) {
-                                       uiDialog.resizable('destroy');
-                               }
-
-                               // currently resizable, changing handles
-                               if (isResizable && typeof value === 'string') {
-                                       uiDialog.resizable('option', 'handles', value);
-                               }
-
-                               // currently non-resizable, becoming resizable
-                               if (!isResizable && value !== false) {
-                                       self._makeResizable(value);
-                               }
-                               break;
-                       case "title":
-                               // convert whatever was passed in o a string, for html() to not throw up
-                               $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
-                               break;
-               }
-
-               $.Widget.prototype._setOption.apply(self, arguments);
-       },
-
-       _size: function() {
-               /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
-                * divs will both have width and height set, so we need to reset them
-                */
-               var options = this.options,
-                       nonContentHeight,
-                       minContentHeight,
-                       isVisible = this.uiDialog.is( ":visible" );
-
-               // reset content sizing
-               this.element.show().css({
-                       width: 'auto',
-                       minHeight: 0,
-                       height: 0
-               });
-
-               if (options.minWidth > options.width) {
-                       options.width = options.minWidth;
-               }
-
-               // reset wrapper sizing
-               // determine the height of all the non-content elements
-               nonContentHeight = this.uiDialog.css({
-                               height: 'auto',
-                               width: options.width
-                       })
-                       .height();
-               minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
-               
-               if ( options.height === "auto" ) {
-                       // only needed for IE6 support
-                       if ( $.support.minHeight ) {
-                               this.element.css({
-                                       minHeight: minContentHeight,
-                                       height: "auto"
-                               });
-                       } else {
-                               this.uiDialog.show();
-                               var autoHeight = this.element.css( "height", "auto" ).height();
-                               if ( !isVisible ) {
-                                       this.uiDialog.hide();
-                               }
-                               this.element.height( Math.max( autoHeight, minContentHeight ) );
-                       }
-               } else {
-                       this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
-               }
-
-               if (this.uiDialog.is(':data(resizable)')) {
-                       this.uiDialog.resizable('option', 'minHeight', this._minHeight());
-               }
-       }
-});
-
-$.extend($.ui.dialog, {
-       version: "1.8.24",
-
-       uuid: 0,
-       maxZ: 0,
-
-       getTitleId: function($el) {
-               var id = $el.attr('id');
-               if (!id) {
-                       this.uuid += 1;
-                       id = this.uuid;
-               }
-               return 'ui-dialog-title-' + id;
-       },
-
-       overlay: function(dialog) {
-               this.$el = $.ui.dialog.overlay.create(dialog);
-       }
-});
-
-$.extend($.ui.dialog.overlay, {
-       instances: [],
-       // reuse old instances due to IE memory leak with alpha transparency (see #5185)
-       oldInstances: [],
-       maxZ: 0,
-       events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
-               function(event) { return event + '.dialog-overlay'; }).join(' '),
-       create: function(dialog) {
-               if (this.instances.length === 0) {
-                       // prevent use of anchors and inputs
-                       // we use a setTimeout in case the overlay is created from an
-                       // event that we're going to be cancelling (see #2804)
-                       setTimeout(function() {
-                               // handle $(el).dialog().dialog('close') (see #4065)
-                               if ($.ui.dialog.overlay.instances.length) {
-                                       $(document).bind($.ui.dialog.overlay.events, function(event) {
-                                               // stop events if the z-index of the target is < the z-index of the overlay
-                                               // we cannot return true when we don't want to cancel the event (#3523)
-                                               if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
-                                                       return false;
-                                               }
-                                       });
-                               }
-                       }, 1);
-
-                       // allow closing by pressing the escape key
-                       $(document).bind('keydown.dialog-overlay', function(event) {
-                               if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
-                                       event.keyCode === $.ui.keyCode.ESCAPE) {
-                                       
-                                       dialog.close(event);
-                                       event.preventDefault();
-                               }
-                       });
-
-                       // handle window resize
-                       $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
-               }
-
-               var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
-                       .appendTo(document.body)
-                       .css({
-                               width: this.width(),
-                               height: this.height()
-                       });
-
-               if ($.fn.bgiframe) {
-                       $el.bgiframe();
-               }
-
-               this.instances.push($el);
-               return $el;
-       },
-
-       destroy: function($el) {
-               var indexOf = $.inArray($el, this.instances);
-               if (indexOf != -1){
-                       this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
-               }
-
-               if (this.instances.length === 0) {
-                       $([document, window]).unbind('.dialog-overlay');
-               }
-
-               $el.remove();
-               
-               // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
-               var maxZ = 0;
-               $.each(this.instances, function() {
-                       maxZ = Math.max(maxZ, this.css('z-index'));
-               });
-               this.maxZ = maxZ;
-       },
-
-       height: function() {
-               var scrollHeight,
-                       offsetHeight;
-               // handle IE 6
-               if ($.browser.msie && $.browser.version < 7) {
-                       scrollHeight = Math.max(
-                               document.documentElement.scrollHeight,
-                               document.body.scrollHeight
-                       );
-                       offsetHeight = Math.max(
-                               document.documentElement.offsetHeight,
-                               document.body.offsetHeight
-                       );
-
-                       if (scrollHeight < offsetHeight) {
-                               return $(window).height() + 'px';
-                       } else {
-                               return scrollHeight + 'px';
-                       }
-               // handle "good" browsers
-               } else {
-                       return $(document).height() + 'px';
-               }
-       },
-
-       width: function() {
-               var scrollWidth,
-                       offsetWidth;
-               // handle IE
-               if ( $.browser.msie ) {
-                       scrollWidth = Math.max(
-                               document.documentElement.scrollWidth,
-                               document.body.scrollWidth
-                       );
-                       offsetWidth = Math.max(
-                               document.documentElement.offsetWidth,
-                               document.body.offsetWidth
-                       );
-
-                       if (scrollWidth < offsetWidth) {
-                               return $(window).width() + 'px';
-                       } else {
-                               return scrollWidth + 'px';
-                       }
-               // handle "good" browsers
-               } else {
-                       return $(document).width() + 'px';
-               }
-       },
-
-       resize: function() {
-               /* If the dialog is draggable and the user drags it past the
-                * right edge of the window, the document becomes wider so we
-                * need to stretch the overlay. If the user then drags the
-                * dialog back to the left, the document will become narrower,
-                * so we need to shrink the overlay to the appropriate size.
-                * This is handled by shrinking the overlay before setting it
-                * to the full document size.
-                */
-               var $overlays = $([]);
-               $.each($.ui.dialog.overlay.instances, function() {
-                       $overlays = $overlays.add(this);
-               });
-
-               $overlays.css({
-                       width: 0,
-                       height: 0
-               }).css({
-                       width: $.ui.dialog.overlay.width(),
-                       height: $.ui.dialog.overlay.height()
-               });
-       }
-});
-
-$.extend($.ui.dialog.overlay.prototype, {
-       destroy: function() {
-               $.ui.dialog.overlay.destroy(this.$el);
-       }
-});
-
-}(jQuery));
diff --git a/resources/jquery.ui/jquery.ui.draggable.js b/resources/jquery.ui/jquery.ui.draggable.js
deleted file mode 100644 (file)
index 149035c..0000000
+++ /dev/null
@@ -1,832 +0,0 @@
-/*!
- * jQuery UI Draggable 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Draggables
- *
- * Depends:
- *     jquery.ui.core.js
- *     jquery.ui.mouse.js
- *     jquery.ui.widget.js
- */
-(function( $, undefined ) {
-
-$.widget("ui.draggable", $.ui.mouse, {
-       widgetEventPrefix: "drag",
-       options: {
-               addClasses: true,
-               appendTo: "parent",
-               axis: false,
-               connectToSortable: false,
-               containment: false,
-               cursor: "auto",
-               cursorAt: false,
-               grid: false,
-               handle: false,
-               helper: "original",
-               iframeFix: false,
-               opacity: false,
-               refreshPositions: false,
-               revert: false,
-               revertDuration: 500,
-               scope: "default",
-               scroll: true,
-               scrollSensitivity: 20,
-               scrollSpeed: 20,
-               snap: false,
-               snapMode: "both",
-               snapTolerance: 20,
-               stack: false,
-               zIndex: false
-       },
-       _create: function() {
-
-               if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
-                       this.element[0].style.position = 'relative';
-
-               (this.options.addClasses && this.element.addClass("ui-draggable"));
-               (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
-
-               this._mouseInit();
-
-       },
-
-       destroy: function() {
-               if(!this.element.data('draggable')) return;
-               this.element
-                       .removeData("draggable")
-                       .unbind(".draggable")
-                       .removeClass("ui-draggable"
-                               + " ui-draggable-dragging"
-                               + " ui-draggable-disabled");
-               this._mouseDestroy();
-
-               return this;
-       },
-
-       _mouseCapture: function(event) {
-
-               var o = this.options;
-
-               // among others, prevent a drag on a resizable-handle
-               if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
-                       return false;
-
-               //Quit if we're not on a valid handle
-               this.handle = this._getHandle(event);
-               if (!this.handle)
-                       return false;
-               
-               if ( o.iframeFix ) {
-                       $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
-                               $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
-                               .css({
-                                       width: this.offsetWidth+"px", height: this.offsetHeight+"px",
-                                       position: "absolute", opacity: "0.001", zIndex: 1000
-                               })
-                               .css($(this).offset())
-                               .appendTo("body");
-                       });
-               }
-
-               return true;
-
-       },
-
-       _mouseStart: function(event) {
-
-               var o = this.options;
-
-               //Create and append the visible helper
-               this.helper = this._createHelper(event);
-
-               this.helper.addClass("ui-draggable-dragging");
-
-               //Cache the helper size
-               this._cacheHelperProportions();
-
-               //If ddmanager is used for droppables, set the global draggable
-               if($.ui.ddmanager)
-                       $.ui.ddmanager.current = this;
-
-               /*
-                * - Position generation -
-                * This block generates everything position related - it's the core of draggables.
-                */
-
-               //Cache the margins of the original element
-               this._cacheMargins();
-
-               //Store the helper's css position
-               this.cssPosition = this.helper.css("position");
-               this.scrollParent = this.helper.scrollParent();
-
-               //The element's absolute position on the page minus margins
-               this.offset = this.positionAbs = this.element.offset();
-               this.offset = {
-                       top: this.offset.top - this.margins.top,
-                       left: this.offset.left - this.margins.left
-               };
-
-               $.extend(this.offset, {
-                       click: { //Where the click happened, relative to the element
-                               left: event.pageX - this.offset.left,
-                               top: event.pageY - this.offset.top
-                       },
-                       parent: this._getParentOffset(),
-                       relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
-               });
-
-               //Generate the original position
-               this.originalPosition = this.position = this._generatePosition(event);
-               this.originalPageX = event.pageX;
-               this.originalPageY = event.pageY;
-
-               //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
-               (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
-
-               //Set a containment if given in the options
-               if(o.containment)
-                       this._setContainment();
-
-               //Trigger event + callbacks
-               if(this._trigger("start", event) === false) {
-                       this._clear();
-                       return false;
-               }
-
-               //Recache the helper size
-               this._cacheHelperProportions();
-
-               //Prepare the droppable offsets
-               if ($.ui.ddmanager && !o.dropBehaviour)
-                       $.ui.ddmanager.prepareOffsets(this, event);
-
-               
-               this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
-               
-               //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
-               if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
-               
-               return true;
-       },
-
-       _mouseDrag: function(event, noPropagation) {
-
-               //Compute the helpers position
-               this.position = this._generatePosition(event);
-               this.positionAbs = this._convertPositionTo("absolute");
-
-               //Call plugins and callbacks and use the resulting position if something is returned
-               if (!noPropagation) {
-                       var ui = this._uiHash();
-                       if(this._trigger('drag', event, ui) === false) {
-                               this._mouseUp({});
-                               return false;
-                       }
-                       this.position = ui.position;
-               }
-
-               if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
-               if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
-               if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
-
-               return false;
-       },
-
-       _mouseStop: function(event) {
-
-               //If we are using droppables, inform the manager about the drop
-               var dropped = false;
-               if ($.ui.ddmanager && !this.options.dropBehaviour)
-                       dropped = $.ui.ddmanager.drop(this, event);
-
-               //if a drop comes from outside (a sortable)
-               if(this.dropped) {
-                       dropped = this.dropped;
-                       this.dropped = false;
-               }
-               
-               //if the original element is no longer in the DOM don't bother to continue (see #8269)
-               var element = this.element[0], elementInDom = false;
-               while ( element && (element = element.parentNode) ) {
-                       if (element == document ) {
-                               elementInDom = true;
-                       }
-               }
-               if ( !elementInDom && this.options.helper === "original" )
-                       return false;
-
-               if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
-                       var self = this;
-                       $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
-                               if(self._trigger("stop", event) !== false) {
-                                       self._clear();
-                               }
-                       });
-               } else {
-                       if(this._trigger("stop", event) !== false) {
-                               this._clear();
-                       }
-               }
-
-               return false;
-       },
-       
-       _mouseUp: function(event) {
-               //Remove frame helpers
-               $("div.ui-draggable-iframeFix").each(function() { 
-                       this.parentNode.removeChild(this); 
-               });
-               
-               //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
-               if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
-               
-               return $.ui.mouse.prototype._mouseUp.call(this, event);
-       },
-       
-       cancel: function() {
-               
-               if(this.helper.is(".ui-draggable-dragging")) {
-                       this._mouseUp({});
-               } else {
-                       this._clear();
-               }
-               
-               return this;
-               
-       },
-
-       _getHandle: function(event) {
-
-               var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
-               $(this.options.handle, this.element)
-                       .find("*")
-                       .andSelf()
-                       .each(function() {
-                               if(this == event.target) handle = true;
-                       });
-
-               return handle;
-
-       },
-
-       _createHelper: function(event) {
-
-               var o = this.options;
-               var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
-
-               if(!helper.parents('body').length)
-                       helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
-
-               if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
-                       helper.css("position", "absolute");
-
-               return helper;
-
-       },
-
-       _adjustOffsetFromHelper: function(obj) {
-               if (typeof obj == 'string') {
-                       obj = obj.split(' ');
-               }
-               if ($.isArray(obj)) {
-                       obj = {left: +obj[0], top: +obj[1] || 0};
-               }
-               if ('left' in obj) {
-                       this.offset.click.left = obj.left + this.margins.left;
-               }
-               if ('right' in obj) {
-                       this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
-               }
-               if ('top' in obj) {
-                       this.offset.click.top = obj.top + this.margins.top;
-               }
-               if ('bottom' in obj) {
-                       this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
-               }
-       },
-
-       _getParentOffset: function() {
-
-               //Get the offsetParent and cache its position
-               this.offsetParent = this.helper.offsetParent();
-               var po = this.offsetParent.offset();
-
-               // This is a special case where we need to modify a offset calculated on start, since the following happened:
-               // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
-               // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
-               //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
-               if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
-                       po.left += this.scrollParent.scrollLeft();
-                       po.top += this.scrollParent.scrollTop();
-               }
-
-               if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
-               || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
-                       po = { top: 0, left: 0 };
-
-               return {
-                       top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
-                       left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
-               };
-
-       },
-
-       _getRelativeOffset: function() {
-
-               if(this.cssPosition == "relative") {
-                       var p = this.element.position();
-                       return {
-                               top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
-                               left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
-                       };
-               } else {
-                       return { top: 0, left: 0 };
-               }
-
-       },
-
-       _cacheMargins: function() {
-               this.margins = {
-                       left: (parseInt(this.element.css("marginLeft"),10) || 0),
-                       top: (parseInt(this.element.css("marginTop"),10) || 0),
-                       right: (parseInt(this.element.css("marginRight"),10) || 0),
-                       bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
-               };
-       },
-
-       _cacheHelperProportions: function() {
-               this.helperProportions = {
-                       width: this.helper.outerWidth(),
-                       height: this.helper.outerHeight()
-               };
-       },
-
-       _setContainment: function() {
-
-               var o = this.options;
-               if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
-               if(o.containment == 'document' || o.containment == 'window') this.containment = [
-                       o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
-                       o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
-                       (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
-                       (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
-               ];
-
-               if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
-                       var c = $(o.containment);
-                       var ce = c[0]; if(!ce) return;
-                       var co = c.offset();
-                       var over = ($(ce).css("overflow") != 'hidden');
-
-                       this.containment = [
-                               (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
-                               (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
-                               (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
-                               (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top  - this.margins.bottom
-                       ];
-                       this.relative_container = c;
-
-               } else if(o.containment.constructor == Array) {
-                       this.containment = o.containment;
-               }
-
-       },
-
-       _convertPositionTo: function(d, pos) {
-
-               if(!pos) pos = this.position;
-               var mod = d == "absolute" ? 1 : -1;
-               var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
-
-               return {
-                       top: (
-                               pos.top                                                                                                                                 // The absolute mouse position
-                               + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
-                               + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
-                               - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
-                       ),
-                       left: (
-                               pos.left                                                                                                                                // The absolute mouse position
-                               + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
-                               + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
-                               - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
-                       )
-               };
-
-       },
-
-       _generatePosition: function(event) {
-
-               var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
-               var pageX = event.pageX;
-               var pageY = event.pageY;
-
-               /*
-                * - Position constraining -
-                * Constrain the position to a mix of grid, containment.
-                */
-
-               if(this.originalPosition) { //If we are not dragging yet, we won't check for options
-                        var containment;
-                        if(this.containment) {
-                                if (this.relative_container){
-                                    var co = this.relative_container.offset();
-                                    containment = [ this.containment[0] + co.left,
-                                                    this.containment[1] + co.top,
-                                                    this.containment[2] + co.left,
-                                                    this.containment[3] + co.top ];
-                                }
-                                else {
-                                    containment = this.containment;
-                                }
-
-                               if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
-                               if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
-                               if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
-                               if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
-                       }
-
-                       if(o.grid) {
-                               //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
-                               var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
-                               pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
-
-                               var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
-                               pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
-                       }
-
-               }
-
-               return {
-                       top: (
-                               pageY                                                                                                                           // The absolute mouse position
-                               - this.offset.click.top                                                                                                 // Click offset (relative to the element)
-                               - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
-                               - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
-                               + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
-                       ),
-                       left: (
-                               pageX                                                                                                                           // The absolute mouse position
-                               - this.offset.click.left                                                                                                // Click offset (relative to the element)
-                               - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
-                               - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
-                               + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
-                       )
-               };
-
-       },
-
-       _clear: function() {
-               this.helper.removeClass("ui-draggable-dragging");
-               if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
-               //if($.ui.ddmanager) $.ui.ddmanager.current = null;
-               this.helper = null;
-               this.cancelHelperRemoval = false;
-       },
-
-       // From now on bulk stuff - mainly helpers
-
-       _trigger: function(type, event, ui) {
-               ui = ui || this._uiHash();
-               $.ui.plugin.call(this, type, [event, ui]);
-               if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
-               return $.Widget.prototype._trigger.call(this, type, event, ui);
-       },
-
-       plugins: {},
-
-       _uiHash: function(event) {
-               return {
-                       helper: this.helper,
-                       position: this.position,
-                       originalPosition: this.originalPosition,
-                       offset: this.positionAbs
-               };
-       }
-
-});
-
-$.extend($.ui.draggable, {
-       version: "1.8.24"
-});
-
-$.ui.plugin.add("draggable", "connectToSortable", {
-       start: function(event, ui) {
-
-               var inst = $(this).data("draggable"), o = inst.options,
-                       uiSortable = $.extend({}, ui, { item: inst.element });
-               inst.sortables = [];
-               $(o.connectToSortable).each(function() {
-                       var sortable = $.data(this, 'sortable');
-                       if (sortable && !sortable.options.disabled) {
-                               inst.sortables.push({
-                                       instance: sortable,
-                                       shouldRevert: sortable.options.revert
-                               });
-                               sortable.refreshPositions();    // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
-                               sortable._trigger("activate", event, uiSortable);
-                       }
-               });
-
-       },
-       stop: function(event, ui) {
-
-               //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
-               var inst = $(this).data("draggable"),
-                       uiSortable = $.extend({}, ui, { item: inst.element });
-
-               $.each(inst.sortables, function() {
-                       if(this.instance.isOver) {
-
-                               this.instance.isOver = 0;
-
-                               inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
-                               this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
-
-                               //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
-                               if(this.shouldRevert) this.instance.options.revert = true;
-
-                               //Trigger the stop of the sortable
-                               this.instance._mouseStop(event);
-
-                               this.instance.options.helper = this.instance.options._helper;
-
-                               //If the helper has been the original item, restore properties in the sortable
-                               if(inst.options.helper == 'original')
-                                       this.instance.currentItem.css({ top: 'auto', left: 'auto' });
-
-                       } else {
-                               this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
-                               this.instance._trigger("deactivate", event, uiSortable);
-                       }
-
-               });
-
-       },
-       drag: function(event, ui) {
-
-               var inst = $(this).data("draggable"), self = this;
-
-               var checkPos = function(o) {
-                       var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
-                       var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
-                       var itemHeight = o.height, itemWidth = o.width;
-                       var itemTop = o.top, itemLeft = o.left;
-
-                       return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
-               };
-
-               $.each(inst.sortables, function(i) {
-                       
-                       //Copy over some variables to allow calling the sortable's native _intersectsWith
-                       this.instance.positionAbs = inst.positionAbs;
-                       this.instance.helperProportions = inst.helperProportions;
-                       this.instance.offset.click = inst.offset.click;
-                       
-                       if(this.instance._intersectsWith(this.instance.containerCache)) {
-
-                               //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
-                               if(!this.instance.isOver) {
-
-                                       this.instance.isOver = 1;
-                                       //Now we fake the start of dragging for the sortable instance,
-                                       //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
-                                       //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
-                                       this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
-                                       this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
-                                       this.instance.options.helper = function() { return ui.helper[0]; };
-
-                                       event.target = this.instance.currentItem[0];
-                                       this.instance._mouseCapture(event, true);
-                                       this.instance._mouseStart(event, true, true);
-
-                                       //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
-                                       this.instance.offset.click.top = inst.offset.click.top;
-                                       this.instance.offset.click.left = inst.offset.click.left;
-                                       this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
-                                       this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
-
-                                       inst._trigger("toSortable", event);
-                                       inst.dropped = this.instance.element; //draggable revert needs that
-                                       //hack so receive/update callbacks work (mostly)
-                                       inst.currentItem = inst.element;
-                                       this.instance.fromOutside = inst;
-
-                               }
-
-                               //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
-                               if(this.instance.currentItem) this.instance._mouseDrag(event);
-
-                       } else {
-
-                               //If it doesn't intersect with the sortable, and it intersected before,
-                               //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
-                               if(this.instance.isOver) {
-
-                                       this.instance.isOver = 0;
-                                       this.instance.cancelHelperRemoval = true;
-                                       
-                                       //Prevent reverting on this forced stop
-                                       this.instance.options.revert = false;
-                                       
-                                       // The out event needs to be triggered independently
-                                       this.instance._trigger('out', event, this.instance._uiHash(this.instance));
-                                       
-                                       this.instance._mouseStop(event, true);
-                                       this.instance.options.helper = this.instance.options._helper;
-
-                                       //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
-                                       this.instance.currentItem.remove();
-                                       if(this.instance.placeholder) this.instance.placeholder.remove();
-
-                                       inst._trigger("fromSortable", event);
-                                       inst.dropped = false; //draggable revert needs that
-                               }
-
-                       };
-
-               });
-
-       }
-});
-
-$.ui.plugin.add("draggable", "cursor", {
-       start: function(event, ui) {
-               var t = $('body'), o = $(this).data('draggable').options;
-               if (t.css("cursor")) o._cursor = t.css("cursor");
-               t.css("cursor", o.cursor);
-       },
-       stop: function(event, ui) {
-               var o = $(this).data('draggable').options;
-               if (o._cursor) $('body').css("cursor", o._cursor);
-       }
-});
-
-$.ui.plugin.add("draggable", "opacity", {
-       start: function(event, ui) {
-               var t = $(ui.helper), o = $(this).data('draggable').options;
-               if(t.css("opacity")) o._opacity = t.css("opacity");
-               t.css('opacity', o.opacity);
-       },
-       stop: function(event, ui) {
-               var o = $(this).data('draggable').options;
-               if(o._opacity) $(ui.helper).css('opacity', o._opacity);
-       }
-});
-
-$.ui.plugin.add("draggable", "scroll", {
-       start: function(event, ui) {
-               var i = $(this).data("draggable");
-               if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
-       },
-       drag: function(event, ui) {
-
-               var i = $(this).data("draggable"), o = i.options, scrolled = false;
-
-               if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
-
-                       if(!o.axis || o.axis != 'x') {
-                               if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
-                                       i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
-                               else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
-                                       i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
-                       }
-
-                       if(!o.axis || o.axis != 'y') {
-                               if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
-                                       i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
-                               else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
-                                       i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
-                       }
-
-               } else {
-
-                       if(!o.axis || o.axis != 'x') {
-                               if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
-                                       scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
-                               else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
-                                       scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
-                       }
-
-                       if(!o.axis || o.axis != 'y') {
-                               if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
-                                       scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
-                               else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
-                                       scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
-                       }
-
-               }
-
-               if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
-                       $.ui.ddmanager.prepareOffsets(i, event);
-
-       }
-});
-
-$.ui.plugin.add("draggable", "snap", {
-       start: function(event, ui) {
-
-               var i = $(this).data("draggable"), o = i.options;
-               i.snapElements = [];
-
-               $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
-                       var $t = $(this); var $o = $t.offset();
-                       if(this != i.element[0]) i.snapElements.push({
-                               item: this,
-                               width: $t.outerWidth(), height: $t.outerHeight(),
-                               top: $o.top, left: $o.left
-                       });
-               });
-
-       },
-       drag: function(event, ui) {
-
-               var inst = $(this).data("draggable"), o = inst.options;
-               var d = o.snapTolerance;
-
-               var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
-                       y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
-
-               for (var i = inst.snapElements.length - 1; i >= 0; i--){
-
-                       var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
-                               t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
-
-                       //Yes, I know, this is insane ;)
-                       if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
-                               if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
-                               inst.snapElements[i].snapping = false;
-                               continue;
-                       }
-
-                       if(o.snapMode != 'inner') {
-                               var ts = Math.abs(t - y2) <= d;
-                               var bs = Math.abs(b - y1) <= d;
-                               var ls = Math.abs(l - x2) <= d;
-                               var rs = Math.abs(r - x1) <= d;
-                               if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
-                               if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
-                               if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
-                               if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
-                       }
-
-                       var first = (ts || bs || ls || rs);
-
-                       if(o.snapMode != 'outer') {
-                               var ts = Math.abs(t - y1) <= d;
-                               var bs = Math.abs(b - y2) <= d;
-                               var ls = Math.abs(l - x1) <= d;
-                               var rs = Math.abs(r - x2) <= d;
-                               if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
-                               if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
-                               if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
-                               if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
-                       }
-
-                       if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
-                               (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
-                       inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
-
-               };
-
-       }
-});
-
-$.ui.plugin.add("draggable", "stack", {
-       start: function(event, ui) {
-
-               var o = $(this).data("draggable").options;
-
-               var group = $.makeArray($(o.stack)).sort(function(a,b) {
-                       return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
-               });
-               if (!group.length) { return; }
-               
-               var min = parseInt(group[0].style.zIndex) || 0;
-               $(group).each(function(i) {
-                       this.style.zIndex = min + i;
-               });
-
-               this[0].style.zIndex = min + group.length;
-
-       }
-});
-
-$.ui.plugin.add("draggable", "zIndex", {
-       start: function(event, ui) {
-               var t = $(ui.helper), o = $(this).data("draggable").options;
-               if(t.css("zIndex")) o._zIndex = t.css("zIndex");
-               t.css('zIndex', o.zIndex);
-       },
-       stop: function(event, ui) {
-               var o = $(this).data("draggable").options;
-               if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
-       }
-});
-
-})(jQuery);
diff --git a/resources/jquery.ui/jquery.ui.droppable.js b/resources/jquery.ui/jquery.ui.droppable.js
deleted file mode 100644 (file)
index f17c222..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-/*!
- * jQuery UI Droppable 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Droppables
- *
- * Depends:
- *     jquery.ui.core.js
- *     jquery.ui.widget.js
- *     jquery.ui.mouse.js
- *     jquery.ui.draggable.js
- */
-(function( $, undefined ) {
-
-$.widget("ui.droppable", {
-       widgetEventPrefix: "drop",
-       options: {
-               accept: '*',
-               activeClass: false,
-               addClasses: true,
-               greedy: false,
-               hoverClass: false,
-               scope: 'default',
-               tolerance: 'intersect'
-       },
-       _create: function() {
-
-               var o = this.options, accept = o.accept;
-               this.isover = 0; this.isout = 1;
-
-               this.accept = $.isFunction(accept) ? accept : function(d) {
-                       return d.is(accept);
-               };
-
-               //Store the droppable's proportions
-               this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
-
-               // Add the reference and positions to the manager
-               $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
-               $.ui.ddmanager.droppables[o.scope].push(this);
-
-               (o.addClasses && this.element.addClass("ui-droppable"));
-
-       },
-
-       destroy: function() {
-               var drop = $.ui.ddmanager.droppables[this.options.scope];
-               for ( var i = 0; i < drop.length; i++ )
-                       if ( drop[i] == this )
-                               drop.splice(i, 1);
-
-               this.element
-                       .removeClass("ui-droppable ui-droppable-disabled")
-                       .removeData("droppable")
-                       .unbind(".droppable");
-
-               return this;
-       },
-
-       _setOption: function(key, value) {
-
-               if(key == 'accept') {
-                       this.accept = $.isFunction(value) ? value : function(d) {
-                               return d.is(value);
-                       };
-               }
-               $.Widget.prototype._setOption.apply(this, arguments);
-       },
-
-       _activate: function(event) {
-               var draggable = $.ui.ddmanager.current;
-               if(this.options.activeClass) this.element.addClass(this.options.activeClass);
-               (draggable && this._trigger('activate', event, this.ui(draggable)));
-       },
-
-       _deactivate: function(event) {
-               var draggable = $.ui.ddmanager.current;
-               if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
-               (draggable && this._trigger('deactivate', event, this.ui(draggable)));
-       },
-
-       _over: function(event) {
-
-               var draggable = $.ui.ddmanager.current;
-               if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
-
-               if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
-                       if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
-                       this._trigger('over', event, this.ui(draggable));
-               }
-
-       },
-
-       _out: function(event) {
-
-               var draggable = $.ui.ddmanager.current;
-               if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
-
-               if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
-                       if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
-                       this._trigger('out', event, this.ui(draggable));
-               }
-
-       },
-
-       _drop: function(event,custom) {
-
-               var draggable = custom || $.ui.ddmanager.current;
-               if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
-
-               var childrenIntersection = false;
-               this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
-                       var inst = $.data(this, 'droppable');
-                       if(
-                               inst.options.greedy
-                               && !inst.options.disabled
-                               && inst.options.scope == draggable.options.scope
-                               && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
-                               && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
-                       ) { childrenIntersection = true; return false; }
-               });
-               if(childrenIntersection) return false;
-
-               if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
-                       if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
-                       if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
-                       this._trigger('drop', event, this.ui(draggable));
-                       return this.element;
-               }
-
-               return false;
-
-       },
-
-       ui: function(c) {
-               return {
-                       draggable: (c.currentItem || c.element),
-                       helper: c.helper,
-                       position: c.position,
-                       offset: c.positionAbs
-               };
-       }
-
-});
-
-$.extend($.ui.droppable, {
-       version: "1.8.24"
-});
-
-$.ui.intersect = function(draggable, droppable, toleranceMode) {
-
-       if (!droppable.offset) return false;
-
-       var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
-               y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
-       var l = droppable.offset.left, r = l + droppable.proportions.width,
-               t = droppable.offset.top, b = t + droppable.proportions.height;
-
-       switch (toleranceMode) {
-               case 'fit':
-                       return (l <= x1 && x2 <= r
-                               && t <= y1 && y2 <= b);
-                       break;
-               case 'intersect':
-                       return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
-                               && x2 - (draggable.helperProportions.width / 2) < r // Left Half
-                               && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
-                               && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
-                       break;
-               case 'pointer':
-                       var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
-                               draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
-                               isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
-                       return isOver;
-                       break;
-               case 'touch':
-                       return (
-                                       (y1 >= t && y1 <= b) || // Top edge touching
-                                       (y2 >= t && y2 <= b) || // Bottom edge touching
-                                       (y1 < t && y2 > b)              // Surrounded vertically
-                               ) && (
-                                       (x1 >= l && x1 <= r) || // Left edge touching
-                                       (x2 >= l && x2 <= r) || // Right edge touching
-                                       (x1 < l && x2 > r)              // Surrounded horizontally
-                               );
-                       break;
-               default:
-                       return false;
-                       break;
-               }
-
-};
-
-/*
-       This manager tracks offsets of draggables and droppables
-*/
-$.ui.ddmanager = {
-       current: null,
-       droppables: { 'default': [] },
-       prepareOffsets: function(t, event) {
-
-               var m = $.ui.ddmanager.droppables[t.options.scope] || [];
-               var type = event ? event.type : null; // workaround for #2317
-               var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
-
-               droppablesLoop: for (var i = 0; i < m.length; i++) {
-
-                       if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;   //No disabled and non-accepted
-                       for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
-                       m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;                                                                       //If the element is not visible, continue
-
-                       if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
-
-                       m[i].offset = m[i].element.offset();
-                       m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
-
-               }
-
-       },
-       drop: function(draggable, event) {
-
-               var dropped = false;
-               $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
-
-                       if(!this.options) return;
-                       if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
-                               dropped = this._drop.call(this, event) || dropped;
-
-                       if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
-                               this.isout = 1; this.isover = 0;
-                               this._deactivate.call(this, event);
-                       }
-
-               });
-               return dropped;
-
-       },
-       dragStart: function( draggable, event ) {
-               //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
-               draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() {
-                       if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
-               });
-       },
-       drag: function(draggable, event) {
-
-               //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
-               if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
-
-               //Run through all droppables and check their positions based on specific tolerance options
-               $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
-
-                       if(this.options.disabled || this.greedyChild || !this.visible) return;
-                       var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
-
-                       var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
-                       if(!c) return;
-
-                       var parentInstance;
-                       if (this.options.greedy) {
-                               // find droppable parents with same scope
-                               var scope = this.options.scope;
-                               var parent = this.element.parents(':data(droppable)').filter(function () {
-                                       return $.data(this, 'droppable').options.scope === scope;
-                               });
-
-                               if (parent.length) {
-                                       parentInstance = $.data(parent[0], 'droppable');
-                                       parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
-                               }
-                       }
-
-                       // we just moved into a greedy child
-                       if (parentInstance && c == 'isover') {
-                               parentInstance['isover'] = 0;
-                               parentInstance['isout'] = 1;
-                               parentInstance._out.call(parentInstance, event);
-                       }
-
-                       this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
-                       this[c == "isover" ? "_over" : "_out"].call(this, event);
-
-                       // we just moved out of a greedy child
-                       if (parentInstance && c == 'isout') {
-                               parentInstance['isout'] = 0;
-                               parentInstance['isover'] = 1;
-                               parentInstance._over.call(parentInstance, event);
-                       }
-               });
-
-       },
-       dragStop: function( draggable, event ) {
-               draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" );
-               //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
-               if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
-       }
-};
-
-})(jQuery);
diff --git a/resources/jquery.ui/jquery.ui.mouse.js b/resources/jquery.ui/jquery.ui.mouse.js
deleted file mode 100644 (file)
index 52a1786..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*!
- * jQuery UI Mouse 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Mouse
- *
- * Depends:
- *     jquery.ui.widget.js
- */
-(function( $, undefined ) {
-
-var mouseHandled = false;
-$( document ).mouseup( function( e ) {
-       mouseHandled = false;
-});
-
-$.widget("ui.mouse", {
-       options: {
-               cancel: ':input,option',
-               distance: 1,
-               delay: 0
-       },
-       _mouseInit: function() {
-               var self = this;
-
-               this.element
-                       .bind('mousedown.'+this.widgetName, function(event) {
-                               return self._mouseDown(event);
-                       })
-                       .bind('click.'+this.widgetName, function(event) {
-                               if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
-                                   $.removeData(event.target, self.widgetName + '.preventClickEvent');
-                                       event.stopImmediatePropagation();
-                                       return false;
-                               }
-                       });
-
-               this.started = false;
-       },
-
-       // TODO: make sure destroying one instance of mouse doesn't mess with
-       // other instances of mouse
-       _mouseDestroy: function() {
-               this.element.unbind('.'+this.widgetName);
-               if ( this._mouseMoveDelegate ) {
-                       $(document)
-                               .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
-                               .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
-               }
-       },
-
-       _mouseDown: function(event) {
-               // don't let more than one widget handle mouseStart
-               if( mouseHandled ) { return };
-
-               // we may have missed mouseup (out of window)
-               (this._mouseStarted && this._mouseUp(event));
-
-               this._mouseDownEvent = event;
-
-               var self = this,
-                       btnIsLeft = (event.which == 1),
-                       // event.target.nodeName works around a bug in IE 8 with
-                       // disabled inputs (#7620)
-                       elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
-               if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
-                       return true;
-               }
-
-               this.mouseDelayMet = !this.options.delay;
-               if (!this.mouseDelayMet) {
-                       this._mouseDelayTimer = setTimeout(function() {
-                               self.mouseDelayMet = true;
-                       }, this.options.delay);
-               }
-
-               if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
-                       this._mouseStarted = (this._mouseStart(event) !== false);
-                       if (!this._mouseStarted) {
-                               event.preventDefault();
-                               return true;
-                       }
-               }
-
-               // Click event may never have fired (Gecko & Opera)
-               if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
-                       $.removeData(event.target, this.widgetName + '.preventClickEvent');
-               }
-
-               // these delegates are required to keep context
-               this._mouseMoveDelegate = function(event) {
-                       return self._mouseMove(event);
-               };
-               this._mouseUpDelegate = function(event) {
-                       return self._mouseUp(event);
-               };
-               $(document)
-                       .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
-                       .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
-
-               event.preventDefault();
-               
-               mouseHandled = true;
-               return true;
-       },
-
-       _mouseMove: function(event) {
-               // IE mouseup check - mouseup happened when mouse was out of window
-               if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
-                       return this._mouseUp(event);
-               }
-
-               if (this._mouseStarted) {
-                       this._mouseDrag(event);
-                       return event.preventDefault();
-               }
-
-               if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
-                       this._mouseStarted =
-                               (this._mouseStart(this._mouseDownEvent, event) !== false);
-                       (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
-               }
-
-               return !this._mouseStarted;
-       },
-
-       _mouseUp: function(event) {
-               $(document)
-                       .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
-                       .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
-
-               if (this._mouseStarted) {
-                       this._mouseStarted = false;
-
-                       if (event.target == this._mouseDownEvent.target) {
-                           $.data(event.target, this.widgetName + '.preventClickEvent', true);
-                       }
-
-                       this._mouseStop(event);
-               }
-
-               return false;
-       },
-
-       _mouseDistanceMet: function(event) {
-               return (Math.max(
-                               Math.abs(this._mouseDownEvent.pageX - event.pageX),
-                               Math.abs(this._mouseDownEvent.pageY - event.pageY)
-                       ) >= this.options.distance
-               );
-       },
-
-       _mouseDelayMet: function(event) {
-               return this.mouseDelayMet;
-       },
-
-       // These are placeholder methods, to be overriden by extending plugin
-       _mouseStart: function(event) {},
-       _mouseDrag: function(event) {},
-       _mouseStop: function(event) {},
-       _mouseCapture: function(event) { return true; }
-});
-
-})(jQuery);
diff --git a/resources/jquery.ui/jquery.ui.position.js b/resources/jquery.ui/jquery.ui.position.js
deleted file mode 100644 (file)
index 8b20179..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/*!
- * jQuery UI Position 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Position
- */
-(function( $, undefined ) {
-
-$.ui = $.ui || {};
-
-var horizontalPositions = /left|center|right/,
-       verticalPositions = /top|center|bottom/,
-       center = "center",
-       support = {},
-       _position = $.fn.position,
-       _offset = $.fn.offset;
-
-$.fn.position = function( options ) {
-       if ( !options || !options.of ) {
-               return _position.apply( this, arguments );
-       }
-
-       // make a copy, we don't want to modify arguments
-       options = $.extend( {}, options );
-
-       var target = $( options.of ),
-               targetElem = target[0],
-               collision = ( options.collision || "flip" ).split( " " ),
-               offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
-               targetWidth,
-               targetHeight,
-               basePosition;
-
-       if ( targetElem.nodeType === 9 ) {
-               targetWidth = target.width();
-               targetHeight = target.height();
-               basePosition = { top: 0, left: 0 };
-       // TODO: use $.isWindow() in 1.9
-       } else if ( targetElem.setTimeout ) {
-               targetWidth = target.width();
-               targetHeight = target.height();
-               basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
-       } else if ( targetElem.preventDefault ) {
-               // force left top to allow flipping
-               options.at = "left top";
-               targetWidth = targetHeight = 0;
-               basePosition = { top: options.of.pageY, left: options.of.pageX };
-       } else {
-               targetWidth = target.outerWidth();
-               targetHeight = target.outerHeight();
-               basePosition = target.offset();
-       }
-
-       // force my and at to have valid horizontal and veritcal positions
-       // if a value is missing or invalid, it will be converted to center 
-       $.each( [ "my", "at" ], function() {
-               var pos = ( options[this] || "" ).split( " " );
-               if ( pos.length === 1) {
-                       pos = horizontalPositions.test( pos[0] ) ?
-                               pos.concat( [center] ) :
-                               verticalPositions.test( pos[0] ) ?
-                                       [ center ].concat( pos ) :
-                                       [ center, center ];
-               }
-               pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
-               pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
-               options[ this ] = pos;
-       });
-
-       // normalize collision option
-       if ( collision.length === 1 ) {
-               collision[ 1 ] = collision[ 0 ];
-       }
-
-       // normalize offset option
-       offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
-       if ( offset.length === 1 ) {
-               offset[ 1 ] = offset[ 0 ];
-       }
-       offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
-
-       if ( options.at[0] === "right" ) {
-               basePosition.left += targetWidth;
-       } else if ( options.at[0] === center ) {
-               basePosition.left += targetWidth / 2;
-       }
-
-       if ( options.at[1] === "bottom" ) {
-               basePosition.top += targetHeight;
-       } else if ( options.at[1] === center ) {
-               basePosition.top += targetHeight / 2;
-       }
-
-       basePosition.left += offset[ 0 ];
-       basePosition.top += offset[ 1 ];
-
-       return this.each(function() {
-               var elem = $( this ),
-                       elemWidth = elem.outerWidth(),
-                       elemHeight = elem.outerHeight(),
-                       marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
-                       marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
-                       collisionWidth = elemWidth + marginLeft +
-                               ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
-                       collisionHeight = elemHeight + marginTop +
-                               ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
-                       position = $.extend( {}, basePosition ),
-                       collisionPosition;
-
-               if ( options.my[0] === "right" ) {
-                       position.left -= elemWidth;
-               } else if ( options.my[0] === center ) {
-                       position.left -= elemWidth / 2;
-               }
-
-               if ( options.my[1] === "bottom" ) {
-                       position.top -= elemHeight;
-               } else if ( options.my[1] === center ) {
-                       position.top -= elemHeight / 2;
-               }
-
-               // prevent fractions if jQuery version doesn't support them (see #5280)
-               if ( !support.fractions ) {
-                       position.left = Math.round( position.left );
-                       position.top = Math.round( position.top );
-               }
-
-               collisionPosition = {
-                       left: position.left - marginLeft,
-                       top: position.top - marginTop
-               };
-
-               $.each( [ "left", "top" ], function( i, dir ) {
-                       if ( $.ui.position[ collision[i] ] ) {
-                               $.ui.position[ collision[i] ][ dir ]( position, {
-                                       targetWidth: targetWidth,
-                                       targetHeight: targetHeight,
-                                       elemWidth: elemWidth,
-                                       elemHeight: elemHeight,
-                                       collisionPosition: collisionPosition,
-                                       collisionWidth: collisionWidth,
-                                       collisionHeight: collisionHeight,
-                                       offset: offset,
-                                       my: options.my,
-                                       at: options.at
-                               });
-                       }
-               });
-
-               if ( $.fn.bgiframe ) {
-                       elem.bgiframe();
-               }
-               elem.offset( $.extend( position, { using: options.using } ) );
-       });
-};
-
-$.ui.position = {
-       fit: {
-               left: function( position, data ) {
-                       var win = $( window ),
-                               over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
-                       position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
-               },
-               top: function( position, data ) {
-                       var win = $( window ),
-                               over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
-                       position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
-               }
-       },
-
-       flip: {
-               left: function( position, data ) {
-                       if ( data.at[0] === center ) {
-                               return;
-                       }
-                       var win = $( window ),
-                               over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
-                               myOffset = data.my[ 0 ] === "left" ?
-                                       -data.elemWidth :
-                                       data.my[ 0 ] === "right" ?
-                                               data.elemWidth :
-                                               0,
-                               atOffset = data.at[ 0 ] === "left" ?
-                                       data.targetWidth :
-                                       -data.targetWidth,
-                               offset = -2 * data.offset[ 0 ];
-                       position.left += data.collisionPosition.left < 0 ?
-                               myOffset + atOffset + offset :
-                               over > 0 ?
-                                       myOffset + atOffset + offset :
-                                       0;
-               },
-               top: function( position, data ) {
-                       if ( data.at[1] === center ) {
-                               return;
-                       }
-                       var win = $( window ),
-                               over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
-                               myOffset = data.my[ 1 ] === "top" ?
-                                       -data.elemHeight :
-                                       data.my[ 1 ] === "bottom" ?
-                                               data.elemHeight :
-                                               0,
-                               atOffset = data.at[ 1 ] === "top" ?
-                                       data.targetHeight :
-                                       -data.targetHeight,
-                               offset = -2 * data.offset[ 1 ];
-                       position.top += data.collisionPosition.top < 0 ?
-                               myOffset + atOffset + offset :
-                               over > 0 ?
-                                       myOffset + atOffset + offset :
-                                       0;
-               }
-       }
-};
-
-// offset setter from jQuery 1.4
-if ( !$.offset.setOffset ) {
-       $.offset.setOffset = function( elem, options ) {
-               // set position first, in-case top/left are set even on static elem
-               if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
-                       elem.style.position = "relative";
-               }
-               var curElem   = $( elem ),
-                       curOffset = curElem.offset(),
-                       curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
-                       curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
-                       props     = {
-                               top:  (options.top  - curOffset.top)  + curTop,
-                               left: (options.left - curOffset.left) + curLeft
-                       };
-               
-               if ( 'using' in options ) {
-                       options.using.call( elem, props );
-               } else {
-                       curElem.css( props );
-               }
-       };
-
-       $.fn.offset = function( options ) {
-               var elem = this[ 0 ];
-               if ( !elem || !elem.ownerDocument ) { return null; }
-               if ( options ) {
-                       if ( $.isFunction( options ) ) {
-                               return this.each(function( i ) {
-                                       $( this ).offset( options.call( this, i, $( this ).offset() ) );
-                               });
-                       }
-                       return this.each(function() {
-                               $.offset.setOffset( this, options );
-                       });
-               }
-               return _offset.call( this );
-       };
-}
-
-// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
-if ( !$.curCSS ) {
-       $.curCSS = $.css;
-}
-
-// fraction support test (older versions of jQuery don't support fractions)
-(function () {
-       var body = document.getElementsByTagName( "body" )[ 0 ], 
-               div = document.createElement( "div" ),
-               testElement, testElementParent, testElementStyle, offset, offsetTotal;
-
-       //Create a "fake body" for testing based on method used in jQuery.support
-       testElement = document.createElement( body ? "div" : "body" );
-       testElementStyle = {
-               visibility: "hidden",
-               width: 0,
-               height: 0,
-               border: 0,
-               margin: 0,
-               background: "none"
-       };
-       if ( body ) {
-               $.extend( testElementStyle, {
-                       position: "absolute",
-                       left: "-1000px",
-                       top: "-1000px"
-               });
-       }
-       for ( var i in testElementStyle ) {
-               testElement.style[ i ] = testElementStyle[ i ];
-       }
-       testElement.appendChild( div );
-       testElementParent = body || document.documentElement;
-       testElementParent.insertBefore( testElement, testElementParent.firstChild );
-
-       div.style.cssText = "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;";
-
-       offset = $( div ).offset( function( _, offset ) {
-               return offset;
-       }).offset();
-
-       testElement.innerHTML = "";
-       testElementParent.removeChild( testElement );
-
-       offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 );
-       support.fractions = offsetTotal > 21 && offsetTotal < 22;
-})();
-
-}( jQuery ));
diff --git a/resources/jquery.ui/jquery.ui.progressbar.js b/resources/jquery.ui/jquery.ui.progressbar.js
deleted file mode 100644 (file)
index 7cea1ba..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*!
- * jQuery UI Progressbar 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Progressbar
- *
- * Depends:
- *   jquery.ui.core.js
- *   jquery.ui.widget.js
- */
-(function( $, undefined ) {
-
-$.widget( "ui.progressbar", {
-       options: {
-               value: 0,
-               max: 100
-       },
-
-       min: 0,
-
-       _create: function() {
-               this.element
-                       .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
-                       .attr({
-                               role: "progressbar",
-                               "aria-valuemin": this.min,
-                               "aria-valuemax": this.options.max,
-                               "aria-valuenow": this._value()
-                       });
-
-               this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
-                       .appendTo( this.element );
-
-               this.oldValue = this._value();
-               this._refreshValue();
-       },
-
-       destroy: function() {
-               this.element
-                       .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
-                       .removeAttr( "role" )
-                       .removeAttr( "aria-valuemin" )
-                       .removeAttr( "aria-valuemax" )
-                       .removeAttr( "aria-valuenow" );
-
-               this.valueDiv.remove();
-
-               $.Widget.prototype.destroy.apply( this, arguments );
-       },
-
-       value: function( newValue ) {
-               if ( newValue === undefined ) {
-                       return this._value();
-               }
-
-               this._setOption( "value", newValue );
-               return this;
-       },
-
-       _setOption: function( key, value ) {
-               if ( key === "value" ) {
-                       this.options.value = value;
-                       this._refreshValue();
-                       if ( this._value() === this.options.max ) {
-                               this._trigger( "complete" );
-                       }
-               }
-
-               $.Widget.prototype._setOption.apply( this, arguments );
-       },
-
-       _value: function() {
-               var val = this.options.value;
-               // normalize invalid value
-               if ( typeof val !== "number" ) {
-                       val = 0;
-               }
-               return Math.min( this.options.max, Math.max( this.min, val ) );
-       },
-
-       _percentage: function() {
-               return 100 * this._value() / this.options.max;
-       },
-
-       _refreshValue: function() {
-               var value = this.value();
-               var percentage = this._percentage();
-
-               if ( this.oldValue !== value ) {
-                       this.oldValue = value;
-                       this._trigger( "change" );
-               }
-
-               this.valueDiv
-                       .toggle( value > this.min )
-                       .toggleClass( "ui-corner-right", value === this.options.max )
-                       .width( percentage.toFixed(0) + "%" );
-               this.element.attr( "aria-valuenow", value );
-       }
-});
-
-$.extend( $.ui.progressbar, {
-       version: "1.8.24"
-});
-
-})( jQuery );
diff --git a/resources/jquery.ui/jquery.ui.resizable.js b/resources/jquery.ui/jquery.ui.resizable.js
deleted file mode 100644 (file)
index 6cc6f41..0000000
+++ /dev/null
@@ -1,807 +0,0 @@
-/*!
- * jQuery UI Resizable 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Resizables
- *
- * Depends:
- *     jquery.ui.core.js
- *     jquery.ui.mouse.js
- *     jquery.ui.widget.js
- */
-(function( $, undefined ) {
-
-$.widget("ui.resizable", $.ui.mouse, {
-       widgetEventPrefix: "resize",
-       options: {
-               alsoResize: false,
-               animate: false,
-               animateDuration: "slow",
-               animateEasing: "swing",
-               aspectRatio: false,
-               autoHide: false,
-               containment: false,
-               ghost: false,
-               grid: false,
-               handles: "e,s,se",
-               helper: false,
-               maxHeight: null,
-               maxWidth: null,
-               minHeight: 10,
-               minWidth: 10,
-               zIndex: 1000
-       },
-       _create: function() {
-
-               var self = this, o = this.options;
-               this.element.addClass("ui-resizable");
-
-               $.extend(this, {
-                       _aspectRatio: !!(o.aspectRatio),
-                       aspectRatio: o.aspectRatio,
-                       originalElement: this.element,
-                       _proportionallyResizeElements: [],
-                       _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
-               });
-
-               //Wrap the element if it cannot hold child nodes
-               if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
-
-                       //Create a wrapper element and set the wrapper to the new current internal element
-                       this.element.wrap(
-                               $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
-                                       position: this.element.css('position'),
-                                       width: this.element.outerWidth(),
-                                       height: this.element.outerHeight(),
-                                       top: this.element.css('top'),
-                                       left: this.element.css('left')
-                               })
-                       );
-
-                       //Overwrite the original this.element
-                       this.element = this.element.parent().data(
-                               "resizable", this.element.data('resizable')
-                       );
-
-                       this.elementIsWrapper = true;
-
-                       //Move margins to the wrapper
-                       this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
-                       this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
-
-                       //Prevent Safari textarea resize
-                       this.originalResizeStyle = this.originalElement.css('resize');
-                       this.originalElement.css('resize', 'none');
-
-                       //Push the actual element to our proportionallyResize internal array
-                       this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
-
-                       // avoid IE jump (hard set the margin)
-                       this.originalElement.css({ margin: this.originalElement.css('margin') });
-
-                       // fix handlers offset
-                       this._proportionallyResize();
-
-               }
-
-               this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
-               if(this.handles.constructor == String) {
-
-                       if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
-                       var n = this.handles.split(","); this.handles = {};
-
-                       for(var i = 0; i < n.length; i++) {
-
-                               var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
-                               var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
-
-                               // Apply zIndex to all handles - see #7960
-                               axis.css({ zIndex: o.zIndex });
-
-                               //TODO : What's going on here?
-                               if ('se' == handle) {
-                                       axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
-                               };
-
-                               //Insert into internal handles object and append to element
-                               this.handles[handle] = '.ui-resizable-'+handle;
-                               this.element.append(axis);
-                       }
-
-               }
-
-               this._renderAxis = function(target) {
-
-                       target = target || this.element;
-
-                       for(var i in this.handles) {
-
-                               if(this.handles[i].constructor == String)
-                                       this.handles[i] = $(this.handles[i], this.element).show();
-
-                               //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
-                               if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
-
-                                       var axis = $(this.handles[i], this.element), padWrapper = 0;
-
-                                       //Checking the correct pad and border
-                                       padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
-
-                                       //The padding type i have to apply...
-                                       var padPos = [ 'padding',
-                                               /ne|nw|n/.test(i) ? 'Top' :
-                                               /se|sw|s/.test(i) ? 'Bottom' :
-                                               /^e$/.test(i) ? 'Right' : 'Left' ].join("");
-
-                                       target.css(padPos, padWrapper);
-
-                                       this._proportionallyResize();
-
-                               }
-
-                               //TODO: What's that good for? There's not anything to be executed left
-                               if(!$(this.handles[i]).length)
-                                       continue;
-
-                       }
-               };
-
-               //TODO: make renderAxis a prototype function
-               this._renderAxis(this.element);
-
-               this._handles = $('.ui-resizable-handle', this.element)
-                       .disableSelection();
-
-               //Matching axis name
-               this._handles.mouseover(function() {
-                       if (!self.resizing) {
-                               if (this.className)
-                                       var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
-                               //Axis, default = se
-                               self.axis = axis && axis[1] ? axis[1] : 'se';
-                       }
-               });
-
-               //If we want to auto hide the elements
-               if (o.autoHide) {
-                       this._handles.hide();
-                       $(this.element)
-                               .addClass("ui-resizable-autohide")
-                               .hover(function() {
-                                       if (o.disabled) return;
-                                       $(this).removeClass("ui-resizable-autohide");
-                                       self._handles.show();
-                               },
-                               function(){
-                                       if (o.disabled) return;
-                                       if (!self.resizing) {
-                                               $(this).addClass("ui-resizable-autohide");
-                                               self._handles.hide();
-                                       }
-                               });
-               }
-
-               //Initialize the mouse interaction
-               this._mouseInit();
-
-       },
-
-       destroy: function() {
-
-               this._mouseDestroy();
-
-               var _destroy = function(exp) {
-                       $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
-                               .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
-               };
-
-               //TODO: Unwrap at same DOM position
-               if (this.elementIsWrapper) {
-                       _destroy(this.element);
-                       var wrapper = this.element;
-                       wrapper.after(
-                               this.originalElement.css({
-                                       position: wrapper.css('position'),
-                                       width: wrapper.outerWidth(),
-                                       height: wrapper.outerHeight(),
-                                       top: wrapper.css('top'),
-                                       left: wrapper.css('left')
-                               })
-                       ).remove();
-               }
-
-               this.originalElement.css('resize', this.originalResizeStyle);
-               _destroy(this.originalElement);
-
-               return this;
-       },
-
-       _mouseCapture: function(event) {
-               var handle = false;
-               for (var i in this.handles) {
-                       if ($(this.handles[i])[0] == event.target) {
-                               handle = true;
-                       }
-               }
-
-               return !this.options.disabled && handle;
-       },
-
-       _mouseStart: function(event) {
-
-               var o = this.options, iniPos = this.element.position(), el = this.element;
-
-               this.resizing = true;
-               this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
-
-               // bugfix for http://dev.jquery.com/ticket/1749
-               if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
-                       el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
-               }
-
-               this._renderProxy();
-
-               var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
-
-               if (o.containment) {
-                       curleft += $(o.containment).scrollLeft() || 0;
-                       curtop += $(o.containment).scrollTop() || 0;
-               }
-
-               //Store needed variables
-               this.offset = this.helper.offset();
-               this.position = { left: curleft, top: curtop };
-               this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
-               this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
-               this.originalPosition = { left: curleft, top: curtop };
-               this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
-               this.originalMousePosition = { left: event.pageX, top: event.pageY };
-
-               //Aspect Ratio
-               this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
-
-           var cursor = $('.ui-resizable-' + this.axis).css('cursor');
-           $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
-
-               el.addClass("ui-resizable-resizing");
-               this._propagate("start", event);
-               return true;
-       },
-
-       _mouseDrag: function(event) {
-
-               //Increase performance, avoid regex
-               var el = this.helper, o = this.options, props = {},
-                       self = this, smp = this.originalMousePosition, a = this.axis;
-
-               var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
-               var trigger = this._change[a];
-               if (!trigger) return false;
-
-               // Calculate the attrs that will be change
-               var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
-
-               // Put this in the mouseDrag handler since the user can start pressing shift while resizing
-               this._updateVirtualBoundaries(event.shiftKey);
-               if (this._aspectRatio || event.shiftKey)
-                       data = this._updateRatio(data, event);
-
-               data = this._respectSize(data, event);
-
-               // plugins callbacks need to be called first
-               this._propagate("resize", event);
-
-               el.css({
-                       top: this.position.top + "px", left: this.position.left + "px",
-                       width: this.size.width + "px", height: this.size.height + "px"
-               });
-
-               if (!this._helper && this._proportionallyResizeElements.length)
-                       this._proportionallyResize();
-
-               this._updateCache(data);
-
-               // calling the user callback at the end
-               this._trigger('resize', event, this.ui());
-
-               return false;
-       },
-
-       _mouseStop: function(event) {
-
-               this.resizing = false;
-               var o = this.options, self = this;
-
-               if(this._helper) {
-                       var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
-                               soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
-                               soffsetw = ista ? 0 : self.sizeDiff.width;
-
-                       var s = { width: (self.helper.width()  - soffsetw), height: (self.helper.height() - soffseth) },
-                               left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
-                               top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
-
-                       if (!o.animate)
-                               this.element.css($.extend(s, { top: top, left: left }));
-
-                       self.helper.height(self.size.height);
-                       self.helper.width(self.size.width);
-
-                       if (this._helper && !o.animate) this._proportionallyResize();
-               }
-
-               $('body').css('cursor', 'auto');
-
-               this.element.removeClass("ui-resizable-resizing");
-
-               this._propagate("stop", event);
-
-               if (this._helper) this.helper.remove();
-               return false;
-
-       },
-
-    _updateVirtualBoundaries: function(forceAspectRatio) {
-        var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
-
-        b = {
-            minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
-            maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
-            minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
-            maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
-        };
-
-        if(this._aspectRatio || forceAspectRatio) {
-            // We want to create an enclosing box whose aspect ration is the requested one
-            // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
-            pMinWidth = b.minHeight * this.aspectRatio;
-            pMinHeight = b.minWidth / this.aspectRatio;
-            pMaxWidth = b.maxHeight * this.aspectRatio;
-            pMaxHeight = b.maxWidth / this.aspectRatio;
-
-            if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
-            if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
-            if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
-            if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
-        }
-        this._vBoundaries = b;
-    },
-
-       _updateCache: function(data) {
-               var o = this.options;
-               this.offset = this.helper.offset();
-               if (isNumber(data.left)) this.position.left = data.left;
-               if (isNumber(data.top)) this.position.top = data.top;
-               if (isNumber(data.height)) this.size.height = data.height;
-               if (isNumber(data.width)) this.size.width = data.width;
-       },
-
-       _updateRatio: function(data, event) {
-
-               var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
-
-               if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
-               else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
-
-               if (a == 'sw') {
-                       data.left = cpos.left + (csize.width - data.width);
-                       data.top = null;
-               }
-               if (a == 'nw') {
-                       data.top = cpos.top + (csize.height - data.height);
-                       data.left = cpos.left + (csize.width - data.width);
-               }
-
-               return data;
-       },
-
-       _respectSize: function(data, event) {
-
-               var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
-                               ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
-                                       isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
-
-               if (isminw) data.width = o.minWidth;
-               if (isminh) data.height = o.minHeight;
-               if (ismaxw) data.width = o.maxWidth;
-               if (ismaxh) data.height = o.maxHeight;
-
-               var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
-               var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
-
-               if (isminw && cw) data.left = dw - o.minWidth;
-               if (ismaxw && cw) data.left = dw - o.maxWidth;
-               if (isminh && ch)       data.top = dh - o.minHeight;
-               if (ismaxh && ch)       data.top = dh - o.maxHeight;
-
-               // fixing jump error on top/left - bug #2330
-               var isNotwh = !data.width && !data.height;
-               if (isNotwh && !data.left && data.top) data.top = null;
-               else if (isNotwh && !data.top && data.left) data.left = null;
-
-               return data;
-       },
-
-       _proportionallyResize: function() {
-
-               var o = this.options;
-               if (!this._proportionallyResizeElements.length) return;
-               var element = this.helper || this.element;
-
-               for (var i=0; i < this._proportionallyResizeElements.length; i++) {
-
-                       var prel = this._proportionallyResizeElements[i];
-
-                       if (!this.borderDif) {
-                               var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
-                                       p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
-
-                               this.borderDif = $.map(b, function(v, i) {
-                                       var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
-                                       return border + padding;
-                               });
-                       }
-
-                       if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
-                               continue;
-
-                       prel.css({
-                               height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
-                               width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
-                       });
-
-               };
-
-       },
-
-       _renderProxy: function() {
-
-               var el = this.element, o = this.options;
-               this.elementOffset = el.offset();
-
-               if(this._helper) {
-
-                       this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
-
-                       // fix ie6 offset TODO: This seems broken
-                       var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
-                       pxyoffset = ( ie6 ? 2 : -1 );
-
-                       this.helper.addClass(this._helper).css({
-                               width: this.element.outerWidth() + pxyoffset,
-                               height: this.element.outerHeight() + pxyoffset,
-                               position: 'absolute',
-                               left: this.elementOffset.left - ie6offset +'px',
-                               top: this.elementOffset.top - ie6offset +'px',
-                               zIndex: ++o.zIndex //TODO: Don't modify option
-                       });
-
-                       this.helper
-                               .appendTo("body")
-                               .disableSelection();
-
-               } else {
-                       this.helper = this.element;
-               }
-
-       },
-
-       _change: {
-               e: function(event, dx, dy) {
-                       return { width: this.originalSize.width + dx };
-               },
-               w: function(event, dx, dy) {
-                       var o = this.options, cs = this.originalSize, sp = this.originalPosition;
-                       return { left: sp.left + dx, width: cs.width - dx };
-               },
-               n: function(event, dx, dy) {
-                       var o = this.options, cs = this.originalSize, sp = this.originalPosition;
-                       return { top: sp.top + dy, height: cs.height - dy };
-               },
-               s: function(event, dx, dy) {
-                       return { height: this.originalSize.height + dy };
-               },
-               se: function(event, dx, dy) {
-                       return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
-               },
-               sw: function(event, dx, dy) {
-                       return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
-               },
-               ne: function(event, dx, dy) {
-                       return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
-               },
-               nw: function(event, dx, dy) {
-                       return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
-               }
-       },
-
-       _propagate: function(n, event) {
-               $.ui.plugin.call(this, n, [event, this.ui()]);
-               (n != "resize" && this._trigger(n, event, this.ui()));
-       },
-
-       plugins: {},
-
-       ui: function() {
-               return {
-                       originalElement: this.originalElement,
-                       element: this.element,
-                       helper: this.helper,
-                       position: this.position,
-                       size: this.size,
-                       originalSize: this.originalSize,
-                       originalPosition: this.originalPosition
-               };
-       }
-
-});
-
-$.extend($.ui.resizable, {
-       version: "1.8.24"
-});
-
-/*
- * Resizable Extensions
- */
-
-$.ui.plugin.add("resizable", "alsoResize", {
-
-       start: function (event, ui) {
-               var self = $(this).data("resizable"), o = self.options;
-
-               var _store = function (exp) {
-                       $(exp).each(function() {
-                               var el = $(this);
-                               el.data("resizable-alsoresize", {
-                                       width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
-                                       left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10)
-                               });
-                       });
-               };
-
-               if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
-                       if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
-                       else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
-               }else{
-                       _store(o.alsoResize);
-               }
-       },
-
-       resize: function (event, ui) {
-               var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
-
-               var delta = {
-                       height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
-                       top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
-               },
-
-               _alsoResize = function (exp, c) {
-                       $(exp).each(function() {
-                               var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
-                                       css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
-
-                               $.each(css, function (i, prop) {
-                                       var sum = (start[prop]||0) + (delta[prop]||0);
-                                       if (sum && sum >= 0)
-                                               style[prop] = sum || null;
-                               });
-
-                               el.css(style);
-                       });
-               };
-
-               if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
-                       $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
-               }else{
-                       _alsoResize(o.alsoResize);
-               }
-       },
-
-       stop: function (event, ui) {
-               $(this).removeData("resizable-alsoresize");
-       }
-});
-
-$.ui.plugin.add("resizable", "animate", {
-
-       stop: function(event, ui) {
-               var self = $(this).data("resizable"), o = self.options;
-
-               var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
-                                       soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
-                                               soffsetw = ista ? 0 : self.sizeDiff.width;
-
-               var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
-                                       left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
-                                               top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
-
-               self.element.animate(
-                       $.extend(style, top && left ? { top: top, left: left } : {}), {
-                               duration: o.animateDuration,
-                               easing: o.animateEasing,
-                               step: function() {
-
-                                       var data = {
-                                               width: parseInt(self.element.css('width'), 10),
-                                               height: parseInt(self.element.css('height'), 10),
-                                               top: parseInt(self.element.css('top'), 10),
-                                               left: parseInt(self.element.css('left'), 10)
-                                       };
-
-                                       if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
-
-                                       // propagating resize, and updating values for each animation step
-                                       self._updateCache(data);
-                                       self._propagate("resize", event);
-
-                               }
-                       }
-               );
-       }
-
-});
-
-$.ui.plugin.add("resizable", "containment", {
-
-       start: function(event, ui) {
-               var self = $(this).data("resizable"), o = self.options, el = self.element;
-               var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
-               if (!ce) return;
-
-               self.containerElement = $(ce);
-
-               if (/document/.test(oc) || oc == document) {
-                       self.containerOffset = { left: 0, top: 0 };
-                       self.containerPosition = { left: 0, top: 0 };
-
-                       self.parentData = {
-                               element: $(document), left: 0, top: 0,
-                               width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
-                       };
-               }
-
-               // i'm a node, so compute top, left, right, bottom
-               else {
-                       var element = $(ce), p = [];
-                       $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
-
-                       self.containerOffset = element.offset();
-                       self.containerPosition = element.position();
-                       self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
-
-                       var co = self.containerOffset, ch = self.containerSize.height,  cw = self.containerSize.width,
-                                               width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
-
-                       self.parentData = {
-                               element: ce, left: co.left, top: co.top, width: width, height: height
-                       };
-               }
-       },
-
-       resize: function(event, ui) {
-               var self = $(this).data("resizable"), o = self.options,
-                               ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
-                               pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
-
-               if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
-
-               if (cp.left < (self._helper ? co.left : 0)) {
-                       self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
-                       if (pRatio) self.size.height = self.size.width / self.aspectRatio;
-                       self.position.left = o.helper ? co.left : 0;
-               }
-
-               if (cp.top < (self._helper ? co.top : 0)) {
-                       self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
-                       if (pRatio) self.size.width = self.size.height * self.aspectRatio;
-                       self.position.top = self._helper ? co.top : 0;
-               }
-
-               self.offset.left = self.parentData.left+self.position.left;
-               self.offset.top = self.parentData.top+self.position.top;
-
-               var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
-                                       hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
-
-               var isParent = self.containerElement.get(0) == self.element.parent().get(0),
-                   isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
-
-               if(isParent && isOffsetRelative) woset -= self.parentData.left;
-
-               if (woset + self.size.width >= self.parentData.width) {
-                       self.size.width = self.parentData.width - woset;
-                       if (pRatio) self.size.height = self.size.width / self.aspectRatio;
-               }
-
-               if (hoset + self.size.height >= self.parentData.height) {
-                       self.size.height = self.parentData.height - hoset;
-                       if (pRatio) self.size.width = self.size.height * self.aspectRatio;
-               }
-       },
-
-       stop: function(event, ui){
-               var self = $(this).data("resizable"), o = self.options, cp = self.position,
-                               co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
-
-               var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
-
-               if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
-                       $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
-
-               if (self._helper && !o.animate && (/static/).test(ce.css('position')))
-                       $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
-
-       }
-});
-
-$.ui.plugin.add("resizable", "ghost", {
-
-       start: function(event, ui) {
-
-               var self = $(this).data("resizable"), o = self.options, cs = self.size;
-
-               self.ghost = self.originalElement.clone();
-               self.ghost
-                       .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
-                       .addClass('ui-resizable-ghost')
-                       .addClass(typeof o.ghost == 'string' ? o.ghost : '');
-
-               self.ghost.appendTo(self.helper);
-
-       },
-
-       resize: function(event, ui){
-               var self = $(this).data("resizable"), o = self.options;
-               if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
-       },
-
-       stop: function(event, ui){
-               var self = $(this).data("resizable"), o = self.options;
-               if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
-       }
-
-});
-
-$.ui.plugin.add("resizable", "grid", {
-
-       resize: function(event, ui) {
-               var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
-               o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
-               var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
-
-               if (/^(se|s|e)$/.test(a)) {
-                       self.size.width = os.width + ox;
-                       self.size.height = os.height + oy;
-               }
-               else if (/^(ne)$/.test(a)) {
-                       self.size.width = os.width + ox;
-                       self.size.height = os.height + oy;
-                       self.position.top = op.top - oy;
-               }
-               else if (/^(sw)$/.test(a)) {
-                       self.size.width = os.width + ox;
-                       self.size.height = os.height + oy;
-                       self.position.left = op.left - ox;
-               }
-               else {
-                       self.size.width = os.width + ox;
-                       self.size.height = os.height + oy;
-                       self.position.top = op.top - oy;
-                       self.position.left = op.left - ox;
-               }
-       }
-
-});
-
-var num = function(v) {
-       return parseInt(v, 10) || 0;
-};
-
-var isNumber = function(value) {
-       return !isNaN(parseInt(value, 10));
-};
-
-})(jQuery);
diff --git a/resources/jquery.ui/jquery.ui.selectable.js b/resources/jquery.ui/jquery.ui.selectable.js
deleted file mode 100644 (file)
index 44c6e8c..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/*!
- * jQuery UI Selectable 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Selectables
- *
- * Depends:
- *     jquery.ui.core.js
- *     jquery.ui.mouse.js
- *     jquery.ui.widget.js
- */
-(function( $, undefined ) {
-
-$.widget("ui.selectable", $.ui.mouse, {
-       options: {
-               appendTo: 'body',
-               autoRefresh: true,
-               distance: 0,
-               filter: '*',
-               tolerance: 'touch'
-       },
-       _create: function() {
-               var self = this;
-
-               this.element.addClass("ui-selectable");
-
-               this.dragged = false;
-
-               // cache selectee children based on filter
-               var selectees;
-               this.refresh = function() {
-                       selectees = $(self.options.filter, self.element[0]);
-                       selectees.addClass("ui-selectee");
-                       selectees.each(function() {
-                               var $this = $(this);
-                               var pos = $this.offset();
-                               $.data(this, "selectable-item", {
-                                       element: this,
-                                       $element: $this,
-                                       left: pos.left,
-                                       top: pos.top,
-                                       right: pos.left + $this.outerWidth(),
-                                       bottom: pos.top + $this.outerHeight(),
-                                       startselected: false,
-                                       selected: $this.hasClass('ui-selected'),
-                                       selecting: $this.hasClass('ui-selecting'),
-                                       unselecting: $this.hasClass('ui-unselecting')
-                               });
-                       });
-               };
-               this.refresh();
-
-               this.selectees = selectees.addClass("ui-selectee");
-
-               this._mouseInit();
-
-               this.helper = $("<div class='ui-selectable-helper'></div>");
-       },
-
-       destroy: function() {
-               this.selectees
-                       .removeClass("ui-selectee")
-                       .removeData("selectable-item");
-               this.element
-                       .removeClass("ui-selectable ui-selectable-disabled")
-                       .removeData("selectable")
-                       .unbind(".selectable");
-               this._mouseDestroy();
-
-               return this;
-       },
-
-       _mouseStart: function(event) {
-               var self = this;
-
-               this.opos = [event.pageX, event.pageY];
-
-               if (this.options.disabled)
-                       return;
-
-               var options = this.options;
-
-               this.selectees = $(options.filter, this.element[0]);
-
-               this._trigger("start", event);
-
-               $(options.appendTo).append(this.helper);
-               // position helper (lasso)
-               this.helper.css({
-                       "left": event.clientX,
-                       "top": event.clientY,
-                       "width": 0,
-                       "height": 0
-               });
-
-               if (options.autoRefresh) {
-                       this.refresh();
-               }
-
-               this.selectees.filter('.ui-selected').each(function() {
-                       var selectee = $.data(this, "selectable-item");
-                       selectee.startselected = true;
-                       if (!event.metaKey && !event.ctrlKey) {
-                               selectee.$element.removeClass('ui-selected');
-                               selectee.selected = false;
-                               selectee.$element.addClass('ui-unselecting');
-                               selectee.unselecting = true;
-                               // selectable UNSELECTING callback
-                               self._trigger("unselecting", event, {
-                                       unselecting: selectee.element
-                               });
-                       }
-               });
-
-               $(event.target).parents().andSelf().each(function() {
-                       var selectee = $.data(this, "selectable-item");
-                       if (selectee) {
-                               var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected');
-                               selectee.$element
-                                       .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
-                                       .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
-                               selectee.unselecting = !doSelect;
-                               selectee.selecting = doSelect;
-                               selectee.selected = doSelect;
-                               // selectable (UN)SELECTING callback
-                               if (doSelect) {
-                                       self._trigger("selecting", event, {
-                                               selecting: selectee.element
-                                       });
-                               } else {
-                                       self._trigger("unselecting", event, {
-                                               unselecting: selectee.element
-                                       });
-                               }
-                               return false;
-                       }
-               });
-
-       },
-
-       _mouseDrag: function(event) {
-               var self = this;
-               this.dragged = true;
-
-               if (this.options.disabled)
-                       return;
-
-               var options = this.options;
-
-               var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
-               if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
-               if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
-               this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
-
-               this.selectees.each(function() {
-                       var selectee = $.data(this, "selectable-item");
-                       //prevent helper from being selected if appendTo: selectable
-                       if (!selectee || selectee.element == self.element[0])
-                               return;
-                       var hit = false;
-                       if (options.tolerance == 'touch') {
-                               hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
-                       } else if (options.tolerance == 'fit') {
-                               hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
-                       }
-
-                       if (hit) {
-                               // SELECT
-                               if (selectee.selected) {
-                                       selectee.$element.removeClass('ui-selected');
-                                       selectee.selected = false;
-                               }
-                               if (selectee.unselecting) {
-                                       selectee.$element.removeClass('ui-unselecting');
-                                       selectee.unselecting = false;
-                               }
-                               if (!selectee.selecting) {
-                                       selectee.$element.addClass('ui-selecting');
-                                       selectee.selecting = true;
-                                       // selectable SELECTING callback
-                                       self._trigger("selecting", event, {
-                                               selecting: selectee.element
-                                       });
-                               }
-                       } else {
-                               // UNSELECT
-                               if (selectee.selecting) {
-                                       if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
-                                               selectee.$element.removeClass('ui-selecting');
-                                               selectee.selecting = false;
-                                               selectee.$element.addClass('ui-selected');
-                                               selectee.selected = true;
-                                       } else {
-                                               selectee.$element.removeClass('ui-selecting');
-                                               selectee.selecting = false;
-                                               if (selectee.startselected) {
-                                                       selectee.$element.addClass('ui-unselecting');
-                                                       selectee.unselecting = true;
-                                               }
-                                               // selectable UNSELECTING callback
-                                               self._trigger("unselecting", event, {
-                                                       unselecting: selectee.element
-                                               });
-                                       }
-                               }
-                               if (selectee.selected) {
-                                       if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
-                                               selectee.$element.removeClass('ui-selected');
-                                               selectee.selected = false;
-
-                                               selectee.$element.addClass('ui-unselecting');
-                                               selectee.unselecting = true;
-                                               // selectable UNSELECTING callback
-                                               self._trigger("unselecting", event, {
-                                                       unselecting: selectee.element
-                                               });
-                                       }
-                               }
-                       }
-               });
-
-               return false;
-       },
-
-       _mouseStop: function(event) {
-               var self = this;
-
-               this.dragged = false;
-
-               var options = this.options;
-
-               $('.ui-unselecting', this.element[0]).each(function() {
-                       var selectee = $.data(this, "selectable-item");
-                       selectee.$element.removeClass('ui-unselecting');
-                       selectee.unselecting = false;
-                       selectee.startselected = false;
-                       self._trigger("unselected", event, {
-                               unselected: selectee.element
-                       });
-               });
-               $('.ui-selecting', this.element[0]).each(function() {
-                       var selectee = $.data(this, "selectable-item");
-                       selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
-                       selectee.selecting = false;
-                       selectee.selected = true;
-                       selectee.startselected = true;
-                       self._trigger("selected", event, {
-                               selected: selectee.element
-                       });
-               });
-               this._trigger("stop", event);
-
-               this.helper.remove();
-
-               return false;
-       }
-
-});
-
-$.extend($.ui.selectable, {
-       version: "1.8.24"
-});
-
-})(jQuery);
diff --git a/resources/jquery.ui/jquery.ui.slider.js b/resources/jquery.ui/jquery.ui.slider.js
deleted file mode 100644 (file)
index c554e78..0000000
+++ /dev/null
@@ -1,662 +0,0 @@
-/*!
- * jQuery UI Slider 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Slider
- *
- * Depends:
- *     jquery.ui.core.js
- *     jquery.ui.mouse.js
- *     jquery.ui.widget.js
- */
-(function( $, undefined ) {
-
-// number of pages in a slider
-// (how many times can you page up/down to go through the whole range)
-var numPages = 5;
-
-$.widget( "ui.slider", $.ui.mouse, {
-
-       widgetEventPrefix: "slide",
-
-       options: {
-               animate: false,
-               distance: 0,
-               max: 100,
-               min: 0,
-               orientation: "horizontal",
-               range: false,
-               step: 1,
-               value: 0,
-               values: null
-       },
-
-       _create: function() {
-               var self = this,
-                       o = this.options,
-                       existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
-                       handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
-                       handleCount = ( o.values && o.values.length ) || 1,
-                       handles = [];
-
-               this._keySliding = false;
-               this._mouseSliding = false;
-               this._animateOff = true;
-               this._handleIndex = null;
-               this._detectOrientation();
-               this._mouseInit();
-
-               this.element
-                       .addClass( "ui-slider" +
-                               " ui-slider-" + this.orientation +
-                               " ui-widget" +
-                               " ui-widget-content" +
-                               " ui-corner-all" +
-                               ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
-
-               this.range = $([]);
-
-               if ( o.range ) {
-                       if ( o.range === true ) {
-                               if ( !o.values ) {
-                                       o.values = [ this._valueMin(), this._valueMin() ];
-                               }
-                               if ( o.values.length && o.values.length !== 2 ) {
-                                       o.values = [ o.values[0], o.values[0] ];
-                               }
-                       }
-
-                       this.range = $( "<div></div>" )
-                               .appendTo( this.element )
-                               .addClass( "ui-slider-range" +
-                               // note: this isn't the most fittingly semantic framework class for this element,
-                               // but worked best visually with a variety of themes
-                               " ui-widget-header" + 
-                               ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
-               }
-
-               for ( var i = existingHandles.length; i < handleCount; i += 1 ) {
-                       handles.push( handle );
-               }
-
-               this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) );
-
-               this.handle = this.handles.eq( 0 );
-
-               this.handles.add( this.range ).filter( "a" )
-                       .click(function( event ) {
-                               event.preventDefault();
-                       })
-                       .hover(function() {
-                               if ( !o.disabled ) {
-                                       $( this ).addClass( "ui-state-hover" );
-                               }
-                       }, function() {
-                               $( this ).removeClass( "ui-state-hover" );
-                       })
-                       .focus(function() {
-                               if ( !o.disabled ) {
-                                       $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
-                                       $( this ).addClass( "ui-state-focus" );
-                               } else {
-                                       $( this ).blur();
-                               }
-                       })
-                       .blur(function() {
-                               $( this ).removeClass( "ui-state-focus" );
-                       });
-
-               this.handles.each(function( i ) {
-                       $( this ).data( "index.ui-slider-handle", i );
-               });
-
-               this.handles
-                       .keydown(function( event ) {
-                               var index = $( this ).data( "index.ui-slider-handle" ),
-                                       allowed,
-                                       curVal,
-                                       newVal,
-                                       step;
-       
-                               if ( self.options.disabled ) {
-                                       return;
-                               }
-       
-                               switch ( event.keyCode ) {
-                                       case $.ui.keyCode.HOME:
-                                       case $.ui.keyCode.END:
-                                       case $.ui.keyCode.PAGE_UP:
-                                       case $.ui.keyCode.PAGE_DOWN:
-                                       case $.ui.keyCode.UP:
-                                       case $.ui.keyCode.RIGHT:
-                                       case $.ui.keyCode.DOWN:
-                                       case $.ui.keyCode.LEFT:
-                                               event.preventDefault();
-                                               if ( !self._keySliding ) {
-                                                       self._keySliding = true;
-                                                       $( this ).addClass( "ui-state-active" );
-                                                       allowed = self._start( event, index );
-                                                       if ( allowed === false ) {
-                                                               return;
-                                                       }
-                                               }
-                                               break;
-                               }
-       
-                               step = self.options.step;
-                               if ( self.options.values && self.options.values.length ) {
-                                       curVal = newVal = self.values( index );
-                               } else {
-                                       curVal = newVal = self.value();
-                               }
-       
-                               switch ( event.keyCode ) {
-                                       case $.ui.keyCode.HOME:
-                                               newVal = self._valueMin();
-                                               break;
-                                       case $.ui.keyCode.END:
-                                               newVal = self._valueMax();
-                                               break;
-                                       case $.ui.keyCode.PAGE_UP:
-                                               newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
-                                               break;
-                                       case $.ui.keyCode.PAGE_DOWN:
-                                               newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
-                                               break;
-                                       case $.ui.keyCode.UP:
-                                       case $.ui.keyCode.RIGHT:
-                                               if ( curVal === self._valueMax() ) {
-                                                       return;
-                                               }
-                                               newVal = self._trimAlignValue( curVal + step );
-                                               break;
-                                       case $.ui.keyCode.DOWN:
-                                       case $.ui.keyCode.LEFT:
-                                               if ( curVal === self._valueMin() ) {
-                                                       return;
-                                               }
-                                               newVal = self._trimAlignValue( curVal - step );
-                                               break;
-                               }
-       
-                               self._slide( event, index, newVal );
-                       })
-                       .keyup(function( event ) {
-                               var index = $( this ).data( "index.ui-slider-handle" );
-       
-                               if ( self._keySliding ) {
-                                       self._keySliding = false;
-                                       self._stop( event, index );
-                                       self._change( event, index );
-                                       $( this ).removeClass( "ui-state-active" );
-                               }
-       
-                       });
-
-               this._refreshValue();
-
-               this._animateOff = false;
-       },
-
-       destroy: function() {
-               this.handles.remove();
-               this.range.remove();
-
-               this.element
-                       .removeClass( "ui-slider" +
-                               " ui-slider-horizontal" +
-                               " ui-slider-vertical" +
-                               " ui-slider-disabled" +
-                               " ui-widget" +
-                               " ui-widget-content" +
-                               " ui-corner-all" )
-                       .removeData( "slider" )
-                       .unbind( ".slider" );
-
-               this._mouseDestroy();
-
-               return this;
-       },
-
-       _mouseCapture: function( event ) {
-               var o = this.options,
-                       position,
-                       normValue,
-                       distance,
-                       closestHandle,
-                       self,
-                       index,
-                       allowed,
-                       offset,
-                       mouseOverHandle;
-
-               if ( o.disabled ) {
-                       return false;
-               }
-
-               this.elementSize = {
-                       width: this.element.outerWidth(),
-                       height: this.element.outerHeight()
-               };
-               this.elementOffset = this.element.offset();
-
-               position = { x: event.pageX, y: event.pageY };
-               normValue = this._normValueFromMouse( position );
-               distance = this._valueMax() - this._valueMin() + 1;
-               self = this;
-               this.handles.each(function( i ) {
-                       var thisDistance = Math.abs( normValue - self.values(i) );
-                       if ( distance > thisDistance ) {
-                               distance = thisDistance;
-                               closestHandle = $( this );
-                               index = i;
-                       }
-               });
-
-               // workaround for bug #3736 (if both handles of a range are at 0,
-               // the first is always used as the one with least distance,
-               // and moving it is obviously prevented by preventing negative ranges)
-               if( o.range === true && this.values(1) === o.min ) {
-                       index += 1;
-                       closestHandle = $( this.handles[index] );
-               }
-
-               allowed = this._start( event, index );
-               if ( allowed === false ) {
-                       return false;
-               }
-               this._mouseSliding = true;
-
-               self._handleIndex = index;
-
-               closestHandle
-                       .addClass( "ui-state-active" )
-                       .focus();
-               
-               offset = closestHandle.offset();
-               mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
-               this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
-                       left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
-                       top: event.pageY - offset.top -
-                               ( closestHandle.height() / 2 ) -
-                               ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
-                               ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
-                               ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
-               };
-
-               if ( !this.handles.hasClass( "ui-state-hover" ) ) {
-                       this._slide( event, index, normValue );
-               }
-               this._animateOff = true;
-               return true;
-       },
-
-       _mouseStart: function( event ) {
-               return true;
-       },
-
-       _mouseDrag: function( event ) {
-               var position = { x: event.pageX, y: event.pageY },
-                       normValue = this._normValueFromMouse( position );
-               
-               this._slide( event, this._handleIndex, normValue );
-
-               return false;
-       },
-
-       _mouseStop: function( event ) {
-               this.handles.removeClass( "ui-state-active" );
-               this._mouseSliding = false;
-
-               this._stop( event, this._handleIndex );
-               this._change( event, this._handleIndex );
-
-               this._handleIndex = null;
-               this._clickOffset = null;
-               this._animateOff = false;
-
-               return false;
-       },
-       
-       _detectOrientation: function() {
-               this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
-       },
-
-       _normValueFromMouse: function( position ) {
-               var pixelTotal,
-                       pixelMouse,
-                       percentMouse,
-                       valueTotal,
-                       valueMouse;
-
-               if ( this.orientation === "horizontal" ) {
-                       pixelTotal = this.elementSize.width;
-                       pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
-               } else {
-                       pixelTotal = this.elementSize.height;
-                       pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
-               }
-
-               percentMouse = ( pixelMouse / pixelTotal );
-               if ( percentMouse > 1 ) {
-                       percentMouse = 1;
-               }
-               if ( percentMouse < 0 ) {
-                       percentMouse = 0;
-               }
-               if ( this.orientation === "vertical" ) {
-                       percentMouse = 1 - percentMouse;
-               }
-
-               valueTotal = this._valueMax() - this._valueMin();
-               valueMouse = this._valueMin() + percentMouse * valueTotal;
-
-               return this._trimAlignValue( valueMouse );
-       },
-
-       _start: function( event, index ) {
-               var uiHash = {
-                       handle: this.handles[ index ],
-                       value: this.value()
-               };
-               if ( this.options.values && this.options.values.length ) {
-                       uiHash.value = this.values( index );
-                       uiHash.values = this.values();
-               }
-               return this._trigger( "start", event, uiHash );
-       },
-
-       _slide: function( event, index, newVal ) {
-               var otherVal,
-                       newValues,
-                       allowed;
-
-               if ( this.options.values && this.options.values.length ) {
-                       otherVal = this.values( index ? 0 : 1 );
-
-                       if ( ( this.options.values.length === 2 && this.options.range === true ) && 
-                                       ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
-                               ) {
-                               newVal = otherVal;
-                       }
-
-                       if ( newVal !== this.values( index ) ) {
-                               newValues = this.values();
-                               newValues[ index ] = newVal;
-                               // A slide can be canceled by returning false from the slide callback
-                               allowed = this._trigger( "slide", event, {
-                                       handle: this.handles[ index ],
-                                       value: newVal,
-                                       values: newValues
-                               } );
-                               otherVal = this.values( index ? 0 : 1 );
-                               if ( allowed !== false ) {
-                                       this.values( index, newVal, true );
-                               }
-                       }
-               } else {
-                       if ( newVal !== this.value() ) {
-                               // A slide can be canceled by returning false from the slide callback
-                               allowed = this._trigger( "slide", event, {
-                                       handle: this.handles[ index ],
-                                       value: newVal
-                               } );
-                               if ( allowed !== false ) {
-                                       this.value( newVal );
-                               }
-                       }
-               }
-       },
-
-       _stop: function( event, index ) {
-               var uiHash = {
-                       handle: this.handles[ index ],
-                       value: this.value()
-               };
-               if ( this.options.values && this.options.values.length ) {
-                       uiHash.value = this.values( index );
-                       uiHash.values = this.values();
-               }
-
-               this._trigger( "stop", event, uiHash );
-       },
-
-       _change: function( event, index ) {
-               if ( !this._keySliding && !this._mouseSliding ) {
-                       var uiHash = {
-                               handle: this.handles[ index ],
-                               value: this.value()
-                       };
-                       if ( this.options.values && this.options.values.length ) {
-                               uiHash.value = this.values( index );
-                               uiHash.values = this.values();
-                       }
-
-                       this._trigger( "change", event, uiHash );
-               }
-       },
-
-       value: function( newValue ) {
-               if ( arguments.length ) {
-                       this.options.value = this._trimAlignValue( newValue );
-                       this._refreshValue();
-                       this._change( null, 0 );
-                       return;
-               }
-
-               return this._value();
-       },
-
-       values: function( index, newValue ) {
-               var vals,
-                       newValues,
-                       i;
-
-               if ( arguments.length > 1 ) {
-                       this.options.values[ index ] = this._trimAlignValue( newValue );
-                       this._refreshValue();
-                       this._change( null, index );
-                       return;
-               }
-
-               if ( arguments.length ) {
-                       if ( $.isArray( arguments[ 0 ] ) ) {
-                               vals = this.options.values;
-                               newValues = arguments[ 0 ];
-                               for ( i = 0; i < vals.length; i += 1 ) {
-                                       vals[ i ] = this._trimAlignValue( newValues[ i ] );
-                                       this._change( null, i );
-                               }
-                               this._refreshValue();
-                       } else {
-                               if ( this.options.values && this.options.values.length ) {
-                                       return this._values( index );
-                               } else {
-                                       return this.value();
-                               }
-                       }
-               } else {
-                       return this._values();
-               }
-       },
-
-       _setOption: function( key, value ) {
-               var i,
-                       valsLength = 0;
-
-               if ( $.isArray( this.options.values ) ) {
-                       valsLength = this.options.values.length;
-               }
-
-               $.Widget.prototype._setOption.apply( this, arguments );
-
-               switch ( key ) {
-                       case "disabled":
-                               if ( value ) {
-                                       this.handles.filter( ".ui-state-focus" ).blur();
-                                       this.handles.removeClass( "ui-state-hover" );
-                                       this.handles.propAttr( "disabled", true );
-                                       this.element.addClass( "ui-disabled" );
-                               } else {
-                                       this.handles.propAttr( "disabled", false );
-                                       this.element.removeClass( "ui-disabled" );
-                               }
-                               break;
-                       case "orientation":
-                               this._detectOrientation();
-                               this.element
-                                       .removeClass( "ui-slider-horizontal ui-slider-vertical" )
-                                       .addClass( "ui-slider-" + this.orientation );
-                               this._refreshValue();
-                               break;
-                       case "value":
-                               this._animateOff = true;
-                               this._refreshValue();
-                               this._change( null, 0 );
-                               this._animateOff = false;
-                               break;
-                       case "values":
-                               this._animateOff = true;
-                               this._refreshValue();
-                               for ( i = 0; i < valsLength; i += 1 ) {
-                                       this._change( null, i );
-                               }
-                               this._animateOff = false;
-                               break;
-               }
-       },
-
-       //internal value getter
-       // _value() returns value trimmed by min and max, aligned by step
-       _value: function() {
-               var val = this.options.value;
-               val = this._trimAlignValue( val );
-
-               return val;
-       },
-
-       //internal values getter
-       // _values() returns array of values trimmed by min and max, aligned by step
-       // _values( index ) returns single value trimmed by min and max, aligned by step
-       _values: function( index ) {
-               var val,
-                       vals,
-                       i;
-
-               if ( arguments.length ) {
-                       val = this.options.values[ index ];
-                       val = this._trimAlignValue( val );
-
-                       return val;
-               } else {
-                       // .slice() creates a copy of the array
-                       // this copy gets trimmed by min and max and then returned
-                       vals = this.options.values.slice();
-                       for ( i = 0; i < vals.length; i+= 1) {
-                               vals[ i ] = this._trimAlignValue( vals[ i ] );
-                       }
-
-                       return vals;
-               }
-       },
-       
-       // returns the step-aligned value that val is closest to, between (inclusive) min and max
-       _trimAlignValue: function( val ) {
-               if ( val <= this._valueMin() ) {
-                       return this._valueMin();
-               }
-               if ( val >= this._valueMax() ) {
-                       return this._valueMax();
-               }
-               var step = ( this.options.step > 0 ) ? this.options.step : 1,
-                       valModStep = (val - this._valueMin()) % step,
-                       alignValue = val - valModStep;
-
-               if ( Math.abs(valModStep) * 2 >= step ) {
-                       alignValue += ( valModStep > 0 ) ? step : ( -step );
-               }
-
-               // Since JavaScript has problems with large floats, round
-               // the final value to 5 digits after the decimal point (see #4124)
-               return parseFloat( alignValue.toFixed(5) );
-       },
-
-       _valueMin: function() {
-               return this.options.min;
-       },
-
-       _valueMax: function() {
-               return this.options.max;
-       },
-       
-       _refreshValue: function() {
-               var oRange = this.options.range,
-                       o = this.options,
-                       self = this,
-                       animate = ( !this._animateOff ) ? o.animate : false,
-                       valPercent,
-                       _set = {},
-                       lastValPercent,
-                       value,
-                       valueMin,
-                       valueMax;
-
-               if ( this.options.values && this.options.values.length ) {
-                       this.handles.each(function( i, j ) {
-                               valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
-                               _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
-                               $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
-                               if ( self.options.range === true ) {
-                                       if ( self.orientation === "horizontal" ) {
-                                               if ( i === 0 ) {
-                                                       self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
-                                               }
-                                               if ( i === 1 ) {
-                                                       self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
-                                               }
-                                       } else {
-                                               if ( i === 0 ) {
-                                                       self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
-                                               }
-                                               if ( i === 1 ) {
-                                                       self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
-                                               }
-                                       }
-                               }
-                               lastValPercent = valPercent;
-                       });
-               } else {
-                       value = this.value();
-                       valueMin = this._valueMin();
-                       valueMax = this._valueMax();
-                       valPercent = ( valueMax !== valueMin ) ?
-                                       ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
-                                       0;
-                       _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
-                       this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
-
-                       if ( oRange === "min" && this.orientation === "horizontal" ) {
-                               this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
-                       }
-                       if ( oRange === "max" && this.orientation === "horizontal" ) {
-                               this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
-                       }
-                       if ( oRange === "min" && this.orientation === "vertical" ) {
-                               this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
-                       }
-                       if ( oRange === "max" && this.orientation === "vertical" ) {
-                               this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
-                       }
-               }
-       }
-
-});
-
-$.extend( $.ui.slider, {
-       version: "1.8.24"
-});
-
-}(jQuery));
diff --git a/resources/jquery.ui/jquery.ui.sortable.js b/resources/jquery.ui/jquery.ui.sortable.js
deleted file mode 100644 (file)
index 9e0cac6..0000000
+++ /dev/null
@@ -1,1094 +0,0 @@
-/*!
- * jQuery UI Sortable 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Sortables
- *
- * Depends:
- *     jquery.ui.core.js
- *     jquery.ui.mouse.js
- *     jquery.ui.widget.js
- */
-(function( $, undefined ) {
-
-$.widget("ui.sortable", $.ui.mouse, {
-       widgetEventPrefix: "sort",
-       ready: false,
-       options: {
-               appendTo: "parent",
-               axis: false,
-               connectWith: false,
-               containment: false,
-               cursor: 'auto',
-               cursorAt: false,
-               dropOnEmpty: true,
-               forcePlaceholderSize: false,
-               forceHelperSize: false,
-               grid: false,
-               handle: false,
-               helper: "original",
-               items: '> *',
-               opacity: false,
-               placeholder: false,
-               revert: false,
-               scroll: true,
-               scrollSensitivity: 20,
-               scrollSpeed: 20,
-               scope: "default",
-               tolerance: "intersect",
-               zIndex: 1000
-       },
-       _create: function() {
-
-               var o = this.options;
-               this.containerCache = {};
-               this.element.addClass("ui-sortable");
-
-               //Get the items
-               this.refresh();
-
-               //Let's determine if the items are being displayed horizontally
-               this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
-
-               //Let's determine the parent's offset
-               this.offset = this.element.offset();
-
-               //Initialize mouse events for interaction
-               this._mouseInit();
-               
-               //We're ready to go
-               this.ready = true
-
-       },
-
-       destroy: function() {
-               $.Widget.prototype.destroy.call( this );
-               this.element
-                       .removeClass("ui-sortable ui-sortable-disabled");
-               this._mouseDestroy();
-
-               for ( var i = this.items.length - 1; i >= 0; i-- )
-                       this.items[i].item.removeData(this.widgetName + "-item");
-
-               return this;
-       },
-
-       _setOption: function(key, value){
-               if ( key === "disabled" ) {
-                       this.options[ key ] = value;
-       
-                       this.widget()
-                               [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
-               } else {
-                       // Don't call widget base _setOption for disable as it adds ui-state-disabled class
-                       $.Widget.prototype._setOption.apply(this, arguments);
-               }
-       },
-
-       _mouseCapture: function(event, overrideHandle) {
-               var that = this;
-
-               if (this.reverting) {
-                       return false;
-               }
-
-               if(this.options.disabled || this.options.type == 'static') return false;
-
-               //We have to refresh the items data once first
-               this._refreshItems(event);
-
-               //Find out if the clicked node (or one of its parents) is a actual item in this.items
-               var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
-                       if($.data(this, that.widgetName + '-item') == self) {
-                               currentItem = $(this);
-                               return false;
-                       }
-               });
-               if($.data(event.target, that.widgetName + '-item') == self) currentItem = $(event.target);
-
-               if(!currentItem) return false;
-               if(this.options.handle && !overrideHandle) {
-                       var validHandle = false;
-
-                       $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
-                       if(!validHandle) return false;
-               }
-
-               this.currentItem = currentItem;
-               this._removeCurrentsFromItems();
-               return true;
-
-       },
-
-       _mouseStart: function(event, overrideHandle, noActivation) {
-
-               var o = this.options, self = this;
-               this.currentContainer = this;
-
-               //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
-               this.refreshPositions();
-
-               //Create and append the visible helper
-               this.helper = this._createHelper(event);
-
-               //Cache the helper size
-               this._cacheHelperProportions();
-
-               /*
-                * - Position generation -
-                * This block generates everything position related - it's the core of draggables.
-                */
-
-               //Cache the margins of the original element
-               this._cacheMargins();
-
-               //Get the next scrolling parent
-               this.scrollParent = this.helper.scrollParent();
-
-               //The element's absolute position on the page minus margins
-               this.offset = this.currentItem.offset();
-               this.offset = {
-                       top: this.offset.top - this.margins.top,
-                       left: this.offset.left - this.margins.left
-               };
-
-               $.extend(this.offset, {
-                       click: { //Where the click happened, relative to the element
-                               left: event.pageX - this.offset.left,
-                               top: event.pageY - this.offset.top
-                       },
-                       parent: this._getParentOffset(),
-                       relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
-               });
-
-               // Only after we got the offset, we can change the helper's position to absolute
-               // TODO: Still need to figure out a way to make relative sorting possible
-               this.helper.css("position", "absolute");
-               this.cssPosition = this.helper.css("position");
-               
-               //Generate the original position
-               this.originalPosition = this._generatePosition(event);
-               this.originalPageX = event.pageX;
-               this.originalPageY = event.pageY;
-
-               //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
-               (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
-
-               //Cache the former DOM position
-               this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
-
-               //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
-               if(this.helper[0] != this.currentItem[0]) {
-                       this.currentItem.hide();
-               }
-
-               //Create the placeholder
-               this._createPlaceholder();
-
-               //Set a containment if given in the options
-               if(o.containment)
-                       this._setContainment();
-
-               if(o.cursor) { // cursor option
-                       if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
-                       $('body').css("cursor", o.cursor);
-               }
-
-               if(o.opacity) { // opacity option
-                       if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
-                       this.helper.css("opacity", o.opacity);
-               }
-
-               if(o.zIndex) { // zIndex option
-                       if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
-                       this.helper.css("zIndex", o.zIndex);
-               }
-
-               //Prepare scrolling
-               if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
-                       this.overflowOffset = this.scrollParent.offset();
-
-               //Call callbacks
-               this._trigger("start", event, this._uiHash());
-
-               //Recache the helper size
-               if(!this._preserveHelperProportions)
-                       this._cacheHelperProportions();
-
-
-               //Post 'activate' events to possible containers
-               if(!noActivation) {
-                        for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
-               }
-
-               //Prepare possible droppables
-               if($.ui.ddmanager)
-                       $.ui.ddmanager.current = this;
-
-               if ($.ui.ddmanager && !o.dropBehaviour)
-                       $.ui.ddmanager.prepareOffsets(this, event);
-
-               this.dragging = true;
-
-               this.helper.addClass("ui-sortable-helper");
-               this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
-               return true;
-
-       },
-
-       _mouseDrag: function(event) {
-
-               //Compute the helpers position
-               this.position = this._generatePosition(event);
-               this.positionAbs = this._convertPositionTo("absolute");
-
-               if (!this.lastPositionAbs) {
-                       this.lastPositionAbs = this.positionAbs;
-               }
-
-               //Do scrolling
-               if(this.options.scroll) {
-                       var o = this.options, scrolled = false;
-                       if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
-
-                               if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
-                                       this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
-                               else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
-                                       this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
-
-                               if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
-                                       this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
-                               else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
-                                       this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
-
-                       } else {
-
-                               if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
-                                       scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
-                               else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
-                                       scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
-
-                               if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
-                                       scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
-                               else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
-                                       scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
-
-                       }
-
-                       if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
-                               $.ui.ddmanager.prepareOffsets(this, event);
-               }
-
-               //Regenerate the absolute position used for position checks
-               this.positionAbs = this._convertPositionTo("absolute");
-
-               //Set the helper position
-               if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
-               if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
-
-               //Rearrange
-               for (var i = this.items.length - 1; i >= 0; i--) {
-
-                       //Cache variables and intersection, continue if no intersection
-                       var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
-                       if (!intersection) continue;
-
-                       // Only put the placeholder inside the current Container, skip all
-                       // items form other containers. This works because when moving
-                       // an item from one container to another the
-                       // currentContainer is switched before the placeholder is moved.
-                       //
-                       // Without this moving items in "sub-sortables" can cause the placeholder to jitter
-                       // beetween the outer and inner container.
-                       if (item.instance !== this.currentContainer) continue;
-
-                       if (itemElement != this.currentItem[0] //cannot intersect with itself
-                               &&      this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
-                               &&      !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
-                               && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
-                               //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
-                       ) {
-
-                               this.direction = intersection == 1 ? "down" : "up";
-
-                               if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
-                                       this._rearrange(event, item);
-                               } else {
-                                       break;
-                               }
-
-                               this._trigger("change", event, this._uiHash());
-                               break;
-                       }
-               }
-
-               //Post events to containers
-               this._contactContainers(event);
-
-               //Interconnect with droppables
-               if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
-
-               //Call callbacks
-               this._trigger('sort', event, this._uiHash());
-
-               this.lastPositionAbs = this.positionAbs;
-               return false;
-
-       },
-
-       _mouseStop: function(event, noPropagation) {
-
-               if(!event) return;
-
-               //If we are using droppables, inform the manager about the drop
-               if ($.ui.ddmanager && !this.options.dropBehaviour)
-                       $.ui.ddmanager.drop(this, event);
-
-               if(this.options.revert) {
-                       var self = this;
-                       var cur = self.placeholder.offset();
-
-                       self.reverting = true;
-
-                       $(this.helper).animate({
-                               left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
-                               top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
-                       }, parseInt(this.options.revert, 10) || 500, function() {
-                               self._clear(event);
-                       });
-               } else {
-                       this._clear(event, noPropagation);
-               }
-
-               return false;
-
-       },
-
-       cancel: function() {
-
-               var self = this;
-
-               if(this.dragging) {
-
-                       this._mouseUp({ target: null });
-
-                       if(this.options.helper == "original")
-                               this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
-                       else
-                               this.currentItem.show();
-
-                       //Post deactivating events to containers
-                       for (var i = this.containers.length - 1; i >= 0; i--){
-                               this.containers[i]._trigger("deactivate", null, self._uiHash(this));
-                               if(this.containers[i].containerCache.over) {
-                                       this.containers[i]._trigger("out", null, self._uiHash(this));
-                                       this.containers[i].containerCache.over = 0;
-                               }
-                       }
-
-               }
-
-               if (this.placeholder) {
-                       //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
-                       if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
-                       if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
-
-                       $.extend(this, {
-                               helper: null,
-                               dragging: false,
-                               reverting: false,
-                               _noFinalSort: null
-                       });
-
-                       if(this.domPosition.prev) {
-                               $(this.domPosition.prev).after(this.currentItem);
-                       } else {
-                               $(this.domPosition.parent).prepend(this.currentItem);
-                       }
-               }
-
-               return this;
-
-       },
-
-       serialize: function(o) {
-
-               var items = this._getItemsAsjQuery(o && o.connected);
-               var str = []; o = o || {};
-
-               $(items).each(function() {
-                       var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
-                       if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
-               });
-
-               if(!str.length && o.key) {
-                       str.push(o.key + '=');
-               }
-
-               return str.join('&');
-
-       },
-
-       toArray: function(o) {
-
-               var items = this._getItemsAsjQuery(o && o.connected);
-               var ret = []; o = o || {};
-
-               items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
-               return ret;
-
-       },
-
-       /* Be careful with the following core functions */
-       _intersectsWith: function(item) {
-
-               var x1 = this.positionAbs.left,
-                       x2 = x1 + this.helperProportions.width,
-                       y1 = this.positionAbs.top,
-                       y2 = y1 + this.helperProportions.height;
-
-               var l = item.left,
-                       r = l + item.width,
-                       t = item.top,
-                       b = t + item.height;
-
-               var dyClick = this.offset.click.top,
-                       dxClick = this.offset.click.left;
-
-               var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
-
-               if(        this.options.tolerance == "pointer"
-                       || this.options.forcePointerForContainers
-                       || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
-               ) {
-                       return isOverElement;
-               } else {
-
-                       return (l < x1 + (this.helperProportions.width / 2) // Right Half
-                               && x2 - (this.helperProportions.width / 2) < r // Left Half
-                               && t < y1 + (this.helperProportions.height / 2) // Bottom Half
-                               && y2 - (this.helperProportions.height / 2) < b ); // Top Half
-
-               }
-       },
-
-       _intersectsWithPointer: function(item) {
-
-               var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
-                       isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
-                       isOverElement = isOverElementHeight && isOverElementWidth,
-                       verticalDirection = this._getDragVerticalDirection(),
-                       horizontalDirection = this._getDragHorizontalDirection();
-
-               if (!isOverElement)
-                       return false;
-
-               return this.floating ?
-                       ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
-                       : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
-
-       },
-
-       _intersectsWithSides: function(item) {
-
-               var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
-                       isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
-                       verticalDirection = this._getDragVerticalDirection(),
-                       horizontalDirection = this._getDragHorizontalDirection();
-
-               if (this.floating && horizontalDirection) {
-                       return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
-               } else {
-                       return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
-               }
-
-       },
-
-       _getDragVerticalDirection: function() {
-               var delta = this.positionAbs.top - this.lastPositionAbs.top;
-               return delta != 0 && (delta > 0 ? "down" : "up");
-       },
-
-       _getDragHorizontalDirection: function() {
-               var delta = this.positionAbs.left - this.lastPositionAbs.left;
-               return delta != 0 && (delta > 0 ? "right" : "left");
-       },
-
-       refresh: function(event) {
-               this._refreshItems(event);
-               this.refreshPositions();
-               return this;
-       },
-
-       _connectWith: function() {
-               var options = this.options;
-               return options.connectWith.constructor == String
-                       ? [options.connectWith]
-                       : options.connectWith;
-       },
-       
-       _getItemsAsjQuery: function(connected) {
-
-               var self = this;
-               var items = [];
-               var queries = [];
-               var connectWith = this._connectWith();
-
-               if(connectWith && connected) {
-                       for (var i = connectWith.length - 1; i >= 0; i--){
-                               var cur = $(connectWith[i]);
-                               for (var j = cur.length - 1; j >= 0; j--){
-                                       var inst = $.data(cur[j], this.widgetName);
-                                       if(inst && inst != this && !inst.options.disabled) {
-                                               queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
-                                       }
-                               };
-                       };
-               }
-
-               queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
-
-               for (var i = queries.length - 1; i >= 0; i--){
-                       queries[i][0].each(function() {
-                               items.push(this);
-                       });
-               };
-
-               return $(items);
-
-       },
-
-       _removeCurrentsFromItems: function() {
-
-               var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
-
-               for (var i=0; i < this.items.length; i++) {
-
-                       for (var j=0; j < list.length; j++) {
-                               if(list[j] == this.items[i].item[0])
-                                       this.items.splice(i,1);
-                       };
-
-               };
-
-       },
-
-       _refreshItems: function(event) {
-
-               this.items = [];
-               this.containers = [this];
-               var items = this.items;
-               var self = this;
-               var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
-               var connectWith = this._connectWith();
-
-               if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
-                       for (var i = connectWith.length - 1; i >= 0; i--){
-                               var cur = $(connectWith[i]);
-                               for (var j = cur.length - 1; j >= 0; j--){
-                                       var inst = $.data(cur[j], this.widgetName);
-                                       if(inst && inst != this && !inst.options.disabled) {
-                                               queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
-                                               this.containers.push(inst);
-                                       }
-                               };
-                       };
-               }
-
-               for (var i = queries.length - 1; i >= 0; i--) {
-                       var targetData = queries[i][1];
-                       var _queries = queries[i][0];
-
-                       for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
-                               var item = $(_queries[j]);
-
-                               item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)
-
-                               items.push({
-                                       item: item,
-                                       instance: targetData,
-                                       width: 0, height: 0,
-                                       left: 0, top: 0
-                               });
-                       };
-               };
-
-       },
-
-       refreshPositions: function(fast) {
-
-               //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
-               if(this.offsetParent && this.helper) {
-                       this.offset.parent = this._getParentOffset();
-               }
-
-               for (var i = this.items.length - 1; i >= 0; i--){
-                       var item = this.items[i];
-
-                       //We ignore calculating positions of all connected containers when we're not over them
-                       if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
-                               continue;
-
-                       var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
-
-                       if (!fast) {
-                               item.width = t.outerWidth();
-                               item.height = t.outerHeight();
-                       }
-
-                       var p = t.offset();
-                       item.left = p.left;
-                       item.top = p.top;
-               };
-
-               if(this.options.custom && this.options.custom.refreshContainers) {
-                       this.options.custom.refreshContainers.call(this);
-               } else {
-                       for (var i = this.containers.length - 1; i >= 0; i--){
-                               var p = this.containers[i].element.offset();
-                               this.containers[i].containerCache.left = p.left;
-                               this.containers[i].containerCache.top = p.top;
-                               this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
-                               this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
-                       };
-               }
-
-               return this;
-       },
-
-       _createPlaceholder: function(that) {
-
-               var self = that || this, o = self.options;
-
-               if(!o.placeholder || o.placeholder.constructor == String) {
-                       var className = o.placeholder;
-                       o.placeholder = {
-                               element: function() {
-
-                                       var el = $(document.createElement(self.currentItem[0].nodeName))
-                                               .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
-                                               .removeClass("ui-sortable-helper")[0];
-
-                                       if(!className)
-                                               el.style.visibility = "hidden";
-
-                                       return el;
-                               },
-                               update: function(container, p) {
-
-                                       // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
-                                       // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
-                                       if(className && !o.forcePlaceholderSize) return;
-
-                                       //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
-                                       if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
-                                       if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
-                               }
-                       };
-               }
-
-               //Create the placeholder
-               self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
-
-               //Append it after the actual current item
-               self.currentItem.after(self.placeholder);
-
-               //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
-               o.placeholder.update(self, self.placeholder);
-
-       },
-
-       _contactContainers: function(event) {
-               
-               // get innermost container that intersects with item 
-               var innermostContainer = null, innermostIndex = null;           
-               
-               
-               for (var i = this.containers.length - 1; i >= 0; i--){
-
-                       // never consider a container that's located within the item itself 
-                       if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
-                               continue;
-
-                       if(this._intersectsWith(this.containers[i].containerCache)) {
-
-                               // if we've already found a container and it's more "inner" than this, then continue 
-                               if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
-                                       continue;
-
-                               innermostContainer = this.containers[i]; 
-                               innermostIndex = i;
-                                       
-                       } else {
-                               // container doesn't intersect. trigger "out" event if necessary 
-                               if(this.containers[i].containerCache.over) {
-                                       this.containers[i]._trigger("out", event, this._uiHash(this));
-                                       this.containers[i].containerCache.over = 0;
-                               }
-                       }
-
-               }
-               
-               // if no intersecting containers found, return 
-               if(!innermostContainer) return; 
-
-               // move the item into the container if it's not there already
-               if(this.containers.length === 1) {
-                       this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
-                       this.containers[innermostIndex].containerCache.over = 1;
-               } else if(this.currentContainer != this.containers[innermostIndex]) {
-
-                       //When entering a new container, we will find the item with the least distance and append our item near it
-                       var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
-                       for (var j = this.items.length - 1; j >= 0; j--) {
-                               if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
-                               var cur = this.containers[innermostIndex].floating ? this.items[j].item.offset().left : this.items[j].item.offset().top;
-                               if(Math.abs(cur - base) < dist) {
-                                       dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
-                                       this.direction = (cur - base > 0) ? 'down' : 'up';
-                               }
-                       }
-
-                       if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
-                               return;
-
-                       this.currentContainer = this.containers[innermostIndex];
-                       itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
-                       this._trigger("change", event, this._uiHash());
-                       this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
-
-                       //Update the placeholder
-                       this.options.placeholder.update(this.currentContainer, this.placeholder);
-
-                       this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
-                       this.containers[innermostIndex].containerCache.over = 1;
-               } 
-       
-               
-       },
-
-       _createHelper: function(event) {
-
-               var o = this.options;
-               var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
-
-               if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
-                       $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
-
-               if(helper[0] == this.currentItem[0])
-                       this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
-
-               if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
-               if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
-
-               return helper;
-
-       },
-
-       _adjustOffsetFromHelper: function(obj) {
-               if (typeof obj == 'string') {
-                       obj = obj.split(' ');
-               }
-               if ($.isArray(obj)) {
-                       obj = {left: +obj[0], top: +obj[1] || 0};
-               }
-               if ('left' in obj) {
-                       this.offset.click.left = obj.left + this.margins.left;
-               }
-               if ('right' in obj) {
-                       this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
-               }
-               if ('top' in obj) {
-                       this.offset.click.top = obj.top + this.margins.top;
-               }
-               if ('bottom' in obj) {
-                       this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
-               }
-       },
-
-       _getParentOffset: function() {
-
-
-               //Get the offsetParent and cache its position
-               this.offsetParent = this.helper.offsetParent();
-               var po = this.offsetParent.offset();
-
-               // This is a special case where we need to modify a offset calculated on start, since the following happened:
-               // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
-               // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
-               //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
-               if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
-                       po.left += this.scrollParent.scrollLeft();
-                       po.top += this.scrollParent.scrollTop();
-               }
-
-               if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
-               || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
-                       po = { top: 0, left: 0 };
-
-               return {
-                       top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
-                       left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
-               };
-
-       },
-
-       _getRelativeOffset: function() {
-
-               if(this.cssPosition == "relative") {
-                       var p = this.currentItem.position();
-                       return {
-                               top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
-                               left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
-                       };
-               } else {
-                       return { top: 0, left: 0 };
-               }
-
-       },
-
-       _cacheMargins: function() {
-               this.margins = {
-                       left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
-                       top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
-               };
-       },
-
-       _cacheHelperProportions: function() {
-               this.helperProportions = {
-                       width: this.helper.outerWidth(),
-                       height: this.helper.outerHeight()
-               };
-       },
-
-       _setContainment: function() {
-
-               var o = this.options;
-               if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
-               if(o.containment == 'document' || o.containment == 'window') this.containment = [
-                       0 - this.offset.relative.left - this.offset.parent.left,
-                       0 - this.offset.relative.top - this.offset.parent.top,
-                       $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
-                       ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
-               ];
-
-               if(!(/^(document|window|parent)$/).test(o.containment)) {
-                       var ce = $(o.containment)[0];
-                       var co = $(o.containment).offset();
-                       var over = ($(ce).css("overflow") != 'hidden');
-
-                       this.containment = [
-                               co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
-                               co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
-                               co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
-                               co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
-                       ];
-               }
-
-       },
-
-       _convertPositionTo: function(d, pos) {
-
-               if(!pos) pos = this.position;
-               var mod = d == "absolute" ? 1 : -1;
-               var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
-
-               return {
-                       top: (
-                               pos.top                                                                                                                                 // The absolute mouse position
-                               + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
-                               + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
-                               - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
-                       ),
-                       left: (
-                               pos.left                                                                                                                                // The absolute mouse position
-                               + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
-                               + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
-                               - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
-                       )
-               };
-
-       },
-
-       _generatePosition: function(event) {
-
-               var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
-
-               // This is another very weird special case that only happens for relative elements:
-               // 1. If the css position is relative
-               // 2. and the scroll parent is the document or similar to the offset parent
-               // we have to refresh the relative offset during the scroll so there are no jumps
-               if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
-                       this.offset.relative = this._getRelativeOffset();
-               }
-
-               var pageX = event.pageX;
-               var pageY = event.pageY;
-
-               /*
-                * - Position constraining -
-                * Constrain the position to a mix of grid, containment.
-                */
-
-               if(this.originalPosition) { //If we are not dragging yet, we won't check for options
-
-                       if(this.containment) {
-                               if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
-                               if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
-                               if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
-                               if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
-                       }
-
-                       if(o.grid) {
-                               var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
-                               pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
-
-                               var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
-                               pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
-                       }
-
-               }
-
-               return {
-                       top: (
-                               pageY                                                                                                                           // The absolute mouse position
-                               - this.offset.click.top                                                                                                 // Click offset (relative to the element)
-                               - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
-                               - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
-                               + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
-                       ),
-                       left: (
-                               pageX                                                                                                                           // The absolute mouse position
-                               - this.offset.click.left                                                                                                // Click offset (relative to the element)
-                               - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
-                               - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
-                               + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
-                       )
-               };
-
-       },
-
-       _rearrange: function(event, i, a, hardRefresh) {
-
-               a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
-
-               //Various things done here to improve the performance:
-               // 1. we create a setTimeout, that calls refreshPositions
-               // 2. on the instance, we have a counter variable, that get's higher after every append
-               // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
-               // 4. this lets only the last addition to the timeout stack through
-               this.counter = this.counter ? ++this.counter : 1;
-               var self = this, counter = this.counter;
-
-               window.setTimeout(function() {
-                       if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
-               },0);
-
-       },
-
-       _clear: function(event, noPropagation) {
-
-               this.reverting = false;
-               // We delay all events that have to be triggered to after the point where the placeholder has been removed and
-               // everything else normalized again
-               var delayedTriggers = [], self = this;
-
-               // We first have to update the dom position of the actual currentItem
-               // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
-               if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
-               this._noFinalSort = null;
-
-               if(this.helper[0] == this.currentItem[0]) {
-                       for(var i in this._storedCSS) {
-                               if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
-                       }
-                       this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
-               } else {
-                       this.currentItem.show();
-               }
-
-               if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
-               if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
-
-               // Check if the items Container has Changed and trigger appropriate
-               // events.
-               if (this !== this.currentContainer) {
-                       if(!noPropagation) {
-                               delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
-                               delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
-                               delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
-                       }
-               }
-
-               //Post events to containers
-               for (var i = this.containers.length - 1; i >= 0; i--){
-                       if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
-                       if(this.containers[i].containerCache.over) {
-                               delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
-                               this.containers[i].containerCache.over = 0;
-                       }
-               }
-
-               //Do what was originally in plugins
-               if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
-               if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
-               if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
-
-               this.dragging = false;
-               if(this.cancelHelperRemoval) {
-                       if(!noPropagation) {
-                               this._trigger("beforeStop", event, this._uiHash());
-                               for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
-                               this._trigger("stop", event, this._uiHash());
-                       }
-
-                       this.fromOutside = false;
-                       return false;
-               }
-
-               if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
-
-               //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
-               this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
-
-               if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
-
-               if(!noPropagation) {
-                       for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
-                       this._trigger("stop", event, this._uiHash());
-               }
-
-               this.fromOutside = false;
-               return true;
-
-       },
-
-       _trigger: function() {
-               if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
-                       this.cancel();
-               }
-       },
-
-       _uiHash: function(inst) {
-               var self = inst || this;
-               return {
-                       helper: self.helper,
-                       placeholder: self.placeholder || $([]),
-                       position: self.position,
-                       originalPosition: self.originalPosition,
-                       offset: self.positionAbs,
-                       item: self.currentItem,
-                       sender: inst ? inst.element : null
-               };
-       }
-
-});
-
-$.extend($.ui.sortable, {
-       version: "1.8.24"
-});
-
-})(jQuery);
diff --git a/resources/jquery.ui/jquery.ui.tabs.js b/resources/jquery.ui/jquery.ui.tabs.js
deleted file mode 100644 (file)
index 0c47f0e..0000000
+++ /dev/null
@@ -1,757 +0,0 @@
-/*!
- * jQuery UI Tabs 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Tabs
- *
- * Depends:
- *     jquery.ui.core.js
- *     jquery.ui.widget.js
- */
-(function( $, undefined ) {
-
-var tabId = 0,
-       listId = 0;
-
-function getNextTabId() {
-       return ++tabId;
-}
-
-function getNextListId() {
-       return ++listId;
-}
-
-$.widget( "ui.tabs", {
-       options: {
-               add: null,
-               ajaxOptions: null,
-               cache: false,
-               cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
-               collapsible: false,
-               disable: null,
-               disabled: [],
-               enable: null,
-               event: "click",
-               fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
-               idPrefix: "ui-tabs-",
-               load: null,
-               panelTemplate: "<div></div>",
-               remove: null,
-               select: null,
-               show: null,
-               spinner: "<em>Loading&#8230;</em>",
-               tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
-       },
-
-       _create: function() {
-               this._tabify( true );
-       },
-
-       _setOption: function( key, value ) {
-               if ( key == "selected" ) {
-                       if (this.options.collapsible && value == this.options.selected ) {
-                               return;
-                       }
-                       this.select( value );
-               } else {
-                       this.options[ key ] = value;
-                       this._tabify();
-               }
-       },
-
-       _tabId: function( a ) {
-               return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
-                       this.options.idPrefix + getNextTabId();
-       },
-
-       _sanitizeSelector: function( hash ) {
-               // we need this because an id may contain a ":"
-               return hash.replace( /:/g, "\\:" );
-       },
-
-       _cookie: function() {
-               var cookie = this.cookie ||
-                       ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
-               return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
-       },
-
-       _ui: function( tab, panel ) {
-               return {
-                       tab: tab,
-                       panel: panel,
-                       index: this.anchors.index( tab )
-               };
-       },
-
-       _cleanup: function() {
-               // restore all former loading tabs labels
-               this.lis.filter( ".ui-state-processing" )
-                       .removeClass( "ui-state-processing" )
-                       .find( "span:data(label.tabs)" )
-                               .each(function() {
-                                       var el = $( this );
-                                       el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
-                               });
-       },
-
-       _tabify: function( init ) {
-               var self = this,
-                       o = this.options,
-                       fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
-
-               this.list = this.element.find( "ol,ul" ).eq( 0 );
-               this.lis = $( " > li:has(a[href])", this.list );
-               this.anchors = this.lis.map(function() {
-                       return $( "a", this )[ 0 ];
-               });
-               this.panels = $( [] );
-
-               this.anchors.each(function( i, a ) {
-                       var href = $( a ).attr( "href" );
-                       // For dynamically created HTML that contains a hash as href IE < 8 expands
-                       // such href to the full page url with hash and then misinterprets tab as ajax.
-                       // Same consideration applies for an added tab with a fragment identifier
-                       // since a[href=#fragment-identifier] does unexpectedly not match.
-                       // Thus normalize href attribute...
-                       var hrefBase = href.split( "#" )[ 0 ],
-                               baseEl;
-                       if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
-                                       ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
-                               href = a.hash;
-                               a.href = href;
-                       }
-
-                       // inline tab
-                       if ( fragmentId.test( href ) ) {
-                               self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
-                       // remote tab
-                       // prevent loading the page itself if href is just "#"
-                       } else if ( href && href !== "#" ) {
-                               // required for restore on destroy
-                               $.data( a, "href.tabs", href );
-
-                               // TODO until #3808 is fixed strip fragment identifier from url
-                               // (IE fails to load from such url)
-                               $.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
-
-                               var id = self._tabId( a );
-                               a.href = "#" + id;
-                               var $panel = self.element.find( "#" + id );
-                               if ( !$panel.length ) {
-                                       $panel = $( o.panelTemplate )
-                                               .attr( "id", id )
-                                               .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
-                                               .insertAfter( self.panels[ i - 1 ] || self.list );
-                                       $panel.data( "destroy.tabs", true );
-                               }
-                               self.panels = self.panels.add( $panel );
-                       // invalid tab href
-                       } else {
-                               o.disabled.push( i );
-                       }
-               });
-
-               // initialization from scratch
-               if ( init ) {
-                       // attach necessary classes for styling
-                       this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
-                       this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
-                       this.lis.addClass( "ui-state-default ui-corner-top" );
-                       this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
-
-                       // Selected tab
-                       // use "selected" option or try to retrieve:
-                       // 1. from fragment identifier in url
-                       // 2. from cookie
-                       // 3. from selected class attribute on <li>
-                       if ( o.selected === undefined ) {
-                               if ( location.hash ) {
-                                       this.anchors.each(function( i, a ) {
-                                               if ( a.hash == location.hash ) {
-                                                       o.selected = i;
-                                                       return false;
-                                               }
-                                       });
-                               }
-                               if ( typeof o.selected !== "number" && o.cookie ) {
-                                       o.selected = parseInt( self._cookie(), 10 );
-                               }
-                               if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
-                                       o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
-                               }
-                               o.selected = o.selected || ( this.lis.length ? 0 : -1 );
-                       } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
-                               o.selected = -1;
-                       }
-
-                       // sanity check - default to first tab...
-                       o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
-                               ? o.selected
-                               : 0;
-
-                       // Take disabling tabs via class attribute from HTML
-                       // into account and update option properly.
-                       // A selected tab cannot become disabled.
-                       o.disabled = $.unique( o.disabled.concat(
-                               $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
-                                       return self.lis.index( n );
-                               })
-                       ) ).sort();
-
-                       if ( $.inArray( o.selected, o.disabled ) != -1 ) {
-                               o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
-                       }
-
-                       // highlight selected tab
-                       this.panels.addClass( "ui-tabs-hide" );
-                       this.lis.removeClass( "ui-tabs-selected ui-state-active" );
-                       // check for length avoids error when initializing empty list
-                       if ( o.selected >= 0 && this.anchors.length ) {
-                               self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
-                               this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
-
-                               // seems to be expected behavior that the show callback is fired
-                               self.element.queue( "tabs", function() {
-                                       self._trigger( "show", null,
-                                               self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) );
-                               });
-
-                               this.load( o.selected );
-                       }
-
-                       // clean up to avoid memory leaks in certain versions of IE 6
-                       // TODO: namespace this event
-                       $( window ).bind( "unload", function() {
-                               self.lis.add( self.anchors ).unbind( ".tabs" );
-                               self.lis = self.anchors = self.panels = null;
-                       });
-               // update selected after add/remove
-               } else {
-                       o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
-               }
-
-               // update collapsible
-               // TODO: use .toggleClass()
-               this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
-
-               // set or update cookie after init and add/remove respectively
-               if ( o.cookie ) {
-                       this._cookie( o.selected, o.cookie );
-               }
-
-               // disable tabs
-               for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
-                       $( li )[ $.inArray( i, o.disabled ) != -1 &&
-                               // TODO: use .toggleClass()
-                               !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
-               }
-
-               // reset cache if switching from cached to not cached
-               if ( o.cache === false ) {
-                       this.anchors.removeData( "cache.tabs" );
-               }
-
-               // remove all handlers before, tabify may run on existing tabs after add or option change
-               this.lis.add( this.anchors ).unbind( ".tabs" );
-
-               if ( o.event !== "mouseover" ) {
-                       var addState = function( state, el ) {
-                               if ( el.is( ":not(.ui-state-disabled)" ) ) {
-                                       el.addClass( "ui-state-" + state );
-                               }
-                       };
-                       var removeState = function( state, el ) {
-                               el.removeClass( "ui-state-" + state );
-                       };
-                       this.lis.bind( "mouseover.tabs" , function() {
-                               addState( "hover", $( this ) );
-                       });
-                       this.lis.bind( "mouseout.tabs", function() {
-                               removeState( "hover", $( this ) );
-                       });
-                       this.anchors.bind( "focus.tabs", function() {
-                               addState( "focus", $( this ).closest( "li" ) );
-                       });
-                       this.anchors.bind( "blur.tabs", function() {
-                               removeState( "focus", $( this ).closest( "li" ) );
-                       });
-               }
-
-               // set up animations
-               var hideFx, showFx;
-               if ( o.fx ) {
-                       if ( $.isArray( o.fx ) ) {
-                               hideFx = o.fx[ 0 ];
-                               showFx = o.fx[ 1 ];
-                       } else {
-                               hideFx = showFx = o.fx;
-                       }
-               }
-
-               // Reset certain styles left over from animation
-               // and prevent IE's ClearType bug...
-               function resetStyle( $el, fx ) {
-                       $el.css( "display", "" );
-                       if ( !$.support.opacity && fx.opacity ) {
-                               $el[ 0 ].style.removeAttribute( "filter" );
-                       }
-               }
-
-               // Show a tab...
-               var showTab = showFx
-                       ? function( clicked, $show ) {
-                               $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
-                               $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
-                                       .animate( showFx, showFx.duration || "normal", function() {
-                                               resetStyle( $show, showFx );
-                                               self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
-                                       });
-                       }
-                       : function( clicked, $show ) {
-                               $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
-                               $show.removeClass( "ui-tabs-hide" );
-                               self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
-                       };
-
-               // Hide a tab, $show is optional...
-               var hideTab = hideFx
-                       ? function( clicked, $hide ) {
-                               $hide.animate( hideFx, hideFx.duration || "normal", function() {
-                                       self.lis.removeClass( "ui-tabs-selected ui-state-active" );
-                                       $hide.addClass( "ui-tabs-hide" );
-                                       resetStyle( $hide, hideFx );
-                                       self.element.dequeue( "tabs" );
-                               });
-                       }
-                       : function( clicked, $hide, $show ) {
-                               self.lis.removeClass( "ui-tabs-selected ui-state-active" );
-                               $hide.addClass( "ui-tabs-hide" );
-                               self.element.dequeue( "tabs" );
-                       };
-
-               // attach tab event handler, unbind to avoid duplicates from former tabifying...
-               this.anchors.bind( o.event + ".tabs", function() {
-                       var el = this,
-                               $li = $(el).closest( "li" ),
-                               $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
-                               $show = self.element.find( self._sanitizeSelector( el.hash ) );
-
-                       // If tab is already selected and not collapsible or tab disabled or
-                       // or is already loading or click callback returns false stop here.
-                       // Check if click handler returns false last so that it is not executed
-                       // for a disabled or loading tab!
-                       if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
-                               $li.hasClass( "ui-state-disabled" ) ||
-                               $li.hasClass( "ui-state-processing" ) ||
-                               self.panels.filter( ":animated" ).length ||
-                               self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
-                               this.blur();
-                               return false;
-                       }
-
-                       o.selected = self.anchors.index( this );
-
-                       self.abort();
-
-                       // if tab may be closed
-                       if ( o.collapsible ) {
-                               if ( $li.hasClass( "ui-tabs-selected" ) ) {
-                                       o.selected = -1;
-
-                                       if ( o.cookie ) {
-                                               self._cookie( o.selected, o.cookie );
-                                       }
-
-                                       self.element.queue( "tabs", function() {
-                                               hideTab( el, $hide );
-                                       }).dequeue( "tabs" );
-
-                                       this.blur();
-                                       return false;
-                               } else if ( !$hide.length ) {
-                                       if ( o.cookie ) {
-                                               self._cookie( o.selected, o.cookie );
-                                       }
-
-                                       self.element.queue( "tabs", function() {
-                                               showTab( el, $show );
-                                       });
-
-                                       // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
-                                       self.load( self.anchors.index( this ) );
-
-                                       this.blur();
-                                       return false;
-                               }
-                       }
-
-                       if ( o.cookie ) {
-                               self._cookie( o.selected, o.cookie );
-                       }
-
-                       // show new tab
-                       if ( $show.length ) {
-                               if ( $hide.length ) {
-                                       self.element.queue( "tabs", function() {
-                                               hideTab( el, $hide );
-                                       });
-                               }
-                               self.element.queue( "tabs", function() {
-                                       showTab( el, $show );
-                               });
-
-                               self.load( self.anchors.index( this ) );
-                       } else {
-                               throw "jQuery UI Tabs: Mismatching fragment identifier.";
-                       }
-
-                       // Prevent IE from keeping other link focussed when using the back button
-                       // and remove dotted border from clicked link. This is controlled via CSS
-                       // in modern browsers; blur() removes focus from address bar in Firefox
-                       // which can become a usability and annoying problem with tabs('rotate').
-                       if ( $.browser.msie ) {
-                               this.blur();
-                       }
-               });
-
-               // disable click in any case
-               this.anchors.bind( "click.tabs", function(){
-                       return false;
-               });
-       },
-
-    _getIndex: function( index ) {
-               // meta-function to give users option to provide a href string instead of a numerical index.
-               // also sanitizes numerical indexes to valid values.
-               if ( typeof index == "string" ) {
-                       index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
-               }
-
-               return index;
-       },
-
-       destroy: function() {
-               var o = this.options;
-
-               this.abort();
-
-               this.element
-                       .unbind( ".tabs" )
-                       .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
-                       .removeData( "tabs" );
-
-               this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
-
-               this.anchors.each(function() {
-                       var href = $.data( this, "href.tabs" );
-                       if ( href ) {
-                               this.href = href;
-                       }
-                       var $this = $( this ).unbind( ".tabs" );
-                       $.each( [ "href", "load", "cache" ], function( i, prefix ) {
-                               $this.removeData( prefix + ".tabs" );
-                       });
-               });
-
-               this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
-                       if ( $.data( this, "destroy.tabs" ) ) {
-                               $( this ).remove();
-                       } else {
-                               $( this ).removeClass([
-                                       "ui-state-default",
-                                       "ui-corner-top",
-                                       "ui-tabs-selected",
-                                       "ui-state-active",
-                                       "ui-state-hover",
-                                       "ui-state-focus",
-                                       "ui-state-disabled",
-                                       "ui-tabs-panel",
-                                       "ui-widget-content",
-                                       "ui-corner-bottom",
-                                       "ui-tabs-hide"
-                               ].join( " " ) );
-                       }
-               });
-
-               if ( o.cookie ) {
-                       this._cookie( null, o.cookie );
-               }
-
-               return this;
-       },
-
-       add: function( url, label, index ) {
-               if ( index === undefined ) {
-                       index = this.anchors.length;
-               }
-
-               var self = this,
-                       o = this.options,
-                       $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
-                       id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
-
-               $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
-
-               // try to find an existing element before creating a new one
-               var $panel = self.element.find( "#" + id );
-               if ( !$panel.length ) {
-                       $panel = $( o.panelTemplate )
-                               .attr( "id", id )
-                               .data( "destroy.tabs", true );
-               }
-               $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
-
-               if ( index >= this.lis.length ) {
-                       $li.appendTo( this.list );
-                       $panel.appendTo( this.list[ 0 ].parentNode );
-               } else {
-                       $li.insertBefore( this.lis[ index ] );
-                       $panel.insertBefore( this.panels[ index ] );
-               }
-
-               o.disabled = $.map( o.disabled, function( n, i ) {
-                       return n >= index ? ++n : n;
-               });
-
-               this._tabify();
-
-               if ( this.anchors.length == 1 ) {
-                       o.selected = 0;
-                       $li.addClass( "ui-tabs-selected ui-state-active" );
-                       $panel.removeClass( "ui-tabs-hide" );
-                       this.element.queue( "tabs", function() {
-                               self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
-                       });
-
-                       this.load( 0 );
-               }
-
-               this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
-               return this;
-       },
-
-       remove: function( index ) {
-               index = this._getIndex( index );
-               var o = this.options,
-                       $li = this.lis.eq( index ).remove(),
-                       $panel = this.panels.eq( index ).remove();
-
-               // If selected tab was removed focus tab to the right or
-               // in case the last tab was removed the tab to the left.
-               if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
-                       this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
-               }
-
-               o.disabled = $.map(
-                       $.grep( o.disabled, function(n, i) {
-                               return n != index;
-                       }),
-                       function( n, i ) {
-                               return n >= index ? --n : n;
-                       });
-
-               this._tabify();
-
-               this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
-               return this;
-       },
-
-       enable: function( index ) {
-               index = this._getIndex( index );
-               var o = this.options;
-               if ( $.inArray( index, o.disabled ) == -1 ) {
-                       return;
-               }
-
-               this.lis.eq( index ).removeClass( "ui-state-disabled" );
-               o.disabled = $.grep( o.disabled, function( n, i ) {
-                       return n != index;
-               });
-
-               this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
-               return this;
-       },
-
-       disable: function( index ) {
-               index = this._getIndex( index );
-               var self = this, o = this.options;
-               // cannot disable already selected tab
-               if ( index != o.selected ) {
-                       this.lis.eq( index ).addClass( "ui-state-disabled" );
-
-                       o.disabled.push( index );
-                       o.disabled.sort();
-
-                       this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
-               }
-
-               return this;
-       },
-
-       select: function( index ) {
-               index = this._getIndex( index );
-               if ( index == -1 ) {
-                       if ( this.options.collapsible && this.options.selected != -1 ) {
-                               index = this.options.selected;
-                       } else {
-                               return this;
-                       }
-               }
-               this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
-               return this;
-       },
-
-       load: function( index ) {
-               index = this._getIndex( index );
-               var self = this,
-                       o = this.options,
-                       a = this.anchors.eq( index )[ 0 ],
-                       url = $.data( a, "load.tabs" );
-
-               this.abort();
-
-               // not remote or from cache
-               if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
-                       this.element.dequeue( "tabs" );
-                       return;
-               }
-
-               // load remote from here on
-               this.lis.eq( index ).addClass( "ui-state-processing" );
-
-               if ( o.spinner ) {
-                       var span = $( "span", a );
-                       span.data( "label.tabs", span.html() ).html( o.spinner );
-               }
-
-               this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
-                       url: url,
-                       success: function( r, s ) {
-                               self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
-
-                               // take care of tab labels
-                               self._cleanup();
-
-                               if ( o.cache ) {
-                                       $.data( a, "cache.tabs", true );
-                               }
-
-                               self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
-                               try {
-                                       o.ajaxOptions.success( r, s );
-                               }
-                               catch ( e ) {}
-                       },
-                       error: function( xhr, s, e ) {
-                               // take care of tab labels
-                               self._cleanup();
-
-                               self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
-                               try {
-                                       // Passing index avoid a race condition when this method is
-                                       // called after the user has selected another tab.
-                                       // Pass the anchor that initiated this request allows
-                                       // loadError to manipulate the tab content panel via $(a.hash)
-                                       o.ajaxOptions.error( xhr, s, index, a );
-                               }
-                               catch ( e ) {}
-                       }
-               } ) );
-
-               // last, so that load event is fired before show...
-               self.element.dequeue( "tabs" );
-
-               return this;
-       },
-
-       abort: function() {
-               // stop possibly running animations
-               this.element.queue( [] );
-               this.panels.stop( false, true );
-
-               // "tabs" queue must not contain more than two elements,
-               // which are the callbacks for the latest clicked tab...
-               this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
-
-               // terminate pending requests from other tabs
-               if ( this.xhr ) {
-                       this.xhr.abort();
-                       delete this.xhr;
-               }
-
-               // take care of tab labels
-               this._cleanup();
-               return this;
-       },
-
-       url: function( index, url ) {
-               this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
-               return this;
-       },
-
-       length: function() {
-               return this.anchors.length;
-       }
-});
-
-$.extend( $.ui.tabs, {
-       version: "1.8.24"
-});
-
-/*
- * Tabs Extensions
- */
-
-/*
- * Rotate
- */
-$.extend( $.ui.tabs.prototype, {
-       rotation: null,
-       rotate: function( ms, continuing ) {
-               var self = this,
-                       o = this.options;
-
-               var rotate = self._rotate || ( self._rotate = function( e ) {
-                       clearTimeout( self.rotation );
-                       self.rotation = setTimeout(function() {
-                               var t = o.selected;
-                               self.select( ++t < self.anchors.length ? t : 0 );
-                       }, ms );
-                       
-                       if ( e ) {
-                               e.stopPropagation();
-                       }
-               });
-
-               var stop = self._unrotate || ( self._unrotate = !continuing
-                       ? function(e) {
-                               if (e.clientX) { // in case of a true click
-                                       self.rotate(null);
-                               }
-                       }
-                       : function( e ) {
-                               rotate();
-                       });
-
-               // start rotation
-               if ( ms ) {
-                       this.element.bind( "tabsshow", rotate );
-                       this.anchors.bind( o.event + ".tabs", stop );
-                       rotate();
-               // stop rotation
-               } else {
-                       clearTimeout( self.rotation );
-                       this.element.unbind( "tabsshow", rotate );
-                       this.anchors.unbind( o.event + ".tabs", stop );
-                       delete this._rotate;
-                       delete this._unrotate;
-               }
-
-               return this;
-       }
-});
-
-})( jQuery );
diff --git a/resources/jquery.ui/jquery.ui.widget.js b/resources/jquery.ui/jquery.ui.widget.js
deleted file mode 100644 (file)
index 66ef013..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-/*!
- * jQuery UI Widget 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Widget
- */
-(function( $, undefined ) {
-
-// jQuery 1.4+
-if ( $.cleanData ) {
-       var _cleanData = $.cleanData;
-       $.cleanData = function( elems ) {
-               for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
-                       try {
-                               $( elem ).triggerHandler( "remove" );
-                       // http://bugs.jquery.com/ticket/8235
-                       } catch( e ) {}
-               }
-               _cleanData( elems );
-       };
-} else {
-       var _remove = $.fn.remove;
-       $.fn.remove = function( selector, keepData ) {
-               return this.each(function() {
-                       if ( !keepData ) {
-                               if ( !selector || $.filter( selector, [ this ] ).length ) {
-                                       $( "*", this ).add( [ this ] ).each(function() {
-                                               try {
-                                                       $( this ).triggerHandler( "remove" );
-                                               // http://bugs.jquery.com/ticket/8235
-                                               } catch( e ) {}
-                                       });
-                               }
-                       }
-                       return _remove.call( $(this), selector, keepData );
-               });
-       };
-}
-
-$.widget = function( name, base, prototype ) {
-       var namespace = name.split( "." )[ 0 ],
-               fullName;
-       name = name.split( "." )[ 1 ];
-       fullName = namespace + "-" + name;
-
-       if ( !prototype ) {
-               prototype = base;
-               base = $.Widget;
-       }
-
-       // create selector for plugin
-       $.expr[ ":" ][ fullName ] = function( elem ) {
-               return !!$.data( elem, name );
-       };
-
-       $[ namespace ] = $[ namespace ] || {};
-       $[ namespace ][ name ] = function( options, element ) {
-               // allow instantiation without initializing for simple inheritance
-               if ( arguments.length ) {
-                       this._createWidget( options, element );
-               }
-       };
-
-       var basePrototype = new base();
-       // we need to make the options hash a property directly on the new instance
-       // otherwise we'll modify the options hash on the prototype that we're
-       // inheriting from
-//     $.each( basePrototype, function( key, val ) {
-//             if ( $.isPlainObject(val) ) {
-//                     basePrototype[ key ] = $.extend( {}, val );
-//             }
-//     });
-       basePrototype.options = $.extend( true, {}, basePrototype.options );
-       $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
-               namespace: namespace,
-               widgetName: name,
-               widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
-               widgetBaseClass: fullName
-       }, prototype );
-
-       $.widget.bridge( name, $[ namespace ][ name ] );
-};
-
-$.widget.bridge = function( name, object ) {
-       $.fn[ name ] = function( options ) {
-               var isMethodCall = typeof options === "string",
-                       args = Array.prototype.slice.call( arguments, 1 ),
-                       returnValue = this;
-
-               // allow multiple hashes to be passed on init
-               options = !isMethodCall && args.length ?
-                       $.extend.apply( null, [ true, options ].concat(args) ) :
-                       options;
-
-               // prevent calls to internal methods
-               if ( isMethodCall && options.charAt( 0 ) === "_" ) {
-                       return returnValue;
-               }
-
-               if ( isMethodCall ) {
-                       this.each(function() {
-                               var instance = $.data( this, name ),
-                                       methodValue = instance && $.isFunction( instance[options] ) ?
-                                               instance[ options ].apply( instance, args ) :
-                                               instance;
-                               // TODO: add this back in 1.9 and use $.error() (see #5972)
-//                             if ( !instance ) {
-//                                     throw "cannot call methods on " + name + " prior to initialization; " +
-//                                             "attempted to call method '" + options + "'";
-//                             }
-//                             if ( !$.isFunction( instance[options] ) ) {
-//                                     throw "no such method '" + options + "' for " + name + " widget instance";
-//                             }
-//                             var methodValue = instance[ options ].apply( instance, args );
-                               if ( methodValue !== instance && methodValue !== undefined ) {
-                                       returnValue = methodValue;
-                                       return false;
-                               }
-                       });
-               } else {
-                       this.each(function() {
-                               var instance = $.data( this, name );
-                               if ( instance ) {
-                                       instance.option( options || {} )._init();
-                               } else {
-                                       $.data( this, name, new object( options, this ) );
-                               }
-                       });
-               }
-
-               return returnValue;
-       };
-};
-
-$.Widget = function( options, element ) {
-       // allow instantiation without initializing for simple inheritance
-       if ( arguments.length ) {
-               this._createWidget( options, element );
-       }
-};
-
-$.Widget.prototype = {
-       widgetName: "widget",
-       widgetEventPrefix: "",
-       options: {
-               disabled: false
-       },
-       _createWidget: function( options, element ) {
-               // $.widget.bridge stores the plugin instance, but we do it anyway
-               // so that it's stored even before the _create function runs
-               $.data( element, this.widgetName, this );
-               this.element = $( element );
-               this.options = $.extend( true, {},
-                       this.options,
-                       this._getCreateOptions(),
-                       options );
-
-               var self = this;
-               this.element.bind( "remove." + this.widgetName, function() {
-                       self.destroy();
-               });
-
-               this._create();
-               this._trigger( "create" );
-               this._init();
-       },
-       _getCreateOptions: function() {
-               return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
-       },
-       _create: function() {},
-       _init: function() {},
-
-       destroy: function() {
-               this.element
-                       .unbind( "." + this.widgetName )
-                       .removeData( this.widgetName );
-               this.widget()
-                       .unbind( "." + this.widgetName )
-                       .removeAttr( "aria-disabled" )
-                       .removeClass(
-                               this.widgetBaseClass + "-disabled " +
-                               "ui-state-disabled" );
-       },
-
-       widget: function() {
-               return this.element;
-       },
-
-       option: function( key, value ) {
-               var options = key;
-
-               if ( arguments.length === 0 ) {
-                       // don't return a reference to the internal hash
-                       return $.extend( {}, this.options );
-               }
-
-               if  (typeof key === "string" ) {
-                       if ( value === undefined ) {
-                               return this.options[ key ];
-                       }
-                       options = {};
-                       options[ key ] = value;
-               }
-
-               this._setOptions( options );
-
-               return this;
-       },
-       _setOptions: function( options ) {
-               var self = this;
-               $.each( options, function( key, value ) {
-                       self._setOption( key, value );
-               });
-
-               return this;
-       },
-       _setOption: function( key, value ) {
-               this.options[ key ] = value;
-
-               if ( key === "disabled" ) {
-                       this.widget()
-                               [ value ? "addClass" : "removeClass"](
-                                       this.widgetBaseClass + "-disabled" + " " +
-                                       "ui-state-disabled" )
-                               .attr( "aria-disabled", value );
-               }
-
-               return this;
-       },
-
-       enable: function() {
-               return this._setOption( "disabled", false );
-       },
-       disable: function() {
-               return this._setOption( "disabled", true );
-       },
-
-       _trigger: function( type, event, data ) {
-               var prop, orig,
-                       callback = this.options[ type ];
-
-               data = data || {};
-               event = $.Event( event );
-               event.type = ( type === this.widgetEventPrefix ?
-                       type :
-                       this.widgetEventPrefix + type ).toLowerCase();
-               // the original event may come from any element
-               // so we need to reset the target on the new event
-               event.target = this.element[ 0 ];
-
-               // copy original event properties over to the new event
-               orig = event.originalEvent;
-               if ( orig ) {
-                       for ( prop in orig ) {
-                               if ( !( prop in event ) ) {
-                                       event[ prop ] = orig[ prop ];
-                               }
-                       }
-               }
-
-               this.element.trigger( event, data );
-
-               return !( $.isFunction(callback) &&
-                       callback.call( this.element[0], event, data ) === false ||
-                       event.isDefaultPrevented() );
-       }
-};
-
-})( jQuery );
diff --git a/resources/jquery.ui/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png b/resources/jquery.ui/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png
deleted file mode 100644 (file)
index e425e6e..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-bg_flat_75_ffffff_40x100.png b/resources/jquery.ui/themes/default/images/ui-bg_flat_75_ffffff_40x100.png
deleted file mode 100644 (file)
index 72d4757..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-bg_flat_75_ffffff_40x100.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-bg_glass_55_fbf9ee_1x400.png b/resources/jquery.ui/themes/default/images/ui-bg_glass_55_fbf9ee_1x400.png
deleted file mode 100644 (file)
index 3b2914a..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-bg_glass_55_fbf9ee_1x400.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-bg_glass_65_ffffff_1x400.png b/resources/jquery.ui/themes/default/images/ui-bg_glass_65_ffffff_1x400.png
deleted file mode 100644 (file)
index 8569c1b..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-bg_glass_65_ffffff_1x400.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-bg_glass_75_dadada_1x400.png b/resources/jquery.ui/themes/default/images/ui-bg_glass_75_dadada_1x400.png
deleted file mode 100644 (file)
index d6cc3c5..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-bg_glass_75_dadada_1x400.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-bg_glass_75_e6e6e6_1x400.png b/resources/jquery.ui/themes/default/images/ui-bg_glass_75_e6e6e6_1x400.png
deleted file mode 100644 (file)
index 86c2baa..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-bg_glass_75_e6e6e6_1x400.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-bg_glass_95_fef1ec_1x400.png b/resources/jquery.ui/themes/default/images/ui-bg_glass_95_fef1ec_1x400.png
deleted file mode 100644 (file)
index 4443fdc..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-bg_glass_95_fef1ec_1x400.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/resources/jquery.ui/themes/default/images/ui-bg_highlight-soft_75_cccccc_1x100.png
deleted file mode 100644 (file)
index 3cd467e..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-bg_highlight-soft_75_cccccc_1x100.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-icons_222222_256x240.png b/resources/jquery.ui/themes/default/images/ui-icons_222222_256x240.png
deleted file mode 100644 (file)
index 9a9606f..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-icons_222222_256x240.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-icons_2e83ff_256x240.png b/resources/jquery.ui/themes/default/images/ui-icons_2e83ff_256x240.png
deleted file mode 100644 (file)
index 08d2617..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-icons_2e83ff_256x240.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-icons_454545_256x240.png b/resources/jquery.ui/themes/default/images/ui-icons_454545_256x240.png
deleted file mode 100644 (file)
index 80cb644..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-icons_454545_256x240.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-icons_888888_256x240.png b/resources/jquery.ui/themes/default/images/ui-icons_888888_256x240.png
deleted file mode 100644 (file)
index 8373712..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-icons_888888_256x240.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/images/ui-icons_cd0a0a_256x240.png b/resources/jquery.ui/themes/default/images/ui-icons_cd0a0a_256x240.png
deleted file mode 100644 (file)
index 34fc893..0000000
Binary files a/resources/jquery.ui/themes/default/images/ui-icons_cd0a0a_256x240.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/default/jquery.ui.accordion.css b/resources/jquery.ui/themes/default/jquery.ui.accordion.css
deleted file mode 100644 (file)
index cd8f971..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*!
- * jQuery UI Accordion 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Accordion#theming
- */
-/* IE/Win - Fix animation bug - #4615 */
-.ui-accordion { width: 100%; }
-.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
-.ui-accordion .ui-accordion-li-fix { display: inline; }
-.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
-.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
-.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
-.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
-.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
-.ui-accordion .ui-accordion-content-active { display: block; }
diff --git a/resources/jquery.ui/themes/default/jquery.ui.autocomplete.css b/resources/jquery.ui/themes/default/jquery.ui.autocomplete.css
deleted file mode 100644 (file)
index c7eaff2..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*!
- * jQuery UI Autocomplete 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Autocomplete#theming
- */
-.ui-autocomplete { position: absolute; cursor: default; }      
-
-/* workarounds */
-* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
-
-/*
- * jQuery UI Menu 1.8.24
- *
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Menu#theming
- */
-.ui-menu {
-       list-style:none;
-       padding: 2px;
-       margin: 0;
-       display:block;
-       float: left;
-}
-.ui-menu .ui-menu {
-       margin-top: -3px;
-}
-.ui-menu .ui-menu-item {
-       margin:0;
-       padding: 0;
-       zoom: 1;
-       float: left;
-       clear: left;
-       width: 100%;
-}
-.ui-menu .ui-menu-item a {
-       text-decoration:none;
-       display:block;
-       padding:.2em .4em;
-       line-height:1.5;
-       zoom:1;
-}
-.ui-menu .ui-menu-item a.ui-state-hover,
-.ui-menu .ui-menu-item a.ui-state-active {
-       font-weight: normal;
-       margin: -1px;
-}
diff --git a/resources/jquery.ui/themes/default/jquery.ui.button.css b/resources/jquery.ui/themes/default/jquery.ui.button.css
deleted file mode 100644 (file)
index cd2dbb6..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*!
- * jQuery UI Button 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Button#theming
- */
-
-.ui-button {
-       display: inline-block;
-       position: relative;
-       padding: 0;
-       margin-right: .1em;
-       text-decoration: none !important;
-       cursor: pointer;
-       text-align: center;
-       zoom: 1;
-       overflow: visible; /* the overflow property removes extra width in IE */
-}
-/* to make room for the icon, a width needs to be set here */
-.ui-button-icon-only {
-       width: 2.2em;
-}
-
-/* button elements seem to need a little more width */
-button.ui-button-icon-only {
-       width: 2.4em;
-}
-.ui-button-icons-only {
-       width: 3.4em;
-}
-button.ui-button-icons-only {
-       width: 3.7em;
-}
-
-/*button text element */
-.ui-button .ui-button-text {
-       display: block;
-       line-height: 1.4;
-}
-.ui-button-text-only .ui-button-text {
-       padding: .4em 1em;
-}
-.ui-button-icon-only .ui-button-text,
-.ui-button-icons-only .ui-button-text {
-       padding: .4em;
-       text-indent: -9999999px;
-}
-.ui-button-text-icon-primary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
-       padding: .4em 1em .4em 2.1em;
-}
-.ui-button-text-icon-secondary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
-       padding: .4em 2.1em .4em 1em;
-}
-.ui-button-text-icons .ui-button-text {
-       padding-left: 2.1em;
-       padding-right: 2.1em;
-}
-/* no icon support for input elements, provide padding by default */
-       input.ui-button {
-       padding: .4em 1em;
-}
-
-/*button icon element(s) */
-.ui-button-icon-only .ui-icon,
-.ui-button-text-icon-primary .ui-icon,
-.ui-button-text-icon-secondary .ui-icon,
-.ui-button-text-icons .ui-icon,
-.ui-button-icons-only .ui-icon {
-       position: absolute;
-       top: 50%;
-       margin-top: -8px;
-}
-.ui-button-icon-only .ui-icon {
-       left: 50%;
-       margin-left: -8px;
-}
-.ui-button-text-icon-primary .ui-button-icon-primary,
-.ui-button-text-icons .ui-button-icon-primary,
-.ui-button-icons-only .ui-button-icon-primary {
-       left: .5em;
-}
-.ui-button-text-icon-secondary .ui-button-icon-secondary,
-.ui-button-text-icons .ui-button-icon-secondary,
-.ui-button-icons-only .ui-button-icon-secondary {
-       right: .5em;
-}
-.ui-button-text-icons .ui-button-icon-secondary,
-.ui-button-icons-only .ui-button-icon-secondary {
-       right: .5em;
-}
-
-/*button sets*/
-.ui-buttonset {
-       margin-right: 7px;
-}
-.ui-buttonset .ui-button {
-       margin-left: 0;
-       margin-right: -.3em;
-}
-
-/* workarounds */
-button.ui-button::-moz-focus-inner {
-       border: 0;
-       padding: 0; /* reset extra padding in Firefox */
-}
diff --git a/resources/jquery.ui/themes/default/jquery.ui.core.css b/resources/jquery.ui/themes/default/jquery.ui.core.css
deleted file mode 100644 (file)
index 8b953a2..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*!
- * jQuery UI CSS Framework 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Theming/API
- */
-
-/* Layout helpers
-----------------------------------*/
-.ui-helper-hidden { display: none; }
-.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
-.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
-.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
-.ui-helper-clearfix:after { clear: both; }
-.ui-helper-clearfix { zoom: 1; }
-.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
-
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled { cursor: default !important; }
-
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
diff --git a/resources/jquery.ui/themes/default/jquery.ui.datepicker.css b/resources/jquery.ui/themes/default/jquery.ui.datepicker.css
deleted file mode 100644 (file)
index 37d3a98..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*!
- * jQuery UI Datepicker 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Datepicker#theming
- */
-.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
-.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
-.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
-.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
-.ui-datepicker .ui-datepicker-prev { left:2px; }
-.ui-datepicker .ui-datepicker-next { right:2px; }
-.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
-.ui-datepicker .ui-datepicker-next-hover { right:1px; }
-.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
-.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
-.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
-.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
-.ui-datepicker select.ui-datepicker-month, 
-.ui-datepicker select.ui-datepicker-year { width: 49%;}
-.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
-.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
-.ui-datepicker td { border: 0; padding: 1px; }
-.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
-.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
-.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi { width:auto; }
-.ui-datepicker-multi .ui-datepicker-group { float:left; }
-.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
-.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
-.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
-.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
-.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
-
-/* RTL support */
-.ui-datepicker-rtl { direction: rtl; }
-.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
-.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
-.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
-.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
-.ui-datepicker-rtl .ui-datepicker-group { float:right; }
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-
-/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
-.ui-datepicker-cover {
-    position: absolute; /*must have*/
-    z-index: -1; /*must have*/
-    filter: mask(); /*must have*/
-    top: -4px; /*must have*/
-    left: -4px; /*must have*/
-    width: 200px; /*must have*/
-    height: 200px; /*must have*/
-}
\ No newline at end of file
diff --git a/resources/jquery.ui/themes/default/jquery.ui.dialog.css b/resources/jquery.ui/themes/default/jquery.ui.dialog.css
deleted file mode 100644 (file)
index 04515f4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*!
- * jQuery UI Dialog 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Dialog#theming
- */
-.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
-.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative;  }
-.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } 
-.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
-.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
-.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
-.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
-.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
-.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
-.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
-.ui-draggable .ui-dialog-titlebar { cursor: move; }
diff --git a/resources/jquery.ui/themes/default/jquery.ui.progressbar.css b/resources/jquery.ui/themes/default/jquery.ui.progressbar.css
deleted file mode 100644 (file)
index 90bf308..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/*!
- * jQuery UI Progressbar 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Progressbar#theming
- */
-.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
-.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff --git a/resources/jquery.ui/themes/default/jquery.ui.resizable.css b/resources/jquery.ui/themes/default/jquery.ui.resizable.css
deleted file mode 100644 (file)
index d17873e..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*!
- * jQuery UI Resizable 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Resizable#theming
- */
-.ui-resizable { position: relative;}
-.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
-.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
-.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
-.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
-.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
-.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
-.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
-.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
-.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
-.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
\ No newline at end of file
diff --git a/resources/jquery.ui/themes/default/jquery.ui.selectable.css b/resources/jquery.ui/themes/default/jquery.ui.selectable.css
deleted file mode 100644 (file)
index 9850ee7..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/*!
- * jQuery UI Selectable 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Selectable#theming
- */
-.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
diff --git a/resources/jquery.ui/themes/default/jquery.ui.slider.css b/resources/jquery.ui/themes/default/jquery.ui.slider.css
deleted file mode 100644 (file)
index fbfe665..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*!
- * jQuery UI Slider 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Slider#theming
- */
-.ui-slider { position: relative; text-align: left; }
-.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
-.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
-
-.ui-slider-horizontal { height: .8em; }
-.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
-.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
-.ui-slider-horizontal .ui-slider-range-min { left: 0; }
-.ui-slider-horizontal .ui-slider-range-max { right: 0; }
-
-.ui-slider-vertical { width: .8em; height: 100px; }
-.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
-.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
-.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
-.ui-slider-vertical .ui-slider-range-max { top: 0; }
\ No newline at end of file
diff --git a/resources/jquery.ui/themes/default/jquery.ui.tabs.css b/resources/jquery.ui/themes/default/jquery.ui.tabs.css
deleted file mode 100644 (file)
index f0bee7a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*!
- * jQuery UI Tabs 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Tabs#theming
- */
-.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
-.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
-.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
-.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
-.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
-.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
-.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/resources/jquery.ui/themes/default/jquery.ui.theme.css b/resources/jquery.ui/themes/default/jquery.ui.theme.css
deleted file mode 100644 (file)
index b7d2f61..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-/*!
- * jQuery UI CSS Framework 1.8.24
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Theming/API
- *
- * To view and modify this theme, visit http://jqueryui.com/themeroller/
- */
-
-
-/* Component containers
-----------------------------------*/
-.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
-.ui-widget .ui-widget { font-size: 1em; }
-.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
-.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
-.ui-widget-content a { color: #222222/*{fcContent}*/; }
-.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
-.ui-widget-header a { color: #222222/*{fcHeader}*/; }
-
-/* Interaction states
-----------------------------------*/
-.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }
-.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
-.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }
-.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; }
-.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }
-.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
-.ui-widget :active { outline: none; }
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
-.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
-.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
-.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
-.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
-.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
-.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
-.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
-.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
-.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }
-.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }
-.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; }
-.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; }
-.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }
-.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }
-
-/* positioning */
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
-.ui-icon-triangle-1-n { background-position: 0 -16px; }
-.ui-icon-triangle-1-ne { background-position: -16px -16px; }
-.ui-icon-triangle-1-e { background-position: -32px -16px; }
-.ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
-.ui-icon-triangle-1-sw { background-position: -80px -16px; }
-.ui-icon-triangle-1-w { background-position: -96px -16px; }
-.ui-icon-triangle-1-nw { background-position: -112px -16px; }
-.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
-.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
-.ui-icon-arrow-1-n { background-position: 0 -32px; }
-.ui-icon-arrow-1-ne { background-position: -16px -32px; }
-.ui-icon-arrow-1-e { background-position: -32px -32px; }
-.ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
-.ui-icon-arrow-1-sw { background-position: -80px -32px; }
-.ui-icon-arrow-1-w { background-position: -96px -32px; }
-.ui-icon-arrow-1-nw { background-position: -112px -32px; }
-.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
-.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
-.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
-.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
-.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
-.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
-.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
-.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
-.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
-.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
-.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
-.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
-.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
-.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
-.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
-.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
-.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
-.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
-.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
-.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
-.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
-.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
-.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
-.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
-.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
-.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
-.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
-.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
-.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
-.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
-.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
-.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
-.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
-.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
-.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
-.ui-icon-arrow-4 { background-position: 0 -80px; }
-.ui-icon-arrow-4-diag { background-position: -16px -80px; }
-.ui-icon-extlink { background-position: -32px -80px; }
-.ui-icon-newwin { background-position: -48px -80px; }
-.ui-icon-refresh { background-position: -64px -80px; }
-.ui-icon-shuffle { background-position: -80px -80px; }
-.ui-icon-transfer-e-w { background-position: -96px -80px; }
-.ui-icon-transferthick-e-w { background-position: -112px -80px; }
-.ui-icon-folder-collapsed { background-position: 0 -96px; }
-.ui-icon-folder-open { background-position: -16px -96px; }
-.ui-icon-document { background-position: -32px -96px; }
-.ui-icon-document-b { background-position: -48px -96px; }
-.ui-icon-note { background-position: -64px -96px; }
-.ui-icon-mail-closed { background-position: -80px -96px; }
-.ui-icon-mail-open { background-position: -96px -96px; }
-.ui-icon-suitcase { background-position: -112px -96px; }
-.ui-icon-comment { background-position: -128px -96px; }
-.ui-icon-person { background-position: -144px -96px; }
-.ui-icon-print { background-position: -160px -96px; }
-.ui-icon-trash { background-position: -176px -96px; }
-.ui-icon-locked { background-position: -192px -96px; }
-.ui-icon-unlocked { background-position: -208px -96px; }
-.ui-icon-bookmark { background-position: -224px -96px; }
-.ui-icon-tag { background-position: -240px -96px; }
-.ui-icon-home { background-position: 0 -112px; }
-.ui-icon-flag { background-position: -16px -112px; }
-.ui-icon-calendar { background-position: -32px -112px; }
-.ui-icon-cart { background-position: -48px -112px; }
-.ui-icon-pencil { background-position: -64px -112px; }
-.ui-icon-clock { background-position: -80px -112px; }
-.ui-icon-disk { background-position: -96px -112px; }
-.ui-icon-calculator { background-position: -112px -112px; }
-.ui-icon-zoomin { background-position: -128px -112px; }
-.ui-icon-zoomout { background-position: -144px -112px; }
-.ui-icon-search { background-position: -160px -112px; }
-.ui-icon-wrench { background-position: -176px -112px; }
-.ui-icon-gear { background-position: -192px -112px; }
-.ui-icon-heart { background-position: -208px -112px; }
-.ui-icon-star { background-position: -224px -112px; }
-.ui-icon-link { background-position: -240px -112px; }
-.ui-icon-cancel { background-position: 0 -128px; }
-.ui-icon-plus { background-position: -16px -128px; }
-.ui-icon-plusthick { background-position: -32px -128px; }
-.ui-icon-minus { background-position: -48px -128px; }
-.ui-icon-minusthick { background-position: -64px -128px; }
-.ui-icon-close { background-position: -80px -128px; }
-.ui-icon-closethick { background-position: -96px -128px; }
-.ui-icon-key { background-position: -112px -128px; }
-.ui-icon-lightbulb { background-position: -128px -128px; }
-.ui-icon-scissors { background-position: -144px -128px; }
-.ui-icon-clipboard { background-position: -160px -128px; }
-.ui-icon-copy { background-position: -176px -128px; }
-.ui-icon-contact { background-position: -192px -128px; }
-.ui-icon-image { background-position: -208px -128px; }
-.ui-icon-video { background-position: -224px -128px; }
-.ui-icon-script { background-position: -240px -128px; }
-.ui-icon-alert { background-position: 0 -144px; }
-.ui-icon-info { background-position: -16px -144px; }
-.ui-icon-notice { background-position: -32px -144px; }
-.ui-icon-help { background-position: -48px -144px; }
-.ui-icon-check { background-position: -64px -144px; }
-.ui-icon-bullet { background-position: -80px -144px; }
-.ui-icon-radio-off { background-position: -96px -144px; }
-.ui-icon-radio-on { background-position: -112px -144px; }
-.ui-icon-pin-w { background-position: -128px -144px; }
-.ui-icon-pin-s { background-position: -144px -144px; }
-.ui-icon-play { background-position: 0 -160px; }
-.ui-icon-pause { background-position: -16px -160px; }
-.ui-icon-seek-next { background-position: -32px -160px; }
-.ui-icon-seek-prev { background-position: -48px -160px; }
-.ui-icon-seek-end { background-position: -64px -160px; }
-.ui-icon-seek-start { background-position: -80px -160px; }
-/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
-.ui-icon-seek-first { background-position: -80px -160px; }
-.ui-icon-stop { background-position: -96px -160px; }
-.ui-icon-eject { background-position: -112px -160px; }
-.ui-icon-volume-off { background-position: -128px -160px; }
-.ui-icon-volume-on { background-position: -144px -160px; }
-.ui-icon-power { background-position: 0 -176px; }
-.ui-icon-signal-diag { background-position: -16px -176px; }
-.ui-icon-signal { background-position: -32px -176px; }
-.ui-icon-battery-0 { background-position: -48px -176px; }
-.ui-icon-battery-1 { background-position: -64px -176px; }
-.ui-icon-battery-2 { background-position: -80px -176px; }
-.ui-icon-battery-3 { background-position: -96px -176px; }
-.ui-icon-circle-plus { background-position: 0 -192px; }
-.ui-icon-circle-minus { background-position: -16px -192px; }
-.ui-icon-circle-close { background-position: -32px -192px; }
-.ui-icon-circle-triangle-e { background-position: -48px -192px; }
-.ui-icon-circle-triangle-s { background-position: -64px -192px; }
-.ui-icon-circle-triangle-w { background-position: -80px -192px; }
-.ui-icon-circle-triangle-n { background-position: -96px -192px; }
-.ui-icon-circle-arrow-e { background-position: -112px -192px; }
-.ui-icon-circle-arrow-s { background-position: -128px -192px; }
-.ui-icon-circle-arrow-w { background-position: -144px -192px; }
-.ui-icon-circle-arrow-n { background-position: -160px -192px; }
-.ui-icon-circle-zoomin { background-position: -176px -192px; }
-.ui-icon-circle-zoomout { background-position: -192px -192px; }
-.ui-icon-circle-check { background-position: -208px -192px; }
-.ui-icon-circlesmall-plus { background-position: 0 -208px; }
-.ui-icon-circlesmall-minus { background-position: -16px -208px; }
-.ui-icon-circlesmall-close { background-position: -32px -208px; }
-.ui-icon-squaresmall-plus { background-position: -48px -208px; }
-.ui-icon-squaresmall-minus { background-position: -64px -208px; }
-.ui-icon-squaresmall-close { background-position: -80px -208px; }
-.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
-.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
-.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
-.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
-.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
-.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Corner radius */
-.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -khtml-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }
-.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -khtml-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
-.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
-.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
-
-/* Overlays */
-.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
-.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; }
\ No newline at end of file
diff --git a/resources/jquery.ui/themes/vector/images/close.png b/resources/jquery.ui/themes/vector/images/close.png
deleted file mode 100644 (file)
index ef0dd9e..0000000
Binary files a/resources/jquery.ui/themes/vector/images/close.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/titlebar-fade.png b/resources/jquery.ui/themes/vector/images/titlebar-fade.png
deleted file mode 100644 (file)
index 12a80c8..0000000
Binary files a/resources/jquery.ui/themes/vector/images/titlebar-fade.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-anim_basic_16x16.gif b/resources/jquery.ui/themes/vector/images/ui-anim_basic_16x16.gif
deleted file mode 100644 (file)
index 085ccae..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-anim_basic_16x16.gif and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png b/resources/jquery.ui/themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png
deleted file mode 100644 (file)
index 09de537..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-bg_flat_70_000000_40x100.png b/resources/jquery.ui/themes/vector/images/ui-bg_flat_70_000000_40x100.png
deleted file mode 100644 (file)
index c06dd56..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-bg_flat_70_000000_40x100.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png b/resources/jquery.ui/themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png
deleted file mode 100644 (file)
index 5308b46..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png b/resources/jquery.ui/themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png
deleted file mode 100644 (file)
index 0c8997f..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png b/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png
deleted file mode 100644 (file)
index 3149255..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png b/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png
deleted file mode 100644 (file)
index 09b2376..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png b/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png
deleted file mode 100644 (file)
index 66627c1..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png b/resources/jquery.ui/themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png
deleted file mode 100644 (file)
index ccb6dc0..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-icons_2694e8_256x240.png b/resources/jquery.ui/themes/vector/images/ui-icons_2694e8_256x240.png
deleted file mode 100644 (file)
index 998ac3b..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-icons_2694e8_256x240.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-icons_2e83ff_256x240.png b/resources/jquery.ui/themes/vector/images/ui-icons_2e83ff_256x240.png
deleted file mode 100644 (file)
index 34e38d1..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-icons_2e83ff_256x240.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-icons_3d80b3_256x240.png b/resources/jquery.ui/themes/vector/images/ui-icons_3d80b3_256x240.png
deleted file mode 100644 (file)
index ec129a8..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-icons_3d80b3_256x240.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-icons_666666_256x240.png b/resources/jquery.ui/themes/vector/images/ui-icons_666666_256x240.png
deleted file mode 100644 (file)
index a32c57d..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-icons_666666_256x240.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-icons_72a7cf_256x240.png b/resources/jquery.ui/themes/vector/images/ui-icons_72a7cf_256x240.png
deleted file mode 100644 (file)
index 88fad1a..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-icons_72a7cf_256x240.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/images/ui-icons_ffffff_256x240.png b/resources/jquery.ui/themes/vector/images/ui-icons_ffffff_256x240.png
deleted file mode 100644 (file)
index 29ba7d2..0000000
Binary files a/resources/jquery.ui/themes/vector/images/ui-icons_ffffff_256x240.png and /dev/null differ
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.accordion.css b/resources/jquery.ui/themes/vector/jquery.ui.accordion.css
deleted file mode 100644 (file)
index 8d8a1a6..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* Accordion
-----------------------------------*/
-.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
-.ui-accordion .ui-accordion-li-fix { display: inline; }
-.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
-.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
-/* IE7-/Win - Fix extra vertical space in lists */
-.ui-accordion a { zoom: 1; }
-.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
-.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
-.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
-.ui-accordion .ui-accordion-content-active { display: block; }
\ No newline at end of file
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.autocomplete.css b/resources/jquery.ui/themes/vector/jquery.ui.autocomplete.css
deleted file mode 100644 (file)
index c06fd18..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Autocomplete
-----------------------------------*/
-.ui-autocomplete { position: absolute; cursor: default; }      
-.ui-autocomplete-loading { /* @embed */ background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; }
-
-/* workarounds */
-* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
-
-/* Menu
-----------------------------------*/
-.ui-menu {
-       list-style:none;
-       padding: 2px;
-       margin: 0;
-       display:block;
-       float: left;
-}
-.ui-menu .ui-menu {
-       margin-top: -3px;
-}
-.ui-menu .ui-menu-item {
-       margin:0;
-       padding: 0;
-       zoom: 1;
-       float: left;
-       clear: left;
-       width: 100%;
-}
-.ui-menu .ui-menu-item a {
-       text-decoration:none;
-       display:block;
-       padding:.2em .4em;
-       line-height:1.5;
-       zoom:1;
-}
-.ui-menu .ui-menu-item a.ui-state-hover,
-.ui-menu .ui-menu-item a.ui-state-active {
-       font-weight: normal;
-       margin: -1px;
-}
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.button.css b/resources/jquery.ui/themes/vector/jquery.ui.button.css
deleted file mode 100644 (file)
index ea14723..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-/* Button
-----------------------------------*/
-
-.ui-button {
-       display: inline-block;
-       position: relative;
-       padding: 0;
-       margin-right: .1em;
-       text-decoration: none !important;
-       cursor: pointer;
-       text-align: center;
-       zoom: 1;
-       overflow: visible; /* the overflow property removes extra width in IE */
-}
-
-/*button text element */
-.ui-button .ui-button-text {
-       display: block;
-       line-height: 1.4;
-       text-shadow: 0 1px 1px #fff;
-}
-.ui-button-text-only .ui-button-text {
-       padding: 0.3em 1em 0.25em 1em;
-}
-.ui-button-icon-only .ui-button-text,
-.ui-button-icons-only .ui-button-text {
-       padding: 0.3em;
-       text-indent: -9999999px;
-}
-.ui-button-text-icon-primary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
-       padding: 0.3em 1em 0.25em 2.1em;
-}
-.ui-button-text-icon-secondary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
-       padding: 0.3em 2.1em 0.25em 1em;
-}
-.ui-button-text-icons .ui-button-text {
-       padding-left: 2.1em;
-       padding-right: 2.1em;
-}
-
-/* no icon support for input elements, provide padding by default */
-input.ui-button {
-       padding: 0.3em 1em;
-}
-
-/*button icon element(s) */
-.ui-button-icon-only .ui-icon,
-.ui-button-text-icon-primary .ui-icon,
-.ui-button-text-icon-secondary .ui-icon,
-.ui-button-text-icons .ui-icon,
-.ui-button-text-icon .ui-icon,
-.ui-button-icons-only .ui-icon {
-       position: absolute;
-       top: 50%;
-       margin-top: -9px;
-}
-.ui-button-icon-only .ui-icon {
-       left: 50%;
-       margin-left: -8px;
-}
-.ui-button-text-icon-primary .ui-button-icon-primary,
-.ui-button-text-icon .ui-button-icon-primary,
-.ui-button-text-icons .ui-button-icon-primary,
-.ui-button-icons-only .ui-button-icon-primary {
-       left: 0.5em;
-}
-.ui-button-text-icon-secondary .ui-button-icon-secondary,
-.ui-button-text-icon .ui-button-icon-secondary,
-.ui-button-text-icons .ui-button-icon-secondary,
-.ui-button-icons-only .ui-button-icon-secondary {
-       right: 0.5em;
-}
-
-/*button sets*/
-.ui-buttonset {
-       margin-right: 7px;
-}
-.ui-buttonset .ui-button {
-       margin-left: 0;
-       margin-right: -.4em;
-}
-
-/* workarounds */
-button.ui-button::-moz-focus-inner {
-       border: 0;
-       padding: 0; /* reset extra padding in Firefox */
-}
-/* Disables the annoying dashed border Firefox puts on active buttons */
-body button.ui-button::-moz-focus-inner {
-       border: 0;
-}
-/* Give large buttons some extra padding */
-body .ui-button-large {
-       padding: 5px;
-}
-/* Use white icons for colored buttons */
-.ui-button-green .ui-icon,
-.ui-button-blue .ui-icon,
-.ui-button-red .ui-icon,
-.ui-button-orange .ui-icon {
-       /* @embed */
-       background-image: url(images/ui-icons_ffffff_256x240.png) !important;
-}
-
-/* Corner radius */
-/* This is normally handled in jquery.ui.theme.css, but in our case, the corner
-   styling of our buttons doesn't match our default widget corner styling */
-.ui-button.ui-corner-all,
-.ui-button.ui-corner-top,
-.ui-button.ui-corner-left,
-.ui-button.ui-corner-tl {
-       -moz-border-radius-topleft: 4px;
-       -webkit-border-top-left-radius: 4px;
-       border-top-left-radius: 4px;
-}
-.ui-button.ui-corner-all,
-.ui-button.ui-corner-top,
-
-.ui-button.ui-corner-right,
-.ui-button.ui-corner-tr {
-       -moz-border-radius-topright: 4px;
-       -webkit-border-top-right-radius: 4px;
-       border-top-right-radius: 4px;
-}
-.ui-button.ui-corner-all,
-.ui-button.ui-corner-bottom,
-.ui-button.ui-corner-left,
-.ui-button.ui-corner-bl {
-       -moz-border-radius-bottomleft: 4px;
-       -webkit-border-bottom-left-radius: 4px;
-       border-bottom-left-radius: 4px;
-}
-.ui-button.ui-corner-all,
-.ui-button.ui-corner-bottom,
-.ui-button.ui-corner-right,
-.ui-button.ui-corner-br {
-       -moz-border-radius-bottomright: 4px;
-       -webkit-border-bottom-right-radius: 4px;
-       border-bottom-right-radius: 4px;
-}
-
-body .ui-button {
-       color: #2779aa;
-       margin: 0.5em 0 0.5em 0.4em;
-       border: 1px solid #aaa !important;
-       background: #f0f0f0 !important;
-       background: -moz-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #fff 0%, #ddd 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#dddddd', GradientType=0); /* IE6-8 */
-       cursor: pointer;
-       font-size: 1em;
-       line-height: 1.4em;
-       width: auto;
-       overflow: visible;
-       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.2);
-       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.2);
-       box-shadow: 0 1px 3px rgba(0,0,0,.2);
-}
-
-body .ui-button-icon-only {
-       width: 2.2em;
-}
-
-body .ui-button-icons-only {
-       width: 3.4em;
-}
-
-body .ui-button:hover {
-       color: #2779aa;
-       border-color: #bbb !important;
-       background: #fff !important;
-       background: -moz-linear-gradient(top, #fff 0%, #eee 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #fff 0%, #eee 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #fff 0%, #eee 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #fff 0%, #eee 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #fff 0%, #eee 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); /* IE6-8 */
-       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.1);
-       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.1);
-       box-shadow: 0 1px 3px rgba(0,0,0,.1);
-}
-body .ui-button:active,
-body .ui-button:focus {
-       border-color: #8ad !important;
-       -webkit-box-shadow: 0 0 1px 1px rgba(167,215,249,.5);
-       -moz-box-shadow: 0 0 1px 1px rgba(167,215,249,.5);
-       box-shadow: 0 0 1px 1px rgba(167,215,249,.5);
-}
-body .ui-button:active {
-       background: #e0e0e0 !important;
-       background: -moz-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #f0f0f0 0%, #d0d0d0 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f0f0f0', endColorstr='#d0d0d0', GradientType=0); /* IE6-8 */
-}
-
-/* Green buttons */
-body .ui-button-green,
-body .ui-button-green .ui-button-text {
-       color: white;
-       text-shadow: 0 -1px 1px #072;
-}
-body .ui-button.ui-button-green {
-       border-color: #294 !important;
-       background: #295 !important;
-       background: -moz-linear-gradient(top, #3c8 0%, #295 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #3c8 0%, #295 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #3c8 0%, #295 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #3c8 0%, #295 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #3c8 0%, #295 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#33cc88', endColorstr='#229955', GradientType=0); /* IE6-8 */
-       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.3);
-       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.3);
-       box-shadow: 0 1px 3px rgba(0,0,0,.3);
-}
-body .ui-button.ui-button-green:hover {
-       background: #33a055 !important;
-       background: -moz-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #44d388 0%, #33a055 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#44d388', endColorstr='#33a055', GradientType=0); /* IE6-8 */
-       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.25);
-       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.25);
-       box-shadow: 0 1px 3px rgba(0,0,0,.25);
-}
-body .ui-button.ui-button-green:active,
-body .ui-button.ui-button-green:focus {
-       border-color: #172 !important;
-       -webkit-box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
-       -moz-box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
-       box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
-}
-body .ui-button.ui-button-green:active {
-       background: #338855 !important;
-       background: -moz-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #30c080 0%, #338855 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#30c080', endColorstr='#338855', GradientType=0); /* IE6-8 */
-}
-
-/* Blue buttons */
-body .ui-button-blue,
-body .ui-button-blue .ui-button-text {
-       color: white;
-       text-shadow: 0 -1px 1px #037;
-}
-body .ui-button.ui-button-blue {
-       border-color: #468 !important;
-       background: #36b !important;
-       background: -moz-linear-gradient(top, #48e 0%, #36b 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #48e 0%, #36b 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #48e 0%, #36b 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #48e 0%, #36b 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #48e 0%, #36b 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4488ee', endColorstr='#3366bb', GradientType=0); /* IE6-8 */
-       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.35);
-       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.35);
-       box-shadow: 0 1px 3px rgba(0,0,0,.35);
-}
-body .ui-button.ui-button-blue:hover {
-       background: #36c !important;
-       background: -moz-linear-gradient(top, #59e 0%, #36c 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #59e 0%, #36c 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #59e 0%, #36c 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #59e 0%, #36c 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #59e 0%, #36c 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5599ee', endColorstr='#3366cc', GradientType=0); /* IE6-8 */
-}
-body .ui-button.ui-button-blue:active,
-body .ui-button.ui-button-blue:focus {
-       border-color: #357 !important;
-       -webkit-box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
-       -moz-box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
-       box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
-}
-body .ui-button.ui-button-blue:active {
-       background: #3060a0 !important;
-       background: -moz-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #4080e0 0%, #3060a0 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4080e0', endColorstr='#3060a0', GradientType=0); /* IE6-8 */
-}
-
-/* Red buttons */
-body .ui-button-red,
-body .ui-button-red .ui-button-text {
-       color: white;
-       text-shadow: 0 -1px 1px #700;
-}
-body .ui-button.ui-button-red {
-       border-color: #944 !important;
-       background: #a22 !important;
-       background: -moz-linear-gradient(top, #d44 0%, #a22 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #d44 0%, #a22 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #d44 0%, #a22 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #d44 0%, #a22 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #d44 0%, #a22 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dd4444', endColorstr='#aa2222', GradientType=0); /* IE6-8 */
-       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.35);
-       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.35);
-       box-shadow: 0 1px 3px rgba(0,0,0,.35);
-}
-body .ui-button.ui-button-red:hover {
-       border-color: #a44 !important;
-       background: #b03333 !important;
-       background: -moz-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #ee4646 0%, #b03333 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee4646', endColorstr='#b03333', GradientType=0); /* IE6-8 */
-       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.3);
-       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.3);
-       box-shadow: 0 1px 3px rgba(0,0,0,.3);
-}
-body .ui-button.ui-button-red:active,
-body .ui-button.ui-button-red:focus {
-       border-color: #747 !important;
-       -webkit-box-shadow: 0 0 2px 2px rgba(167,215,249,.7);
-       -moz-box-shadow: 0 0 2px 2px rgba(167,215,249,.7);
-       box-shadow: 0 0 2px 2px rgba(167,215,249,.7);
-}
-body .ui-button.ui-button-red:active {
-       background: #952020 !important;
-       background: -moz-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #d04545 0%, #952020 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#d04545', endColorstr='#952020', GradientType=0); /* IE6-8 */
-}
-
-/* Disabled buttons */
-body .ui-button-green.disabled,
-body .ui-button-green.disabled:hover,
-body .ui-button-green.disabled:active,
-body .ui-button-green.disabled:focus,
-body .ui-button-blue.disabled,
-body .ui-button-blue.disabled:hover,
-body .ui-button-blue.disabled:active,
-body .ui-button-blue.disabled:focus,
-body .ui-button-red.disabled,
-body .ui-button-red.disabled:hover,
-body .ui-button-red.disabled:active,
-body .ui-button-red.disabled:focus,
-body .ui-button.disabled,
-body .ui-button.disabled:hover {
-       color: #aaa;
-       border-color: #ccc !important;
-       background: #eee !important;
-       background: -moz-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* FF3.6+ */
-       background: -webkit-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* Chrome10+, Safari5.1+ */
-       background: -o-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* Opera 11.10+ */
-       background: -ms-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* IE10+ */
-       background: linear-gradient(to bottom, #f6f6f6 0%, #eee 90%) !important;
-       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6f6f6', endColorstr='#eeeeee', GradientType=0); /* IE6-8 */
-       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0);
-       -moz-box-shadow: 0 1px 3px rgba(0,0,0,0);
-       box-shadow: 0 1px 3px rgba(0,0,0,0);
-}
-body .ui-button-green.disabled .ui-button-text,
-body .ui-button-blue.disabled .ui-button-text,
-body .ui-button-red.disabled .ui-button-text {
-       color: #aaa;
-       text-shadow: 0 1px 1px #fff;
-}
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.core.css b/resources/jquery.ui/themes/vector/jquery.ui.core.css
deleted file mode 100644 (file)
index b3e8193..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-* jQuery UI CSS Framework
-* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
-* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
-*/
-
-/* Layout helpers
-----------------------------------*/
-.ui-helper-hidden { display: none; }
-.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
-.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
-.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
-.ui-helper-clearfix { display: inline-block; }
-/* required comment for clearfix to work in Opera \*/
-* html .ui-helper-clearfix { height:1%; }
-.ui-helper-clearfix { display:block; }
-/* end clearfix */
-.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
-
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled { cursor: default !important; }
-
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.datepicker.css b/resources/jquery.ui/themes/vector/jquery.ui.datepicker.css
deleted file mode 100644 (file)
index 871bf69..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Datepicker
-----------------------------------*/
-.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
-.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
-.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
-.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
-.ui-datepicker .ui-datepicker-prev { left:2px; }
-.ui-datepicker .ui-datepicker-next { right:2px; }
-.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
-.ui-datepicker .ui-datepicker-next-hover { right:1px; }
-.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
-.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
-.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; padding:1px 0; }
-.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
-.ui-datepicker select.ui-datepicker-month, 
-.ui-datepicker select.ui-datepicker-year { width: 49%;}
-.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
-.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
-.ui-datepicker td { border: 0; padding: 1px; }
-.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
-.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .2em 0 0 0; padding: 0 .2em; border-top: 1px solid #DDDDDD; border-left: 0; border-right: 0; border-bottom: 0; }
-.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi { width:auto; }
-.ui-datepicker-multi .ui-datepicker-group { float:left; }
-.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
-.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
-.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
-.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
-.ui-datepicker-row-break { clear:both; width:100%; }
-
-/* RTL support */
-/* @noflip */ .ui-datepicker-rtl { direction: rtl; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-group { float:right; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-/* @noflip */ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-
-/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
-.ui-datepicker-cover {
-    display: none; /*sorry for IE5*/
-    display/**/: block; /*sorry for IE5*/
-    position: absolute; /*must have*/
-    z-index: -1; /*must have*/
-    filter: mask(); /*must have*/
-    top: -4px; /*must have*/
-    left: -4px; /*must have*/
-    width: 200px; /*must have*/
-    height: 200px; /*must have*/
-}
\ No newline at end of file
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.dialog.css b/resources/jquery.ui/themes/vector/jquery.ui.dialog.css
deleted file mode 100644 (file)
index cd85f14..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Dialog
-----------------------------------*/
-.ui-dialog { position: absolute; padding: 0; width: 300px; }
-.ui-dialog .ui-dialog-titlebar { padding: .75em; position: relative;  }
-.ui-dialog .ui-dialog-title { float: left; margin: 0; } 
-.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .75em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
-.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
-.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
-.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
-.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
-.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
-.ui-draggable .ui-dialog-titlebar { cursor: move; }
-/* Customizations */
-body .ui-dialog .ui-dialog-titlebar-close:hover {
-       text-decoration: none;
-}
-body .ui-dialog .ui-dialog-content .status-invalid input {
-       border: 2px solid red;
-       padding: 2px 1px;
-}
-body .ui-dialog .ui-dialog-titlebar {
-       padding: 0.9em 1.4em 0.6em !important;
-}
-body .ui-dialog .ui-widget-header {
-       /* @embed */
-       background: #f0f0f0 url(images/titlebar-fade.png) repeat-x scroll 50% 100% !important;
-}
-/* FIXME: Should just update the icon sprite if we're keeping this X */
-body .ui-dialog .ui-icon-closethick {
-       /* @embed */
-       background: url(images/close.png) no-repeat 50% 50% !important;
-}
-body .ui-dialog .ui-dialog-buttonpane {
-       margin-top: 0 !important;
-       padding:0.3em 1.4em 0.5em 1.4em !important;
-}
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.progressbar.css b/resources/jquery.ui/themes/vector/jquery.ui.progressbar.css
deleted file mode 100644 (file)
index bc0939e..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Progressbar
-----------------------------------*/
-.ui-progressbar { height:2em; text-align: left; }
-.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.resizable.css b/resources/jquery.ui/themes/vector/jquery.ui.resizable.css
deleted file mode 100644 (file)
index f1bd7c5..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Resizable
-----------------------------------*/
-.ui-resizable { position: relative;}
-.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
-.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
-.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
-.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
-/* @noflip */
-.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
-/* @noflip */
-.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
-/* @noflip */
-.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
-/* @noflip */
-.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
-/* @noflip */
-.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
-/* @noflip */
-.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
\ No newline at end of file
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.selectable.css b/resources/jquery.ui/themes/vector/jquery.ui.selectable.css
deleted file mode 100644 (file)
index c5d46ce..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-/* Selectable
-----------------------------------*/
-.ui-selectable-helper { border:1px dotted black }
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.slider.css b/resources/jquery.ui/themes/vector/jquery.ui.slider.css
deleted file mode 100644 (file)
index 07c6f4e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Slider
-----------------------------------*/
-.ui-slider { position: relative; text-align: left; }
-.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
-.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
-
-.ui-slider-horizontal { height: .8em; }
-.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
-.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
-.ui-slider-horizontal .ui-slider-range-min { left: 0; }
-.ui-slider-horizontal .ui-slider-range-max { right: 0; }
-
-.ui-slider-vertical { width: .8em; height: 100px; }
-.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
-.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
-.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
-.ui-slider-vertical .ui-slider-range-max { top: 0; }
\ No newline at end of file
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.tabs.css b/resources/jquery.ui/themes/vector/jquery.ui.tabs.css
deleted file mode 100644 (file)
index 99e16db..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Tabs
-----------------------------------*/
-.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
-.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
-.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
-.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
-.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
-.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
-.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/resources/jquery.ui/themes/vector/jquery.ui.theme.css b/resources/jquery.ui/themes/vector/jquery.ui.theme.css
deleted file mode 100644 (file)
index e39371d..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-
-
-/*
-* jQuery UI CSS Framework
-* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
-* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=sans-serif&fwDefault=normal&fsDefault=1.0em&cornerRadius=3px&bgColorHeader=ffffff&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=100&borderColorHeader=aed0ea&fcHeader=222222&iconColorHeader=72a7cf&bgColorContent=f2f5f7&bgTextureContent=04_highlight_hard.png&bgImgOpacityContent=100&borderColorContent=cccccc&fcContent=362b36&iconColorContent=72a7cf&bgColorDefault=d7ebf9&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=80&borderColorDefault=aed0ea&fcDefault=2779aa&iconColorDefault=3d80b3&bgColorHover=e4f1fb&bgTextureHover=03_highlight_soft.png&bgImgOpacityHover=100&borderColorHover=74b2e2&fcHover=0070a3&iconColorHover=2694e8&bgColorActive=f0f0f0&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=cccccc&fcActive=000000&iconColorActive=666666&bgColorHighlight=ffef8f&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=25&borderColorHighlight=f9dd34&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=cd0a0a&bgTextureError=01_flat.png&bgImgOpacityError=15&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffffff&bgColorOverlay=000000&bgTextureOverlay=21_glow_ball.png&bgImgOpacityOverlay=100&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=70&opacityShadow=20&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px
-*/
-
-
-/* Component containers
-----------------------------------*/
-.ui-widget { font-family: sans-serif; font-size: 0.8em; }
-.ui-widget .ui-widget { font-size: 1em; }
-.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: sans-serif; font-size: 1em; }
-.ui-widget-content { border: 1px solid #cccccc; /* @embed */ background: #f2f5f7 url(images/ui-bg_highlight-hard_100_f2f5f7_1x100.png) 50% top repeat-x; color: #362b36; }
-.ui-widget-content a { color: #362b36; }
-.ui-widget-header { border-bottom: 1px solid #bbbbbb; line-height: 1em; /* @embed */ background: #ffffff url(images/ui-bg_highlight-soft_100_ffffff_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
-.ui-widget-header a { color: #222222; }
-
-/* Interaction states
-----------------------------------*/
-.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #aed0ea; /* @embed */ background: #d7ebf9 url(images/ui-bg_highlight-hard_80_d7ebf9_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #2779aa; }
-.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2779aa; text-decoration: none; }
-.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #74b2e2; /* @embed */ background: #e4f1fb url(images/ui-bg_highlight-soft_100_e4f1fb_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #0070a3; }
-.ui-state-hover a, .ui-state-hover a:hover { color: #0070a3; text-decoration: none; }
-.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #cccccc; background: #f0f0f0 /* @embed */ url(images/ui-bg_inset-hard_100_f0f0f0_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #000000; }
-.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #000000; text-decoration: none; }
-.ui-widget :active { outline: none; }
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #f9dd34; background: #ffef8f /* @embed */ url(images/ui-bg_highlight-soft_25_ffef8f_1x100.png) 50% top repeat-x; color: #363636; }
-.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
-.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #cd0a0a /* @embed */ url(images/ui-bg_flat_15_cd0a0a_40x100.png) 50% 50% repeat-x; color: #ffffff; }
-.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
-.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
-.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
-.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
-.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon { width: 16px; height: 16px; }
-.ui-icon, .ui-widget-content .ui-icon, .ui-widget-header .ui-icon { /* @embed */ background-image: url(images/ui-icons_72a7cf_256x240.png); }
-.ui-state-default .ui-icon { /* @embed */ background-image: url(images/ui-icons_3d80b3_256x240.png); }
-.ui-state-hover .ui-icon, .ui-state-focus .ui-icon { /* @embed */ background-image: url(images/ui-icons_2694e8_256x240.png); }
-.ui-state-active .ui-icon { /* @embed */ background-image: url(images/ui-icons_666666_256x240.png); }
-.ui-state-highlight .ui-icon { /* @embed */ background-image: url(images/ui-icons_2e83ff_256x240.png); }
-.ui-state-error .ui-icon, .ui-state-error-text .ui-icon { /* @embed */ background-image: url(images/ui-icons_ffffff_256x240.png); }
-
-/* positioning */
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
-.ui-icon-triangle-1-n { background-position: 0 -16px; }
-.ui-icon-triangle-1-ne { background-position: -16px -16px; }
-.ui-icon-triangle-1-e { background-position: -32px -16px; }
-.ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
-.ui-icon-triangle-1-sw { background-position: -80px -16px; }
-.ui-icon-triangle-1-w { background-position: -96px -16px; }
-.ui-icon-triangle-1-nw { background-position: -112px -16px; }
-.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
-.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
-.ui-icon-arrow-1-n { background-position: 0 -32px; }
-.ui-icon-arrow-1-ne { background-position: -16px -32px; }
-.ui-icon-arrow-1-e { background-position: -32px -32px; }
-.ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
-.ui-icon-arrow-1-sw { background-position: -80px -32px; }
-.ui-icon-arrow-1-w { background-position: -96px -32px; }
-.ui-icon-arrow-1-nw { background-position: -112px -32px; }
-.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
-.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
-.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
-.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
-.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
-.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
-.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
-.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
-.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
-.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
-.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
-.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
-.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
-.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
-.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
-.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
-.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
-.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
-.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
-.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
-.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
-.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
-.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
-.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
-.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
-.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
-.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
-.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
-.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
-.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
-.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
-.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
-.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
-.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
-.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
-.ui-icon-arrow-4 { background-position: 0 -80px; }
-.ui-icon-arrow-4-diag { background-position: -16px -80px; }
-.ui-icon-extlink { background-position: -32px -80px; }
-.ui-icon-newwin { background-position: -48px -80px; }
-.ui-icon-refresh { background-position: -64px -80px; }
-.ui-icon-shuffle { background-position: -80px -80px; }
-.ui-icon-transfer-e-w { background-position: -96px -80px; }
-.ui-icon-transferthick-e-w { background-position: -112px -80px; }
-.ui-icon-folder-collapsed { background-position: 0 -96px; }
-.ui-icon-folder-open { background-position: -16px -96px; }
-.ui-icon-document { background-position: -32px -96px; }
-.ui-icon-document-b { background-position: -48px -96px; }
-.ui-icon-note { background-position: -64px -96px; }
-.ui-icon-mail-closed { background-position: -80px -96px; }
-.ui-icon-mail-open { background-position: -96px -96px; }
-.ui-icon-suitcase { background-position: -112px -96px; }
-.ui-icon-comment { background-position: -128px -96px; }
-.ui-icon-person { background-position: -144px -96px; }
-.ui-icon-print { background-position: -160px -96px; }
-.ui-icon-trash { background-position: -176px -96px; }
-.ui-icon-locked { background-position: -192px -96px; }
-.ui-icon-unlocked { background-position: -208px -96px; }
-.ui-icon-bookmark { background-position: -224px -96px; }
-.ui-icon-tag { background-position: -240px -96px; }
-.ui-icon-home { background-position: 0 -112px; }
-.ui-icon-flag { background-position: -16px -112px; }
-.ui-icon-calendar { background-position: -32px -112px; }
-.ui-icon-cart { background-position: -48px -112px; }
-.ui-icon-pencil { background-position: -64px -112px; }
-.ui-icon-clock { background-position: -80px -112px; }
-.ui-icon-disk { background-position: -96px -112px; }
-.ui-icon-calculator { background-position: -112px -112px; }
-.ui-icon-zoomin { background-position: -128px -112px; }
-.ui-icon-zoomout { background-position: -144px -112px; }
-.ui-icon-search { background-position: -160px -112px; }
-.ui-icon-wrench { background-position: -176px -112px; }
-.ui-icon-gear { background-position: -192px -112px; }
-.ui-icon-heart { background-position: -208px -112px; }
-.ui-icon-star { background-position: -224px -112px; }
-.ui-icon-link { background-position: -240px -112px; }
-.ui-icon-cancel { background-position: 0 -128px; }
-.ui-icon-plus { background-position: -16px -128px; }
-.ui-icon-plusthick { background-position: -32px -128px; }
-.ui-icon-minus { background-position: -48px -128px; }
-.ui-icon-minusthick { background-position: -64px -128px; }
-.ui-icon-close { background-position: -80px -128px; }
-.ui-icon-closethick { background-position: -96px -128px; }
-.ui-icon-key { background-position: -112px -128px; }
-.ui-icon-lightbulb { background-position: -128px -128px; }
-.ui-icon-scissors { background-position: -144px -128px; }
-.ui-icon-clipboard { background-position: -160px -128px; }
-.ui-icon-copy { background-position: -176px -128px; }
-.ui-icon-contact { background-position: -192px -128px; }
-.ui-icon-image { background-position: -208px -128px; }
-.ui-icon-video { background-position: -224px -128px; }
-.ui-icon-script { background-position: -240px -128px; }
-.ui-icon-alert { background-position: 0 -144px; }
-.ui-icon-info { background-position: -16px -144px; }
-.ui-icon-notice { background-position: -32px -144px; }
-.ui-icon-help { background-position: -48px -144px; }
-.ui-icon-check { background-position: -64px -144px; }
-.ui-icon-bullet { background-position: -80px -144px; }
-.ui-icon-radio-off { background-position: -96px -144px; }
-.ui-icon-radio-on { background-position: -112px -144px; }
-.ui-icon-pin-w { background-position: -128px -144px; }
-.ui-icon-pin-s { background-position: -144px -144px; }
-.ui-icon-play { background-position: 0 -160px; }
-.ui-icon-pause { background-position: -16px -160px; }
-.ui-icon-seek-next { background-position: -32px -160px; }
-.ui-icon-seek-prev { background-position: -48px -160px; }
-.ui-icon-seek-end { background-position: -64px -160px; }
-.ui-icon-seek-start { background-position: -80px -160px; }
-/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
-.ui-icon-seek-first { background-position: -80px -160px; }
-.ui-icon-stop { background-position: -96px -160px; }
-.ui-icon-eject { background-position: -112px -160px; }
-.ui-icon-volume-off { background-position: -128px -160px; }
-.ui-icon-volume-on { background-position: -144px -160px; }
-.ui-icon-power { background-position: 0 -176px; }
-.ui-icon-signal-diag { background-position: -16px -176px; }
-.ui-icon-signal { background-position: -32px -176px; }
-.ui-icon-battery-0 { background-position: -48px -176px; }
-.ui-icon-battery-1 { background-position: -64px -176px; }
-.ui-icon-battery-2 { background-position: -80px -176px; }
-.ui-icon-battery-3 { background-position: -96px -176px; }
-.ui-icon-circle-plus { background-position: 0 -192px; }
-.ui-icon-circle-minus { background-position: -16px -192px; }
-.ui-icon-circle-close { background-position: -32px -192px; }
-.ui-icon-circle-triangle-e { background-position: -48px -192px; }
-.ui-icon-circle-triangle-s { background-position: -64px -192px; }
-.ui-icon-circle-triangle-w { background-position: -80px -192px; }
-.ui-icon-circle-triangle-n { background-position: -96px -192px; }
-.ui-icon-circle-arrow-e { background-position: -112px -192px; }
-.ui-icon-circle-arrow-s { background-position: -128px -192px; }
-.ui-icon-circle-arrow-w { background-position: -144px -192px; }
-.ui-icon-circle-arrow-n { background-position: -160px -192px; }
-.ui-icon-circle-zoomin { background-position: -176px -192px; }
-.ui-icon-circle-zoomout { background-position: -192px -192px; }
-.ui-icon-circle-check { background-position: -208px -192px; }
-.ui-icon-circlesmall-plus { background-position: 0 -208px; }
-.ui-icon-circlesmall-minus { background-position: -16px -208px; }
-.ui-icon-circlesmall-close { background-position: -32px -208px; }
-.ui-icon-squaresmall-plus { background-position: -48px -208px; }
-.ui-icon-squaresmall-minus { background-position: -64px -208px; }
-.ui-icon-squaresmall-close { background-position: -80px -208px; }
-.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
-.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
-.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
-.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
-.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
-.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Corner radius */
-.ui-corner-tl { -moz-border-radius-topleft: 0; -webkit-border-top-left-radius: 0; }
-.ui-corner-tr { -moz-border-radius-topright: 0; -webkit-border-top-right-radius: 0; }
-.ui-corner-bl { -moz-border-radius-bottomleft: 0; -webkit-border-bottom-left-radius: 0; }
-.ui-corner-br { -moz-border-radius-bottomright: 0; -webkit-border-bottom-right-radius: 0; }
-.ui-corner-top { -moz-border-radius-topleft: 0; -webkit-border-top-left-radius: 0; -moz-border-radius-topright: 0; -webkit-border-top-right-radius: 0; }
-.ui-corner-bottom { -moz-border-radius-bottomleft: 0; -webkit-border-bottom-left-radius: 0; -moz-border-radius-bottomright: 0; -webkit-border-bottom-right-radius: 0; }
-.ui-corner-right {  -moz-border-radius-topright: 0; -webkit-border-top-right-radius: 0; -moz-border-radius-bottomright: 0; -webkit-border-bottom-right-radius: 0; }
-.ui-corner-left { -moz-border-radius-topleft: 0; -webkit-border-top-left-radius: 0; -moz-border-radius-bottomleft: 0; -webkit-border-bottom-left-radius: 0; }
-.ui-corner-all { -moz-border-radius: 0; -webkit-border-radius: 0; }
-
-/* Overlays */
-.ui-widget-overlay { background: #000000; opacity: .75;filter:Alpha(Opacity=75); }
-.ui-widget-shadow { margin: -7px 0 0 -7px; padding: 7px; /* @embed */ background: #000000 url(images/ui-bg_flat_70_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
\ No newline at end of file
diff --git a/resources/jquery/images/jquery.arrowSteps.divider-ltr.png b/resources/jquery/images/jquery.arrowSteps.divider-ltr.png
deleted file mode 100644 (file)
index 84ed2a2..0000000
Binary files a/resources/jquery/images/jquery.arrowSteps.divider-ltr.png and /dev/null differ
diff --git a/resources/jquery/images/jquery.arrowSteps.divider-rtl.png b/resources/jquery/images/jquery.arrowSteps.divider-rtl.png
deleted file mode 100644 (file)
index 7cfbfeb..0000000
Binary files a/resources/jquery/images/jquery.arrowSteps.divider-rtl.png and /dev/null differ
diff --git a/resources/jquery/images/jquery.arrowSteps.head-ltr.png b/resources/jquery/images/jquery.arrowSteps.head-ltr.png
deleted file mode 100644 (file)
index eb07028..0000000
Binary files a/resources/jquery/images/jquery.arrowSteps.head-ltr.png and /dev/null differ
diff --git a/resources/jquery/images/jquery.arrowSteps.head-rtl.png b/resources/jquery/images/jquery.arrowSteps.head-rtl.png
deleted file mode 100644 (file)
index 7ea2fdb..0000000
Binary files a/resources/jquery/images/jquery.arrowSteps.head-rtl.png and /dev/null differ
diff --git a/resources/jquery/images/jquery.arrowSteps.tail-ltr.png b/resources/jquery/images/jquery.arrowSteps.tail-ltr.png
deleted file mode 100644 (file)
index 3ad990b..0000000
Binary files a/resources/jquery/images/jquery.arrowSteps.tail-ltr.png and /dev/null differ
diff --git a/resources/jquery/images/jquery.arrowSteps.tail-rtl.png b/resources/jquery/images/jquery.arrowSteps.tail-rtl.png
deleted file mode 100644 (file)
index 1d3048e..0000000
Binary files a/resources/jquery/images/jquery.arrowSteps.tail-rtl.png and /dev/null differ
diff --git a/resources/jquery/images/marker.png b/resources/jquery/images/marker.png
deleted file mode 100644 (file)
index 19efb6c..0000000
Binary files a/resources/jquery/images/marker.png and /dev/null differ
diff --git a/resources/jquery/images/mask.png b/resources/jquery/images/mask.png
deleted file mode 100644 (file)
index fe08de0..0000000
Binary files a/resources/jquery/images/mask.png and /dev/null differ
diff --git a/resources/jquery/images/sort_both.gif b/resources/jquery/images/sort_both.gif
deleted file mode 100644 (file)
index 50ad15a..0000000
Binary files a/resources/jquery/images/sort_both.gif and /dev/null differ
diff --git a/resources/jquery/images/sort_down.gif b/resources/jquery/images/sort_down.gif
deleted file mode 100644 (file)
index ec4f41b..0000000
Binary files a/resources/jquery/images/sort_down.gif and /dev/null differ
diff --git a/resources/jquery/images/sort_none.gif b/resources/jquery/images/sort_none.gif
deleted file mode 100644 (file)
index edd07e5..0000000
Binary files a/resources/jquery/images/sort_none.gif and /dev/null differ
diff --git a/resources/jquery/images/sort_up.gif b/resources/jquery/images/sort_up.gif
deleted file mode 100644 (file)
index 8018918..0000000
Binary files a/resources/jquery/images/sort_up.gif and /dev/null differ
diff --git a/resources/jquery/images/spinner-large.gif b/resources/jquery/images/spinner-large.gif
deleted file mode 100644 (file)
index 72203fd..0000000
Binary files a/resources/jquery/images/spinner-large.gif and /dev/null differ
diff --git a/resources/jquery/images/spinner.gif b/resources/jquery/images/spinner.gif
deleted file mode 100644 (file)
index 6146be4..0000000
Binary files a/resources/jquery/images/spinner.gif and /dev/null differ
diff --git a/resources/jquery/images/wheel.png b/resources/jquery/images/wheel.png
deleted file mode 100644 (file)
index 7e53103..0000000
Binary files a/resources/jquery/images/wheel.png and /dev/null differ
diff --git a/resources/jquery/jquery.appear.js b/resources/jquery/jquery.appear.js
deleted file mode 100644 (file)
index 4f77886..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * jQuery.appear
- * http://code.google.com/p/jquery-appear/
- *
- * Copyright (c) 2009 Michael Hixson
- * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
-*/
-(function($) {
-        
-       $.fn.appear = function(fn, options) {
-                
-               var settings = $.extend({
-                       //arbitrary data to pass to fn
-                       data: undefined,
-                       //call fn only on the first appear?
-                       one: true
-                        
-               }, options);
-                
-               return this.each(function() {
-                
-                       var t = $(this);
-                        
-                       //whether the element is currently visible
-                       t.appeared = false;
-                        
-                       if (!fn) {
-                               //trigger the custom event
-                               t.trigger('appear', settings.data);
-                               return;
-                       }
-                        
-                       var w = $(window);
-                        
-                       //fires the appear event when appropriate
-                       var check = function() {
-                               //is the element hidden?
-                               if (!t.is(':visible')) {
-                                        
-                                       //it became hidden
-                                       t.appeared = false;
-                                       return;
-                               }
-                               //is the element inside the visible window?
-                               var a = w.scrollLeft();
-                               var b = w.scrollTop();
-                               var o = t.offset();
-                               var x = o.left;
-                               var y = o.top;
-                                
-                               if (y + t.height() >= b && 
-                                               y <= b + w.height() &&
-                                               x + t.width() >= a && 
-                                               x <= a + w.width()) {
-                                       //trigger the custom event
-                                       if (!t.appeared) t.trigger('appear', settings.data);
-                                        
-                               } else {
-                                       //it scrolled out of view
-                                       t.appeared = false;
-                               }
-                       };
-                       //create a modified fn with some additional logic
-                       var modifiedFn = function() {
-                                
-                               //mark the element as visible
-                               t.appeared = true;
-                               //is this supposed to happen only once?
-                               if (settings.one) {
-                                       //remove the check
-                                       w.unbind('scroll', check);
-                                       var i = $.inArray(check, $.fn.appear.checks);
-                                       if (i >= 0) $.fn.appear.checks.splice(i, 1);
-                               }
-                               //trigger the original fn
-                               fn.apply(this, arguments);
-                       };
-                        
-                       //bind the modified fn to the element
-                       if (settings.one) t.one('appear', settings.data, modifiedFn);
-                       else t.bind('appear', settings.data, modifiedFn);
-                        
-                       //check whenever the window scrolls
-                       w.scroll(check);
-                        
-                       //check whenever the dom changes
-                       $.fn.appear.checks.push(check);
-                        
-                       //check now
-                       (check)();
-               });
-       };
-        
-       //keep a queue of appearance checks
-       $.extend($.fn.appear, {
-                
-               checks: [],
-               timeout: null,
-               //process the queue
-               checkAll: function() {
-                       var length = $.fn.appear.checks.length;
-                       if (length > 0) while (length--) ($.fn.appear.checks[length])();
-               },
-               //check the queue asynchronously
-               run: function() {
-                       if ($.fn.appear.timeout) clearTimeout($.fn.appear.timeout);
-                       $.fn.appear.timeout = setTimeout($.fn.appear.checkAll, 20);
-               }
-       });
-        
-       //run checks when these methods are called
-       $.each(['append', 'prepend', 'after', 'before', 'attr', 
-                                       'removeAttr', 'addClass', 'removeClass', 'toggleClass', 
-                                       'remove', 'css', 'show', 'hide'], function(i, n) {
-               var old = $.fn[n];
-               if (old) {
-                       $.fn[n] = function() {
-                               var r = old.apply(this, arguments);
-                               $.fn.appear.run();
-                               return r;
-                       }
-               }
-       });
-        
-})(jQuery);
\ No newline at end of file
diff --git a/resources/jquery/jquery.arrowSteps.css b/resources/jquery/jquery.arrowSteps.css
deleted file mode 100644 (file)
index f8f6e95..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-.arrowSteps {
-       list-style-type: none;
-       list-style-image: none;
-       border: 1px solid #666666;
-       position: relative;
-}
-
-.arrowSteps li {
-       float: left;
-       padding: 0px;
-       margin: 0px;
-       border: 0 none;
-}
-
-.arrowSteps li div {
-       padding: 0.5em;
-       text-align: center;
-       white-space: nowrap;
-       overflow: hidden;
-}
-
-.arrowSteps li.arrow div {
-       /* @embed */
-       background: url(images/jquery.arrowSteps.divider-ltr.png) no-repeat right center;
-}
-
-/* applied to the element preceding the highlighted step */
-.arrowSteps li.arrow.tail div {
-       /* @embed */
-       background: url(images/jquery.arrowSteps.tail-ltr.png) no-repeat right center;
-}
-
-/* this applies to all highlighted, including the last */
-.arrowSteps li.head div {
-       /* @embed */
-       background: url(images/jquery.arrowSteps.head-ltr.png) no-repeat left center;
-       font-weight: bold;
-}
-
-/* this applies to all highlighted arrows except the last */
-.arrowSteps li.arrow.head div {
-       /* TODO: eliminate duplication of jquery.arrowSteps.head.png embedding */
-       /* @embed */
-       background: url(images/jquery.arrowSteps.head-ltr.png) no-repeat right center;
-}
diff --git a/resources/jquery/jquery.arrowSteps.js b/resources/jquery/jquery.arrowSteps.js
deleted file mode 100644 (file)
index c44e7c5..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*!
- * jQuery arrowSteps plugin
- * Copyright Neil Kandalgaonkar, 2010
- *
- * This work is licensed under the terms of the GNU General Public License,
- * version 2 or later.
- * (see http://www.fsf.org/licensing/licenses/gpl.html).
- * Derivative works and later versions of the code must be free software
- * licensed under the same or a compatible license.
- */
-
-/**
- * @class jQuery.plugin.arrowSteps
- */
-( function ( $ ) {
-       /**
-        * Show users their progress through a series of steps, via a row of items that fit
-        * together like arrows. One item can be highlighted at a time.
-        *
-        *     <ul id="robin-hood-daffy">
-        *       <li id="guard"><div>Guard!</div></li>
-        *       <li id="turn"><div>Turn!</div></li>
-        *       <li id="parry"><div>Parry!</div></li>
-        *       <li id="dodge"><div>Dodge!</div></li>
-        *       <li id="spin"><div>Spin!</div></li>
-        *       <li id="ha"><div>Ha!</div></li>
-        *       <li id="thrust"><div>Thrust!</div></li>
-        *     </ul>
-        *
-        *     <script>
-        *       $( '#robin-hood-daffy' ).arrowSteps();
-        *     </script>
-        *
-        * @return {jQuery}
-        * @chainable
-        */
-       $.fn.arrowSteps = function () {
-               var $steps, width, arrowWidth,
-                       paddingSide = $( 'body' ).hasClass( 'rtl' ) ? 'padding-left' : 'padding-right';
-
-               this.addClass( 'arrowSteps' );
-               $steps = this.find( 'li' );
-
-               width = parseInt( 100 / $steps.length, 10 );
-               $steps.css( 'width', width + '%' );
-
-               // Every step except the last one has an arrow pointing forward:
-               // at the right hand side in LTR languages, and at the left hand side in RTL.
-               // Also add in the padding for the calculated arrow width.
-               arrowWidth = parseInt( this.outerHeight(), 10 );
-               $steps.filter( ':not(:last-child)' ).addClass( 'arrow' )
-                     .find( 'div' ).css( paddingSide, arrowWidth.toString() + 'px' );
-
-               this.data( 'arrowSteps', $steps );
-               return this;
-       };
-
-       /**
-        * Highlights the element selected by the selector.
-        *
-        *       $( '#robin-hood-daffy' ).arrowStepsHighlight( '#guard' );
-        *       // 'Guard!' is highlighted.
-        *
-        *       // ... user completes the 'guard' step ...
-        *
-        *       $( '#robin-hood-daffy' ).arrowStepsHighlight( '#turn' );
-        *       // 'Turn!' is highlighted.
-        *
-        * @param {string} selector
-        */
-       $.fn.arrowStepsHighlight = function ( selector ) {
-               var $previous,
-                       $steps = this.data( 'arrowSteps' );
-               $.each( $steps, function ( i, step ) {
-                       var $step = $( step );
-                       if ( $step.is( selector ) ) {
-                               if ($previous) {
-                                       $previous.addClass( 'tail' );
-                               }
-                               $step.addClass( 'head' );
-                       } else {
-                               $step.removeClass( 'head tail lasthead' );
-                       }
-                       $previous = $step;
-               } );
-       };
-
-       /**
-        * @class jQuery
-        * @mixins jQuery.plugin.arrowSteps
-        */
-}( jQuery ) );
diff --git a/resources/jquery/jquery.async.js b/resources/jquery/jquery.async.js
deleted file mode 100644 (file)
index 2161f6b..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * jQuery Asynchronous Plugin 1.0
- *
- * Copyright (c) 2008 Vincent Robert (genezys.net)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- *
- */
-(function($){
-
-// opts.delay : (default 10) delay between async call in ms
-// opts.bulk : (default 500) delay during which the loop can continue synchronously without yielding the CPU
-// opts.test : (default true) function to test in the while test part
-// opts.loop : (default empty) function to call in the while loop part
-// opts.end : (default empty) function to call at the end of the while loop
-$.whileAsync = function(opts) {
-       var delay = Math.abs(opts.delay) || 10,
-               bulk = isNaN(opts.bulk) ? 500 : Math.abs(opts.bulk),
-               test = opts.test || function(){ return true; },
-               loop = opts.loop || function(){},
-               end = opts.end || function(){};
-       
-       (function(){
-
-               var t = false,
-                       begin = new Date();
-                       
-               while( t = test() ) {
-                       loop();
-                       if( bulk === 0 || (new Date() - begin) > bulk ) {
-                               break;
-                       }
-               }
-               if( t ) {
-                       setTimeout(arguments.callee, delay);
-               }
-               else {
-                       end();
-               }
-               
-       })();
-};
-
-// opts.delay : (default 10) delay between async call in ms
-// opts.bulk : (default 500) delay during which the loop can continue synchronously without yielding the CPU
-// opts.loop : (default empty) function to call in the each loop part, signature: function(index, value) this = value
-// opts.end : (default empty) function to call at the end of the each loop
-$.eachAsync = function(array, opts) {
-       var     i = 0,
-               l = array.length,
-               loop = opts.loop || function(){};
-       
-       $.whileAsync(
-               $.extend(opts, {
-                       test: function() { return i < l; },
-                       loop: function() {
-                               var val = array[i];
-                               return loop.call(val, i++, val);
-                       }
-               })
-       );
-};
-
-$.fn.eachAsync = function(opts) {
-       $.eachAsync(this, opts);
-       return this;
-}
-
-})(jQuery);
\ No newline at end of file
diff --git a/resources/jquery/jquery.autoEllipsis.js b/resources/jquery/jquery.autoEllipsis.js
deleted file mode 100644 (file)
index 57d8f94..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * @class jQuery.plugin.autoEllipsis
- */
-( function ( $ ) {
-
-var
-       // Cache ellipsed substrings for every string-width-position combination
-       cache = {},
-
-       // Use a separate cache when match highlighting is enabled
-       matchTextCache = {};
-
-/**
- * Automatically truncate the plain text contents of an element and add an ellipsis
- *
- * @param {Object} options
- * @param {'center'|'left'|'right'} [options.position='center'] Where to remove text.
- * @param {boolean} [options.tooltip=false] Whether to show a tooltip with the remainder
- * of the text.
- * @param {boolean} [options.restoreText=false] Whether to save the text for restoring
- * later.
- * @param {boolean} [options.hasSpan=false] Whether the element is already a container,
- * or if the library should create a new container for it.
- * @param {string|null} [options.matchText=null] Text to highlight, e.g. search terms.
- * @return {jQuery}
- * @chainable
- */
-$.fn.autoEllipsis = function ( options ) {
-       options = $.extend( {
-               position: 'center',
-               tooltip: false,
-               restoreText: false,
-               hasSpan: false,
-               matchText: null
-       }, options );
-
-       return this.each( function () {
-               var $trimmableText,
-                       text, trimmableText, w, pw,
-                       l, r, i, side, m,
-                       // container element - used for measuring against
-                       $container = $(this);
-
-               if ( options.restoreText ) {
-                       if ( !$container.data( 'autoEllipsis.originalText' ) ) {
-                               $container.data( 'autoEllipsis.originalText', $container.text() );
-                       } else {
-                               $container.text( $container.data( 'autoEllipsis.originalText' ) );
-                       }
-               }
-
-               // trimmable text element - only the text within this element will be trimmed
-               if ( options.hasSpan ) {
-                       $trimmableText = $container.children( options.selector );
-               } else {
-                       $trimmableText = $( '<span>' )
-                               .css( 'whiteSpace', 'nowrap' )
-                               .text( $container.text() );
-                       $container
-                               .empty()
-                               .append( $trimmableText );
-               }
-
-               text = $container.text();
-               trimmableText = $trimmableText.text();
-               w = $container.width();
-               pw = 0;
-
-               // Try cache
-               if ( options.matchText ) {
-                       if ( !( text in matchTextCache ) ) {
-                               matchTextCache[text] = {};
-                       }
-                       if ( !( options.matchText in matchTextCache[text] ) ) {
-                               matchTextCache[text][options.matchText] = {};
-                       }
-                       if ( !( w in matchTextCache[text][options.matchText] ) ) {
-                               matchTextCache[text][options.matchText][w] = {};
-                       }
-                       if ( options.position in matchTextCache[text][options.matchText][w] ) {
-                               $container.html( matchTextCache[text][options.matchText][w][options.position] );
-                               if ( options.tooltip ) {
-                                       $container.attr( 'title', text );
-                               }
-                               return;
-                       }
-               } else {
-                       if ( !( text in cache ) ) {
-                               cache[text] = {};
-                       }
-                       if ( !( w in cache[text] ) ) {
-                               cache[text][w] = {};
-                       }
-                       if ( options.position in cache[text][w] ) {
-                               $container.html( cache[text][w][options.position] );
-                               if ( options.tooltip ) {
-                                       $container.attr( 'title', text );
-                               }
-                               return;
-                       }
-               }
-
-               if ( $trimmableText.width() + pw > w ) {
-                       switch ( options.position ) {
-                               case 'right':
-                                       // Use binary search-like technique for efficiency
-                                       l = 0;
-                                       r = trimmableText.length;
-                                       do {
-                                               m = Math.ceil( ( l + r ) / 2 );
-                                               $trimmableText.text( trimmableText.substr( 0, m ) + '...' );
-                                               if ( $trimmableText.width() + pw > w ) {
-                                                       // Text is too long
-                                                       r = m - 1;
-                                               } else {
-                                                       l = m;
-                                               }
-                                       } while ( l < r );
-                                       $trimmableText.text( trimmableText.substr( 0, l ) + '...' );
-                                       break;
-                               case 'center':
-                                       // TODO: Use binary search like for 'right'
-                                       i = [Math.round( trimmableText.length / 2 ), Math.round( trimmableText.length / 2 )];
-                                       // Begin with making the end shorter
-                                       side = 1;
-                                       while ( $trimmableText.outerWidth() + pw > w && i[0] > 0 ) {
-                                               $trimmableText.text( trimmableText.substr( 0, i[0] ) + '...' + trimmableText.substr( i[1] ) );
-                                               // Alternate between trimming the end and begining
-                                               if ( side === 0 ) {
-                                                       // Make the begining shorter
-                                                       i[0]--;
-                                                       side = 1;
-                                               } else {
-                                                       // Make the end shorter
-                                                       i[1]++;
-                                                       side = 0;
-                                               }
-                                       }
-                                       break;
-                               case 'left':
-                                       // TODO: Use binary search like for 'right'
-                                       r = 0;
-                                       while ( $trimmableText.outerWidth() + pw > w && r < trimmableText.length ) {
-                                               $trimmableText.text( '...' + trimmableText.substr( r ) );
-                                               r++;
-                                       }
-                                       break;
-                       }
-               }
-               if ( options.tooltip ) {
-                       $container.attr( 'title', text );
-               }
-               if ( options.matchText ) {
-                       $container.highlightText( options.matchText );
-                       matchTextCache[text][options.matchText][w][options.position] = $container.html();
-               } else {
-                       cache[text][w][options.position] = $container.html();
-               }
-
-       } );
-};
-
-/**
- * @class jQuery
- * @mixins jQuery.plugin.autoEllipsis
- */
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.ba-throttle-debounce.js b/resources/jquery/jquery.ba-throttle-debounce.js
deleted file mode 100644 (file)
index fa30bdf..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*!
- * jQuery throttle / debounce - v1.1 - 3/7/2010
- * http://benalman.com/projects/jquery-throttle-debounce-plugin/
- * 
- * Copyright (c) 2010 "Cowboy" Ben Alman
- * Dual licensed under the MIT and GPL licenses.
- * http://benalman.com/about/license/
- */
-
-// Script: jQuery throttle / debounce: Sometimes, less is more!
-//
-// *Version: 1.1, Last updated: 3/7/2010*
-// 
-// Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
-// GitHub       - http://github.com/cowboy/jquery-throttle-debounce/
-// Source       - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
-// (Minified)   - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
-// 
-// About: License
-// 
-// Copyright (c) 2010 "Cowboy" Ben Alman,
-// Dual licensed under the MIT and GPL licenses.
-// http://benalman.com/about/license/
-// 
-// About: Examples
-// 
-// These working examples, complete with fully commented code, illustrate a few
-// ways in which this plugin can be used.
-// 
-// Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
-// Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
-// 
-// About: Support and Testing
-// 
-// Information about what version or versions of jQuery this plugin has been
-// tested with, what browsers it has been tested in, and where the unit tests
-// reside (so you can test it yourself).
-// 
-// jQuery Versions - none, 1.3.2, 1.4.2
-// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
-// Unit Tests      - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
-// 
-// About: Release History
-// 
-// 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
-//       executed later than they should. Reworked a fair amount of internal
-//       logic as well.
-// 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
-//       from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
-//       no_trailing throttle parameter and debounce functionality.
-// 
-// Topic: Note for non-jQuery users
-// 
-// jQuery isn't actually required for this plugin, because nothing internal
-// uses any jQuery methods or properties. jQuery is just used as a namespace
-// under which these methods can exist.
-// 
-// Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
-// when this plugin is loaded, the method described below will be created in
-// the `Cowboy` namespace. Usage will be exactly the same, but instead of
-// $.method() or jQuery.method(), you'll need to use Cowboy.method().
-
-(function(window,undefined){
-  '$:nomunge'; // Used by YUI compressor.
-  
-  // Since jQuery really isn't required for this plugin, use `jQuery` as the
-  // namespace only if it already exists, otherwise use the `Cowboy` namespace,
-  // creating it if necessary.
-  var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
-    
-    // Internal method reference.
-    jq_throttle;
-  
-  // Method: jQuery.throttle
-  // 
-  // Throttle execution of a function. Especially useful for rate limiting
-  // execution of handlers on events like resize and scroll. If you want to
-  // rate-limit execution of a function to a single time, see the
-  // <jQuery.debounce> method.
-  // 
-  // In this visualization, | is a throttled-function call and X is the actual
-  // callback execution:
-  // 
-  // > Throttled with `no_trailing` specified as false or unspecified:
-  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
-  // > X    X    X    X    X    X        X    X    X    X    X    X
-  // > 
-  // > Throttled with `no_trailing` specified as true:
-  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
-  // > X    X    X    X    X             X    X    X    X    X
-  // 
-  // Usage:
-  // 
-  // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
-  // > 
-  // > jQuery('selector').bind( 'someevent', throttled );
-  // > jQuery('selector').unbind( 'someevent', throttled );
-  // 
-  // This also works in jQuery 1.4+:
-  // 
-  // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
-  // > jQuery('selector').unbind( 'someevent', callback );
-  // 
-  // Arguments:
-  // 
-  //  delay - (Number) A zero-or-greater delay in milliseconds. For event
-  //    callbacks, values around 100 or 250 (or even higher) are most useful.
-  //  no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
-  //    true, callback will only execute every `delay` milliseconds while the
-  //    throttled-function is being called. If no_trailing is false or
-  //    unspecified, callback will be executed one final time after the last
-  //    throttled-function call. (After the throttled-function has not been
-  //    called for `delay` milliseconds, the internal counter is reset)
-  //  callback - (Function) A function to be executed after delay milliseconds.
-  //    The `this` context and all arguments are passed through, as-is, to
-  //    `callback` when the throttled-function is executed.
-  // 
-  // Returns:
-  // 
-  //  (Function) A new, throttled, function.
-  
-  $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
-    // After wrapper has stopped being called, this timeout ensures that
-    // `callback` is executed at the proper times in `throttle` and `end`
-    // debounce modes.
-    var timeout_id,
-      
-      // Keep track of the last time `callback` was executed.
-      last_exec = 0;
-    
-    // `no_trailing` defaults to falsy.
-    if ( typeof no_trailing !== 'boolean' ) {
-      debounce_mode = callback;
-      callback = no_trailing;
-      no_trailing = undefined;
-    }
-    
-    // The `wrapper` function encapsulates all of the throttling / debouncing
-    // functionality and when executed will limit the rate at which `callback`
-    // is executed.
-    function wrapper() {
-      var that = this,
-        elapsed = +new Date() - last_exec,
-        args = arguments;
-      
-      // Execute `callback` and update the `last_exec` timestamp.
-      function exec() {
-        last_exec = +new Date();
-        callback.apply( that, args );
-      };
-      
-      // If `debounce_mode` is true (at_begin) this is used to clear the flag
-      // to allow future `callback` executions.
-      function clear() {
-        timeout_id = undefined;
-      };
-      
-      if ( debounce_mode && !timeout_id ) {
-        // Since `wrapper` is being called for the first time and
-        // `debounce_mode` is true (at_begin), execute `callback`.
-        exec();
-      }
-      
-      // Clear any existing timeout.
-      timeout_id && clearTimeout( timeout_id );
-      
-      if ( debounce_mode === undefined && elapsed > delay ) {
-        // In throttle mode, if `delay` time has been exceeded, execute
-        // `callback`.
-        exec();
-        
-      } else if ( no_trailing !== true ) {
-        // In trailing throttle mode, since `delay` time has not been
-        // exceeded, schedule `callback` to execute `delay` ms after most
-        // recent execution.
-        // 
-        // If `debounce_mode` is true (at_begin), schedule `clear` to execute
-        // after `delay` ms.
-        // 
-        // If `debounce_mode` is false (at end), schedule `callback` to
-        // execute after `delay` ms.
-        timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
-      }
-    };
-    
-    // Set the guid of `wrapper` function to the same of original callback, so
-    // it can be removed in jQuery 1.4+ .unbind or .die by using the original
-    // callback as a reference.
-    if ( $.guid ) {
-      wrapper.guid = callback.guid = callback.guid || $.guid++;
-    }
-    
-    // Return the wrapper function.
-    return wrapper;
-  };
-  
-  // Method: jQuery.debounce
-  // 
-  // Debounce execution of a function. Debouncing, unlike throttling,
-  // guarantees that a function is only executed a single time, either at the
-  // very beginning of a series of calls, or at the very end. If you want to
-  // simply rate-limit execution of a function, see the <jQuery.throttle>
-  // method.
-  // 
-  // In this visualization, | is a debounced-function call and X is the actual
-  // callback execution:
-  // 
-  // > Debounced with `at_begin` specified as false or unspecified:
-  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
-  // >                          X                                 X
-  // > 
-  // > Debounced with `at_begin` specified as true:
-  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
-  // > X                                 X
-  // 
-  // Usage:
-  // 
-  // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
-  // > 
-  // > jQuery('selector').bind( 'someevent', debounced );
-  // > jQuery('selector').unbind( 'someevent', debounced );
-  // 
-  // This also works in jQuery 1.4+:
-  // 
-  // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
-  // > jQuery('selector').unbind( 'someevent', callback );
-  // 
-  // Arguments:
-  // 
-  //  delay - (Number) A zero-or-greater delay in milliseconds. For event
-  //    callbacks, values around 100 or 250 (or even higher) are most useful.
-  //  at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
-  //    unspecified, callback will only be executed `delay` milliseconds after
-  //    the last debounced-function call. If at_begin is true, callback will be
-  //    executed only at the first debounced-function call. (After the
-  //    throttled-function has not been called for `delay` milliseconds, the
-  //    internal counter is reset)
-  //  callback - (Function) A function to be executed after delay milliseconds.
-  //    The `this` context and all arguments are passed through, as-is, to
-  //    `callback` when the debounced-function is executed.
-  // 
-  // Returns:
-  // 
-  //  (Function) A new, debounced, function.
-  
-  $.debounce = function( delay, at_begin, callback ) {
-    return callback === undefined
-      ? jq_throttle( delay, at_begin, false )
-      : jq_throttle( delay, callback, at_begin !== false );
-  };
-  
-})(this);
diff --git a/resources/jquery/jquery.badge.css b/resources/jquery/jquery.badge.css
deleted file mode 100644 (file)
index f313663..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-.mw-badge {
-       min-width: 7px;
-       border-radius: 2px;
-       padding: 1px 4px;
-       text-align: center;
-       font-size: 12px;
-       line-height: 12px;
-       background-color: #d2d2d2;
-       cursor: pointer;
-}
-
-.mw-badge-content {
-       font-weight: bold;
-       color: white;
-       vertical-align: baseline;
-       text-shadow: 0 1px rgba(0, 0, 0, 0.4);
-}
-
-.mw-badge-inline {
-       margin-left: 3px;
-       display: inline-block;
-       /* Hack for IE6 and IE7 (bug 47926) */
-       zoom: 1;
-       *display: inline;
-
-}
-.mw-badge-overlay {
-       position: absolute;
-       bottom: -1px;
-       right: -3px;
-       z-index: 50;
-}
-
-.mw-badge-important {
-       background-color: #cc0000;
-}
-
diff --git a/resources/jquery/jquery.badge.js b/resources/jquery/jquery.badge.js
deleted file mode 100644 (file)
index 023b6e2..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*!
- * jQuery Badge plugin
- *
- * @license MIT
- *
- * @author Ryan Kaldari <rkaldari@wikimedia.org>, 2012
- * @author Andrew Garrett <agarrett@wikimedia.org>, 2012
- * @author Marius Hoch <hoo@online.de>, 2012
- *
- * 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.
- *
- * This program is distributed WITHOUT ANY WARRANTY.
- */
-
-/**
- * @class jQuery.plugin.badge
- */
-( function ( $, mw ) {
-       /**
-        * Put a badge on an item on the page. The badge container will be appended to the selected element(s).
-        *
-        *     $element.badge( text );
-        *     $element.badge( 5 );
-        *     $element.badge( '100+' );
-        *     $element.badge( text, inline );
-        *     $element.badge( 'New', true );
-        *
-        * @param {number|string} text The value to display in the badge. If the value is falsey (0,
-        *  null, false, '', etc.), any existing badge will be removed.
-        * @param {boolean} [inline=true] True if the badge should be displayed inline, false
-        *  if the badge should overlay the parent element.
-        * @param {boolean} [displayZero=false] True if the number zero should be displayed,
-        *  false if the number zero should result in the badge being hidden
-        * @return {jQuery}
-        * @chainable
-        */
-       $.fn.badge = function ( text, inline, displayZero ) {
-               var $badge = this.find( '.mw-badge' ),
-                       badgeStyleClass = 'mw-badge-' + ( inline ? 'inline' : 'overlay' ),
-                       isImportant = true, displayBadge = true;
-
-               // If we're displaying zero, ensure style to be non-important
-               if ( mw.language.convertNumber( text, true ) === 0 ) {
-                       isImportant = false;
-                       if ( !displayZero ) {
-                               displayBadge = false;
-                       }
-               // If text is falsey (besides 0), hide the badge
-               } else if ( !text ) {
-                       displayBadge = false;
-               }
-
-               if ( displayBadge ) {
-                       // If a badge already exists, reuse it
-                       if ( $badge.length ) {
-                               $badge
-                                       .toggleClass( 'mw-badge-important', isImportant )
-                                       .find( '.mw-badge-content' )
-                                               .text( text );
-                       } else {
-                               // Otherwise, create a new badge with the specified text and style
-                               $badge = $( '<div class="mw-badge"></div>' )
-                                       .addClass( badgeStyleClass )
-                                       .toggleClass( 'mw-badge-important', isImportant )
-                                       .append(
-                                               $( '<span class="mw-badge-content"></span>' ).text( text )
-                                       )
-                                       .appendTo( this );
-                       }
-               } else {
-                       $badge.remove();
-               }
-               return this;
-       };
-
-       /**
-        * @class jQuery
-        * @mixins jQuery.plugin.badge
-        */
-}( jQuery, mediaWiki ) );
diff --git a/resources/jquery/jquery.byteLength.js b/resources/jquery/jquery.byteLength.js
deleted file mode 100644 (file)
index 398937e..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * jQuery.byteLength
- *
- * Calculate the byte length of a string (accounting for UTF-8).
- *
- * @author Jan Paul Posma, 2011
- * @author Timo Tijhof, 2012
- * @author David Chan, 2013
- */
-jQuery.byteLength = function ( str ) {
-
-       // This basically figures out how many bytes a UTF-16 string (which is what js sees)
-       // will take in UTF-8 by replacing a 2 byte character with 2 *'s, etc, and counting that.
-       // Note, surrogate (\uD800-\uDFFF) characters are counted as 2 bytes, since there's two of them
-       // and the actual character takes 4 bytes in UTF-8 (2*2=4). Might not work perfectly in
-       // edge cases such as illegal sequences, but that should never happen.
-
-       // https://en.wikipedia.org/wiki/UTF-8#Description
-       // The mapping from UTF-16 code units to UTF-8 bytes is as follows:
-       // > Range 0000-007F: codepoints that become 1 byte of UTF-8
-       // > Range 0080-07FF: codepoints that become 2 bytes of UTF-8
-       // > Range 0800-D7FF: codepoints that become 3 bytes of UTF-8
-       // > Range D800-DFFF: Surrogates (each pair becomes 4 bytes of UTF-8)
-       // > Range E000-FFFF: codepoints that become 3 bytes of UTF-8 (continued)
-
-       return str
-               .replace( /[\u0080-\u07FF\uD800-\uDFFF]/g, '**' )
-               .replace( /[\u0800-\uD7FF\uE000-\uFFFF]/g, '***' )
-               .length;
-
-};
diff --git a/resources/jquery/jquery.byteLimit.js b/resources/jquery/jquery.byteLimit.js
deleted file mode 100644 (file)
index 17c1821..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/**
- * @class jQuery.plugin.byteLimit
- */
-( function ( $ ) {
-
-       /**
-        * Utility function to trim down a string, based on byteLimit
-        * and given a safe start position. It supports insertion anywhere
-        * in the string, so "foo" to "fobaro" if limit is 4 will result in
-        * "fobo", not "foba". Basically emulating the native maxlength by
-        * reconstructing where the insertion occured.
-        *
-        * @private
-        * @param {string} safeVal Known value that was previously returned by this
-        * function, if none, pass empty string.
-        * @param {string} newVal New value that may have to be trimmed down.
-        * @param {number} byteLimit Number of bytes the value may be in size.
-        * @param {Function} [fn] See jQuery.byteLimit.
-        * @return {Object}
-        * @return {string} return.newVal
-        * @return {boolean} return.trimmed
-        */
-       function trimValForByteLength( safeVal, newVal, byteLimit, fn ) {
-               var startMatches, endMatches, matchesLen, inpParts,
-                       oldVal = safeVal;
-
-               // Run the hook if one was provided, but only on the length
-               // assessment. The value itself is not to be affected by the hook.
-               if ( $.byteLength( fn ? fn( newVal ) : newVal ) <= byteLimit ) {
-                       // Limit was not reached, just remember the new value
-                       // and let the user continue.
-                       return {
-                               newVal: newVal,
-                               trimmed: false
-                       };
-               }
-
-               // Current input is longer than the active limit.
-               // Figure out what was added and limit the addition.
-               startMatches = 0;
-               endMatches = 0;
-
-               // It is important that we keep the search within the range of
-               // the shortest string's length.
-               // Imagine a user adds text that matches the end of the old value
-               // (e.g. "foo" -> "foofoo"). startMatches would be 3, but without
-               // limiting both searches to the shortest length, endMatches would
-               // also be 3.
-               matchesLen = Math.min( newVal.length, oldVal.length );
-
-               // Count same characters from the left, first.
-               // (if "foo" -> "foofoo", assume addition was at the end).
-               while (
-                       startMatches < matchesLen &&
-                       oldVal.charAt( startMatches ) === newVal.charAt( startMatches )
-               ) {
-                       startMatches += 1;
-               }
-
-               while (
-                       endMatches < ( matchesLen - startMatches ) &&
-                       oldVal.charAt( oldVal.length - 1 - endMatches ) === newVal.charAt( newVal.length - 1 - endMatches )
-               ) {
-                       endMatches += 1;
-               }
-
-               inpParts = [
-                       // Same start
-                       newVal.substring( 0, startMatches ),
-                       // Inserted content
-                       newVal.substring( startMatches, newVal.length - endMatches ),
-                       // Same end
-                       newVal.substring( newVal.length - endMatches )
-               ];
-
-               // Chop off characters from the end of the "inserted content" string
-               // until the limit is statisfied.
-               if ( fn ) {
-                       // stop, when there is nothing to slice - bug 41450
-                       while ( $.byteLength( fn( inpParts.join( '' ) ) ) > byteLimit && inpParts[1].length > 0 ) {
-                               inpParts[1] = inpParts[1].slice( 0, -1 );
-                       }
-               } else {
-                       while ( $.byteLength( inpParts.join( '' ) ) > byteLimit ) {
-                               inpParts[1] = inpParts[1].slice( 0, -1 );
-                       }
-               }
-
-               newVal = inpParts.join( '' );
-
-               return {
-                       newVal: newVal,
-                       trimmed: true
-               };
-       }
-
-       var eventKeys = [
-               'keyup.byteLimit',
-               'keydown.byteLimit',
-               'change.byteLimit',
-               'mouseup.byteLimit',
-               'cut.byteLimit',
-               'paste.byteLimit',
-               'focus.byteLimit',
-               'blur.byteLimit'
-       ].join( ' ' );
-
-       /**
-        * Enforces a byte limit on an input field, so that UTF-8 entries are counted as well,
-        * when, for example, a database field has a byte limit rather than a character limit.
-        * Plugin rationale: Browser has native maxlength for number of characters, this plugin
-        * exists to limit number of bytes instead.
-        *
-        * Can be called with a custom limit (to use that limit instead of the maxlength attribute
-        * value), a filter function (in case the limit should apply to something other than the
-        * exact input value), or both. Order of parameters is important!
-        *
-        * @param {number} [limit] Limit to enforce, fallsback to maxLength-attribute,
-        *  called with fetched value as argument.
-        * @param {Function} [fn] Function to call on the string before assessing the length.
-        * @return {jQuery}
-        * @chainable
-        */
-       $.fn.byteLimit = function ( limit, fn ) {
-               // If the first argument is the function,
-               // set fn to the first argument's value and ignore the second argument.
-               if ( $.isFunction( limit ) ) {
-                       fn = limit;
-                       limit = undefined;
-               // Either way, verify it is a function so we don't have to call
-               // isFunction again after this.
-               } else if ( !fn || !$.isFunction( fn ) ) {
-                       fn = undefined;
-               }
-
-               // The following is specific to each element in the collection.
-               return this.each( function ( i, el ) {
-                       var $el, elLimit, prevSafeVal;
-
-                       $el = $( el );
-
-                       // If no limit was passed to byteLimit(), use the maxlength value.
-                       // Can't re-use 'limit' variable because it's in the higher scope
-                       // that would affect the next each() iteration as well.
-                       // Note that we use attribute to read the value instead of property,
-                       // because in Chrome the maxLength property by default returns the
-                       // highest supported value (no indication that it is being enforced
-                       // by choice). We don't want to bind all of this for some ridiculously
-                       // high default number, unless it was explicitly set in the HTML.
-                       // Also cast to a (primitive) number (most commonly because the maxlength
-                       // attribute contains a string, but theoretically the limit parameter
-                       // could be something else as well).
-                       elLimit = Number( limit === undefined ? $el.attr( 'maxlength' ) : limit );
-
-                       // If there is no (valid) limit passed or found in the property,
-                       // skip this. The < 0 check is required for Firefox, which returns
-                       // -1  (instead of undefined) for maxLength if it is not set.
-                       if ( !elLimit || elLimit < 0 ) {
-                               return;
-                       }
-
-                       if ( fn ) {
-                               // Save function for reference
-                               $el.data( 'byteLimit.callback', fn );
-                       }
-
-                       // Remove old event handlers (if there are any)
-                       $el.off( '.byteLimit' );
-
-                       if ( fn ) {
-                               // Disable the native maxLength (if there is any), because it interferes
-                               // with the (differently calculated) byte limit.
-                               // Aside from being differently calculated (average chars with byteLimit
-                               // is lower), we also support a callback which can make it to allow longer
-                               // values (e.g. count "Foo" from "User:Foo").
-                               // maxLength is a strange property. Removing or setting the property to
-                               // undefined directly doesn't work. Instead, it can only be unset internally
-                               // by the browser when removing the associated attribute (Firefox/Chrome).
-                               // http://code.google.com/p/chromium/issues/detail?id=136004
-                               $el.removeAttr( 'maxlength' );
-
-                       } else {
-                               // If we don't have a callback the bytelimit can only be lower than the charlimit
-                               // (that is, there are no characters less than 1 byte in size). So lets (re-)enforce
-                               // the native limit for efficiency when possible (it will make the while-loop below
-                               // faster by there being less left to interate over).
-                               $el.attr( 'maxlength', elLimit );
-                       }
-
-                       // Safe base value, used to determine the path between the previous state
-                       // and the state that triggered the event handler below - and enforce the
-                       // limit approppiately (e.g. don't chop from the end if text was inserted
-                       // at the beginning of the string).
-                       prevSafeVal = '';
-
-                       // We need to listen to after the change has already happened because we've
-                       // learned that trying to guess the new value and canceling the event
-                       // accordingly doesn't work because the new value is not always as simple as:
-                       // oldValue + String.fromCharCode( e.which ); because of cut, paste, select-drag
-                       // replacements, and custom input methods and what not.
-                       // Even though we only trim input after it was changed (never prevent it), we do
-                       // listen on events that input text, because there are cases where the text has
-                       // changed while text is being entered and keyup/change will not be fired yet
-                       // (such as holding down a single key, fires keydown, and after each keydown,
-                       // we can trim the previous one).
-                       // See http://www.w3.org/TR/DOM-Level-3-Events/#events-keyboard-event-order for
-                       // the order and characteristics of the key events.
-                       $el.on( eventKeys, function () {
-                               var res = trimValForByteLength(
-                                       prevSafeVal,
-                                       this.value,
-                                       elLimit,
-                                       fn
-                               );
-
-                               // Only set value property if it was trimmed, because whenever the
-                               // value property is set, the browser needs to re-initiate the text context,
-                               // which moves the cursor at the end the input, moving it away from wherever it was.
-                               // This is a side-effect of limiting after the fact.
-                               if ( res.trimmed === true ) {
-                                       this.value = res.newVal;
-                               }
-                               // Always adjust prevSafeVal to reflect the input value. Not doing this could cause
-                               // trimValForByteLength to compare the new value to an empty string instead of the
-                               // old value, resulting in trimming always from the end (bug 40850).
-                               prevSafeVal = res.newVal;
-                       } );
-               } );
-       };
-
-       /**
-        * @class jQuery
-        * @mixins jQuery.plugin.byteLimit
-        */
-}( jQuery ) );
diff --git a/resources/jquery/jquery.checkboxShiftClick.js b/resources/jquery/jquery.checkboxShiftClick.js
deleted file mode 100644 (file)
index b206566..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * jQuery checkboxShiftClick
- *
- * This will enable checkboxes to be checked or unchecked in a row by clicking one,
- * holding shift and clicking another one.
- *
- * @author Timo Tijhof, 2011 - 2012
- * @license GPL v2
- */
-( function ( $ ) {
-       $.fn.checkboxShiftClick = function () {
-               var prevCheckbox = null,
-                       $box = this;
-               // When our boxes are clicked..
-               $box.click( function ( e ) {
-                       // And one has been clicked before...
-                       if ( prevCheckbox !== null && e.shiftKey ) {
-                               // Check or uncheck this one and all in-between checkboxes,
-                               // except for disabled ones
-                               $box
-                                       .slice(
-                                               Math.min( $box.index( prevCheckbox ), $box.index( e.target ) ),
-                                               Math.max( $box.index( prevCheckbox ), $box.index( e.target ) ) + 1
-                                       )
-                                       .filter( function () {
-                                               return !this.disabled;
-                                       } )
-                                       .prop( 'checked', !!e.target.checked );
-                       }
-                       // Either way, update the prevCheckbox variable to the one clicked now
-                       prevCheckbox = e.target;
-               } );
-               return $box;
-       };
-}( jQuery ) );
diff --git a/resources/jquery/jquery.client.js b/resources/jquery/jquery.client.js
deleted file mode 100644 (file)
index 6689b7c..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/**
- * User-agent detection
- */
-( function ( $ ) {
-
-       /* Private Members */
-
-       /**
-        * @var {Object} profileCache Keyed by userAgent string,
-        * value is the parsed $.client.profile object for that user agent.
-        */
-       var profileCache = {};
-
-       /* Public Methods */
-
-       $.client = {
-
-               /**
-                * Get an object containing information about the client.
-                *
-                * @param {Object} nav An object with atleast a 'userAgent' and 'platform' key.
-                * Defaults to the global Navigator object.
-                * @return {Object} The resulting client object will be in the following format:
-                *  {
-                *   'name': 'firefox',
-                *   'layout': 'gecko',
-                *   'layoutVersion': 20101026,
-                *   'platform': 'linux'
-                *   'version': '3.5.1',
-                *   'versionBase': '3',
-                *   'versionNumber': 3.5,
-                *  }
-                */
-               profile: function ( nav ) {
-                       /*jshint boss: true */
-
-                       if ( nav === undefined ) {
-                               nav = window.navigator;
-                       }
-
-                       // Use the cached version if possible
-                       if ( profileCache[ nav.userAgent + '|' + nav.platform ] !== undefined ) {
-                               return profileCache[ nav.userAgent + '|' + nav.platform ];
-                       }
-
-                       var
-                               versionNumber,
-                               key = nav.userAgent + '|' + nav.platform,
-
-                               /* Configuration */
-
-                               // Name of browsers or layout engines we don't recognize
-                               uk = 'unknown',
-                               // Generic version digit
-                               x = 'x',
-                               // Strings found in user agent strings that need to be conformed
-                               wildUserAgents = ['Opera', 'Navigator', 'Minefield', 'KHTML', 'Chrome', 'PLAYSTATION 3', 'Iceweasel'],
-                               // Translations for conforming user agent strings
-                               userAgentTranslations = [
-                                       // Tons of browsers lie about being something they are not
-                                       [/(Firefox|MSIE|KHTML,?\slike\sGecko|Konqueror)/, ''],
-                                       // Chrome lives in the shadow of Safari still
-                                       ['Chrome Safari', 'Chrome'],
-                                       // KHTML is the layout engine not the browser - LIES!
-                                       ['KHTML', 'Konqueror'],
-                                       // Firefox nightly builds
-                                       ['Minefield', 'Firefox'],
-                                       // This helps keep different versions consistent
-                                       ['Navigator', 'Netscape'],
-                                       // This prevents version extraction issues, otherwise translation would happen later
-                                       ['PLAYSTATION 3', 'PS3']
-                               ],
-                               // Strings which precede a version number in a user agent string - combined and used as
-                               // match 1 in version detection
-                               versionPrefixes = [
-                                       'camino', 'chrome', 'firefox', 'iceweasel', 'netscape', 'netscape6', 'opera', 'version', 'konqueror',
-                                       'lynx', 'msie', 'safari', 'ps3', 'android'
-                               ],
-                               // Used as matches 2, 3 and 4 in version extraction - 3 is used as actual version number
-                               versionSuffix = '(\\/|\\;?\\s|)([a-z0-9\\.\\+]*?)(\\;|dev|rel|\\)|\\s|$)',
-                               // Names of known browsers
-                               names = [
-                                       'camino', 'chrome', 'firefox', 'iceweasel', 'netscape', 'konqueror', 'lynx', 'msie', 'opera',
-                                       'safari', 'ipod', 'iphone', 'blackberry', 'ps3', 'rekonq', 'android'
-                               ],
-                               // Tanslations for conforming browser names
-                               nameTranslations = [],
-                               // Names of known layout engines
-                               layouts = ['gecko', 'konqueror', 'msie', 'trident', 'opera', 'webkit'],
-                               // Translations for conforming layout names
-                               layoutTranslations = [ ['konqueror', 'khtml'], ['msie', 'trident'], ['opera', 'presto'] ],
-                               // Names of supported layout engines for version number
-                               layoutVersions = ['applewebkit', 'gecko', 'trident'],
-                               // Names of known operating systems
-                               platforms = ['win', 'wow64', 'mac', 'linux', 'sunos', 'solaris', 'iphone'],
-                               // Translations for conforming operating system names
-                               platformTranslations = [ ['sunos', 'solaris'], ['wow64', 'win'] ],
-
-                               /* Methods */
-
-                               /**
-                                * Performs multiple replacements on a string
-                                */
-                               translate = function ( source, translations ) {
-                                       var i;
-                                       for ( i = 0; i < translations.length; i++ ) {
-                                               source = source.replace( translations[i][0], translations[i][1] );
-                                       }
-                                       return source;
-                               },
-
-                               /* Pre-processing */
-
-                               ua = nav.userAgent,
-                               match,
-                               name = uk,
-                               layout = uk,
-                               layoutversion = uk,
-                               platform = uk,
-                               version = x;
-
-                       if ( match = new RegExp( '(' + wildUserAgents.join( '|' ) + ')' ).exec( ua ) ) {
-                               // Takes a userAgent string and translates given text into something we can more easily work with
-                               ua = translate( ua, userAgentTranslations );
-                       }
-                       // Everything will be in lowercase from now on
-                       ua = ua.toLowerCase();
-
-                       /* Extraction */
-
-                       if ( match = new RegExp( '(' + names.join( '|' ) + ')' ).exec( ua ) ) {
-                               name = translate( match[1], nameTranslations );
-                       }
-                       if ( match = new RegExp( '(' + layouts.join( '|' ) + ')' ).exec( ua ) ) {
-                               layout = translate( match[1], layoutTranslations );
-                       }
-                       if ( match = new RegExp( '(' + layoutVersions.join( '|' ) + ')\\\/(\\d+)').exec( ua ) ) {
-                               layoutversion = parseInt( match[2], 10 );
-                       }
-                       if ( match = new RegExp( '(' + platforms.join( '|' ) + ')' ).exec( nav.platform.toLowerCase() ) ) {
-                               platform = translate( match[1], platformTranslations );
-                       }
-                       if ( match = new RegExp( '(' + versionPrefixes.join( '|' ) + ')' + versionSuffix ).exec( ua ) ) {
-                               version = match[3];
-                       }
-
-                       /* Edge Cases -- did I mention about how user agent string lie? */
-
-                       // Decode Safari's crazy 400+ version numbers
-                       if ( name === 'safari' && version > 400 ) {
-                               version = '2.0';
-                       }
-                       // Expose Opera 10's lies about being Opera 9.8
-                       if ( name === 'opera' && version >= 9.8 ) {
-                               match = ua.match( /\bversion\/([0-9\.]*)/ );
-                               if ( match && match[1] ) {
-                                       version = match[1];
-                               } else {
-                                       version = '10';
-                               }
-                       }
-                       // And Opera 15's lies about being Chrome
-                       if ( name === 'chrome' && ( match = ua.match( /\bopr\/([0-9\.]*)/ ) ) ) {
-                               if ( match[1] ) {
-                                       name = 'opera';
-                                       version = match[1];
-                               }
-                       }
-                       // And IE 11's lies about being not being IE
-                       if ( layout === 'trident' && layoutversion >= 7 && ( match = ua.match( /\brv[ :\/]([0-9\.]*)/ ) ) ) {
-                               if ( match[1] ) {
-                                       name = 'msie';
-                                       version = match[1];
-                               }
-                       }
-                       // And Amazon Silk's lies about being Android on mobile or Safari on desktop
-                       if ( match = ua.match( /\bsilk\/([0-9.\-_]*)/ ) ) {
-                               if ( match[1] ) {
-                                       name = 'silk';
-                                       version = match[1];
-                               }
-                       }
-
-                       versionNumber = parseFloat( version, 10 ) || 0.0;
-
-                       /* Caching */
-
-                       return profileCache[ key  ] = {
-                               name: name,
-                               layout: layout,
-                               layoutVersion: layoutversion,
-                               platform: platform,
-                               version: version,
-                               versionBase: ( version !== x ? Math.floor( versionNumber ).toString() : x ),
-                               versionNumber: versionNumber
-                       };
-               },
-
-               /**
-                * Checks the current browser against a support map object.
-                *
-                * Version numbers passed as numeric values will be compared like numbers (1.2 > 1.11).
-                * Version numbers passed as string values will be compared using a simple component-wise
-                * algorithm, similar to PHP's version_compare ('1.2' < '1.11').
-                *
-                * A browser map is in the following format:
-                * {
-                *   // Multiple rules with configurable operators
-                *   'msie': [['>=', 7], ['!=', 9]],
-                *    // Match no versions
-                *   'iphone': false,
-                *    // Match any version
-                *   'android': null
-                * }
-                *
-                * It can optionally be split into ltr/rtl sections:
-                * {
-                *   'ltr': {
-                *     'android': null,
-                *     'iphone': false
-                *   },
-                *   'rtl': {
-                *     'android': false,
-                *     // rules are not inherited from ltr
-                *     'iphone': false
-                *   }
-                * }
-                *
-                * @param {Object} map Browser support map
-                * @param {Object} [profile] A client-profile object
-                * @param {boolean} [exactMatchOnly=false] Only return true if the browser is matched, otherwise
-                * returns true if the browser is not found.
-                *
-                * @return {boolean} The current browser is in the support map
-                */
-               test: function ( map, profile, exactMatchOnly ) {
-                       /*jshint evil: true */
-
-                       var conditions, dir, i, op, val, j, pieceVersion, pieceVal, compare;
-                       profile = $.isPlainObject( profile ) ? profile : $.client.profile();
-                       if ( map.ltr && map.rtl ) {
-                               dir = $( 'body' ).is( '.rtl' ) ? 'rtl' : 'ltr';
-                               map = map[dir];
-                       }
-                       // Check over each browser condition to determine if we are running in a compatible client
-                       if ( typeof map !== 'object' || map[profile.name] === undefined ) {
-                               // Not found, return true if exactMatchOnly not set, false otherwise
-                               return !exactMatchOnly;
-                       }
-                       conditions = map[profile.name];
-                       if ( conditions === false ) {
-                               // Match no versions
-                               return false;
-                       }
-                       if ( conditions === null ) {
-                               // Match all versions
-                               return true;
-                       }
-                       for ( i = 0; i < conditions.length; i++ ) {
-                               op = conditions[i][0];
-                               val = conditions[i][1];
-                               if ( typeof val === 'string' ) {
-                                       // Perform a component-wise comparison of versions, similar to PHP's version_compare
-                                       // but simpler. '1.11' is larger than '1.2'.
-                                       pieceVersion = profile.version.toString().split( '.' );
-                                       pieceVal = val.split( '.' );
-                                       // Extend with zeroes to equal length
-                                       while ( pieceVersion.length < pieceVal.length ) {
-                                               pieceVersion.push( '0' );
-                                       }
-                                       while ( pieceVal.length < pieceVersion.length ) {
-                                               pieceVal.push( '0' );
-                                       }
-                                       // Compare components
-                                       compare = 0;
-                                       for ( j = 0; j < pieceVersion.length; j++ ) {
-                                               if ( Number( pieceVersion[j] ) < Number( pieceVal[j] ) ) {
-                                                       compare = -1;
-                                                       break;
-                                               } else if ( Number( pieceVersion[j] ) > Number( pieceVal[j] ) ) {
-                                                       compare = 1;
-                                                       break;
-                                               }
-                                       }
-                                       // compare will be -1, 0 or 1, depending on comparison result
-                                       if ( !( eval( '' + compare + op + '0' ) ) ) {
-                                               return false;
-                                       }
-                               } else if ( typeof val === 'number' ) {
-                                       if ( !( eval( 'profile.versionNumber' + op + val ) ) ) {
-                                               return false;
-                                       }
-                               }
-                       }
-
-                       return true;
-               }
-       };
-}( jQuery ) );
diff --git a/resources/jquery/jquery.color.js b/resources/jquery/jquery.color.js
deleted file mode 100644 (file)
index 04f8047..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * jQuery Color Animations
- *
- * @author John Resig, 2007
- * @author Krinkle, 2011
- * Released under the MIT and GPL licenses.
- *
- * - 2011-01-05: Forked for MediaWiki. See also jQuery.colorUtil plugin
- */
-( function ( $ ) {
-
-       function getColor( elem, attr ) {
-               /*jshint boss:true */
-               var color;
-
-               do {
-                       color = $.css( elem, attr );
-
-                       // Keep going until we find an element that has color, or we hit the body
-                       if ( color !== '' && color !== 'transparent' || $.nodeName( elem, 'body' ) ) {
-                               break;
-                       }
-
-                       attr = 'backgroundColor';
-               } while ( elem = elem.parentNode );
-
-               return $.colorUtil.getRGB( color );
-       }
-
-       // We override the animation for all of these color styles
-       $.each([
-               'backgroundColor',
-               'borderBottomColor',
-               'borderLeftColor',
-               'borderRightColor',
-               'borderTopColor',
-               'color',
-               'outlineColor'
-       ], function ( i, attr ) {
-               $.fx.step[attr] = function ( fx ) {
-                       if ( !fx.colorInit ) {
-                               fx.start = getColor( fx.elem, attr );
-                               fx.end = $.colorUtil.getRGB( fx.end );
-                               fx.colorInit = true;
-                       }
-
-                       fx.elem.style[attr] = 'rgb(' + [
-                               Math.max( Math.min( parseInt( (fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10 ), 255 ), 0 ),
-                               Math.max( Math.min( parseInt( (fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10 ), 255 ), 0 ),
-                               Math.max( Math.min( parseInt( (fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10 ), 255 ), 0 )
-                       ].join( ',' ) + ')';
-               };
-       } );
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.colorUtil.js b/resources/jquery/jquery.colorUtil.js
deleted file mode 100644 (file)
index 37bf176..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/**
- * jQuery Color Utilities
- * Written by Krinkle in 2011
- * Released under the MIT and GPL licenses.
- * Mostly based on other plugins and functions (linted and optimized a little).
- * Sources cited inline.
- */
-( function ( $ ) {
-       $.colorUtil = {
-
-               // Color Conversion function from highlightFade
-               // By Blair Mitchelmore
-               // http://jquery.offput.ca/highlightFade/
-               // Parse strings looking for color tuples [255,255,255]
-               getRGB: function ( color ) {
-                       /*jshint boss:true */
-                       var result;
-
-                       // Check if we're already dealing with an array of colors
-                       if ( color && $.isArray( color ) && color.length === 3 ) {
-                               return color;
-                       }
-
-                       // Look for rgb(num,num,num)
-                       if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) {
-                               return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
-                       }
-
-                       // Look for rgb(num%,num%,num%)
-                       if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) {
-                               return [parseFloat(result[1],10) * 2.55, parseFloat(result[2],10) * 2.55, parseFloat(result[3]) * 2.55];
-                       }
-
-                       // Look for #a0b1c2
-                       if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) {
-                               return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
-                       }
-
-                       // Look for #fff
-                       if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) {
-                               return [parseInt(result[1] + result[1],16), parseInt(result[2] + result[2],16), parseInt(result[3] + result[3],16)];
-                       }
-
-                       // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
-                       if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) {
-                               return $.colorUtil.colors.transparent;
-                       }
-
-                       // Otherwise, we're most likely dealing with a named color
-                       return $.colorUtil.colors[$.trim(color).toLowerCase()];
-               },
-
-               // Some named colors to work with
-               // From Interface by Stefan Petre
-               // http://interface.eyecon.ro/
-               colors: {
-                       aqua: [0,255,255],
-                       azure: [240,255,255],
-                       beige: [245,245,220],
-                       black: [0,0,0],
-                       blue: [0,0,255],
-                       brown: [165,42,42],
-                       cyan: [0,255,255],
-                       darkblue: [0,0,139],
-                       darkcyan: [0,139,139],
-                       darkgrey: [169,169,169],
-                       darkgreen: [0,100,0],
-                       darkkhaki: [189,183,107],
-                       darkmagenta: [139,0,139],
-                       darkolivegreen: [85,107,47],
-                       darkorange: [255,140,0],
-                       darkorchid: [153,50,204],
-                       darkred: [139,0,0],
-                       darksalmon: [233,150,122],
-                       darkviolet: [148,0,211],
-                       fuchsia: [255,0,255],
-                       gold: [255,215,0],
-                       green: [0,128,0],
-                       indigo: [75,0,130],
-                       khaki: [240,230,140],
-                       lightblue: [173,216,230],
-                       lightcyan: [224,255,255],
-                       lightgreen: [144,238,144],
-                       lightgrey: [211,211,211],
-                       lightpink: [255,182,193],
-                       lightyellow: [255,255,224],
-                       lime: [0,255,0],
-                       magenta: [255,0,255],
-                       maroon: [128,0,0],
-                       navy: [0,0,128],
-                       olive: [128,128,0],
-                       orange: [255,165,0],
-                       pink: [255,192,203],
-                       purple: [128,0,128],
-                       violet: [128,0,128],
-                       red: [255,0,0],
-                       silver: [192,192,192],
-                       white: [255,255,255],
-                       yellow: [255,255,0],
-                       transparent: [255,255,255]
-               },
-
-               /**
-                * http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
-                * Converts an RGB color value to HSL. Conversion formula
-                * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
-                * Assumes r, g, and b are contained in the set [0, 255] and
-                * returns h, s, and l in the set [0, 1].
-                *
-                * @param       Number  R               The red color value
-                * @param       Number  G               The green color value
-                * @param       Number  B               The blue color value
-                * @return      Array                   The HSL representation
-                */
-               rgbToHsl: function ( R, G, B ) {
-                       var d,
-                               r = R / 255,
-                               g = G / 255,
-                               b = B / 255,
-                               max = Math.max( r, g, b ), min = Math.min( r, g, b ),
-                               h,
-                               s,
-                               l = (max + min) / 2;
-
-                       if ( max === min ) {
-                               // achromatic
-                               h = s = 0;
-                       } else {
-                               d = max - min;
-                               s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
-                               switch ( max ) {
-                                       case r:
-                                               h = (g - b) / d + (g < b ? 6 : 0);
-                                               break;
-                                       case g:
-                                               h = (b - r) / d + 2;
-                                               break;
-                                       case b:
-                                               h = (r - g) / d + 4;
-                                               break;
-                               }
-                               h /= 6;
-                       }
-
-                       return [h, s, l];
-               },
-
-               /**
-                * http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
-                * Converts an HSL color value to RGB. Conversion formula
-                * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
-                * Assumes h, s, and l are contained in the set [0, 1] and
-                * returns r, g, and b in the set [0, 255].
-                *
-                * @param       Number  h               The hue
-                * @param       Number  s               The saturation
-                * @param       Number  l               The lightness
-                * @return      Array                   The RGB representation
-                */
-               hslToRgb: function ( h, s, l ) {
-                       var r, g, b, hue2rgb, q, p;
-
-                       if ( s === 0 ) {
-                               r = g = b = l; // achromatic
-                       } else {
-                               hue2rgb = function ( p, q, t ) {
-                                       if ( t < 0 ) {
-                                               t += 1;
-                                       }
-                                       if ( t > 1 ) {
-                                               t -= 1;
-                                       }
-                                       if ( t < 1 / 6 ) {
-                                               return p + (q - p) * 6 * t;
-                                       }
-                                       if ( t < 1 / 2 ) {
-                                               return q;
-                                       }
-                                       if ( t < 2 / 3 ) {
-                                               return p + (q - p) * (2 / 3 - t) * 6;
-                                       }
-                                       return p;
-                               };
-
-                               q = l < 0.5 ? l * (1 + s) : l + s - l * s;
-                               p = 2 * l - q;
-                               r = hue2rgb( p, q, h + 1 / 3 );
-                               g = hue2rgb( p, q, h );
-                               b = hue2rgb( p, q, h - 1 / 3 );
-                       }
-
-                       return [r * 255, g * 255, b * 255];
-               },
-
-               /**
-                * Get's a brighter or darker rgb() value string.
-                *
-                * @author Krinkle
-                *
-                * @example     getCSSColorMod( 'red', +0.1 )
-                * @example     getCSSColorMod( 'rgb(200,50,50)', -0.2 )
-                *
-                * @param       Mixed   currentColor current value in css
-                * @param       Number  mod wanted brightness modification between -1 and 1
-                * @return      String 'rgb(r,g,b)'
-                */
-               getColorBrightness: function ( currentColor, mod ) {
-                       var rgbArr = $.colorUtil.getRGB( currentColor ),
-                               hslArr = $.colorUtil.rgbToHsl(rgbArr[0], rgbArr[1], rgbArr[2] );
-                       rgbArr = $.colorUtil.hslToRgb(hslArr[0], hslArr[1], hslArr[2] + mod);
-
-                       return 'rgb(' +
-                               [parseInt( rgbArr[0], 10), parseInt( rgbArr[1], 10 ), parseInt( rgbArr[2], 10 )].join( ',' ) +
-                               ')';
-               }
-
-       };
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.cookie.js b/resources/jquery/jquery.cookie.js
deleted file mode 100644 (file)
index 6d5974a..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*!
- * jQuery Cookie Plugin
- * https://github.com/carhartl/jquery-cookie
- *
- * Copyright 2011, Klaus Hartl
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.opensource.org/licenses/GPL-2.0
- */
-(function($) {
-    $.cookie = function(key, value, options) {
-
-        // key and at least value given, set cookie...
-        if (arguments.length > 1 && (!/Object/.test(Object.prototype.toString.call(value)) || value === null || value === undefined)) {
-            options = $.extend({}, options);
-
-            if (value === null || value === undefined) {
-                options.expires = -1;
-            }
-
-            if (typeof options.expires === 'number') {
-                var days = options.expires, t = options.expires = new Date();
-                t.setDate(t.getDate() + days);
-            }
-
-            value = String(value);
-
-            return (document.cookie = [
-                encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value),
-                options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
-                options.path    ? '; path=' + options.path : '',
-                options.domain  ? '; domain=' + options.domain : '',
-                options.secure  ? '; secure' : ''
-            ].join(''));
-        }
-
-        // key and possibly options given, get cookie...
-        options = value || {};
-        var decode = options.raw ? function(s) { return s; } : decodeURIComponent;
-
-        var pairs = document.cookie.split('; ');
-        for (var i = 0, pair; pair = pairs[i] && pairs[i].split('='); i++) {
-            if (decode(pair[0]) === key) return decode(pair[1] || ''); // IE saves cookies with empty string as "c; ", e.g. without "=" as opposed to EOMB, thus pair[1] may be undefined
-        }
-        return null;
-    };
-})(jQuery);
diff --git a/resources/jquery/jquery.cycle.all.js b/resources/jquery/jquery.cycle.all.js
deleted file mode 100644 (file)
index d57fb72..0000000
+++ /dev/null
@@ -1,1529 +0,0 @@
-/*!
- * jQuery Cycle Plugin (with Transition Definitions)
- * Examples and documentation at: http://jquery.malsup.com/cycle/
- * Copyright (c) 2007-2010 M. Alsup
- * Version: 2.9999 (13-NOV-2011)
- * Dual licensed under the MIT and GPL licenses.
- * http://jquery.malsup.com/license.html
- * Requires: jQuery v1.3.2 or later
- */
-;(function($, undefined) {
-
-var ver = '2.9999';
-
-// if $.support is not defined (pre jQuery 1.3) add what I need
-if ($.support == undefined) {
-       $.support = {
-               opacity: !($.browser.msie)
-       };
-}
-
-function debug(s) {
-       $.fn.cycle.debug && log(s);
-}              
-function log() {
-       window.console && console.log && console.log('[cycle] ' + Array.prototype.join.call(arguments,' '));
-}
-$.expr[':'].paused = function(el) {
-       return el.cyclePause;
-}
-
-
-// the options arg can be...
-//   a number  - indicates an immediate transition should occur to the given slide index
-//   a string  - 'pause', 'resume', 'toggle', 'next', 'prev', 'stop', 'destroy' or the name of a transition effect (ie, 'fade', 'zoom', etc)
-//   an object - properties to control the slideshow
-//
-// the arg2 arg can be...
-//   the name of an fx (only used in conjunction with a numeric value for 'options')
-//   the value true (only used in first arg == 'resume') and indicates
-//      that the resume should occur immediately (not wait for next timeout)
-
-$.fn.cycle = function(options, arg2) {
-       var o = { s: this.selector, c: this.context };
-
-       // in 1.3+ we can fix mistakes with the ready state
-       if (this.length === 0 && options != 'stop') {
-               if (!$.isReady && o.s) {
-                       log('DOM not ready, queuing slideshow');
-                       $(function() {
-                               $(o.s,o.c).cycle(options,arg2);
-                       });
-                       return this;
-               }
-               // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
-               log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
-               return this;
-       }
-
-       // iterate the matched nodeset
-       return this.each(function() {
-               var opts = handleArguments(this, options, arg2);
-               if (opts === false)
-                       return;
-
-               opts.updateActivePagerLink = opts.updateActivePagerLink || $.fn.cycle.updateActivePagerLink;
-               
-               // stop existing slideshow for this container (if there is one)
-               if (this.cycleTimeout)
-                       clearTimeout(this.cycleTimeout);
-               this.cycleTimeout = this.cyclePause = 0;
-
-               var $cont = $(this);
-               var $slides = opts.slideExpr ? $(opts.slideExpr, this) : $cont.children();
-               var els = $slides.get();
-
-               var opts2 = buildOptions($cont, $slides, els, opts, o);
-               if (opts2 === false)
-                       return;
-
-               if (els.length < 2) {
-                       log('terminating; too few slides: ' + els.length);
-                       return;
-               }
-
-               var startTime = opts2.continuous ? 10 : getTimeout(els[opts2.currSlide], els[opts2.nextSlide], opts2, !opts2.backwards);
-
-               // if it's an auto slideshow, kick it off
-               if (startTime) {
-                       startTime += (opts2.delay || 0);
-                       if (startTime < 10)
-                               startTime = 10;
-                       debug('first timeout: ' + startTime);
-                       this.cycleTimeout = setTimeout(function(){go(els,opts2,0,!opts.backwards)}, startTime);
-               }
-       });
-};
-
-function triggerPause(cont, byHover, onPager) {
-       var opts = $(cont).data('cycle.opts');
-       var paused = !!cont.cyclePause;
-       if (paused && opts.paused)
-               opts.paused(cont, opts, byHover, onPager);
-       else if (!paused && opts.resumed)
-               opts.resumed(cont, opts, byHover, onPager);
-}
-
-// process the args that were passed to the plugin fn
-function handleArguments(cont, options, arg2) {
-       if (cont.cycleStop == undefined)
-               cont.cycleStop = 0;
-       if (options === undefined || options === null)
-               options = {};
-       if (options.constructor == String) {
-               switch(options) {
-               case 'destroy':
-               case 'stop':
-                       var opts = $(cont).data('cycle.opts');
-                       if (!opts)
-                               return false;
-                       cont.cycleStop++; // callbacks look for change
-                       if (cont.cycleTimeout)
-                               clearTimeout(cont.cycleTimeout);
-                       cont.cycleTimeout = 0;
-                       opts.elements && $(opts.elements).stop();
-                       $(cont).removeData('cycle.opts');
-                       if (options == 'destroy')
-                               destroy(opts);
-                       return false;
-               case 'toggle':
-                       cont.cyclePause = (cont.cyclePause === 1) ? 0 : 1;
-                       checkInstantResume(cont.cyclePause, arg2, cont);
-                       triggerPause(cont);
-                       return false;
-               case 'pause':
-                       cont.cyclePause = 1;
-                       triggerPause(cont);
-                       return false;
-               case 'resume':
-                       cont.cyclePause = 0;
-                       checkInstantResume(false, arg2, cont);
-                       triggerPause(cont);
-                       return false;
-               case 'prev':
-               case 'next':
-                       var opts = $(cont).data('cycle.opts');
-                       if (!opts) {
-                               log('options not found, "prev/next" ignored');
-                               return false;
-                       }
-                       $.fn.cycle[options](opts);
-                       return false;
-               default:
-                       options = { fx: options };
-               };
-               return options;
-       }
-       else if (options.constructor == Number) {
-               // go to the requested slide
-               var num = options;
-               options = $(cont).data('cycle.opts');
-               if (!options) {
-                       log('options not found, can not advance slide');
-                       return false;
-               }
-               if (num < 0 || num >= options.elements.length) {
-                       log('invalid slide index: ' + num);
-                       return false;
-               }
-               options.nextSlide = num;
-               if (cont.cycleTimeout) {
-                       clearTimeout(cont.cycleTimeout);
-                       cont.cycleTimeout = 0;
-               }
-               if (typeof arg2 == 'string')
-                       options.oneTimeFx = arg2;
-               go(options.elements, options, 1, num >= options.currSlide);
-               return false;
-       }
-       return options;
-       
-       function checkInstantResume(isPaused, arg2, cont) {
-               if (!isPaused && arg2 === true) { // resume now!
-                       var options = $(cont).data('cycle.opts');
-                       if (!options) {
-                               log('options not found, can not resume');
-                               return false;
-                       }
-                       if (cont.cycleTimeout) {
-                               clearTimeout(cont.cycleTimeout);
-                               cont.cycleTimeout = 0;
-                       }
-                       go(options.elements, options, 1, !options.backwards);
-               }
-       }
-};
-
-function removeFilter(el, opts) {
-       if (!$.support.opacity && opts.cleartype && el.style.filter) {
-               try { el.style.removeAttribute('filter'); }
-               catch(smother) {} // handle old opera versions
-       }
-};
-
-// unbind event handlers
-function destroy(opts) {
-       if (opts.next)
-               $(opts.next).unbind(opts.prevNextEvent);
-       if (opts.prev)
-               $(opts.prev).unbind(opts.prevNextEvent);
-       
-       if (opts.pager || opts.pagerAnchorBuilder)
-               $.each(opts.pagerAnchors || [], function() {
-                       this.unbind().remove();
-               });
-       opts.pagerAnchors = null;
-       if (opts.destroy) // callback
-               opts.destroy(opts);
-};
-
-// one-time initialization
-function buildOptions($cont, $slides, els, options, o) {
-       var startingSlideSpecified;
-       // support metadata plugin (v1.0 and v2.0)
-       var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});
-       var meta = $.isFunction($cont.data) ? $cont.data(opts.metaAttr) : null;
-       if (meta)
-               opts = $.extend(opts, meta);
-       if (opts.autostop)
-               opts.countdown = opts.autostopCount || els.length;
-
-       var cont = $cont[0];
-       $cont.data('cycle.opts', opts);
-       opts.$cont = $cont;
-       opts.stopCount = cont.cycleStop;
-       opts.elements = els;
-       opts.before = opts.before ? [opts.before] : [];
-       opts.after = opts.after ? [opts.after] : [];
-
-       // push some after callbacks
-       if (!$.support.opacity && opts.cleartype)
-               opts.after.push(function() { removeFilter(this, opts); });
-       if (opts.continuous)
-               opts.after.push(function() { go(els,opts,0,!opts.backwards); });
-
-       saveOriginalOpts(opts);
-
-       // clearType corrections
-       if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
-               clearTypeFix($slides);
-
-       // container requires non-static position so that slides can be position within
-       if ($cont.css('position') == 'static')
-               $cont.css('position', 'relative');
-       if (opts.width)
-               $cont.width(opts.width);
-       if (opts.height && opts.height != 'auto')
-               $cont.height(opts.height);
-
-       if (opts.startingSlide != undefined) {
-               opts.startingSlide = parseInt(opts.startingSlide,10);
-               if (opts.startingSlide >= els.length || opts.startSlide < 0)
-                       opts.startingSlide = 0; // catch bogus input
-               else 
-                       startingSlideSpecified = true;
-       }
-       else if (opts.backwards)
-               opts.startingSlide = els.length - 1;
-       else
-               opts.startingSlide = 0;
-
-       // if random, mix up the slide array
-       if (opts.random) {
-               opts.randomMap = [];
-               for (var i = 0; i < els.length; i++)
-                       opts.randomMap.push(i);
-               opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
-               if (startingSlideSpecified) {
-                       // try to find the specified starting slide and if found set start slide index in the map accordingly
-                       for ( var cnt = 0; cnt < els.length; cnt++ ) {
-                               if ( opts.startingSlide == opts.randomMap[cnt] ) {
-                                       opts.randomIndex = cnt;
-                               }
-                       }
-               }
-               else {
-                       opts.randomIndex = 1;
-                       opts.startingSlide = opts.randomMap[1];
-               }
-       }
-       else if (opts.startingSlide >= els.length)
-               opts.startingSlide = 0; // catch bogus input
-       opts.currSlide = opts.startingSlide || 0;
-       var first = opts.startingSlide;
-
-       // set position and zIndex on all the slides
-       $slides.css({position: 'absolute', top:0, left:0}).hide().each(function(i) {
-               var z;
-               if (opts.backwards)
-                       z = first ? i <= first ? els.length + (i-first) : first-i : els.length-i;
-               else
-                       z = first ? i >= first ? els.length - (i-first) : first-i : els.length-i;
-               $(this).css('z-index', z)
-       });
-
-       // make sure first slide is visible
-       $(els[first]).css('opacity',1).show(); // opacity bit needed to handle restart use case
-       removeFilter(els[first], opts);
-
-       // stretch slides
-       if (opts.fit) {
-               if (!opts.aspect) {
-               if (opts.width)
-                   $slides.width(opts.width);
-               if (opts.height && opts.height != 'auto')
-                   $slides.height(opts.height);
-               } else {
-                       $slides.each(function(){
-                               var $slide = $(this);
-                               var ratio = (opts.aspect === true) ? $slide.width()/$slide.height() : opts.aspect;
-                               if( opts.width && $slide.width() != opts.width ) {
-                                       $slide.width( opts.width );
-                                       $slide.height( opts.width / ratio );
-                               }
-
-                               if( opts.height && $slide.height() < opts.height ) {
-                                       $slide.height( opts.height );
-                                       $slide.width( opts.height * ratio );
-                               }
-                       });
-               }
-       }
-
-       if (opts.center && ((!opts.fit) || opts.aspect)) {
-               $slides.each(function(){
-                       var $slide = $(this);
-                       $slide.css({
-                               "margin-left": opts.width ?
-                                       ((opts.width - $slide.width()) / 2) + "px" :
-                                       0,
-                               "margin-top": opts.height ?
-                                       ((opts.height - $slide.height()) / 2) + "px" :
-                                       0
-                       });
-               });
-       }
-
-       if (opts.center && !opts.fit && !opts.slideResize) {
-               $slides.each(function(){
-               var $slide = $(this);
-               $slide.css({
-                       "margin-left": opts.width ? ((opts.width - $slide.width()) / 2) + "px" : 0,
-                       "margin-top": opts.height ? ((opts.height - $slide.height()) / 2) + "px" : 0
-               });
-               });
-       }
-               
-       // stretch container
-       var reshape = opts.containerResize && !$cont.innerHeight();
-       if (reshape) { // do this only if container has no size http://tinyurl.com/da2oa9
-               var maxw = 0, maxh = 0;
-               for(var j=0; j < els.length; j++) {
-                       var $e = $(els[j]), e = $e[0], w = $e.outerWidth(), h = $e.outerHeight();
-                       if (!w) w = e.offsetWidth || e.width || $e.attr('width');
-                       if (!h) h = e.offsetHeight || e.height || $e.attr('height');
-                       maxw = w > maxw ? w : maxw;
-                       maxh = h > maxh ? h : maxh;
-               }
-               if (maxw > 0 && maxh > 0)
-                       $cont.css({width:maxw+'px',height:maxh+'px'});
-       }
-
-       var pauseFlag = false;  // https://github.com/malsup/cycle/issues/44
-       if (opts.pause)
-               $cont.hover(
-                       function(){
-                               pauseFlag = true;
-                               this.cyclePause++;
-                               triggerPause(cont, true);
-                       },
-                       function(){
-                               pauseFlag && this.cyclePause--;
-                               triggerPause(cont, true);
-                       }
-               );
-
-       if (supportMultiTransitions(opts) === false)
-               return false;
-
-       // apparently a lot of people use image slideshows without height/width attributes on the images.
-       // Cycle 2.50+ requires the sizing info for every slide; this block tries to deal with that.
-       var requeue = false;
-       options.requeueAttempts = options.requeueAttempts || 0;
-       $slides.each(function() {
-               // try to get height/width of each slide
-               var $el = $(this);
-               this.cycleH = (opts.fit && opts.height) ? opts.height : ($el.height() || this.offsetHeight || this.height || $el.attr('height') || 0);
-               this.cycleW = (opts.fit && opts.width) ? opts.width : ($el.width() || this.offsetWidth || this.width || $el.attr('width') || 0);
-
-               if ( $el.is('img') ) {
-                       // sigh..  sniffing, hacking, shrugging...  this crappy hack tries to account for what browsers do when
-                       // an image is being downloaded and the markup did not include sizing info (height/width attributes);
-                       // there seems to be some "default" sizes used in this situation
-                       var loadingIE   = ($.browser.msie  && this.cycleW == 28 && this.cycleH == 30 && !this.complete);
-                       var loadingFF   = ($.browser.mozilla && this.cycleW == 34 && this.cycleH == 19 && !this.complete);
-                       var loadingOp   = ($.browser.opera && ((this.cycleW == 42 && this.cycleH == 19) || (this.cycleW == 37 && this.cycleH == 17)) && !this.complete);
-                       var loadingOther = (this.cycleH == 0 && this.cycleW == 0 && !this.complete);
-                       // don't requeue for images that are still loading but have a valid size
-                       if (loadingIE || loadingFF || loadingOp || loadingOther) {
-                               if (o.s && opts.requeueOnImageNotLoaded && ++options.requeueAttempts < 100) { // track retry count so we don't loop forever
-                                       log(options.requeueAttempts,' - img slide not loaded, requeuing slideshow: ', this.src, this.cycleW, this.cycleH);
-                                       setTimeout(function() {$(o.s,o.c).cycle(options)}, opts.requeueTimeout);
-                                       requeue = true;
-                                       return false; // break each loop
-                               }
-                               else {
-                                       log('could not determine size of image: '+this.src, this.cycleW, this.cycleH);
-                               }
-                       }
-               }
-               return true;
-       });
-
-       if (requeue)
-               return false;
-
-       opts.cssBefore = opts.cssBefore || {};
-       opts.cssAfter = opts.cssAfter || {};
-       opts.cssFirst = opts.cssFirst || {};
-       opts.animIn = opts.animIn || {};
-       opts.animOut = opts.animOut || {};
-
-       $slides.not(':eq('+first+')').css(opts.cssBefore);
-       $($slides[first]).css(opts.cssFirst);
-
-       if (opts.timeout) {
-               opts.timeout = parseInt(opts.timeout,10);
-               // ensure that timeout and speed settings are sane
-               if (opts.speed.constructor == String)
-                       opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed,10);
-               if (!opts.sync)
-                       opts.speed = opts.speed / 2;
-               
-               var buffer = opts.fx == 'none' ? 0 : opts.fx == 'shuffle' ? 500 : 250;
-               while((opts.timeout - opts.speed) < buffer) // sanitize timeout
-                       opts.timeout += opts.speed;
-       }
-       if (opts.easing)
-               opts.easeIn = opts.easeOut = opts.easing;
-       if (!opts.speedIn)
-               opts.speedIn = opts.speed;
-       if (!opts.speedOut)
-               opts.speedOut = opts.speed;
-
-       opts.slideCount = els.length;
-       opts.currSlide = opts.lastSlide = first;
-       if (opts.random) {
-               if (++opts.randomIndex == els.length)
-                       opts.randomIndex = 0;
-               opts.nextSlide = opts.randomMap[opts.randomIndex];
-       }
-       else if (opts.backwards)
-               opts.nextSlide = opts.startingSlide == 0 ? (els.length-1) : opts.startingSlide-1;
-       else
-               opts.nextSlide = opts.startingSlide >= (els.length-1) ? 0 : opts.startingSlide+1;
-
-       // run transition init fn
-       if (!opts.multiFx) {
-               var init = $.fn.cycle.transitions[opts.fx];
-               if ($.isFunction(init))
-                       init($cont, $slides, opts);
-               else if (opts.fx != 'custom' && !opts.multiFx) {
-                       log('unknown transition: ' + opts.fx,'; slideshow terminating');
-                       return false;
-               }
-       }
-
-       // fire artificial events
-       var e0 = $slides[first];
-       if (!opts.skipInitializationCallbacks) {
-               if (opts.before.length)
-                       opts.before[0].apply(e0, [e0, e0, opts, true]);
-               if (opts.after.length)
-                       opts.after[0].apply(e0, [e0, e0, opts, true]);
-       }
-       if (opts.next)
-               $(opts.next).bind(opts.prevNextEvent,function(){return advance(opts,1)});
-       if (opts.prev)
-               $(opts.prev).bind(opts.prevNextEvent,function(){return advance(opts,0)});
-       if (opts.pager || opts.pagerAnchorBuilder)
-               buildPager(els,opts);
-
-       exposeAddSlide(opts, els);
-
-       return opts;
-};
-
-// save off original opts so we can restore after clearing state
-function saveOriginalOpts(opts) {
-       opts.original = { before: [], after: [] };
-       opts.original.cssBefore = $.extend({}, opts.cssBefore);
-       opts.original.cssAfter  = $.extend({}, opts.cssAfter);
-       opts.original.animIn    = $.extend({}, opts.animIn);
-       opts.original.animOut   = $.extend({}, opts.animOut);
-       $.each(opts.before, function() { opts.original.before.push(this); });
-       $.each(opts.after,  function() { opts.original.after.push(this); });
-};
-
-function supportMultiTransitions(opts) {
-       var i, tx, txs = $.fn.cycle.transitions;
-       // look for multiple effects
-       if (opts.fx.indexOf(',') > 0) {
-               opts.multiFx = true;
-               opts.fxs = opts.fx.replace(/\s*/g,'').split(',');
-               // discard any bogus effect names
-               for (i=0; i < opts.fxs.length; i++) {
-                       var fx = opts.fxs[i];
-                       tx = txs[fx];
-                       if (!tx || !txs.hasOwnProperty(fx) || !$.isFunction(tx)) {
-                               log('discarding unknown transition: ',fx);
-                               opts.fxs.splice(i,1);
-                               i--;
-                       }
-               }
-               // if we have an empty list then we threw everything away!
-               if (!opts.fxs.length) {
-                       log('No valid transitions named; slideshow terminating.');
-                       return false;
-               }
-       }
-       else if (opts.fx == 'all') {  // auto-gen the list of transitions
-               opts.multiFx = true;
-               opts.fxs = [];
-               for (p in txs) {
-                       tx = txs[p];
-                       if (txs.hasOwnProperty(p) && $.isFunction(tx))
-                               opts.fxs.push(p);
-               }
-       }
-       if (opts.multiFx && opts.randomizeEffects) {
-               // munge the fxs array to make effect selection random
-               var r1 = Math.floor(Math.random() * 20) + 30;
-               for (i = 0; i < r1; i++) {
-                       var r2 = Math.floor(Math.random() * opts.fxs.length);
-                       opts.fxs.push(opts.fxs.splice(r2,1)[0]);
-               }
-               debug('randomized fx sequence: ',opts.fxs);
-       }
-       return true;
-};
-
-// provide a mechanism for adding slides after the slideshow has started
-function exposeAddSlide(opts, els) {
-       opts.addSlide = function(newSlide, prepend) {
-               var $s = $(newSlide), s = $s[0];
-               if (!opts.autostopCount)
-                       opts.countdown++;
-               els[prepend?'unshift':'push'](s);
-               if (opts.els)
-                       opts.els[prepend?'unshift':'push'](s); // shuffle needs this
-               opts.slideCount = els.length;
-
-               // add the slide to the random map and resort
-               if (opts.random) {
-                       opts.randomMap.push(opts.slideCount-1);
-                       opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
-               }
-
-               $s.css('position','absolute');
-               $s[prepend?'prependTo':'appendTo'](opts.$cont);
-
-               if (prepend) {
-                       opts.currSlide++;
-                       opts.nextSlide++;
-               }
-
-               if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
-                       clearTypeFix($s);
-
-               if (opts.fit && opts.width)
-                       $s.width(opts.width);
-               if (opts.fit && opts.height && opts.height != 'auto')
-                       $s.height(opts.height);
-               s.cycleH = (opts.fit && opts.height) ? opts.height : $s.height();
-               s.cycleW = (opts.fit && opts.width) ? opts.width : $s.width();
-
-               $s.css(opts.cssBefore);
-
-               if (opts.pager || opts.pagerAnchorBuilder)
-                       $.fn.cycle.createPagerAnchor(els.length-1, s, $(opts.pager), els, opts);
-
-               if ($.isFunction(opts.onAddSlide))
-                       opts.onAddSlide($s);
-               else
-                       $s.hide(); // default behavior
-       };
-}
-
-// reset internal state; we do this on every pass in order to support multiple effects
-$.fn.cycle.resetState = function(opts, fx) {
-       fx = fx || opts.fx;
-       opts.before = []; opts.after = [];
-       opts.cssBefore = $.extend({}, opts.original.cssBefore);
-       opts.cssAfter  = $.extend({}, opts.original.cssAfter);
-       opts.animIn     = $.extend({}, opts.original.animIn);
-       opts.animOut   = $.extend({}, opts.original.animOut);
-       opts.fxFn = null;
-       $.each(opts.original.before, function() { opts.before.push(this); });
-       $.each(opts.original.after,  function() { opts.after.push(this); });
-
-       // re-init
-       var init = $.fn.cycle.transitions[fx];
-       if ($.isFunction(init))
-               init(opts.$cont, $(opts.elements), opts);
-};
-
-// this is the main engine fn, it handles the timeouts, callbacks and slide index mgmt
-function go(els, opts, manual, fwd) {
-       // opts.busy is true if we're in the middle of an animation
-       if (manual && opts.busy && opts.manualTrump) {
-               // let manual transitions requests trump active ones
-               debug('manualTrump in go(), stopping active transition');
-               $(els).stop(true,true);
-               opts.busy = 0;
-       }
-       // don't begin another timeout-based transition if there is one active
-       if (opts.busy) {
-               debug('transition active, ignoring new tx request');
-               return;
-       }
-
-       var p = opts.$cont[0], curr = els[opts.currSlide], next = els[opts.nextSlide];
-
-       // stop cycling if we have an outstanding stop request
-       if (p.cycleStop != opts.stopCount || p.cycleTimeout === 0 && !manual)
-               return;
-
-       // check to see if we should stop cycling based on autostop options
-       if (!manual && !p.cyclePause && !opts.bounce &&
-               ((opts.autostop && (--opts.countdown <= 0)) ||
-               (opts.nowrap && !opts.random && opts.nextSlide < opts.currSlide))) {
-               if (opts.end)
-                       opts.end(opts);
-               return;
-       }
-
-       // if slideshow is paused, only transition on a manual trigger
-       var changed = false;
-       if ((manual || !p.cyclePause) && (opts.nextSlide != opts.currSlide)) {
-               changed = true;
-               var fx = opts.fx;
-               // keep trying to get the slide size if we don't have it yet
-               curr.cycleH = curr.cycleH || $(curr).height();
-               curr.cycleW = curr.cycleW || $(curr).width();
-               next.cycleH = next.cycleH || $(next).height();
-               next.cycleW = next.cycleW || $(next).width();
-
-               // support multiple transition types
-               if (opts.multiFx) {
-                       if (fwd && (opts.lastFx == undefined || ++opts.lastFx >= opts.fxs.length))
-                               opts.lastFx = 0;
-                       else if (!fwd && (opts.lastFx == undefined || --opts.lastFx < 0))
-                               opts.lastFx = opts.fxs.length - 1;
-                       fx = opts.fxs[opts.lastFx];
-               }
-
-               // one-time fx overrides apply to:  $('div').cycle(3,'zoom');
-               if (opts.oneTimeFx) {
-                       fx = opts.oneTimeFx;
-                       opts.oneTimeFx = null;
-               }
-
-               $.fn.cycle.resetState(opts, fx);
-
-               // run the before callbacks
-               if (opts.before.length)
-                       $.each(opts.before, function(i,o) {
-                               if (p.cycleStop != opts.stopCount) return;
-                               o.apply(next, [curr, next, opts, fwd]);
-                       });
-
-               // stage the after callacks
-               var after = function() {
-                       opts.busy = 0;
-                       $.each(opts.after, function(i,o) {
-                               if (p.cycleStop != opts.stopCount) return;
-                               o.apply(next, [curr, next, opts, fwd]);
-                       });
-                       if (!p.cycleStop) {
-                               // queue next transition
-                               queueNext();
-                       }
-               };
-
-               debug('tx firing('+fx+'); currSlide: ' + opts.currSlide + '; nextSlide: ' + opts.nextSlide);
-               
-               // get ready to perform the transition
-               opts.busy = 1;
-               if (opts.fxFn) // fx function provided?
-                       opts.fxFn(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
-               else if ($.isFunction($.fn.cycle[opts.fx])) // fx plugin ?
-                       $.fn.cycle[opts.fx](curr, next, opts, after, fwd, manual && opts.fastOnEvent);
-               else
-                       $.fn.cycle.custom(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
-       }
-       else {
-               queueNext();
-       }
-
-       if (changed || opts.nextSlide == opts.currSlide) {
-               // calculate the next slide
-               opts.lastSlide = opts.currSlide;
-               if (opts.random) {
-                       opts.currSlide = opts.nextSlide;
-                       if (++opts.randomIndex == els.length) {
-                               opts.randomIndex = 0;
-                               opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
-                       }
-                       opts.nextSlide = opts.randomMap[opts.randomIndex];
-                       if (opts.nextSlide == opts.currSlide)
-                               opts.nextSlide = (opts.currSlide == opts.slideCount - 1) ? 0 : opts.currSlide + 1;
-               }
-               else if (opts.backwards) {
-                       var roll = (opts.nextSlide - 1) < 0;
-                       if (roll && opts.bounce) {
-                               opts.backwards = !opts.backwards;
-                               opts.nextSlide = 1;
-                               opts.currSlide = 0;
-                       }
-                       else {
-                               opts.nextSlide = roll ? (els.length-1) : opts.nextSlide-1;
-                               opts.currSlide = roll ? 0 : opts.nextSlide+1;
-                       }
-               }
-               else { // sequence
-                       var roll = (opts.nextSlide + 1) == els.length;
-                       if (roll && opts.bounce) {
-                               opts.backwards = !opts.backwards;
-                               opts.nextSlide = els.length-2;
-                               opts.currSlide = els.length-1;
-                       }
-                       else {
-                               opts.nextSlide = roll ? 0 : opts.nextSlide+1;
-                               opts.currSlide = roll ? els.length-1 : opts.nextSlide-1;
-                       }
-               }
-       }
-       if (changed && opts.pager)
-               opts.updateActivePagerLink(opts.pager, opts.currSlide, opts.activePagerClass);
-       
-       function queueNext() {
-               // stage the next transition
-               var ms = 0, timeout = opts.timeout;
-               if (opts.timeout && !opts.continuous) {
-                       ms = getTimeout(els[opts.currSlide], els[opts.nextSlide], opts, fwd);
-         if (opts.fx == 'shuffle')
-            ms -= opts.speedOut;
-      }
-               else if (opts.continuous && p.cyclePause) // continuous shows work off an after callback, not this timer logic
-                       ms = 10;
-               if (ms > 0)
-                       p.cycleTimeout = setTimeout(function(){ go(els, opts, 0, !opts.backwards) }, ms);
-       }
-};
-
-// invoked after transition
-$.fn.cycle.updateActivePagerLink = function(pager, currSlide, clsName) {
-   $(pager).each(function() {
-       $(this).children().removeClass(clsName).eq(currSlide).addClass(clsName);
-   });
-};
-
-// calculate timeout value for current transition
-function getTimeout(curr, next, opts, fwd) {
-       if (opts.timeoutFn) {
-               // call user provided calc fn
-               var t = opts.timeoutFn.call(curr,curr,next,opts,fwd);
-               while (opts.fx != 'none' && (t - opts.speed) < 250) // sanitize timeout
-                       t += opts.speed;
-               debug('calculated timeout: ' + t + '; speed: ' + opts.speed);
-               if (t !== false)
-                       return t;
-       }
-       return opts.timeout;
-};
-
-// expose next/prev function, caller must pass in state
-$.fn.cycle.next = function(opts) { advance(opts,1); };
-$.fn.cycle.prev = function(opts) { advance(opts,0);};
-
-// advance slide forward or back
-function advance(opts, moveForward) {
-       var val = moveForward ? 1 : -1;
-       var els = opts.elements;
-       var p = opts.$cont[0], timeout = p.cycleTimeout;
-       if (timeout) {
-               clearTimeout(timeout);
-               p.cycleTimeout = 0;
-       }
-       if (opts.random && val < 0) {
-               // move back to the previously display slide
-               opts.randomIndex--;
-               if (--opts.randomIndex == -2)
-                       opts.randomIndex = els.length-2;
-               else if (opts.randomIndex == -1)
-                       opts.randomIndex = els.length-1;
-               opts.nextSlide = opts.randomMap[opts.randomIndex];
-       }
-       else if (opts.random) {
-               opts.nextSlide = opts.randomMap[opts.randomIndex];
-       }
-       else {
-               opts.nextSlide = opts.currSlide + val;
-               if (opts.nextSlide < 0) {
-                       if (opts.nowrap) return false;
-                       opts.nextSlide = els.length - 1;
-               }
-               else if (opts.nextSlide >= els.length) {
-                       if (opts.nowrap) return false;
-                       opts.nextSlide = 0;
-               }
-       }
-
-       var cb = opts.onPrevNextEvent || opts.prevNextClick; // prevNextClick is deprecated
-       if ($.isFunction(cb))
-               cb(val > 0, opts.nextSlide, els[opts.nextSlide]);
-       go(els, opts, 1, moveForward);
-       return false;
-};
-
-function buildPager(els, opts) {
-       var $p = $(opts.pager);
-       $.each(els, function(i,o) {
-               $.fn.cycle.createPagerAnchor(i,o,$p,els,opts);
-       });
-       opts.updateActivePagerLink(opts.pager, opts.startingSlide, opts.activePagerClass);
-};
-
-$.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
-       var a;
-       if ($.isFunction(opts.pagerAnchorBuilder)) {
-               a = opts.pagerAnchorBuilder(i,el);
-               debug('pagerAnchorBuilder('+i+', el) returned: ' + a);
-       }
-       else
-               a = '<a href="#">'+(i+1)+'</a>';
-               
-       if (!a)
-               return;
-       var $a = $(a);
-       // don't reparent if anchor is in the dom
-       if ($a.parents('body').length === 0) {
-               var arr = [];
-               if ($p.length > 1) {
-                       $p.each(function() {
-                               var $clone = $a.clone(true);
-                               $(this).append($clone);
-                               arr.push($clone[0]);
-                       });
-                       $a = $(arr);
-               }
-               else {
-                       $a.appendTo($p);
-               }
-       }
-
-       opts.pagerAnchors =  opts.pagerAnchors || [];
-       opts.pagerAnchors.push($a);
-       
-       var pagerFn = function(e) {
-               e.preventDefault();
-               opts.nextSlide = i;
-               var p = opts.$cont[0], timeout = p.cycleTimeout;
-               if (timeout) {
-                       clearTimeout(timeout);
-                       p.cycleTimeout = 0;
-               }
-               var cb = opts.onPagerEvent || opts.pagerClick; // pagerClick is deprecated
-               if ($.isFunction(cb))
-                       cb(opts.nextSlide, els[opts.nextSlide]);
-               go(els,opts,1,opts.currSlide < i); // trigger the trans
-//             return false; // <== allow bubble
-       }
-       
-       if ( /mouseenter|mouseover/i.test(opts.pagerEvent) ) {
-               $a.hover(pagerFn, function(){/* no-op */} );
-       }
-       else {
-               $a.bind(opts.pagerEvent, pagerFn);
-       }
-       
-       if ( ! /^click/.test(opts.pagerEvent) && !opts.allowPagerClickBubble)
-               $a.bind('click.cycle', function(){return false;}); // suppress click
-       
-       var cont = opts.$cont[0];
-       var pauseFlag = false; // https://github.com/malsup/cycle/issues/44
-       if (opts.pauseOnPagerHover) {
-               $a.hover(
-                       function() { 
-                               pauseFlag = true;
-                               cont.cyclePause++; 
-                               triggerPause(cont,true,true);
-                       }, function() { 
-                               pauseFlag && cont.cyclePause--; 
-                               triggerPause(cont,true,true);
-                       } 
-               );
-       }
-};
-
-// helper fn to calculate the number of slides between the current and the next
-$.fn.cycle.hopsFromLast = function(opts, fwd) {
-       var hops, l = opts.lastSlide, c = opts.currSlide;
-       if (fwd)
-               hops = c > l ? c - l : opts.slideCount - l;
-       else
-               hops = c < l ? l - c : l + opts.slideCount - c;
-       return hops;
-};
-
-// fix clearType problems in ie6 by setting an explicit bg color
-// (otherwise text slides look horrible during a fade transition)
-function clearTypeFix($slides) {
-       debug('applying clearType background-color hack');
-       function hex(s) {
-               s = parseInt(s,10).toString(16);
-               return s.length < 2 ? '0'+s : s;
-       };
-       function getBg(e) {
-               for ( ; e && e.nodeName.toLowerCase() != 'html'; e = e.parentNode) {
-                       var v = $.css(e,'background-color');
-                       if (v && v.indexOf('rgb') >= 0 ) {
-                               var rgb = v.match(/\d+/g);
-                               return '#'+ hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
-                       }
-                       if (v && v != 'transparent')
-                               return v;
-               }
-               return '#ffffff';
-       };
-       $slides.each(function() { $(this).css('background-color', getBg(this)); });
-};
-
-// reset common props before the next transition
-$.fn.cycle.commonReset = function(curr,next,opts,w,h,rev) {
-       $(opts.elements).not(curr).hide();
-       if (typeof opts.cssBefore.opacity == 'undefined')
-               opts.cssBefore.opacity = 1;
-       opts.cssBefore.display = 'block';
-       if (opts.slideResize && w !== false && next.cycleW > 0)
-               opts.cssBefore.width = next.cycleW;
-       if (opts.slideResize && h !== false && next.cycleH > 0)
-               opts.cssBefore.height = next.cycleH;
-       opts.cssAfter = opts.cssAfter || {};
-       opts.cssAfter.display = 'none';
-       $(curr).css('zIndex',opts.slideCount + (rev === true ? 1 : 0));
-       $(next).css('zIndex',opts.slideCount + (rev === true ? 0 : 1));
-};
-
-// the actual fn for effecting a transition
-$.fn.cycle.custom = function(curr, next, opts, cb, fwd, speedOverride) {
-       var $l = $(curr), $n = $(next);
-       var speedIn = opts.speedIn, speedOut = opts.speedOut, easeIn = opts.easeIn, easeOut = opts.easeOut;
-       $n.css(opts.cssBefore);
-       if (speedOverride) {
-               if (typeof speedOverride == 'number')
-                       speedIn = speedOut = speedOverride;
-               else
-                       speedIn = speedOut = 1;
-               easeIn = easeOut = null;
-       }
-       var fn = function() {
-               $n.animate(opts.animIn, speedIn, easeIn, function() {
-                       cb();
-               });
-       };
-       $l.animate(opts.animOut, speedOut, easeOut, function() {
-               $l.css(opts.cssAfter);
-               if (!opts.sync) 
-                       fn();
-       });
-       if (opts.sync) fn();
-};
-
-// transition definitions - only fade is defined here, transition pack defines the rest
-$.fn.cycle.transitions = {
-       fade: function($cont, $slides, opts) {
-               $slides.not(':eq('+opts.currSlide+')').css('opacity',0);
-               opts.before.push(function(curr,next,opts) {
-                       $.fn.cycle.commonReset(curr,next,opts);
-                       opts.cssBefore.opacity = 0;
-               });
-               opts.animIn        = { opacity: 1 };
-               opts.animOut   = { opacity: 0 };
-               opts.cssBefore = { top: 0, left: 0 };
-       }
-};
-
-$.fn.cycle.ver = function() { return ver; };
-
-// override these globally if you like (they are all optional)
-$.fn.cycle.defaults = {
-       activePagerClass: 'activeSlide', // class name used for the active pager link
-       after:             null,  // transition callback (scope set to element that was shown):  function(currSlideElement, nextSlideElement, options, forwardFlag)
-       allowPagerClickBubble: false, // allows or prevents click event on pager anchors from bubbling
-       animIn:            null,  // properties that define how the slide animates in
-       animOut:           null,  // properties that define how the slide animates out
-       aspect:            false,  // preserve aspect ratio during fit resizing, cropping if necessary (must be used with fit option)
-       autostop:          0,     // true to end slideshow after X transitions (where X == slide count)
-       autostopCount: 0,         // number of transitions (optionally used with autostop to define X)
-       backwards:     false, // true to start slideshow at last slide and move backwards through the stack
-       before:            null,  // transition callback (scope set to element to be shown):     function(currSlideElement, nextSlideElement, options, forwardFlag)
-       center:            null,  // set to true to have cycle add top/left margin to each slide (use with width and height options)
-       cleartype:         !$.support.opacity,  // true if clearType corrections should be applied (for IE)
-       cleartypeNoBg: false, // set to true to disable extra cleartype fixing (leave false to force background color setting on slides)
-       containerResize: 1,       // resize container to fit largest slide
-       continuous:        0,     // true to start next transition immediately after current one completes
-       cssAfter:          null,  // properties that defined the state of the slide after transitioning out
-       cssBefore:         null,  // properties that define the initial state of the slide before transitioning in
-       delay:             0,     // additional delay (in ms) for first transition (hint: can be negative)
-       easeIn:            null,  // easing for "in" transition
-       easeOut:           null,  // easing for "out" transition
-       easing:            null,  // easing method for both in and out transitions
-       end:               null,  // callback invoked when the slideshow terminates (use with autostop or nowrap options): function(options)
-       fastOnEvent:   0,         // force fast transitions when triggered manually (via pager or prev/next); value == time in ms
-       fit:               0,     // force slides to fit container
-       fx:                       'fade', // name of transition effect (or comma separated names, ex: 'fade,scrollUp,shuffle')
-       fxFn:              null,  // function used to control the transition: function(currSlideElement, nextSlideElement, options, afterCalback, forwardFlag)
-       height:           'auto', // container height (if the 'fit' option is true, the slides will be set to this height as well)
-       manualTrump:   true,  // causes manual transition to stop an active transition instead of being ignored
-       metaAttr:     'cycle',// data- attribute that holds the option data for the slideshow
-       next:              null,  // element, jQuery object, or jQuery selector string for the element to use as event trigger for next slide
-       nowrap:            0,     // true to prevent slideshow from wrapping
-       onPagerEvent:  null,  // callback fn for pager events: function(zeroBasedSlideIndex, slideElement)
-       onPrevNextEvent: null,// callback fn for prev/next events: function(isNext, zeroBasedSlideIndex, slideElement)
-       pager:             null,  // element, jQuery object, or jQuery selector string for the element to use as pager container
-       pagerAnchorBuilder: null, // callback fn for building anchor links:  function(index, DOMelement)
-       pagerEvent:       'click.cycle', // name of event which drives the pager navigation
-       pause:             0,     // true to enable "pause on hover"
-       pauseOnPagerHover: 0, // true to pause when hovering over pager link
-       prev:              null,  // element, jQuery object, or jQuery selector string for the element to use as event trigger for previous slide
-       prevNextEvent:'click.cycle',// event which drives the manual transition to the previous or next slide
-       random:            0,     // true for random, false for sequence (not applicable to shuffle fx)
-       randomizeEffects: 1,  // valid when multiple effects are used; true to make the effect sequence random
-       requeueOnImageNotLoaded: true, // requeue the slideshow if any image slides are not yet loaded
-       requeueTimeout: 250,  // ms delay for requeue
-       rev:               0,     // causes animations to transition in reverse (for effects that support it such as scrollHorz/scrollVert/shuffle)
-       shuffle:           null,  // coords for shuffle animation, ex: { top:15, left: 200 }
-       skipInitializationCallbacks: false, // set to true to disable the first before/after callback that occurs prior to any transition
-       slideExpr:         null,  // expression for selecting slides (if something other than all children is required)
-       slideResize:   1,     // force slide width/height to fixed size before every transition
-       speed:             1000,  // speed of the transition (any valid fx speed value)
-       speedIn:           null,  // speed of the 'in' transition
-       speedOut:          null,  // speed of the 'out' transition
-       startingSlide: undefined,         // zero-based index of the first slide to be displayed
-       sync:              1,     // true if in/out transitions should occur simultaneously
-       timeout:           4000,  // milliseconds between slide transitions (0 to disable auto advance)
-       timeoutFn:     null,  // callback for determining per-slide timeout value:  function(currSlideElement, nextSlideElement, options, forwardFlag)
-       updateActivePagerLink: null, // callback fn invoked to update the active pager link (adds/removes activePagerClass style)
-       width:         null   // container width (if the 'fit' option is true, the slides will be set to this width as well)
-};
-
-})(jQuery);
-
-
-/*!
- * jQuery Cycle Plugin Transition Definitions
- * This script is a plugin for the jQuery Cycle Plugin
- * Examples and documentation at: http://malsup.com/jquery/cycle/
- * Copyright (c) 2007-2010 M. Alsup
- * Version:     2.73
- * Dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- */
-(function($) {
-
-//
-// These functions define slide initialization and properties for the named
-// transitions. To save file size feel free to remove any of these that you
-// don't need.
-//
-$.fn.cycle.transitions.none = function($cont, $slides, opts) {
-       opts.fxFn = function(curr,next,opts,after){
-               $(next).show();
-               $(curr).hide();
-               after();
-       };
-};
-
-// not a cross-fade, fadeout only fades out the top slide
-$.fn.cycle.transitions.fadeout = function($cont, $slides, opts) {
-       $slides.not(':eq('+opts.currSlide+')').css({ display: 'block', 'opacity': 1 });
-       opts.before.push(function(curr,next,opts,w,h,rev) {
-               $(curr).css('zIndex',opts.slideCount + (!rev === true ? 1 : 0));
-               $(next).css('zIndex',opts.slideCount + (!rev === true ? 0 : 1));
-       });
-       opts.animIn.opacity = 1;
-       opts.animOut.opacity = 0;
-       opts.cssBefore.opacity = 1;
-       opts.cssBefore.display = 'block';
-       opts.cssAfter.zIndex = 0;
-};
-
-// scrollUp/Down/Left/Right
-$.fn.cycle.transitions.scrollUp = function($cont, $slides, opts) {
-       $cont.css('overflow','hidden');
-       opts.before.push($.fn.cycle.commonReset);
-       var h = $cont.height();
-       opts.cssBefore.top = h;
-       opts.cssBefore.left = 0;
-       opts.cssFirst.top = 0;
-       opts.animIn.top = 0;
-       opts.animOut.top = -h;
-};
-$.fn.cycle.transitions.scrollDown = function($cont, $slides, opts) {
-       $cont.css('overflow','hidden');
-       opts.before.push($.fn.cycle.commonReset);
-       var h = $cont.height();
-       opts.cssFirst.top = 0;
-       opts.cssBefore.top = -h;
-       opts.cssBefore.left = 0;
-       opts.animIn.top = 0;
-       opts.animOut.top = h;
-};
-$.fn.cycle.transitions.scrollLeft = function($cont, $slides, opts) {
-       $cont.css('overflow','hidden');
-       opts.before.push($.fn.cycle.commonReset);
-       var w = $cont.width();
-       opts.cssFirst.left = 0;
-       opts.cssBefore.left = w;
-       opts.cssBefore.top = 0;
-       opts.animIn.left = 0;
-       opts.animOut.left = 0-w;
-};
-$.fn.cycle.transitions.scrollRight = function($cont, $slides, opts) {
-       $cont.css('overflow','hidden');
-       opts.before.push($.fn.cycle.commonReset);
-       var w = $cont.width();
-       opts.cssFirst.left = 0;
-       opts.cssBefore.left = -w;
-       opts.cssBefore.top = 0;
-       opts.animIn.left = 0;
-       opts.animOut.left = w;
-};
-$.fn.cycle.transitions.scrollHorz = function($cont, $slides, opts) {
-       $cont.css('overflow','hidden').width();
-       opts.before.push(function(curr, next, opts, fwd) {
-               if (opts.rev)
-                       fwd = !fwd;
-               $.fn.cycle.commonReset(curr,next,opts);
-               opts.cssBefore.left = fwd ? (next.cycleW-1) : (1-next.cycleW);
-               opts.animOut.left = fwd ? -curr.cycleW : curr.cycleW;
-       });
-       opts.cssFirst.left = 0;
-       opts.cssBefore.top = 0;
-       opts.animIn.left = 0;
-       opts.animOut.top = 0;
-};
-$.fn.cycle.transitions.scrollVert = function($cont, $slides, opts) {
-       $cont.css('overflow','hidden');
-       opts.before.push(function(curr, next, opts, fwd) {
-               if (opts.rev)
-                       fwd = !fwd;
-               $.fn.cycle.commonReset(curr,next,opts);
-               opts.cssBefore.top = fwd ? (1-next.cycleH) : (next.cycleH-1);
-               opts.animOut.top = fwd ? curr.cycleH : -curr.cycleH;
-       });
-       opts.cssFirst.top = 0;
-       opts.cssBefore.left = 0;
-       opts.animIn.top = 0;
-       opts.animOut.left = 0;
-};
-
-// slideX/slideY
-$.fn.cycle.transitions.slideX = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $(opts.elements).not(curr).hide();
-               $.fn.cycle.commonReset(curr,next,opts,false,true);
-               opts.animIn.width = next.cycleW;
-       });
-       opts.cssBefore.left = 0;
-       opts.cssBefore.top = 0;
-       opts.cssBefore.width = 0;
-       opts.animIn.width = 'show';
-       opts.animOut.width = 0;
-};
-$.fn.cycle.transitions.slideY = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $(opts.elements).not(curr).hide();
-               $.fn.cycle.commonReset(curr,next,opts,true,false);
-               opts.animIn.height = next.cycleH;
-       });
-       opts.cssBefore.left = 0;
-       opts.cssBefore.top = 0;
-       opts.cssBefore.height = 0;
-       opts.animIn.height = 'show';
-       opts.animOut.height = 0;
-};
-
-// shuffle
-$.fn.cycle.transitions.shuffle = function($cont, $slides, opts) {
-       var i, w = $cont.css('overflow', 'visible').width();
-       $slides.css({left: 0, top: 0});
-       opts.before.push(function(curr,next,opts) {
-               $.fn.cycle.commonReset(curr,next,opts,true,true,true);
-       });
-       // only adjust speed once!
-       if (!opts.speedAdjusted) {
-               opts.speed = opts.speed / 2; // shuffle has 2 transitions
-               opts.speedAdjusted = true;
-       }
-       opts.random = 0;
-       opts.shuffle = opts.shuffle || {left:-w, top:15};
-       opts.els = [];
-       for (i=0; i < $slides.length; i++)
-               opts.els.push($slides[i]);
-
-       for (i=0; i < opts.currSlide; i++)
-               opts.els.push(opts.els.shift());
-
-       // custom transition fn (hat tip to Benjamin Sterling for this bit of sweetness!)
-       opts.fxFn = function(curr, next, opts, cb, fwd) {
-               if (opts.rev)
-                       fwd = !fwd;
-               var $el = fwd ? $(curr) : $(next);
-               $(next).css(opts.cssBefore);
-               var count = opts.slideCount;
-               $el.animate(opts.shuffle, opts.speedIn, opts.easeIn, function() {
-                       var hops = $.fn.cycle.hopsFromLast(opts, fwd);
-                       for (var k=0; k < hops; k++)
-                               fwd ? opts.els.push(opts.els.shift()) : opts.els.unshift(opts.els.pop());
-                       if (fwd) {
-                               for (var i=0, len=opts.els.length; i < len; i++)
-                                       $(opts.els[i]).css('z-index', len-i+count);
-                       }
-                       else {
-                               var z = $(curr).css('z-index');
-                               $el.css('z-index', parseInt(z,10)+1+count);
-                       }
-                       $el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() {
-                               $(fwd ? this : curr).hide();
-                               if (cb) cb();
-                       });
-               });
-       };
-       $.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
-};
-
-// turnUp/Down/Left/Right
-$.fn.cycle.transitions.turnUp = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,true,false);
-               opts.cssBefore.top = next.cycleH;
-               opts.animIn.height = next.cycleH;
-               opts.animOut.width = next.cycleW;
-       });
-       opts.cssFirst.top = 0;
-       opts.cssBefore.left = 0;
-       opts.cssBefore.height = 0;
-       opts.animIn.top = 0;
-       opts.animOut.height = 0;
-};
-$.fn.cycle.transitions.turnDown = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,true,false);
-               opts.animIn.height = next.cycleH;
-               opts.animOut.top   = curr.cycleH;
-       });
-       opts.cssFirst.top = 0;
-       opts.cssBefore.left = 0;
-       opts.cssBefore.top = 0;
-       opts.cssBefore.height = 0;
-       opts.animOut.height = 0;
-};
-$.fn.cycle.transitions.turnLeft = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,false,true);
-               opts.cssBefore.left = next.cycleW;
-               opts.animIn.width = next.cycleW;
-       });
-       opts.cssBefore.top = 0;
-       opts.cssBefore.width = 0;
-       opts.animIn.left = 0;
-       opts.animOut.width = 0;
-};
-$.fn.cycle.transitions.turnRight = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,false,true);
-               opts.animIn.width = next.cycleW;
-               opts.animOut.left = curr.cycleW;
-       });
-       $.extend(opts.cssBefore, { top: 0, left: 0, width: 0 });
-       opts.animIn.left = 0;
-       opts.animOut.width = 0;
-};
-
-// zoom
-$.fn.cycle.transitions.zoom = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,false,false,true);
-               opts.cssBefore.top = next.cycleH/2;
-               opts.cssBefore.left = next.cycleW/2;
-               $.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
-               $.extend(opts.animOut, { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 });
-       });
-       opts.cssFirst.top = 0;
-       opts.cssFirst.left = 0;
-       opts.cssBefore.width = 0;
-       opts.cssBefore.height = 0;
-};
-
-// fadeZoom
-$.fn.cycle.transitions.fadeZoom = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,false,false);
-               opts.cssBefore.left = next.cycleW/2;
-               opts.cssBefore.top = next.cycleH/2;
-               $.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
-       });
-       opts.cssBefore.width = 0;
-       opts.cssBefore.height = 0;
-       opts.animOut.opacity = 0;
-};
-
-// blindX
-$.fn.cycle.transitions.blindX = function($cont, $slides, opts) {
-       var w = $cont.css('overflow','hidden').width();
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts);
-               opts.animIn.width = next.cycleW;
-               opts.animOut.left   = curr.cycleW;
-       });
-       opts.cssBefore.left = w;
-       opts.cssBefore.top = 0;
-       opts.animIn.left = 0;
-       opts.animOut.left = w;
-};
-// blindY
-$.fn.cycle.transitions.blindY = function($cont, $slides, opts) {
-       var h = $cont.css('overflow','hidden').height();
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts);
-               opts.animIn.height = next.cycleH;
-               opts.animOut.top   = curr.cycleH;
-       });
-       opts.cssBefore.top = h;
-       opts.cssBefore.left = 0;
-       opts.animIn.top = 0;
-       opts.animOut.top = h;
-};
-// blindZ
-$.fn.cycle.transitions.blindZ = function($cont, $slides, opts) {
-       var h = $cont.css('overflow','hidden').height();
-       var w = $cont.width();
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts);
-               opts.animIn.height = next.cycleH;
-               opts.animOut.top   = curr.cycleH;
-       });
-       opts.cssBefore.top = h;
-       opts.cssBefore.left = w;
-       opts.animIn.top = 0;
-       opts.animIn.left = 0;
-       opts.animOut.top = h;
-       opts.animOut.left = w;
-};
-
-// growX - grow horizontally from centered 0 width
-$.fn.cycle.transitions.growX = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,false,true);
-               opts.cssBefore.left = this.cycleW/2;
-               opts.animIn.left = 0;
-               opts.animIn.width = this.cycleW;
-               opts.animOut.left = 0;
-       });
-       opts.cssBefore.top = 0;
-       opts.cssBefore.width = 0;
-};
-// growY - grow vertically from centered 0 height
-$.fn.cycle.transitions.growY = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,true,false);
-               opts.cssBefore.top = this.cycleH/2;
-               opts.animIn.top = 0;
-               opts.animIn.height = this.cycleH;
-               opts.animOut.top = 0;
-       });
-       opts.cssBefore.height = 0;
-       opts.cssBefore.left = 0;
-};
-
-// curtainX - squeeze in both edges horizontally
-$.fn.cycle.transitions.curtainX = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,false,true,true);
-               opts.cssBefore.left = next.cycleW/2;
-               opts.animIn.left = 0;
-               opts.animIn.width = this.cycleW;
-               opts.animOut.left = curr.cycleW/2;
-               opts.animOut.width = 0;
-       });
-       opts.cssBefore.top = 0;
-       opts.cssBefore.width = 0;
-};
-// curtainY - squeeze in both edges vertically
-$.fn.cycle.transitions.curtainY = function($cont, $slides, opts) {
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,true,false,true);
-               opts.cssBefore.top = next.cycleH/2;
-               opts.animIn.top = 0;
-               opts.animIn.height = next.cycleH;
-               opts.animOut.top = curr.cycleH/2;
-               opts.animOut.height = 0;
-       });
-       opts.cssBefore.height = 0;
-       opts.cssBefore.left = 0;
-};
-
-// cover - curr slide covered by next slide
-$.fn.cycle.transitions.cover = function($cont, $slides, opts) {
-       var d = opts.direction || 'left';
-       var w = $cont.css('overflow','hidden').width();
-       var h = $cont.height();
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts);
-               if (d == 'right')
-                       opts.cssBefore.left = -w;
-               else if (d == 'up')
-                       opts.cssBefore.top = h;
-               else if (d == 'down')
-                       opts.cssBefore.top = -h;
-               else
-                       opts.cssBefore.left = w;
-       });
-       opts.animIn.left = 0;
-       opts.animIn.top = 0;
-       opts.cssBefore.top = 0;
-       opts.cssBefore.left = 0;
-};
-
-// uncover - curr slide moves off next slide
-$.fn.cycle.transitions.uncover = function($cont, $slides, opts) {
-       var d = opts.direction || 'left';
-       var w = $cont.css('overflow','hidden').width();
-       var h = $cont.height();
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,true,true,true);
-               if (d == 'right')
-                       opts.animOut.left = w;
-               else if (d == 'up')
-                       opts.animOut.top = -h;
-               else if (d == 'down')
-                       opts.animOut.top = h;
-               else
-                       opts.animOut.left = -w;
-       });
-       opts.animIn.left = 0;
-       opts.animIn.top = 0;
-       opts.cssBefore.top = 0;
-       opts.cssBefore.left = 0;
-};
-
-// toss - move top slide and fade away
-$.fn.cycle.transitions.toss = function($cont, $slides, opts) {
-       var w = $cont.css('overflow','visible').width();
-       var h = $cont.height();
-       opts.before.push(function(curr, next, opts) {
-               $.fn.cycle.commonReset(curr,next,opts,true,true,true);
-               // provide default toss settings if animOut not provided
-               if (!opts.animOut.left && !opts.animOut.top)
-                       $.extend(opts.animOut, { left: w*2, top: -h/2, opacity: 0 });
-               else
-                       opts.animOut.opacity = 0;
-       });
-       opts.cssBefore.left = 0;
-       opts.cssBefore.top = 0;
-       opts.animIn.left = 0;
-};
-
-// wipe - clip animation
-$.fn.cycle.transitions.wipe = function($cont, $slides, opts) {
-       var w = $cont.css('overflow','hidden').width();
-       var h = $cont.height();
-       opts.cssBefore = opts.cssBefore || {};
-       var clip;
-       if (opts.clip) {
-               if (/l2r/.test(opts.clip))
-                       clip = 'rect(0px 0px '+h+'px 0px)';
-               else if (/r2l/.test(opts.clip))
-                       clip = 'rect(0px '+w+'px '+h+'px '+w+'px)';
-               else if (/t2b/.test(opts.clip))
-                       clip = 'rect(0px '+w+'px 0px 0px)';
-               else if (/b2t/.test(opts.clip))
-                       clip = 'rect('+h+'px '+w+'px '+h+'px 0px)';
-               else if (/zoom/.test(opts.clip)) {
-                       var top = parseInt(h/2,10);
-                       var left = parseInt(w/2,10);
-                       clip = 'rect('+top+'px '+left+'px '+top+'px '+left+'px)';
-               }
-       }
-
-       opts.cssBefore.clip = opts.cssBefore.clip || clip || 'rect(0px 0px 0px 0px)';
-
-       var d = opts.cssBefore.clip.match(/(\d+)/g);
-       var t = parseInt(d[0],10), r = parseInt(d[1],10), b = parseInt(d[2],10), l = parseInt(d[3],10);
-
-       opts.before.push(function(curr, next, opts) {
-               if (curr == next) return;
-               var $curr = $(curr), $next = $(next);
-               $.fn.cycle.commonReset(curr,next,opts,true,true,false);
-               opts.cssAfter.display = 'block';
-
-               var step = 1, count = parseInt((opts.speedIn / 13),10) - 1;
-               (function f() {
-                       var tt = t ? t - parseInt(step * (t/count),10) : 0;
-                       var ll = l ? l - parseInt(step * (l/count),10) : 0;
-                       var bb = b < h ? b + parseInt(step * ((h-b)/count || 1),10) : h;
-                       var rr = r < w ? r + parseInt(step * ((w-r)/count || 1),10) : w;
-                       $next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' });
-                       (step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none');
-               })();
-       });
-       $.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
-       opts.animIn        = { left: 0 };
-       opts.animOut   = { left: 0 };
-};
-
-})(jQuery);
diff --git a/resources/jquery/jquery.delayedBind.js b/resources/jquery/jquery.delayedBind.js
deleted file mode 100644 (file)
index 874c111..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-( function ( mw, $ ) {
-/**
- * Function that escapes spaces in event names. This is needed because
- * "_delayedBind-foo bar-1000" refers to two events
- */
-function encodeEvent( event ) {
-       return event.replace( /-/g, '--' ).replace( / /g, '-' );
-}
-
-$.fn.extend( {
-       /**
-        * Bind a callback to an event in a delayed fashion.
-        * In detail, this means that the callback will be called a certain
-        * time after the event fires, but the timer is reset every time
-        * the event fires.
-        * @param timeout Number of milliseconds to wait
-        * @param event Name of the event (string)
-        * @param data Data to pass to the event handler (optional)
-        * @param callback Function to call
-        */
-       delayedBind: function ( timeout, event, data, callback ) {
-               if ( arguments.length === 3 ) {
-                       // Shift optional parameter down
-                       callback = data;
-                       data = undefined;
-               }
-               var encEvent = encodeEvent( event );
-               return this.each( function () {
-                       var that = this;
-                       // Bind the top half
-                       // Do this only once for every (event, timeout) pair
-                       if (  !( $(this).data( '_delayedBindBound-' + encEvent + '-' + timeout ) ) ) {
-                               $(this).data( '_delayedBindBound-' + encEvent + '-' + timeout, true );
-                               $(this).bind( event, function () {
-                                       var timerID = $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout );
-                                       // Cancel the running timer
-                                       if ( timerID !== null ) {
-                                               clearTimeout( timerID );
-                                       }
-                                       timerID = setTimeout( function () {
-                                               $(that).trigger( '_delayedBind-' + encEvent + '-' + timeout );
-                                       }, timeout );
-                                       $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout, timerID );
-                               } );
-                       }
-
-                       // Bottom half
-                       $(this).bind( '_delayedBind-' + encEvent + '-' + timeout, data, callback );
-               } );
-       },
-
-       /**
-        * Cancel the timers for delayed events on the selected elements.
-        */
-       delayedBindCancel: function ( timeout, event ) {
-               var encEvent = encodeEvent( event );
-               return this.each( function () {
-                       var timerID = $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout );
-                       if ( timerID !== null ) {
-                               clearTimeout( timerID );
-                       }
-               } );
-       },
-
-       /**
-        * Unbind an event bound with delayedBind()
-        */
-       delayedBindUnbind: function ( timeout, event, callback ) {
-               var encEvent = encodeEvent( event );
-               return this.each( function () {
-                       $(this).unbind( '_delayedBind-' + encEvent + '-' + timeout, callback );
-               } );
-       }
-} );
-
-mw.log.deprecate( $.fn, 'delayedBind', $.fn.delayedBind,
-       'Use the jquery.throttle-debounce module instead' );
-mw.log.deprecate( $.fn, 'delayedBindCancel', $.fn.delayedBindCancel,
-       'Use the jquery.throttle-debounce module instead' );
-mw.log.deprecate( $.fn, 'delayedBindUnbind', $.fn.delayedBindUnbind,
-       'Use the jquery.throttle-debounce module instead' );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/jquery/jquery.expandableField.js b/resources/jquery/jquery.expandableField.js
deleted file mode 100644 (file)
index 732cc6e..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- * This plugin provides functionality to expand a text box on focus to double it's current width
- *
- * Usage:
- *
- * Set options:
- *             $('#textbox').expandableField( { option1: value1, option2: value2 } );
- *             $('#textbox').expandableField( option, value );
- * Get option:
- *             value = $('#textbox').expandableField( option );
- * Initialize:
- *             $('#textbox').expandableField();
- *
- * Options:
- *
- */
-( function ( $ ) {
-
-       $.expandableField = {
-               /**
-                * Expand the field, make the callback
-                */
-               expandField: function ( e, context ) {
-                       context.config.beforeExpand.call( context.data.$field, context );
-                       context.data.$field
-                               .animate( { 'width': context.data.expandedWidth }, 'fast', function () {
-                                       context.config.afterExpand.call( this, context );
-                               } );
-               },
-               /**
-                * Condense the field, make the callback
-                */
-               condenseField: function ( e, context ) {
-                       context.config.beforeCondense.call( context.data.$field, context );
-                       context.data.$field
-                               .animate( { 'width': context.data.condensedWidth }, 'fast', function () {
-                                       context.config.afterCondense.call( this, context );
-                               } );
-               },
-               /**
-                * Sets the value of a property, and updates the widget accordingly
-                * @param property String Name of property
-                * @param value Mixed Value to set property with
-                */
-               configure: function ( context, property, value ) {
-                       // TODO: Validate creation using fallback values
-                       context.config[property] = value;
-               }
-
-       };
-
-       $.fn.expandableField = function () {
-
-               // Multi-context fields
-               var returnValue,
-                       args = arguments;
-
-               $( this ).each( function () {
-                       var key, context, timeout;
-
-                       /* Construction / Loading */
-
-                       context = $( this ).data( 'expandableField-context' );
-
-                       // TODO: Do we need to check both null and undefined?
-                       if ( context === undefined || context === null ) {
-                               context = {
-                                       config: {
-                                               // callback function for before collapse
-                                               beforeCondense: function () {},
-
-                                               // callback function for before expand
-                                               beforeExpand: function () {},
-
-                                               // callback function for after collapse
-                                               afterCondense: function () {},
-
-                                               // callback function for after expand
-                                               afterExpand: function () {},
-
-                                               // Whether the field should expand to the left or the right -- defaults to left
-                                               expandToLeft: true
-                                       }
-                               };
-                       }
-
-                       /* API */
-                       // Handle various calling styles
-                       if ( args.length > 0 ) {
-                               if ( typeof args[0] === 'object' ) {
-                                       // Apply set of properties
-                                       for ( key in args[0] ) {
-                                               $.expandableField.configure( context, key, args[0][key] );
-                                       }
-                               } else if ( typeof args[0] === 'string' ) {
-                                       if ( args.length > 1 ) {
-                                               // Set property values
-                                               $.expandableField.configure( context, args[0], args[1] );
-
-                                       // TODO: Do we need to check both null and undefined?
-                                       } else if ( returnValue === null || returnValue === undefined ) {
-                                               // Get property values, but don't give access to internal data - returns only the first
-                                               returnValue = ( args[0] in context.config ? undefined : context.config[args[0]] );
-                                       }
-                               }
-                       }
-
-                       /* Initialization */
-
-                       if ( context.data === undefined ) {
-                               context.data = {
-                                       // The width of the field in it's condensed state
-                                       condensedWidth: $( this ).width(),
-
-                                       // The width of the field in it's expanded state
-                                       expandedWidth: $( this ).width() * 2,
-
-                                       // Reference to the field
-                                       $field: $( this )
-                               };
-
-                               $( this )
-                                       .addClass( 'expandableField' )
-                                       .focus( function ( e ) {
-                                               clearTimeout( timeout );
-                                               $.expandableField.expandField( e, context );
-                                       } )
-                                       .blur( function ( e ) {
-                                               timeout = setTimeout( function () {
-                                                       $.expandableField.condenseField( e, context );
-                                               }, 250 );
-                                       } );
-                       }
-                       // Store the context for next time
-                       $( this ).data( 'expandableField-context', context );
-               } );
-               return returnValue !== undefined ? returnValue : $(this);
-       };
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.farbtastic.css b/resources/jquery/jquery.farbtastic.css
deleted file mode 100644 (file)
index 1c6428f..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Farbtastic Color Picker 1.2
- * © 2008 Steven Wittens
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-.farbtastic {
-       position: relative;
-}
-.farbtastic * {
-       position: absolute;
-       cursor: crosshair;
-}
-.farbtastic, .farbtastic .wheel {
-       width: 195px;
-       height: 195px;
-}
-.farbtastic .color, .farbtastic .overlay {
-       top: 47px;
-       left: 47px;
-       width: 101px;
-       height: 101px;
-}
-.farbtastic .wheel {
-       /* @embed */
-       background: url(images/wheel.png) no-repeat;
-       width: 195px;
-       height: 195px;
-}
-.farbtastic .overlay {
-       /* @embed */
-       background: url(images/mask.png) no-repeat;
-}
-.farbtastic .marker {
-       width: 17px;
-       height: 17px;
-       margin: -8px 0 0 -8px;
-       overflow: hidden;
-       /* @embed */
-       background: url(images/marker.png) no-repeat;
-}
-
diff --git a/resources/jquery/jquery.farbtastic.js b/resources/jquery/jquery.farbtastic.js
deleted file mode 100644 (file)
index 1881085..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-/**
- * Farbtastic Color Picker 1.2
- * © 2008 Steven Wittens
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-//Adapted to uniform style with jQuery UI widgets and slightly change behavior
-//TODO:
-// - remove duplicated code by replacing it with jquery.colorUtils and modern jQuery
-// - uniform code style
-
-jQuery.fn.farbtastic = function (callback) {
-       $.farbtastic(this, callback);
-       return this;
-};
-
-jQuery.farbtastic = function (container, callback) {
-       var container = $(container).get(0);
-       return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback));
-}
-
-jQuery._farbtastic = function (container, callback) {
-       // Store farbtastic object
-       var fb = this;
-
-       // Insert markup
-       $(container).html('<div class="farbtastic ui-widget-content"><div class="color"></div><div class="wheel"></div><div class="overlay"></div><div class="h-marker marker"></div><div class="sl-marker marker"></div></div>');
-       $(container).addClass('ui-widget');
-       var e = $('.farbtastic', container);
-       fb.wheel = $('.wheel', container).get(0);
-       // Dimensions
-       fb.radius = 84;
-       fb.square = 100;
-       fb.width = 194;
-
-       // Fix background PNGs in IE6
-       if (navigator.appVersion.match(/MSIE [0-6]\./)) {
-               $('*', e).each(function () {
-                       if (this.currentStyle.backgroundImage != 'none') {
-                               var image = this.currentStyle.backgroundImage;
-                               image = this.currentStyle.backgroundImage.substring(5, image.length - 2);
-                               $(this).css({
-                                       'backgroundImage': 'none',
-                                       'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
-                               });
-                       }
-               });
-       }
-
-       /**
-        * Link to the given element(s) or callback.
-        */
-       fb.linkTo = function (callback) {
-               // Unbind previous nodes
-               if (typeof fb.callback == 'object') {
-                       $(fb.callback).unbind('keyup', fb.updateValue);
-               }
-
-               // Reset color
-               fb.color = null;
-
-               // Bind callback or elements
-               if (typeof callback == 'function') {
-                       fb.callback = callback;
-               }
-               else if (typeof callback == 'object' || typeof callback == 'string') {
-                       fb.callback = $(callback);
-                       fb.callback.bind('keyup', fb.updateValue);
-                       if (fb.callback.get(0).value) {
-                               fb.setColor(fb.callback.get(0).value);
-                       }
-               }
-               return this;
-       }
-       fb.updateValue = function (event) {
-               if (this.value != fb.color) {
-                       fb.setColor(this.value);
-               }
-       }
-
-       /**
-        * Change color with HTML syntax #123456
-        */
-       fb.setColor = function (color) {
-               var rgb = $.colorUtil.getRGB( color );
-               if (fb.color != color && rgb) {
-                       rgb = rgb.slice( 0 ); //make a clone
-                       //TODO: rewrite code so that this is not needed
-                       rgb[0] /= 255;
-                       rgb[1] /= 255;
-                       rgb[2] /= 255;
-                       fb.color = color;
-                       fb.rgb = rgb;
-                       fb.hsl = fb.RGBToHSL(fb.rgb);
-                       fb.updateDisplay();
-               }
-               return this;
-       }
-
-       /**
-        * Change color with HSL triplet [0..1, 0..1, 0..1]
-        */
-       fb.setHSL = function (hsl) {
-               fb.hsl = hsl;
-               fb.rgb = fb.HSLToRGB(hsl);
-               fb.color = fb.pack(fb.rgb);
-               fb.updateDisplay();
-               return this;
-       }
-
-       /////////////////////////////////////////////////////
-
-       /**
-        * Retrieve the coordinates of the given event relative to the center
-        * of the widget.
-        */
-       fb.widgetCoords = function (event) {
-               var ref = $( fb.wheel ).offset();
-               return {
-                       x: event.pageX - ref.left - fb.width / 2,
-                       y: event.pageY - ref.top - fb.width / 2
-               };
-       }
-
-       /**
-        * Mousedown handler
-        */
-       fb.mousedown = function (event) {
-               // Capture mouse
-               if (!document.dragging) {
-                       $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup);
-                       document.dragging = true;
-               }
-
-               // Check which area is being dragged
-               var pos = fb.widgetCoords(event);
-               fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square;
-
-               // Process
-               fb.mousemove(event);
-               return false;
-       }
-
-       /**
-        * Mousemove handler
-        */
-       fb.mousemove = function (event) {
-               // Get coordinates relative to color picker center
-               var pos = fb.widgetCoords(event);
-
-               // Set new HSL parameters
-               if (fb.circleDrag) {
-                       var hue = Math.atan2(pos.x, -pos.y) / 6.28;
-                       if (hue < 0) hue += 1;
-                       fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]);
-               }
-               else {
-                       var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5));
-                       var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5));
-                       fb.setHSL([fb.hsl[0], sat, lum]);
-               }
-               return false;
-       }
-
-       /**
-        * Mouseup handler
-        */
-       fb.mouseup = function () {
-               // Uncapture mouse
-               $(document).unbind('mousemove', fb.mousemove);
-               $(document).unbind('mouseup', fb.mouseup);
-               document.dragging = false;
-       }
-
-       /**
-        * Update the markers and styles
-        */
-       fb.updateDisplay = function () {
-               // Markers
-               var angle = fb.hsl[0] * 6.28;
-               $('.h-marker', e).css({
-                       left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px',
-                       top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px'
-               });
-
-               $('.sl-marker', e).css({
-                       left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px',
-                       top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px'
-               });
-
-               // Saturation/Luminance gradient
-               $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5])));
-
-               // Linked elements or callback
-               if (typeof fb.callback == 'object') {
-                       // Set background/foreground color
-                       $(fb.callback).css({
-                               backgroundColor: fb.color,
-                               color: fb.hsl[2] > 0.5 ? '#000' : '#fff'
-                       });
-
-                       // Change linked value
-                       $(fb.callback).each(function() {
-                               if ( $( this ).val() != fb.color) {
-                                       $( this ).val( fb.color ).change();
-                               }
-                       });
-               }
-               else if (typeof fb.callback == 'function') {
-                       fb.callback.call(fb, fb.color);
-               }
-       }
-
-       /* Various color utility functions */
-       fb.pack = function (rgb) {
-               var r = Math.round(rgb[0] * 255);
-               var g = Math.round(rgb[1] * 255);
-               var b = Math.round(rgb[2] * 255);
-               return '#' + (r < 16 ? '0' : '') + r.toString(16) +
-                                        (g < 16 ? '0' : '') + g.toString(16) +
-                                        (b < 16 ? '0' : '') + b.toString(16);
-       }
-
-       fb.HSLToRGB = function (hsl) {
-               var m1, m2, r, g, b;
-               var h = hsl[0], s = hsl[1], l = hsl[2];
-               m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s;
-               m1 = l * 2 - m2;
-               return [this.hueToRGB(m1, m2, h+0.33333),
-                               this.hueToRGB(m1, m2, h),
-                               this.hueToRGB(m1, m2, h-0.33333)];
-       }
-
-       fb.hueToRGB = function (m1, m2, h) {
-               h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
-               if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
-               if (h * 2 < 1) return m2;
-               if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
-               return m1;
-       }
-
-       fb.RGBToHSL = function (rgb) {
-               var min, max, delta, h, s, l;
-               var r = rgb[0], g = rgb[1], b = rgb[2];
-               min = Math.min(r, Math.min(g, b));
-               max = Math.max(r, Math.max(g, b));
-               delta = max - min;
-               l = (min + max) / 2;
-               s = 0;
-               if (l > 0 && l < 1) {
-                       s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
-               }
-               h = 0;
-               if (delta > 0) {
-                       if (max == r && max != g) h += (g - b) / delta;
-                       if (max == g && max != b) h += (2 + (b - r) / delta);
-                       if (max == b && max != r) h += (4 + (r - g) / delta);
-                       h /= 6;
-               }
-               return [h, s, l];
-       }
-
-       // Install mousedown handler (the others are set on the document on-demand)
-       $('*', e).mousedown(fb.mousedown);
-
-               // Init color
-       fb.setColor('#000000');
-
-       // Set linked elements/callback
-       if (callback) {
-               fb.linkTo(callback);
-       }
-}
diff --git a/resources/jquery/jquery.footHovzer.css b/resources/jquery/jquery.footHovzer.css
deleted file mode 100644 (file)
index 77d9514..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#jquery-foot-hovzer {
-       position: fixed;
-       bottom: 0;
-       width: 100%;
-       z-index: 1000;
-}
diff --git a/resources/jquery/jquery.footHovzer.js b/resources/jquery/jquery.footHovzer.js
deleted file mode 100644 (file)
index 56fc32d..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Utility to stack stuff in an overlay fixed on the bottom of the page.
- *
- * Usage:
- * <code>
- *     var hovzer = $.getFootHovzer();
- *     hovzer.$.append( $myCollection );
- *     hovzer.update();
- * </code>
- *
- * @author Timo Tijhof, 2012
- */
-( function ( $ ) {
-       var $hovzer, footHovzer, prevHeight, newHeight;
-
-       function getHovzer() {
-               if ( $hovzer === undefined ) {
-                       $hovzer = $( '<div id="jquery-foot-hovzer"></div>' ).appendTo( 'body' );
-               }
-               return $hovzer;
-       }
-
-       footHovzer = {
-               update: function () {
-                       var $body;
-
-                       $body = $( 'body' );
-                       if ( prevHeight === undefined ) {
-                               prevHeight = getHovzer().outerHeight( /*includeMargin=*/true );
-                               $body.css( 'paddingBottom', '+=' + prevHeight + 'px' );
-                       } else {
-                               newHeight = getHovzer().outerHeight( true );
-                               $body.css( 'paddingBottom', ( parseFloat( $body.css( 'paddingBottom' ) ) - prevHeight ) + newHeight );
-
-                               prevHeight = newHeight;
-                       }
-               }
-       };
-
-       $.getFootHovzer = function () {
-               footHovzer.$ = getHovzer();
-               return footHovzer;
-       };
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.form.js b/resources/jquery/jquery.form.js
deleted file mode 100644 (file)
index 13e9a55..0000000
+++ /dev/null
@@ -1,1089 +0,0 @@
-/*!
- * jQuery Form Plugin
- * version: 3.14 (30-JUL-2012)
- * @requires jQuery v1.3.2 or later
- *
- * Examples and documentation at: http://malsup.com/jquery/form/
- * Project repository: https://github.com/malsup/form
- * Dual licensed under the MIT and GPL licenses:
- *    http://malsup.github.com/mit-license.txt
- *    http://malsup.github.com/gpl-license-v2.txt
- */
-/*global ActiveXObject alert */
-;(function($) {
-"use strict";
-
-/*
-    Usage Note:
-    -----------
-    Do not use both ajaxSubmit and ajaxForm on the same form.  These
-    functions are mutually exclusive.  Use ajaxSubmit if you want
-    to bind your own submit handler to the form.  For example,
-
-    $(document).ready(function() {
-        $('#myForm').on('submit', function(e) {
-            e.preventDefault(); // <-- important
-            $(this).ajaxSubmit({
-                target: '#output'
-            });
-        });
-    });
-
-    Use ajaxForm when you want the plugin to manage all the event binding
-    for you.  For example,
-
-    $(document).ready(function() {
-        $('#myForm').ajaxForm({
-            target: '#output'
-        });
-    });
-    
-    You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
-    form does not have to exist when you invoke ajaxForm:
-
-    $('#myForm').ajaxForm({
-        delegation: true,
-        target: '#output'
-    });
-    
-    When using ajaxForm, the ajaxSubmit function will be invoked for you
-    at the appropriate time.
-*/
-
-/**
- * Feature detection
- */
-var feature = {};
-feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
-feature.formdata = window.FormData !== undefined;
-
-/**
- * ajaxSubmit() provides a mechanism for immediately submitting
- * an HTML form using AJAX.
- */
-$.fn.ajaxSubmit = function(options) {
-    /*jshint scripturl:true */
-
-    // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
-    if (!this.length) {
-        log('ajaxSubmit: skipping submit process - no element selected');
-        return this;
-    }
-    
-    var method, action, url, $form = this;
-
-    if (typeof options == 'function') {
-        options = { success: options };
-    }
-
-    method = this.attr('method');
-    action = this.attr('action');
-    url = (typeof action === 'string') ? $.trim(action) : '';
-    url = url || window.location.href || '';
-    if (url) {
-        // clean url (don't include hash vaue)
-        url = (url.match(/^([^#]+)/)||[])[1];
-    }
-
-    options = $.extend(true, {
-        url:  url,
-        success: $.ajaxSettings.success,
-        type: method || 'GET',
-        iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
-    }, options);
-
-    // hook for manipulating the form data before it is extracted;
-    // convenient for use with rich editors like tinyMCE or FCKEditor
-    var veto = {};
-    this.trigger('form-pre-serialize', [this, options, veto]);
-    if (veto.veto) {
-        log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
-        return this;
-    }
-
-    // provide opportunity to alter form data before it is serialized
-    if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
-        log('ajaxSubmit: submit aborted via beforeSerialize callback');
-        return this;
-    }
-
-    var traditional = options.traditional;
-    if ( traditional === undefined ) {
-        traditional = $.ajaxSettings.traditional;
-    }
-    
-    var elements = [];
-    var qx, a = this.formToArray(options.semantic, elements);
-    if (options.data) {
-        options.extraData = options.data;
-        qx = $.param(options.data, traditional);
-    }
-
-    // give pre-submit callback an opportunity to abort the submit
-    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
-        log('ajaxSubmit: submit aborted via beforeSubmit callback');
-        return this;
-    }
-
-    // fire vetoable 'validate' event
-    this.trigger('form-submit-validate', [a, this, options, veto]);
-    if (veto.veto) {
-        log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
-        return this;
-    }
-
-    var q = $.param(a, traditional);
-    if (qx) {
-        q = ( q ? (q + '&' + qx) : qx );
-    }    
-    if (options.type.toUpperCase() == 'GET') {
-        options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
-        options.data = null;  // data is null for 'get'
-    }
-    else {
-        options.data = q; // data is the query string for 'post'
-    }
-
-    var callbacks = [];
-    if (options.resetForm) {
-        callbacks.push(function() { $form.resetForm(); });
-    }
-    if (options.clearForm) {
-        callbacks.push(function() { $form.clearForm(options.includeHidden); });
-    }
-
-    // perform a load on the target only if dataType is not provided
-    if (!options.dataType && options.target) {
-        var oldSuccess = options.success || function(){};
-        callbacks.push(function(data) {
-            var fn = options.replaceTarget ? 'replaceWith' : 'html';
-            $(options.target)[fn](data).each(oldSuccess, arguments);
-        });
-    }
-    else if (options.success) {
-        callbacks.push(options.success);
-    }
-
-    options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
-        var context = options.context || this ;    // jQuery 1.4+ supports scope context 
-        for (var i=0, max=callbacks.length; i < max; i++) {
-            callbacks[i].apply(context, [data, status, xhr || $form, $form]);
-        }
-    };
-
-    // are there files to upload?
-    var fileInputs = $('input:file:enabled[value]', this); // [value] (issue #113)
-    var hasFileInputs = fileInputs.length > 0;
-    var mp = 'multipart/form-data';
-    var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
-
-    var fileAPI = feature.fileapi && feature.formdata;
-    log("fileAPI :" + fileAPI);
-    var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
-
-    // options.iframe allows user to force iframe mode
-    // 06-NOV-09: now defaulting to iframe mode if file input is detected
-    if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
-        // hack to fix Safari hang (thanks to Tim Molendijk for this)
-        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
-        if (options.closeKeepAlive) {
-            $.get(options.closeKeepAlive, function() {
-                fileUploadIframe(a);
-            });
-        }
-          else {
-            fileUploadIframe(a);
-          }
-    }
-    else if ((hasFileInputs || multipart) && fileAPI) {
-        fileUploadXhr(a);
-    }
-    else {
-        $.ajax(options);
-    }
-
-    // clear element array
-    for (var k=0; k < elements.length; k++)
-        elements[k] = null;
-
-    // fire 'notify' event
-    this.trigger('form-submit-notify', [this, options]);
-    return this;
-
-     // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
-    function fileUploadXhr(a) {
-        var formdata = new FormData();
-
-        for (var i=0; i < a.length; i++) {
-            formdata.append(a[i].name, a[i].value);
-        }
-
-        if (options.extraData) {
-            for (var p in options.extraData)
-                if (options.extraData.hasOwnProperty(p))
-                    formdata.append(p, options.extraData[p]);
-        }
-
-        options.data = null;
-
-        var s = $.extend(true, {}, $.ajaxSettings, options, {
-            contentType: false,
-            processData: false,
-            cache: false,
-            type: 'POST'
-        });
-        
-        if (options.uploadProgress) {
-            // workaround because jqXHR does not expose upload property
-            s.xhr = function() {
-                var xhr = jQuery.ajaxSettings.xhr();
-                if (xhr.upload) {
-                    xhr.upload.onprogress = function(event) {
-                        var percent = 0;
-                        var position = event.loaded || event.position; /*event.position is deprecated*/
-                        var total = event.total;
-                        if (event.lengthComputable) {
-                            percent = Math.ceil(position / total * 100);
-                        }
-                        options.uploadProgress(event, position, total, percent);
-                    };
-                }
-                return xhr;
-            };
-        }
-
-        s.data = null;
-            var beforeSend = s.beforeSend;
-            s.beforeSend = function(xhr, o) {
-                o.data = formdata;
-                if(beforeSend)
-                    beforeSend.call(this, xhr, o);
-        };
-        $.ajax(s);
-    }
-
-    // private function for handling file uploads (hat tip to YAHOO!)
-    function fileUploadIframe(a) {
-        var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
-        var useProp = !!$.fn.prop;
-
-        if ($(':input[name=submit],:input[id=submit]', form).length) {
-            // if there is an input with a name or id of 'submit' then we won't be
-            // able to invoke the submit fn on the form (at least not x-browser)
-            alert('Error: Form elements must not have name or id of "submit".');
-            return;
-        }
-        
-        if (a) {
-            // ensure that every serialized input is still enabled
-            for (i=0; i < elements.length; i++) {
-                el = $(elements[i]);
-                if ( useProp )
-                    el.prop('disabled', false);
-                else
-                    el.removeAttr('disabled');
-            }
-        }
-
-        s = $.extend(true, {}, $.ajaxSettings, options);
-        s.context = s.context || s;
-        id = 'jqFormIO' + (new Date().getTime());
-        if (s.iframeTarget) {
-            $io = $(s.iframeTarget);
-            n = $io.attr('name');
-            if (!n)
-                 $io.attr('name', id);
-            else
-                id = n;
-        }
-        else {
-            $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
-            $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
-        }
-        io = $io[0];
-
-
-        xhr = { // mock object
-            aborted: 0,
-            responseText: null,
-            responseXML: null,
-            status: 0,
-            statusText: 'n/a',
-            getAllResponseHeaders: function() {},
-            getResponseHeader: function() {},
-            setRequestHeader: function() {},
-            abort: function(status) {
-                var e = (status === 'timeout' ? 'timeout' : 'aborted');
-                log('aborting upload... ' + e);
-                this.aborted = 1;
-                // #214
-                if (io.contentWindow.document.execCommand) {
-                    try { // #214
-                        io.contentWindow.document.execCommand('Stop');
-                    } catch(ignore) {}
-                }
-                $io.attr('src', s.iframeSrc); // abort op in progress
-                xhr.error = e;
-                if (s.error)
-                    s.error.call(s.context, xhr, e, status);
-                if (g)
-                    $.event.trigger("ajaxError", [xhr, s, e]);
-                if (s.complete)
-                    s.complete.call(s.context, xhr, e);
-            }
-        };
-
-        g = s.global;
-        // trigger ajax global events so that activity/block indicators work like normal
-        if (g && 0 === $.active++) {
-            $.event.trigger("ajaxStart");
-        }
-        if (g) {
-            $.event.trigger("ajaxSend", [xhr, s]);
-        }
-
-        if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
-            if (s.global) {
-                $.active--;
-            }
-            return;
-        }
-        if (xhr.aborted) {
-            return;
-        }
-
-        // add submitting element to data if we know it
-        sub = form.clk;
-        if (sub) {
-            n = sub.name;
-            if (n && !sub.disabled) {
-                s.extraData = s.extraData || {};
-                s.extraData[n] = sub.value;
-                if (sub.type == "image") {
-                    s.extraData[n+'.x'] = form.clk_x;
-                    s.extraData[n+'.y'] = form.clk_y;
-                }
-            }
-        }
-        
-        var CLIENT_TIMEOUT_ABORT = 1;
-        var SERVER_ABORT = 2;
-
-        function getDoc(frame) {
-            var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
-            return doc;
-        }
-        
-        // Rails CSRF hack (thanks to Yvan Barthelemy)
-        var csrf_token = $('meta[name=csrf-token]').attr('content');
-        var csrf_param = $('meta[name=csrf-param]').attr('content');
-        if (csrf_param && csrf_token) {
-            s.extraData = s.extraData || {};
-            s.extraData[csrf_param] = csrf_token;
-        }
-
-        // take a breath so that pending repaints get some cpu time before the upload starts
-        function doSubmit() {
-            // make sure form attrs are set
-            var t = $form.attr('target'), a = $form.attr('action');
-
-            // update form attrs in IE friendly way
-            form.setAttribute('target',id);
-            if (!method) {
-                form.setAttribute('method', 'POST');
-            }
-            if (a != s.url) {
-                form.setAttribute('action', s.url);
-            }
-
-            // ie borks in some cases when setting encoding
-            if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
-                $form.attr({
-                    encoding: 'multipart/form-data',
-                    enctype:  'multipart/form-data'
-                });
-            }
-
-            // support timout
-            if (s.timeout) {
-                timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
-            }
-            
-            // look for server aborts
-            function checkState() {
-                try {
-                    var state = getDoc(io).readyState;
-                    log('state = ' + state);
-                    if (state && state.toLowerCase() == 'uninitialized')
-                        setTimeout(checkState,50);
-                }
-                catch(e) {
-                    log('Server abort: ' , e, ' (', e.name, ')');
-                    cb(SERVER_ABORT);
-                    if (timeoutHandle)
-                        clearTimeout(timeoutHandle);
-                    timeoutHandle = undefined;
-                }
-            }
-
-            // add "extra" data to form if provided in options
-            var extraInputs = [];
-            try {
-                if (s.extraData) {
-                    for (var n in s.extraData) {
-                        if (s.extraData.hasOwnProperty(n)) {
-                           // if using the $.param format that allows for multiple values with the same name
-                           if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
-                               extraInputs.push(
-                               $('<input type="hidden" name="'+s.extraData[n].name+'">').attr('value',s.extraData[n].value)
-                                   .appendTo(form)[0]);
-                           } else {
-                               extraInputs.push(
-                               $('<input type="hidden" name="'+n+'">').attr('value',s.extraData[n])
-                                   .appendTo(form)[0]);
-                           }
-                        }
-                    }
-                }
-
-                if (!s.iframeTarget) {
-                    // add iframe to doc and submit the form
-                    $io.appendTo('body');
-                    if (io.attachEvent)
-                        io.attachEvent('onload', cb);
-                    else
-                        io.addEventListener('load', cb, false);
-                }
-                setTimeout(checkState,15);
-                form.submit();
-            }
-            finally {
-                // reset attrs and remove "extra" input elements
-                form.setAttribute('action',a);
-                if(t) {
-                    form.setAttribute('target', t);
-                } else {
-                    $form.removeAttr('target');
-                }
-                $(extraInputs).remove();
-            }
-        }
-
-        if (s.forceSync) {
-            doSubmit();
-        }
-        else {
-            setTimeout(doSubmit, 10); // this lets dom updates render
-        }
-
-        var data, doc, domCheckCount = 50, callbackProcessed;
-
-        function cb(e) {
-            if (xhr.aborted || callbackProcessed) {
-                return;
-            }
-            try {
-                doc = getDoc(io);
-            }
-            catch(ex) {
-                log('cannot access response document: ', ex);
-                e = SERVER_ABORT;
-            }
-            if (e === CLIENT_TIMEOUT_ABORT && xhr) {
-                xhr.abort('timeout');
-                return;
-            }
-            else if (e == SERVER_ABORT && xhr) {
-                xhr.abort('server abort');
-                return;
-            }
-
-            if (!doc || doc.location.href == s.iframeSrc) {
-                // response not received yet
-                if (!timedOut)
-                    return;
-            }
-            if (io.detachEvent)
-                io.detachEvent('onload', cb);
-            else    
-                io.removeEventListener('load', cb, false);
-
-            var status = 'success', errMsg;
-            try {
-                if (timedOut) {
-                    throw 'timeout';
-                }
-
-                var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
-                log('isXml='+isXml);
-                if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
-                    if (--domCheckCount) {
-                        // in some browsers (Opera) the iframe DOM is not always traversable when
-                        // the onload callback fires, so we loop a bit to accommodate
-                        log('requeing onLoad callback, DOM not available');
-                        setTimeout(cb, 250);
-                        return;
-                    }
-                    // let this fall through because server response could be an empty document
-                    //log('Could not access iframe DOM after mutiple tries.');
-                    //throw 'DOMException: not available';
-                }
-
-                //log('response detected');
-                var docRoot = doc.body ? doc.body : doc.documentElement;
-                xhr.responseText = docRoot ? docRoot.innerHTML : null;
-                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
-                if (isXml)
-                    s.dataType = 'xml';
-                xhr.getResponseHeader = function(header){
-                    var headers = {'content-type': s.dataType};
-                    return headers[header];
-                };
-                // support for XHR 'status' & 'statusText' emulation :
-                if (docRoot) {
-                    xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
-                    xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
-                }
-
-                var dt = (s.dataType || '').toLowerCase();
-                var scr = /(json|script|text)/.test(dt);
-                if (scr || s.textarea) {
-                    // see if user embedded response in textarea
-                    var ta = doc.getElementsByTagName('textarea')[0];
-                    if (ta) {
-                        xhr.responseText = ta.value;
-                        // support for XHR 'status' & 'statusText' emulation :
-                        xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
-                        xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
-                    }
-                    else if (scr) {
-                        // account for browsers injecting pre around json response
-                        var pre = doc.getElementsByTagName('pre')[0];
-                        var b = doc.getElementsByTagName('body')[0];
-                        if (pre) {
-                            xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
-                        }
-                        else if (b) {
-                            xhr.responseText = b.textContent ? b.textContent : b.innerText;
-                        }
-                    }
-                }
-                else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
-                    xhr.responseXML = toXml(xhr.responseText);
-                }
-
-                try {
-                    data = httpData(xhr, dt, s);
-                }
-                catch (e) {
-                    status = 'parsererror';
-                    xhr.error = errMsg = (e || status);
-                }
-            }
-            catch (e) {
-                log('error caught: ',e);
-                status = 'error';
-                xhr.error = errMsg = (e || status);
-            }
-
-            if (xhr.aborted) {
-                log('upload aborted');
-                status = null;
-            }
-
-            if (xhr.status) { // we've set xhr.status
-                status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
-            }
-
-            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
-            if (status === 'success') {
-                if (s.success)
-                    s.success.call(s.context, data, 'success', xhr);
-                if (g)
-                    $.event.trigger("ajaxSuccess", [xhr, s]);
-            }
-            else if (status) {
-                if (errMsg === undefined)
-                    errMsg = xhr.statusText;
-                if (s.error)
-                    s.error.call(s.context, xhr, status, errMsg);
-                if (g)
-                    $.event.trigger("ajaxError", [xhr, s, errMsg]);
-            }
-
-            if (g)
-                $.event.trigger("ajaxComplete", [xhr, s]);
-
-            if (g && ! --$.active) {
-                $.event.trigger("ajaxStop");
-            }
-
-            if (s.complete)
-                s.complete.call(s.context, xhr, status);
-
-            callbackProcessed = true;
-            if (s.timeout)
-                clearTimeout(timeoutHandle);
-
-            // clean up
-            setTimeout(function() {
-                if (!s.iframeTarget)
-                    $io.remove();
-                xhr.responseXML = null;
-            }, 100);
-        }
-
-        var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
-            if (window.ActiveXObject) {
-                doc = new ActiveXObject('Microsoft.XMLDOM');
-                doc.async = 'false';
-                doc.loadXML(s);
-            }
-            else {
-                doc = (new DOMParser()).parseFromString(s, 'text/xml');
-            }
-            return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
-        };
-        var parseJSON = $.parseJSON || function(s) {
-            /*jslint evil:true */
-            return window['eval']('(' + s + ')');
-        };
-
-        var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
-
-            var ct = xhr.getResponseHeader('content-type') || '',
-                xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
-                data = xml ? xhr.responseXML : xhr.responseText;
-
-            if (xml && data.documentElement.nodeName === 'parsererror') {
-                if ($.error)
-                    $.error('parsererror');
-            }
-            if (s && s.dataFilter) {
-                data = s.dataFilter(data, type);
-            }
-            if (typeof data === 'string') {
-                if (type === 'json' || !type && ct.indexOf('json') >= 0) {
-                    data = parseJSON(data);
-                } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
-                    $.globalEval(data);
-                }
-            }
-            return data;
-        };
-    }
-};
-
-/**
- * ajaxForm() provides a mechanism for fully automating form submission.
- *
- * The advantages of using this method instead of ajaxSubmit() are:
- *
- * 1: This method will include coordinates for <input type="image" /> elements (if the element
- *    is used to submit the form).
- * 2. This method will include the submit element's name/value data (for the element that was
- *    used to submit the form).
- * 3. This method binds the submit() method to the form for you.
- *
- * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
- * passes the options argument along after properly binding events for submit elements and
- * the form itself.
- */
-$.fn.ajaxForm = function(options) {
-    options = options || {};
-    options.delegation = options.delegation && $.isFunction($.fn.on);
-    
-    // in jQuery 1.3+ we can fix mistakes with the ready state
-    if (!options.delegation && this.length === 0) {
-        var o = { s: this.selector, c: this.context };
-        if (!$.isReady && o.s) {
-            log('DOM not ready, queuing ajaxForm');
-            $(function() {
-                $(o.s,o.c).ajaxForm(options);
-            });
-            return this;
-        }
-        // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
-        log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
-        return this;
-    }
-
-    if ( options.delegation ) {
-        $(document)
-            .off('submit.form-plugin', this.selector, doAjaxSubmit)
-            .off('click.form-plugin', this.selector, captureSubmittingElement)
-            .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
-            .on('click.form-plugin', this.selector, options, captureSubmittingElement);
-        return this;
-    }
-
-    return this.ajaxFormUnbind()
-        .bind('submit.form-plugin', options, doAjaxSubmit)
-        .bind('click.form-plugin', options, captureSubmittingElement);
-};
-
-// private event handlers    
-function doAjaxSubmit(e) {
-    /*jshint validthis:true */
-    var options = e.data;
-    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
-        e.preventDefault();
-        $(this).ajaxSubmit(options);
-    }
-}
-    
-function captureSubmittingElement(e) {
-    /*jshint validthis:true */
-    var target = e.target;
-    var $el = $(target);
-    if (!($el.is(":submit,input:image"))) {
-        // is this a child element of the submit el?  (ex: a span within a button)
-        var t = $el.closest(':submit');
-        if (t.length === 0) {
-            return;
-        }
-        target = t[0];
-    }
-    var form = this;
-    form.clk = target;
-    if (target.type == 'image') {
-        if (e.offsetX !== undefined) {
-            form.clk_x = e.offsetX;
-            form.clk_y = e.offsetY;
-        } else if (typeof $.fn.offset == 'function') {
-            var offset = $el.offset();
-            form.clk_x = e.pageX - offset.left;
-            form.clk_y = e.pageY - offset.top;
-        } else {
-            form.clk_x = e.pageX - target.offsetLeft;
-            form.clk_y = e.pageY - target.offsetTop;
-        }
-    }
-    // clear form vars
-    setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
-}
-
-
-// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
-$.fn.ajaxFormUnbind = function() {
-    return this.unbind('submit.form-plugin click.form-plugin');
-};
-
-/**
- * formToArray() gathers form element data into an array of objects that can
- * be passed to any of the following ajax functions: $.get, $.post, or load.
- * Each object in the array has both a 'name' and 'value' property.  An example of
- * an array for a simple login form might be:
- *
- * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
- *
- * It is this array that is passed to pre-submit callback functions provided to the
- * ajaxSubmit() and ajaxForm() methods.
- */
-$.fn.formToArray = function(semantic, elements) {
-    var a = [];
-    if (this.length === 0) {
-        return a;
-    }
-
-    var form = this[0];
-    var els = semantic ? form.getElementsByTagName('*') : form.elements;
-    if (!els) {
-        return a;
-    }
-
-    var i,j,n,v,el,max,jmax;
-    for(i=0, max=els.length; i < max; i++) {
-        el = els[i];
-        n = el.name;
-        if (!n) {
-            continue;
-        }
-
-        if (semantic && form.clk && el.type == "image") {
-            // handle image inputs on the fly when semantic == true
-            if(!el.disabled && form.clk == el) {
-                a.push({name: n, value: $(el).val(), type: el.type });
-                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
-            }
-            continue;
-        }
-
-        v = $.fieldValue(el, true);
-        if (v && v.constructor == Array) {
-            if (elements) 
-                elements.push(el);
-            for(j=0, jmax=v.length; j < jmax; j++) {
-                a.push({name: n, value: v[j]});
-            }
-        }
-        else if (feature.fileapi && el.type == 'file' && !el.disabled) {
-            if (elements) 
-                elements.push(el);
-            var files = el.files;
-            if (files.length) {
-                for (j=0; j < files.length; j++) {
-                    a.push({name: n, value: files[j], type: el.type});
-                }
-            }
-            else {
-                // #180
-                a.push({ name: n, value: '', type: el.type });
-            }
-        }
-        else if (v !== null && typeof v != 'undefined') {
-            if (elements) 
-                elements.push(el);
-            a.push({name: n, value: v, type: el.type, required: el.required});
-        }
-    }
-
-    if (!semantic && form.clk) {
-        // input type=='image' are not found in elements array! handle it here
-        var $input = $(form.clk), input = $input[0];
-        n = input.name;
-        if (n && !input.disabled && input.type == 'image') {
-            a.push({name: n, value: $input.val()});
-            a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
-        }
-    }
-    return a;
-};
-
-/**
- * Serializes form data into a 'submittable' string. This method will return a string
- * in the format: name1=value1&amp;name2=value2
- */
-$.fn.formSerialize = function(semantic) {
-    //hand off to jQuery.param for proper encoding
-    return $.param(this.formToArray(semantic));
-};
-
-/**
- * Serializes all field elements in the jQuery object into a query string.
- * This method will return a string in the format: name1=value1&amp;name2=value2
- */
-$.fn.fieldSerialize = function(successful) {
-    var a = [];
-    this.each(function() {
-        var n = this.name;
-        if (!n) {
-            return;
-        }
-        var v = $.fieldValue(this, successful);
-        if (v && v.constructor == Array) {
-            for (var i=0,max=v.length; i < max; i++) {
-                a.push({name: n, value: v[i]});
-            }
-        }
-        else if (v !== null && typeof v != 'undefined') {
-            a.push({name: this.name, value: v});
-        }
-    });
-    //hand off to jQuery.param for proper encoding
-    return $.param(a);
-};
-
-/**
- * Returns the value(s) of the element in the matched set.  For example, consider the following form:
- *
- *  <form><fieldset>
- *      <input name="A" type="text" />
- *      <input name="A" type="text" />
- *      <input name="B" type="checkbox" value="B1" />
- *      <input name="B" type="checkbox" value="B2"/>
- *      <input name="C" type="radio" value="C1" />
- *      <input name="C" type="radio" value="C2" />
- *  </fieldset></form>
- *
- *  var v = $(':text').fieldValue();
- *  // if no values are entered into the text inputs
- *  v == ['','']
- *  // if values entered into the text inputs are 'foo' and 'bar'
- *  v == ['foo','bar']
- *
- *  var v = $(':checkbox').fieldValue();
- *  // if neither checkbox is checked
- *  v === undefined
- *  // if both checkboxes are checked
- *  v == ['B1', 'B2']
- *
- *  var v = $(':radio').fieldValue();
- *  // if neither radio is checked
- *  v === undefined
- *  // if first radio is checked
- *  v == ['C1']
- *
- * The successful argument controls whether or not the field element must be 'successful'
- * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
- * The default value of the successful argument is true.  If this value is false the value(s)
- * for each element is returned.
- *
- * Note: This method *always* returns an array.  If no valid value can be determined the
- *    array will be empty, otherwise it will contain one or more values.
- */
-$.fn.fieldValue = function(successful) {
-    for (var val=[], i=0, max=this.length; i < max; i++) {
-        var el = this[i];
-        var v = $.fieldValue(el, successful);
-        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
-            continue;
-        }
-        if (v.constructor == Array)
-            $.merge(val, v);
-        else
-            val.push(v);
-    }
-    return val;
-};
-
-/**
- * Returns the value of the field element.
- */
-$.fieldValue = function(el, successful) {
-    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
-    if (successful === undefined) {
-        successful = true;
-    }
-
-    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
-        (t == 'checkbox' || t == 'radio') && !el.checked ||
-        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
-        tag == 'select' && el.selectedIndex == -1)) {
-            return null;
-    }
-
-    if (tag == 'select') {
-        var index = el.selectedIndex;
-        if (index < 0) {
-            return null;
-        }
-        var a = [], ops = el.options;
-        var one = (t == 'select-one');
-        var max = (one ? index+1 : ops.length);
-        for(var i=(one ? index : 0); i < max; i++) {
-            var op = ops[i];
-            if (op.selected) {
-                var v = op.value;
-                if (!v) { // extra pain for IE...
-                    v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
-                }
-                if (one) {
-                    return v;
-                }
-                a.push(v);
-            }
-        }
-        return a;
-    }
-    return $(el).val();
-};
-
-/**
- * Clears the form data.  Takes the following actions on the form's input fields:
- *  - input text fields will have their 'value' property set to the empty string
- *  - select elements will have their 'selectedIndex' property set to -1
- *  - checkbox and radio inputs will have their 'checked' property set to false
- *  - inputs of type submit, button, reset, and hidden will *not* be effected
- *  - button elements will *not* be effected
- */
-$.fn.clearForm = function(includeHidden) {
-    return this.each(function() {
-        $('input,select,textarea', this).clearFields(includeHidden);
-    });
-};
-
-/**
- * Clears the selected form elements.
- */
-$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
-    var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
-    return this.each(function() {
-        var t = this.type, tag = this.tagName.toLowerCase();
-        if (re.test(t) || tag == 'textarea') {
-            this.value = '';
-        }
-        else if (t == 'checkbox' || t == 'radio') {
-            this.checked = false;
-        }
-        else if (tag == 'select') {
-            this.selectedIndex = -1;
-        }
-        else if (includeHidden) {
-            // includeHidden can be the value true, or it can be a selector string
-            // indicating a special test; for example:
-            //  $('#myForm').clearForm('.special:hidden')
-            // the above would clean hidden inputs that have the class of 'special'
-            if ( (includeHidden === true && /hidden/.test(t)) ||
-                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) )
-                this.value = '';
-        }
-    });
-};
-
-/**
- * Resets the form data.  Causes all form elements to be reset to their original value.
- */
-$.fn.resetForm = function() {
-    return this.each(function() {
-        // guard against an input with the name of 'reset'
-        // note that IE reports the reset function as an 'object'
-        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
-            this.reset();
-        }
-    });
-};
-
-/**
- * Enables or disables any matching elements.
- */
-$.fn.enable = function(b) {
-    if (b === undefined) {
-        b = true;
-    }
-    return this.each(function() {
-        this.disabled = !b;
-    });
-};
-
-/**
- * Checks/unchecks any matching checkboxes or radio buttons and
- * selects/deselects and matching option elements.
- */
-$.fn.selected = function(select) {
-    if (select === undefined) {
-        select = true;
-    }
-    return this.each(function() {
-        var t = this.type;
-        if (t == 'checkbox' || t == 'radio') {
-            this.checked = select;
-        }
-        else if (this.tagName.toLowerCase() == 'option') {
-            var $sel = $(this).parent('select');
-            if (select && $sel[0] && $sel[0].type == 'select-one') {
-                // deselect all other options
-                $sel.find('option').selected(false);
-            }
-            this.selected = select;
-        }
-    });
-};
-
-// expose debug var
-$.fn.ajaxSubmit.debug = false;
-
-// helper fn for console logging
-function log() {
-    if (!$.fn.ajaxSubmit.debug) 
-        return;
-    var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
-    if (window.console && window.console.log) {
-        window.console.log(msg);
-    }
-    else if (window.opera && window.opera.postError) {
-        window.opera.postError(msg);
-    }
-}
-
-})(jQuery);
diff --git a/resources/jquery/jquery.fullscreen.js b/resources/jquery/jquery.fullscreen.js
deleted file mode 100644 (file)
index 3d1f29a..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * jQuery fullscreen plugin v2.0.0
- * https://github.com/theopolisme/jquery-fullscreen/tree/v2.0.0
- *
- * Documentation at <https://github.com/theopolisme/jquery-fullscreen/blob/v2.0.0/README.md>
- *
- * Copyright (c) 2013 Theopolisme <theopolismewiki@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-( function ( $ ) {
-       var setupFullscreen,
-               fsClass = 'jq-fullscreened';
-
-       /**
-        * On fullscreenchange, trigger a jq-fullscreen-change event
-        * The event is given an object, which contains the fullscreened DOM element (element), if any
-        * and a boolean value (fullscreen) indicating if we've entered or exited fullscreen mode
-        * Also remove the 'fullscreened' class from elements that are no longer fullscreen
-        */
-       function handleFullscreenChange () {
-               var fullscreenElement = document.fullscreenElement ||
-                       document.mozFullScreenElement ||
-                       document.webkitFullscreenElement ||
-                       document.msFullscreenElement;
-
-               if ( !fullscreenElement ) {
-                       $( '.' + fsClass ).data( 'isFullscreened', false ).removeClass( fsClass );
-               }
-
-               $( document ).trigger( $.Event( 'jq-fullscreen-change', { element: fullscreenElement, fullscreen: !!fullscreenElement } ) );
-       }
-
-       /**
-        * Enters full screen with the "this" element in focus.
-        * Check the .data( 'isFullscreened' ) of the return value to check
-        * success or failure, if you're into that sort of thing.
-        * @chainable
-        * @return {jQuery}
-        */
-       function enterFullscreen () {
-               var element = this.get(0),
-                       $element = this.first();
-               if ( element ) {
-                       if ( element.requestFullscreen ) {
-                               element.requestFullscreen();
-                       } else if ( element.mozRequestFullScreen ) {
-                               element.mozRequestFullScreen();
-                       } else if ( element.webkitRequestFullscreen ) {
-                               element.webkitRequestFullscreen();
-                       } else if ( element.msRequestFullscreen ) {
-                               element.msRequestFullscreen();
-                       } else {
-                               // Unable to make fullscreen
-                               $element.data( 'isFullscreened', false );
-                               return this;
-                       }
-                       // Add the fullscreen class and data attribute to `element`
-                       $element.addClass( fsClass ).data( 'isFullscreened', true );
-                       return this;
-               } else {
-                       $element.data( 'isFullscreened', false );
-                       return this;
-               }
-       }
-
-       /**
-        * Brings the "this" element out of fullscreen.
-        * Check the .data( 'isFullscreened' ) of the return value to check
-        * success or failure, if you're into that sort of thing.
-        * @chainable
-        * @return {jQuery}
-        */
-       function exitFullscreen () {
-               var fullscreenElement = ( document.fullscreenElement ||
-                               document.mozFullScreenElement ||
-                               document.webkitFullscreenElement ||
-                               document.msFullscreenElement );
-
-               // Ensure that we only exit fullscreen if exitFullscreen() is being called on the same element that is currently fullscreen
-               if ( fullscreenElement && this.get(0) === fullscreenElement ) {
-                       if ( document.exitFullscreen ) {
-                               document.exitFullscreen();
-                       } else if ( document.mozCancelFullScreen ) {
-                               document.mozCancelFullScreen();
-                       } else if ( document.webkitCancelFullScreen ) {
-                               document.webkitCancelFullScreen();
-                       } else if ( document.msCancelFullScreen ) {
-                               document.msCancelFullScreen();
-                       } else {
-                               // Unable to cancel fullscreen mode
-                               return this;
-                       }
-                       // We don't need to remove the fullscreen class here,
-                       // because it will be removed in handleFullscreenChange.
-                       // But we should change the data on the element so the
-                       // caller can check for success.
-                       this.first().data( 'isFullscreened', false );
-               }
-
-               return this;
-       }
-
-       /**
-        * Set up fullscreen handling and install necessary event handlers.
-        * Return false if fullscreen is not supported.
-        */
-       setupFullscreen = function () {
-               if ( $.support.fullscreen ) {
-                       // When the fullscreen mode is changed, trigger the
-                       // fullscreen events (and when exiting,
-                       // also remove the fullscreen class)
-                       $( document ).on( 'fullscreenchange webkitfullscreenchange mozfullscreenchange msfullscreenchange', handleFullscreenChange);
-                       // Convenience wrapper so that one only needs to listen for
-                       // 'fullscreenerror', not all of the prefixed versions
-                       $( document ).on( 'webkitfullscreenerror mozfullscreenerror msfullscreenerror', function () {
-                               $( document ).trigger( $.Event( 'fullscreenerror' ) );
-                       } );
-                       // Fullscreen has been set up, so always return true
-                       setupFullscreen = function () { return true; };
-                       return true;
-               } else {
-                       // Always return false from now on, since fullscreen is not supported
-                       setupFullscreen = function() { return false; };
-                       return false;
-               }
-       };
-
-       /**
-        * Set up fullscreen handling if necessary, then make the first element
-        * matching the given selector fullscreen
-        * @chainable
-        * @return {jQuery}
-        */
-       $.fn.enterFullscreen = function () {
-               if ( setupFullscreen() ) {
-                       $.fn.enterFullscreen = enterFullscreen;
-                       return this.enterFullscreen();
-               } else {
-                       $.fn.enterFullscreen = function () { return this; };
-                       return this;
-               }
-       };
-
-       /**
-        * Set up fullscreen handling if necessary, then cancel fullscreen mode
-        * for the first element matching the given selector.
-        * @chainable
-        * @return {jQuery}
-        */
-       $.fn.exitFullscreen = function () {
-               if ( setupFullscreen() ) {
-                       $.fn.exitFullscreen = exitFullscreen;
-                       return this.exitFullscreen();
-               } else {
-                       $.fn.exitFullscreen = function () { return this; };
-                       return this;
-               }
-       };
-       
-       $.support.fullscreen = document.fullscreenEnabled ||
-               document.webkitFullscreenEnabled ||
-               document.mozFullScreenEnabled ||
-               document.msFullscreenEnabled;
-}( jQuery ) );
diff --git a/resources/jquery/jquery.getAttrs.js b/resources/jquery/jquery.getAttrs.js
deleted file mode 100644 (file)
index 25b806b..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Utility to get all attributes of an element directy as an object.
- *
- * @author Timo Tijhof, 2011
- */
-jQuery.fn.getAttrs = function ( all ) {
-       var map = this[0].attributes,
-               attrs = {},
-               len = map.length,
-               i, v;
-
-       for ( i = 0; i < len; i++ ) {
-               // IE6 includes *all* allowed attributes for thew element (including those
-               // not set). Those have values like undefined, null, 0, false, "" or "inherit".
-               // However there may be genuine attributes set to that. If you need them,
-               // set all to true. They are excluded by default.
-               v = map[i].nodeValue;
-               if ( all || ( v && v !== 'inherit' ) ) {
-                       attrs[ map[i].nodeName ] = v;
-               }
-       }
-
-       return attrs;
-};
diff --git a/resources/jquery/jquery.hidpi.js b/resources/jquery/jquery.hidpi.js
deleted file mode 100644 (file)
index eb29db9..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * Responsive images based on 'srcset' and 'window.devicePixelRatio' emulation where needed.
- *
- * Call $().hidpi() on a document or part of a document to replace image srcs in that section.
- *
- * $.devicePixelRatio() can be used to supplement window.devicePixelRatio with support on
- * some additional browsers.
- */
-( function ( $ ) {
-
-/**
- * Detect reported or approximate device pixel ratio.
- * 1.0 means 1 CSS pixel is 1 hardware pixel
- * 2.0 means 1 CSS pixel is 2 hardware pixels
- * etc
- *
- * Uses window.devicePixelRatio if available, or CSS media queries on IE.
- *
- * @return {number} Device pixel ratio
- */
-$.devicePixelRatio = function () {
-       if ( window.devicePixelRatio !== undefined ) {
-               // Most web browsers:
-               // * WebKit (Safari, Chrome, Android browser, etc)
-               // * Opera
-               // * Firefox 18+
-               return window.devicePixelRatio;
-       } else if ( window.msMatchMedia !== undefined ) {
-               // Windows 8 desktops / tablets, probably Windows Phone 8
-               //
-               // IE 10 doesn't report pixel ratio directly, but we can get the
-               // screen DPI and divide by 96. We'll bracket to [1, 1.5, 2.0] for
-               // simplicity, but you may get different values depending on zoom
-               // factor, size of screen and orientation in Metro IE.
-               if ( window.msMatchMedia( '(min-resolution: 192dpi)' ).matches ) {
-                       return 2;
-               } else if ( window.msMatchMedia( '(min-resolution: 144dpi)' ).matches ) {
-                       return 1.5;
-               } else {
-                       return 1;
-               }
-       } else {
-               // Legacy browsers...
-               // Assume 1 if unknown.
-               return 1;
-       }
-};
-
-/**
- * Implement responsive images based on srcset attributes, if browser has no
- * native srcset support.
- *
- * @return {jQuery} This selection
- */
-$.fn.hidpi = function () {
-       var $target = this,
-               // @todo add support for dpi media query checks on Firefox, IE
-               devicePixelRatio = $.devicePixelRatio(),
-               testImage = new Image();
-
-       if ( devicePixelRatio > 1 && testImage.srcset === undefined ) {
-               // No native srcset support.
-               $target.find( 'img' ).each( function () {
-                       var $img = $( this ),
-                               srcset = $img.attr( 'srcset' ),
-                               match;
-                       if ( typeof srcset === 'string' && srcset !== '' ) {
-                               match = $.matchSrcSet( devicePixelRatio, srcset );
-                               if (match !== null ) {
-                                       $img.attr( 'src', match );
-                               }
-                       }
-               });
-       }
-
-       return $target;
-};
-
-/**
- * Match a srcset entry for the given device pixel ratio
- *
- * Exposed for testing.
- *
- * @param {number} devicePixelRatio
- * @param {string} srcset
- * @return {mixed} null or the matching src string
- */
-$.matchSrcSet = function ( devicePixelRatio, srcset ) {
-       var candidates,
-               candidate,
-               bits,
-               src,
-               i,
-               ratioStr,
-               ratio,
-               selectedRatio = 1,
-               selectedSrc = null;
-       candidates = srcset.split( / *, */ );
-       for ( i = 0; i < candidates.length; i++ ) {
-               candidate = candidates[i];
-               bits = candidate.split( / +/ );
-               src = bits[0];
-               if ( bits.length > 1 && bits[1].charAt( bits[1].length - 1 ) === 'x' ) {
-                       ratioStr = bits[1].substr( 0, bits[1].length - 1 );
-                       ratio = parseFloat( ratioStr );
-                       if ( ratio <= devicePixelRatio && ratio > selectedRatio ) {
-                               selectedRatio = ratio;
-                               selectedSrc = src;
-                       }
-               }
-       }
-       return selectedSrc;
-};
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.highlightText.js b/resources/jquery/jquery.highlightText.js
deleted file mode 100644 (file)
index 0408151..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * Plugin that highlights matched word partials in a given element.
- * TODO: Add a function for restoring the previous text.
- * TODO: Accept mappings for converting shortcuts like WP: to Wikipedia:.
- */
-( function ( $ ) {
-
-       $.highlightText = {
-
-               // Split our pattern string at spaces and run our highlight function on the results
-               splitAndHighlight: function ( node, pat ) {
-                       var i,
-                               patArray = pat.split( ' ' );
-                       for ( i = 0; i < patArray.length; i++ ) {
-                               if ( patArray[i].length === 0 ) {
-                                       continue;
-                               }
-                               $.highlightText.innerHighlight( node, patArray[i] );
-                       }
-                       return node;
-               },
-
-               // scans a node looking for the pattern and wraps a span around each match
-               innerHighlight: function ( node, pat ) {
-                       var i, match, pos, spannode, middlebit, middleclone;
-                       // if this is a text node
-                       if ( node.nodeType === 3 ) {
-                               // TODO - need to be smarter about the character matching here.
-                               // non latin characters can make regex think a new word has begun: do not use \b
-                               // http://stackoverflow.com/questions/3787072/regex-wordwrap-with-utf8-characters-in-js
-                               // look for an occurrence of our pattern and store the starting position
-                               match = node.data.match( new RegExp( '(^|\\s)' + $.escapeRE( pat ), 'i' ) );
-                               if ( match ) {
-                                       pos = match.index + match[1].length; // include length of any matched spaces
-                                       // create the span wrapper for the matched text
-                                       spannode = document.createElement( 'span' );
-                                       spannode.className = 'highlight';
-                                       // shave off the characters preceding the matched text
-                                       middlebit = node.splitText( pos );
-                                       // shave off any unmatched text off the end
-                                       middlebit.splitText( pat.length );
-                                       // clone for appending to our span
-                                       middleclone = middlebit.cloneNode( true );
-                                       // append the matched text node to the span
-                                       spannode.appendChild( middleclone );
-                                       // replace the matched node, with our span-wrapped clone of the matched node
-                                       middlebit.parentNode.replaceChild( spannode, middlebit );
-                               }
-                       // if this is an element with childnodes, and not a script, style or an element we created
-                       } else if ( node.nodeType === 1 && node.childNodes && !/(script|style)/i.test( node.tagName )
-                                       && !( node.tagName.toLowerCase() === 'span' && node.className.match( /\bhighlight/ ) ) ) {
-                               for ( i = 0; i < node.childNodes.length; ++i ) {
-                                       // call the highlight function for each child node
-                                       $.highlightText.innerHighlight( node.childNodes[i], pat );
-                               }
-                       }
-               }
-       };
-
-       $.fn.highlightText = function ( matchString ) {
-               return this.each( function () {
-                       var $el = $( this );
-                       $el.data( 'highlightText', { originalText: $el.text() } );
-                       $.highlightText.splitAndHighlight( this, matchString );
-               } );
-       };
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.hoverIntent.js b/resources/jquery/jquery.hoverIntent.js
deleted file mode 100644 (file)
index adf948d..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
-* hoverIntent is similar to jQuery's built-in "hover" function except that
-* instead of firing the onMouseOver event immediately, hoverIntent checks
-* to see if the user's mouse has slowed down (beneath the sensitivity
-* threshold) before firing the onMouseOver event.
-* 
-* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
-* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
-* 
-* hoverIntent is currently available for use in all personal or commercial 
-* projects under both MIT and GPL licenses. This means that you can choose 
-* the license that best suits your project, and use it accordingly.
-* 
-* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions
-* $("ul li").hoverIntent( showNav , hideNav );
-* 
-* // advanced usage receives configuration object only
-* $("ul li").hoverIntent({
-*      sensitivity: 7, // number = sensitivity threshold (must be 1 or higher)
-*      interval: 100,   // number = milliseconds of polling interval
-*      over: showNav,  // function = onMouseOver callback (required)
-*      timeout: 0,   // number = milliseconds delay before onMouseOut function call
-*      out: hideNav    // function = onMouseOut callback (required)
-* });
-* 
-* @param  f  onMouseOver function || An object with configuration options
-* @param  g  onMouseOut function  || Nothing (use configuration options object)
-* @author    Brian Cherne <brian@cherne.net>
-*/
-(function($) {
-       $.fn.hoverIntent = function(f,g) {
-               // default configuration options
-               var cfg = {
-                       sensitivity: 7,
-                       interval: 100,
-                       timeout: 0
-               };
-               // override configuration options with user supplied object
-               cfg = $.extend(cfg, g ? { over: f, out: g } : f );
-
-               // instantiate variables
-               // cX, cY = current X and Y position of mouse, updated by mousemove event
-               // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
-               var cX, cY, pX, pY;
-
-               // A private function for getting mouse position
-               var track = function(ev) {
-                       cX = ev.pageX;
-                       cY = ev.pageY;
-               };
-
-               // A private function for comparing current and previous mouse position
-               var compare = function(ev,ob) {
-                       ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
-                       // compare mouse positions to see if they've crossed the threshold
-                       if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
-                               $(ob).unbind("mousemove",track);
-                               // set hoverIntent state to true (so mouseOut can be called)
-                               ob.hoverIntent_s = 1;
-                               return cfg.over.apply(ob,[ev]);
-                       } else {
-                               // set previous coordinates for next time
-                               pX = cX; pY = cY;
-                               // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
-                               ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
-                       }
-               };
-
-               // A private function for delaying the mouseOut function
-               var delay = function(ev,ob) {
-                       ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
-                       ob.hoverIntent_s = 0;
-                       return cfg.out.apply(ob,[ev]);
-               };
-
-               // A private function for handling mouse 'hovering'
-               var handleHover = function(e) {
-                       // next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
-                       var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
-                       while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
-                       if ( p == this ) { return false; }
-
-                       // copy objects to be passed into t (required for event object to be passed in IE)
-                       var ev = $.extend({},e);
-                       var ob = this;
-
-                       // cancel hoverIntent timer if it exists
-                       if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
-
-                       // else e.type == "onmouseover"
-                       if (e.type == "mouseover") {
-                               // set "previous" X and Y position based on initial entry point
-                               pX = ev.pageX; pY = ev.pageY;
-                               // update "current" X and Y position based on mousemove
-                               $(ob).bind("mousemove",track);
-                               // start polling interval (self-calling timeout) to compare mouse coordinates over time
-                               if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
-
-                       // else e.type == "onmouseout"
-                       } else {
-                               // unbind expensive mousemove event
-                               $(ob).unbind("mousemove",track);
-                               // if hoverIntent state is true, then call the mouseOut function after the specified delay
-                               if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
-                       }
-               };
-
-               // bind the function to the two event listeners
-               return this.mouseover(handleHover).mouseout(handleHover);
-       };
-})(jQuery);
\ No newline at end of file
diff --git a/resources/jquery/jquery.jStorage.js b/resources/jquery/jquery.jStorage.js
deleted file mode 100644 (file)
index 324833c..0000000
+++ /dev/null
@@ -1,960 +0,0 @@
-/*
- * ----------------------------- JSTORAGE -------------------------------------
- * Simple local storage wrapper to save data on the browser side, supporting
- * all major browsers - IE6+, Firefox2+, Safari4+, Chrome4+ and Opera 10.5+
- *
- * Author: Andris Reinman, andris.reinman@gmail.com
- * Project homepage: www.jstorage.info
- *
- * Licensed under Unlicense:
- *
- * This is free and unencumbered software released into the public domain.
- * 
- * Anyone is free to copy, modify, publish, use, compile, sell, or
- * distribute this software, either in source code form or as a compiled
- * binary, for any purpose, commercial or non-commercial, and by any
- * means.
- * 
- * In jurisdictions that recognize copyright laws, the author or authors
- * of this software dedicate any and all copyright interest in the
- * software to the public domain. We make this dedication for the benefit
- * of the public at large and to the detriment of our heirs and
- * successors. We intend this dedication to be an overt act of
- * relinquishment in perpetuity of all present and future rights to this
- * software under copyright law.
- * 
- * 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 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.
- * 
- * For more information, please refer to <http://unlicense.org/>
- */
-
- (function(){
-    var
-        /* jStorage version */
-        JSTORAGE_VERSION = "0.4.8",
-
-        /* detect a dollar object or create one if not found */
-        $ = window.jQuery || window.$ || (window.$ = {}),
-
-        /* check for a JSON handling support */
-        JSON = {
-            parse:
-                window.JSON && (window.JSON.parse || window.JSON.decode) ||
-                String.prototype.evalJSON && function(str){return String(str).evalJSON();} ||
-                $.parseJSON ||
-                $.evalJSON,
-            stringify:
-                Object.toJSON ||
-                window.JSON && (window.JSON.stringify || window.JSON.encode) ||
-                $.toJSON
-        };
-
-    // Break if no JSON support was found
-    if(!("parse" in JSON) || !("stringify" in JSON)){
-        throw new Error("No JSON support found, include //cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js to page");
-    }
-
-    var
-        /* This is the object, that holds the cached values */
-        _storage = {__jstorage_meta:{CRC32:{}}},
-
-        /* Actual browser storage (localStorage or globalStorage["domain"]) */
-        _storage_service = {jStorage:"{}"},
-
-        /* DOM element for older IE versions, holds userData behavior */
-        _storage_elm = null,
-
-        /* How much space does the storage take */
-        _storage_size = 0,
-
-        /* which backend is currently used */
-        _backend = false,
-
-        /* onchange observers */
-        _observers = {},
-
-        /* timeout to wait after onchange event */
-        _observer_timeout = false,
-
-        /* last update time */
-        _observer_update = 0,
-
-        /* pubsub observers */
-        _pubsub_observers = {},
-
-        /* skip published items older than current timestamp */
-        _pubsub_last = +new Date(),
-
-        /* Next check for TTL */
-        _ttl_timeout,
-
-        /**
-         * XML encoding and decoding as XML nodes can't be JSON'ized
-         * XML nodes are encoded and decoded if the node is the value to be saved
-         * but not if it's as a property of another object
-         * Eg. -
-         *   $.jStorage.set("key", xmlNode);        // IS OK
-         *   $.jStorage.set("key", {xml: xmlNode}); // NOT OK
-         */
-        _XMLService = {
-
-            /**
-             * Validates a XML node to be XML
-             * based on jQuery.isXML function
-             */
-            isXML: function(elm){
-                var documentElement = (elm ? elm.ownerDocument || elm : 0).documentElement;
-                return documentElement ? documentElement.nodeName !== "HTML" : false;
-            },
-
-            /**
-             * Encodes a XML node to string
-             * based on http://www.mercurytide.co.uk/news/article/issues-when-working-ajax/
-             */
-            encode: function(xmlNode) {
-                if(!this.isXML(xmlNode)){
-                    return false;
-                }
-                try{ // Mozilla, Webkit, Opera
-                    return new XMLSerializer().serializeToString(xmlNode);
-                }catch(E1) {
-                    try {  // IE
-                        return xmlNode.xml;
-                    }catch(E2){}
-                }
-                return false;
-            },
-
-            /**
-             * Decodes a XML node from string
-             * loosely based on http://outwestmedia.com/jquery-plugins/xmldom/
-             */
-            decode: function(xmlString){
-                var dom_parser = ("DOMParser" in window && (new DOMParser()).parseFromString) ||
-                        (window.ActiveXObject && function(_xmlString) {
-                    var xml_doc = new ActiveXObject("Microsoft.XMLDOM");
-                    xml_doc.async = "false";
-                    xml_doc.loadXML(_xmlString);
-                    return xml_doc;
-                }),
-                resultXML;
-                if(!dom_parser){
-                    return false;
-                }
-                resultXML = dom_parser.call("DOMParser" in window && (new DOMParser()) || window, xmlString, "text/xml");
-                return this.isXML(resultXML)?resultXML:false;
-            }
-        };
-
-
-    ////////////////////////// PRIVATE METHODS ////////////////////////
-
-    /**
-     * Initialization function. Detects if the browser supports DOM Storage
-     * or userData behavior and behaves accordingly.
-     */
-    function _init(){
-        /* Check if browser supports localStorage */
-        var localStorageReallyWorks = false;
-        if("localStorage" in window){
-            try {
-                window.localStorage.setItem("_tmptest", "tmpval");
-                localStorageReallyWorks = true;
-                window.localStorage.removeItem("_tmptest");
-            } catch(BogusQuotaExceededErrorOnIos5) {
-                // Thanks be to iOS5 Private Browsing mode which throws
-                // QUOTA_EXCEEDED_ERRROR DOM Exception 22.
-            }
-        }
-
-        if(localStorageReallyWorks){
-            try {
-                if(window.localStorage) {
-                    _storage_service = window.localStorage;
-                    _backend = "localStorage";
-                    _observer_update = _storage_service.jStorage_update;
-                }
-            } catch(E3) {/* Firefox fails when touching localStorage and cookies are disabled */}
-        }
-        /* Check if browser supports globalStorage */
-        else if("globalStorage" in window){
-            try {
-                if(window.globalStorage) {
-                    if(window.location.hostname == "localhost"){
-                        _storage_service = window.globalStorage["localhost.localdomain"];
-                    }
-                    else{
-                        _storage_service = window.globalStorage[window.location.hostname];
-                    }
-                    _backend = "globalStorage";
-                    _observer_update = _storage_service.jStorage_update;
-                }
-            } catch(E4) {/* Firefox fails when touching localStorage and cookies are disabled */}
-        }
-        /* Check if browser supports userData behavior */
-        else {
-            _storage_elm = document.createElement("link");
-            if(_storage_elm.addBehavior){
-
-                /* Use a DOM element to act as userData storage */
-                _storage_elm.style.behavior = "url(#default#userData)";
-
-                /* userData element needs to be inserted into the DOM! */
-                document.getElementsByTagName("head")[0].appendChild(_storage_elm);
-
-                try{
-                    _storage_elm.load("jStorage");
-                }catch(E){
-                    // try to reset cache
-                    _storage_elm.setAttribute("jStorage", "{}");
-                    _storage_elm.save("jStorage");
-                    _storage_elm.load("jStorage");
-                }
-
-                var data = "{}";
-                try{
-                    data = _storage_elm.getAttribute("jStorage");
-                }catch(E5){}
-
-                try{
-                    _observer_update = _storage_elm.getAttribute("jStorage_update");
-                }catch(E6){}
-
-                _storage_service.jStorage = data;
-                _backend = "userDataBehavior";
-            }else{
-                _storage_elm = null;
-                return;
-            }
-        }
-
-        // Load data from storage
-        _load_storage();
-
-        // remove dead keys
-        _handleTTL();
-
-        // start listening for changes
-        _setupObserver();
-
-        // initialize publish-subscribe service
-        _handlePubSub();
-
-        // handle cached navigation
-        if("addEventListener" in window){
-            window.addEventListener("pageshow", function(event){
-                if(event.persisted){
-                    _storageObserver();
-                }
-            }, false);
-        }
-    }
-
-    /**
-     * Reload data from storage when needed
-     */
-    function _reloadData(){
-        var data = "{}";
-
-        if(_backend == "userDataBehavior"){
-            _storage_elm.load("jStorage");
-
-            try{
-                data = _storage_elm.getAttribute("jStorage");
-            }catch(E5){}
-
-            try{
-                _observer_update = _storage_elm.getAttribute("jStorage_update");
-            }catch(E6){}
-
-            _storage_service.jStorage = data;
-        }
-
-        _load_storage();
-
-        // remove dead keys
-        _handleTTL();
-
-        _handlePubSub();
-    }
-
-    /**
-     * Sets up a storage change observer
-     */
-    function _setupObserver(){
-        if(_backend == "localStorage" || _backend == "globalStorage"){
-            if("addEventListener" in window){
-                window.addEventListener("storage", _storageObserver, false);
-            }else{
-                document.attachEvent("onstorage", _storageObserver);
-            }
-        }else if(_backend == "userDataBehavior"){
-            setInterval(_storageObserver, 1000);
-        }
-    }
-
-    /**
-     * Fired on any kind of data change, needs to check if anything has
-     * really been changed
-     */
-    function _storageObserver(){
-        var updateTime;
-        // cumulate change notifications with timeout
-        clearTimeout(_observer_timeout);
-        _observer_timeout = setTimeout(function(){
-
-            if(_backend == "localStorage" || _backend == "globalStorage"){
-                updateTime = _storage_service.jStorage_update;
-            }else if(_backend == "userDataBehavior"){
-                _storage_elm.load("jStorage");
-                try{
-                    updateTime = _storage_elm.getAttribute("jStorage_update");
-                }catch(E5){}
-            }
-
-            if(updateTime && updateTime != _observer_update){
-                _observer_update = updateTime;
-                _checkUpdatedKeys();
-            }
-
-        }, 25);
-    }
-
-    /**
-     * Reloads the data and checks if any keys are changed
-     */
-    function _checkUpdatedKeys(){
-        var oldCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)),
-            newCrc32List;
-
-        _reloadData();
-        newCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32));
-
-        var key,
-            updated = [],
-            removed = [];
-
-        for(key in oldCrc32List){
-            if(oldCrc32List.hasOwnProperty(key)){
-                if(!newCrc32List[key]){
-                    removed.push(key);
-                    continue;
-                }
-                if(oldCrc32List[key] != newCrc32List[key] && String(oldCrc32List[key]).substr(0,2) == "2."){
-                    updated.push(key);
-                }
-            }
-        }
-
-        for(key in newCrc32List){
-            if(newCrc32List.hasOwnProperty(key)){
-                if(!oldCrc32List[key]){
-                    updated.push(key);
-                }
-            }
-        }
-
-        _fireObservers(updated, "updated");
-        _fireObservers(removed, "deleted");
-    }
-
-    /**
-     * Fires observers for updated keys
-     *
-     * @param {Array|String} keys Array of key names or a key
-     * @param {String} action What happened with the value (updated, deleted, flushed)
-     */
-    function _fireObservers(keys, action){
-        keys = [].concat(keys || []);
-        if(action == "flushed"){
-            keys = [];
-            for(var key in _observers){
-                if(_observers.hasOwnProperty(key)){
-                    keys.push(key);
-                }
-            }
-            action = "deleted";
-        }
-        for(var i=0, len = keys.length; i<len; i++){
-            if(_observers[keys[i]]){
-                for(var j=0, jlen = _observers[keys[i]].length; j<jlen; j++){
-                    _observers[keys[i]][j](keys[i], action);
-                }
-            }
-            if(_observers["*"]){
-                for(var j=0, jlen = _observers["*"].length; j<jlen; j++){
-                    _observers["*"][j](keys[i], action);
-                }
-            }
-        }
-    }
-
-    /**
-     * Publishes key change to listeners
-     */
-    function _publishChange(){
-        var updateTime = (+new Date()).toString();
-
-        if(_backend == "localStorage" || _backend == "globalStorage"){
-            try {
-                _storage_service.jStorage_update = updateTime;
-            } catch (E8) {
-                // safari private mode has been enabled after the jStorage initialization
-                _backend = false;
-            }
-        }else if(_backend == "userDataBehavior"){
-            _storage_elm.setAttribute("jStorage_update", updateTime);
-            _storage_elm.save("jStorage");
-        }
-
-        _storageObserver();
-    }
-
-    /**
-     * Loads the data from the storage based on the supported mechanism
-     */
-    function _load_storage(){
-        /* if jStorage string is retrieved, then decode it */
-        if(_storage_service.jStorage){
-            try{
-                _storage = JSON.parse(String(_storage_service.jStorage));
-            }catch(E6){_storage_service.jStorage = "{}";}
-        }else{
-            _storage_service.jStorage = "{}";
-        }
-        _storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0;
-
-        if(!_storage.__jstorage_meta){
-            _storage.__jstorage_meta = {};
-        }
-        if(!_storage.__jstorage_meta.CRC32){
-            _storage.__jstorage_meta.CRC32 = {};
-        }
-    }
-
-    /**
-     * This functions provides the "save" mechanism to store the jStorage object
-     */
-    function _save(){
-        _dropOldEvents(); // remove expired events
-        try{
-            _storage_service.jStorage = JSON.stringify(_storage);
-            // If userData is used as the storage engine, additional
-            if(_storage_elm) {
-                _storage_elm.setAttribute("jStorage",_storage_service.jStorage);
-                _storage_elm.save("jStorage");
-            }
-            _storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0;
-        }catch(E7){/* probably cache is full, nothing is saved this way*/}
-    }
-
-    /**
-     * Function checks if a key is set and is string or numberic
-     *
-     * @param {String} key Key name
-     */
-    function _checkKey(key){
-        if(typeof key != "string" && typeof key != "number"){
-            throw new TypeError("Key name must be string or numeric");
-        }
-        if(key == "__jstorage_meta"){
-            throw new TypeError("Reserved key name");
-        }
-        return true;
-    }
-
-    /**
-     * Removes expired keys
-     */
-    function _handleTTL(){
-        var curtime, i, TTL, CRC32, nextExpire = Infinity, changed = false, deleted = [];
-
-        clearTimeout(_ttl_timeout);
-
-        if(!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL != "object"){
-            // nothing to do here
-            return;
-        }
-
-        curtime = +new Date();
-        TTL = _storage.__jstorage_meta.TTL;
-
-        CRC32 = _storage.__jstorage_meta.CRC32;
-        for(i in TTL){
-            if(TTL.hasOwnProperty(i)){
-                if(TTL[i] <= curtime){
-                    delete TTL[i];
-                    delete CRC32[i];
-                    delete _storage[i];
-                    changed = true;
-                    deleted.push(i);
-                }else if(TTL[i] < nextExpire){
-                    nextExpire = TTL[i];
-                }
-            }
-        }
-
-        // set next check
-        if(nextExpire != Infinity){
-            _ttl_timeout = setTimeout(_handleTTL, nextExpire - curtime);
-        }
-
-        // save changes
-        if(changed){
-            _save();
-            _publishChange();
-            _fireObservers(deleted, "deleted");
-        }
-    }
-
-    /**
-     * Checks if there's any events on hold to be fired to listeners
-     */
-    function _handlePubSub(){
-        var i, len;
-        if(!_storage.__jstorage_meta.PubSub){
-            return;
-        }
-        var pubelm,
-            _pubsubCurrent = _pubsub_last;
-
-        for(i=len=_storage.__jstorage_meta.PubSub.length-1; i>=0; i--){
-            pubelm = _storage.__jstorage_meta.PubSub[i];
-            if(pubelm[0] > _pubsub_last){
-                _pubsubCurrent = pubelm[0];
-                _fireSubscribers(pubelm[1], pubelm[2]);
-            }
-        }
-
-        _pubsub_last = _pubsubCurrent;
-    }
-
-    /**
-     * Fires all subscriber listeners for a pubsub channel
-     *
-     * @param {String} channel Channel name
-     * @param {Mixed} payload Payload data to deliver
-     */
-    function _fireSubscribers(channel, payload){
-        if(_pubsub_observers[channel]){
-            for(var i=0, len = _pubsub_observers[channel].length; i<len; i++){
-                // send immutable data that can't be modified by listeners
-                try{
-                    _pubsub_observers[channel][i](channel, JSON.parse(JSON.stringify(payload)));
-                }catch(E){};
-            }
-        }
-    }
-
-    /**
-     * Remove old events from the publish stream (at least 2sec old)
-     */
-    function _dropOldEvents(){
-        if(!_storage.__jstorage_meta.PubSub){
-            return;
-        }
-
-        var retire = +new Date() - 2000;
-
-        for(var i=0, len = _storage.__jstorage_meta.PubSub.length; i<len; i++){
-            if(_storage.__jstorage_meta.PubSub[i][0] <= retire){
-                // deleteCount is needed for IE6
-                _storage.__jstorage_meta.PubSub.splice(i, _storage.__jstorage_meta.PubSub.length - i);
-                break;
-            }
-        }
-
-        if(!_storage.__jstorage_meta.PubSub.length){
-            delete _storage.__jstorage_meta.PubSub;
-        }
-
-    }
-
-    /**
-     * Publish payload to a channel
-     *
-     * @param {String} channel Channel name
-     * @param {Mixed} payload Payload to send to the subscribers
-     */
-    function _publish(channel, payload){
-        if(!_storage.__jstorage_meta){
-            _storage.__jstorage_meta = {};
-        }
-        if(!_storage.__jstorage_meta.PubSub){
-            _storage.__jstorage_meta.PubSub = [];
-        }
-
-        _storage.__jstorage_meta.PubSub.unshift([+new Date, channel, payload]);
-
-        _save();
-        _publishChange();
-    }
-
-
-    /**
-     * JS Implementation of MurmurHash2
-     *
-     *  SOURCE: https://github.com/garycourt/murmurhash-js (MIT licensed)
-     *
-     * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
-     * @see http://github.com/garycourt/murmurhash-js
-     * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
-     * @see http://sites.google.com/site/murmurhash/
-     *
-     * @param {string} str ASCII only
-     * @param {number} seed Positive integer only
-     * @return {number} 32-bit positive integer hash
-     */
-
-    function murmurhash2_32_gc(str, seed) {
-        var
-            l = str.length,
-            h = seed ^ l,
-            i = 0,
-            k;
-
-        while (l >= 4) {
-            k =
-                ((str.charCodeAt(i) & 0xff)) |
-                ((str.charCodeAt(++i) & 0xff) << 8) |
-                ((str.charCodeAt(++i) & 0xff) << 16) |
-                ((str.charCodeAt(++i) & 0xff) << 24);
-
-            k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
-            k ^= k >>> 24;
-            k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
-
-            h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
-
-            l -= 4;
-            ++i;
-        }
-
-        switch (l) {
-            case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
-            case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
-            case 1: h ^= (str.charCodeAt(i) & 0xff);
-                h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
-        }
-
-        h ^= h >>> 13;
-        h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
-        h ^= h >>> 15;
-
-        return h >>> 0;
-    }
-
-    ////////////////////////// PUBLIC INTERFACE /////////////////////////
-
-    $.jStorage = {
-        /* Version number */
-        version: JSTORAGE_VERSION,
-
-        /**
-         * Sets a key's value.
-         *
-         * @param {String} key Key to set. If this value is not set or not
-         *              a string an exception is raised.
-         * @param {Mixed} value Value to set. This can be any value that is JSON
-         *              compatible (Numbers, Strings, Objects etc.).
-         * @param {Object} [options] - possible options to use
-         * @param {Number} [options.TTL] - optional TTL value
-         * @return {Mixed} the used value
-         */
-        set: function(key, value, options){
-            _checkKey(key);
-
-            options = options || {};
-
-            // undefined values are deleted automatically
-            if(typeof value == "undefined"){
-                this.deleteKey(key);
-                return value;
-            }
-
-            if(_XMLService.isXML(value)){
-                value = {_is_xml:true,xml:_XMLService.encode(value)};
-            }else if(typeof value == "function"){
-                return undefined; // functions can't be saved!
-            }else if(value && typeof value == "object"){
-                // clone the object before saving to _storage tree
-                value = JSON.parse(JSON.stringify(value));
-            }
-
-            _storage[key] = value;
-
-            _storage.__jstorage_meta.CRC32[key] = "2." + murmurhash2_32_gc(JSON.stringify(value), 0x9747b28c);
-
-            this.setTTL(key, options.TTL || 0); // also handles saving and _publishChange
-
-            _fireObservers(key, "updated");
-            return value;
-        },
-
-        /**
-         * Looks up a key in cache
-         *
-         * @param {String} key - Key to look up.
-         * @param {mixed} def - Default value to return, if key didn't exist.
-         * @return {Mixed} the key value, default value or null
-         */
-        get: function(key, def){
-            _checkKey(key);
-            if(key in _storage){
-                if(_storage[key] && typeof _storage[key] == "object" && _storage[key]._is_xml) {
-                    return _XMLService.decode(_storage[key].xml);
-                }else{
-                    return _storage[key];
-                }
-            }
-            return typeof(def) == "undefined" ? null : def;
-        },
-
-        /**
-         * Deletes a key from cache.
-         *
-         * @param {String} key - Key to delete.
-         * @return {Boolean} true if key existed or false if it didn't
-         */
-        deleteKey: function(key){
-            _checkKey(key);
-            if(key in _storage){
-                delete _storage[key];
-                // remove from TTL list
-                if(typeof _storage.__jstorage_meta.TTL == "object" &&
-                  key in _storage.__jstorage_meta.TTL){
-                    delete _storage.__jstorage_meta.TTL[key];
-                }
-
-                delete _storage.__jstorage_meta.CRC32[key];
-
-                _save();
-                _publishChange();
-                _fireObservers(key, "deleted");
-                return true;
-            }
-            return false;
-        },
-
-        /**
-         * Sets a TTL for a key, or remove it if ttl value is 0 or below
-         *
-         * @param {String} key - key to set the TTL for
-         * @param {Number} ttl - TTL timeout in milliseconds
-         * @return {Boolean} true if key existed or false if it didn't
-         */
-        setTTL: function(key, ttl){
-            var curtime = +new Date();
-            _checkKey(key);
-            ttl = Number(ttl) || 0;
-            if(key in _storage){
-
-                if(!_storage.__jstorage_meta.TTL){
-                    _storage.__jstorage_meta.TTL = {};
-                }
-
-                // Set TTL value for the key
-                if(ttl>0){
-                    _storage.__jstorage_meta.TTL[key] = curtime + ttl;
-                }else{
-                    delete _storage.__jstorage_meta.TTL[key];
-                }
-
-                _save();
-
-                _handleTTL();
-
-                _publishChange();
-                return true;
-            }
-            return false;
-        },
-
-        /**
-         * Gets remaining TTL (in milliseconds) for a key or 0 when no TTL has been set
-         *
-         * @param {String} key Key to check
-         * @return {Number} Remaining TTL in milliseconds
-         */
-        getTTL: function(key){
-            var curtime = +new Date(), ttl;
-            _checkKey(key);
-            if(key in _storage && _storage.__jstorage_meta.TTL && _storage.__jstorage_meta.TTL[key]){
-                ttl = _storage.__jstorage_meta.TTL[key] - curtime;
-                return ttl || 0;
-            }
-            return 0;
-        },
-
-        /**
-         * Deletes everything in cache.
-         *
-         * @return {Boolean} Always true
-         */
-        flush: function(){
-            _storage = {__jstorage_meta:{CRC32:{}}};
-            _save();
-            _publishChange();
-            _fireObservers(null, "flushed");
-            return true;
-        },
-
-        /**
-         * Returns a read-only copy of _storage
-         *
-         * @return {Object} Read-only copy of _storage
-        */
-        storageObj: function(){
-            function F() {}
-            F.prototype = _storage;
-            return new F();
-        },
-
-        /**
-         * Returns an index of all used keys as an array
-         * ["key1", "key2",.."keyN"]
-         *
-         * @return {Array} Used keys
-        */
-        index: function(){
-            var index = [], i;
-            for(i in _storage){
-                if(_storage.hasOwnProperty(i) && i != "__jstorage_meta"){
-                    index.push(i);
-                }
-            }
-            return index;
-        },
-
-        /**
-         * How much space in bytes does the storage take?
-         *
-         * @return {Number} Storage size in chars (not the same as in bytes,
-         *                  since some chars may take several bytes)
-         */
-        storageSize: function(){
-            return _storage_size;
-        },
-
-        /**
-         * Which backend is currently in use?
-         *
-         * @return {String} Backend name
-         */
-        currentBackend: function(){
-            return _backend;
-        },
-
-        /**
-         * Test if storage is available
-         *
-         * @return {Boolean} True if storage can be used
-         */
-        storageAvailable: function(){
-            return !!_backend;
-        },
-
-        /**
-         * Register change listeners
-         *
-         * @param {String} key Key name
-         * @param {Function} callback Function to run when the key changes
-         */
-        listenKeyChange: function(key, callback){
-            _checkKey(key);
-            if(!_observers[key]){
-                _observers[key] = [];
-            }
-            _observers[key].push(callback);
-        },
-
-        /**
-         * Remove change listeners
-         *
-         * @param {String} key Key name to unregister listeners against
-         * @param {Function} [callback] If set, unregister the callback, if not - unregister all
-         */
-        stopListening: function(key, callback){
-            _checkKey(key);
-
-            if(!_observers[key]){
-                return;
-            }
-
-            if(!callback){
-                delete _observers[key];
-                return;
-            }
-
-            for(var i = _observers[key].length - 1; i>=0; i--){
-                if(_observers[key][i] == callback){
-                    _observers[key].splice(i,1);
-                }
-            }
-        },
-
-        /**
-         * Subscribe to a Publish/Subscribe event stream
-         *
-         * @param {String} channel Channel name
-         * @param {Function} callback Function to run when the something is published to the channel
-         */
-        subscribe: function(channel, callback){
-            channel = (channel || "").toString();
-            if(!channel){
-                throw new TypeError("Channel not defined");
-            }
-            if(!_pubsub_observers[channel]){
-                _pubsub_observers[channel] = [];
-            }
-            _pubsub_observers[channel].push(callback);
-        },
-
-        /**
-         * Publish data to an event stream
-         *
-         * @param {String} channel Channel name
-         * @param {Mixed} payload Payload to deliver
-         */
-        publish: function(channel, payload){
-            channel = (channel || "").toString();
-            if(!channel){
-                throw new TypeError("Channel not defined");
-            }
-
-            _publish(channel, payload);
-        },
-
-        /**
-         * Reloads the data from browser storage
-         */
-        reInit: function(){
-            _reloadData();
-        },
-
-        /**
-         * Removes reference from global objects and saves it as jStorage
-         *
-         * @param {Boolean} option if needed to save object as simple "jStorage" in windows context
-         */
-         noConflict: function( saveInGlobal ) {
-            delete window.$.jStorage
-
-            if ( saveInGlobal ) {
-                window.jStorage = this;
-            }
-
-            return this;
-         }
-    };
-
-    // Initialize jStorage
-    _init();
-
-})();
diff --git a/resources/jquery/jquery.js b/resources/jquery/jquery.js
deleted file mode 100644 (file)
index a86bf79..0000000
+++ /dev/null
@@ -1,9472 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.8.3
- * http://jquery.com/
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: Tue Nov 13 2012 08:20:33 GMT-0500 (Eastern Standard Time)
- */
-(function( window, undefined ) {
-var
-       // A central reference to the root jQuery(document)
-       rootjQuery,
-
-       // The deferred used on DOM ready
-       readyList,
-
-       // Use the correct document accordingly with window argument (sandbox)
-       document = window.document,
-       location = window.location,
-       navigator = window.navigator,
-
-       // Map over jQuery in case of overwrite
-       _jQuery = window.jQuery,
-
-       // Map over the $ in case of overwrite
-       _$ = window.$,
-
-       // Save a reference to some core methods
-       core_push = Array.prototype.push,
-       core_slice = Array.prototype.slice,
-       core_indexOf = Array.prototype.indexOf,
-       core_toString = Object.prototype.toString,
-       core_hasOwn = Object.prototype.hasOwnProperty,
-       core_trim = String.prototype.trim,
-
-       // Define a local copy of jQuery
-       jQuery = function( selector, context ) {
-               // The jQuery object is actually just the init constructor 'enhanced'
-               return new jQuery.fn.init( selector, context, rootjQuery );
-       },
-
-       // Used for matching numbers
-       core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,
-
-       // Used for detecting and trimming whitespace
-       core_rnotwhite = /\S/,
-       core_rspace = /\s+/,
-
-       // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
-       rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
-
-       // A simple way to check for HTML strings
-       // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
-       rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
-
-       // Match a standalone tag
-       rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
-
-       // JSON RegExp
-       rvalidchars = /^[\],:{}\s]*$/,
-       rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
-       rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
-       rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,
-
-       // Matches dashed string for camelizing
-       rmsPrefix = /^-ms-/,
-       rdashAlpha = /-([\da-z])/gi,
-
-       // Used by jQuery.camelCase as callback to replace()
-       fcamelCase = function( all, letter ) {
-               return ( letter + "" ).toUpperCase();
-       },
-
-       // The ready event handler and self cleanup method
-       DOMContentLoaded = function() {
-               if ( document.addEventListener ) {
-                       document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
-                       jQuery.ready();
-               } else if ( document.readyState === "complete" ) {
-                       // we're here because readyState === "complete" in oldIE
-                       // which is good enough for us to call the dom ready!
-                       document.detachEvent( "onreadystatechange", DOMContentLoaded );
-                       jQuery.ready();
-               }
-       },
-
-       // [[Class]] -> type pairs
-       class2type = {};
-
-jQuery.fn = jQuery.prototype = {
-       constructor: jQuery,
-       init: function( selector, context, rootjQuery ) {
-               var match, elem, ret, doc;
-
-               // Handle $(""), $(null), $(undefined), $(false)
-               if ( !selector ) {
-                       return this;
-               }
-
-               // Handle $(DOMElement)
-               if ( selector.nodeType ) {
-                       this.context = this[0] = selector;
-                       this.length = 1;
-                       return this;
-               }
-
-               // Handle HTML strings
-               if ( typeof selector === "string" ) {
-                       if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
-                               // Assume that strings that start and end with <> are HTML and skip the regex check
-                               match = [ null, selector, null ];
-
-                       } else {
-                               match = rquickExpr.exec( selector );
-                       }
-
-                       // Match html or make sure no context is specified for #id
-                       if ( match && (match[1] || !context) ) {
-
-                               // HANDLE: $(html) -> $(array)
-                               if ( match[1] ) {
-                                       context = context instanceof jQuery ? context[0] : context;
-                                       doc = ( context && context.nodeType ? context.ownerDocument || context : document );
-
-                                       // scripts is true for back-compat
-                                       selector = jQuery.parseHTML( match[1], doc, true );
-                                       if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
-                                               this.attr.call( selector, context, true );
-                                       }
-
-                                       return jQuery.merge( this, selector );
-
-                               // HANDLE: $(#id)
-                               } else {
-                                       elem = document.getElementById( match[2] );
-
-                                       // Check parentNode to catch when Blackberry 4.6 returns
-                                       // nodes that are no longer in the document #6963
-                                       if ( elem && elem.parentNode ) {
-                                               // Handle the case where IE and Opera return items
-                                               // by name instead of ID
-                                               if ( elem.id !== match[2] ) {
-                                                       return rootjQuery.find( selector );
-                                               }
-
-                                               // Otherwise, we inject the element directly into the jQuery object
-                                               this.length = 1;
-                                               this[0] = elem;
-                                       }
-
-                                       this.context = document;
-                                       this.selector = selector;
-                                       return this;
-                               }
-
-                       // HANDLE: $(expr, $(...))
-                       } else if ( !context || context.jquery ) {
-                               return ( context || rootjQuery ).find( selector );
-
-                       // HANDLE: $(expr, context)
-                       // (which is just equivalent to: $(context).find(expr)
-                       } else {
-                               return this.constructor( context ).find( selector );
-                       }
-
-               // HANDLE: $(function)
-               // Shortcut for document ready
-               } else if ( jQuery.isFunction( selector ) ) {
-                       return rootjQuery.ready( selector );
-               }
-
-               if ( selector.selector !== undefined ) {
-                       this.selector = selector.selector;
-                       this.context = selector.context;
-               }
-
-               return jQuery.makeArray( selector, this );
-       },
-
-       // Start with an empty selector
-       selector: "",
-
-       // The current version of jQuery being used
-       jquery: "1.8.3",
-
-       // The default length of a jQuery object is 0
-       length: 0,
-
-       // The number of elements contained in the matched element set
-       size: function() {
-               return this.length;
-       },
-
-       toArray: function() {
-               return core_slice.call( this );
-       },
-
-       // Get the Nth element in the matched element set OR
-       // Get the whole matched element set as a clean array
-       get: function( num ) {
-               return num == null ?
-
-                       // Return a 'clean' array
-                       this.toArray() :
-
-                       // Return just the object
-                       ( num < 0 ? this[ this.length + num ] : this[ num ] );
-       },
-
-       // Take an array of elements and push it onto the stack
-       // (returning the new matched element set)
-       pushStack: function( elems, name, selector ) {
-
-               // Build a new jQuery matched element set
-               var ret = jQuery.merge( this.constructor(), elems );
-
-               // Add the old object onto the stack (as a reference)
-               ret.prevObject = this;
-
-               ret.context = this.context;
-
-               if ( name === "find" ) {
-                       ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
-               } else if ( name ) {
-                       ret.selector = this.selector + "." + name + "(" + selector + ")";
-               }
-
-               // Return the newly-formed element set
-               return ret;
-       },
-
-       // Execute a callback for every element in the matched set.
-       // (You can seed the arguments with an array of args, but this is
-       // only used internally.)
-       each: function( callback, args ) {
-               return jQuery.each( this, callback, args );
-       },
-
-       ready: function( fn ) {
-               // Add the callback
-               jQuery.ready.promise().done( fn );
-
-               return this;
-       },
-
-       eq: function( i ) {
-               i = +i;
-               return i === -1 ?
-                       this.slice( i ) :
-                       this.slice( i, i + 1 );
-       },
-
-       first: function() {
-               return this.eq( 0 );
-       },
-
-       last: function() {
-               return this.eq( -1 );
-       },
-
-       slice: function() {
-               return this.pushStack( core_slice.apply( this, arguments ),
-                       "slice", core_slice.call(arguments).join(",") );
-       },
-
-       map: function( callback ) {
-               return this.pushStack( jQuery.map(this, function( elem, i ) {
-                       return callback.call( elem, i, elem );
-               }));
-       },
-
-       end: function() {
-               return this.prevObject || this.constructor(null);
-       },
-
-       // For internal use only.
-       // Behaves like an Array's method, not like a jQuery method.
-       push: core_push,
-       sort: [].sort,
-       splice: [].splice
-};
-
-// Give the init function the jQuery prototype for later instantiation
-jQuery.fn.init.prototype = jQuery.fn;
-
-jQuery.extend = jQuery.fn.extend = function() {
-       var options, name, src, copy, copyIsArray, clone,
-               target = arguments[0] || {},
-               i = 1,
-               length = arguments.length,
-               deep = false;
-
-       // Handle a deep copy situation
-       if ( typeof target === "boolean" ) {
-               deep = target;
-               target = arguments[1] || {};
-               // skip the boolean and the target
-               i = 2;
-       }
-
-       // Handle case when target is a string or something (possible in deep copy)
-       if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
-               target = {};
-       }
-
-       // extend jQuery itself if only one argument is passed
-       if ( length === i ) {
-               target = this;
-               --i;
-       }
-
-       for ( ; i < length; i++ ) {
-               // Only deal with non-null/undefined values
-               if ( (options = arguments[ i ]) != null ) {
-                       // Extend the base object
-                       for ( name in options ) {
-                               src = target[ name ];
-                               copy = options[ name ];
-
-                               // Prevent never-ending loop
-                               if ( target === copy ) {
-                                       continue;
-                               }
-
-                               // Recurse if we're merging plain objects or arrays
-                               if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
-                                       if ( copyIsArray ) {
-                                               copyIsArray = false;
-                                               clone = src && jQuery.isArray(src) ? src : [];
-
-                                       } else {
-                                               clone = src && jQuery.isPlainObject(src) ? src : {};
-                                       }
-
-                                       // Never move original objects, clone them
-                                       target[ name ] = jQuery.extend( deep, clone, copy );
-
-                               // Don't bring in undefined values
-                               } else if ( copy !== undefined ) {
-                                       target[ name ] = copy;
-                               }
-                       }
-               }
-       }
-
-       // Return the modified object
-       return target;
-};
-
-jQuery.extend({
-       noConflict: function( deep ) {
-               if ( window.$ === jQuery ) {
-                       window.$ = _$;
-               }
-
-               if ( deep && window.jQuery === jQuery ) {
-                       window.jQuery = _jQuery;
-               }
-
-               return jQuery;
-       },
-
-       // Is the DOM ready to be used? Set to true once it occurs.
-       isReady: false,
-
-       // A counter to track how many items to wait for before
-       // the ready event fires. See #6781
-       readyWait: 1,
-
-       // Hold (or release) the ready event
-       holdReady: function( hold ) {
-               if ( hold ) {
-                       jQuery.readyWait++;
-               } else {
-                       jQuery.ready( true );
-               }
-       },
-
-       // Handle when the DOM is ready
-       ready: function( wait ) {
-
-               // Abort if there are pending holds or we're already ready
-               if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
-                       return;
-               }
-
-               // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
-               if ( !document.body ) {
-                       return setTimeout( jQuery.ready, 1 );
-               }
-
-               // Remember that the DOM is ready
-               jQuery.isReady = true;
-
-               // If a normal DOM Ready event fired, decrement, and wait if need be
-               if ( wait !== true && --jQuery.readyWait > 0 ) {
-                       return;
-               }
-
-               // If there are functions bound, to execute
-               readyList.resolveWith( document, [ jQuery ] );
-
-               // Trigger any bound ready events
-               if ( jQuery.fn.trigger ) {
-                       jQuery( document ).trigger("ready").off("ready");
-               }
-       },
-
-       // See test/unit/core.js for details concerning isFunction.
-       // Since version 1.3, DOM methods and functions like alert
-       // aren't supported. They return false on IE (#2968).
-       isFunction: function( obj ) {
-               return jQuery.type(obj) === "function";
-       },
-
-       isArray: Array.isArray || function( obj ) {
-               return jQuery.type(obj) === "array";
-       },
-
-       isWindow: function( obj ) {
-               return obj != null && obj == obj.window;
-       },
-
-       isNumeric: function( obj ) {
-               return !isNaN( parseFloat(obj) ) && isFinite( obj );
-       },
-
-       type: function( obj ) {
-               return obj == null ?
-                       String( obj ) :
-                       class2type[ core_toString.call(obj) ] || "object";
-       },
-
-       isPlainObject: function( obj ) {
-               // Must be an Object.
-               // Because of IE, we also have to check the presence of the constructor property.
-               // Make sure that DOM nodes and window objects don't pass through, as well
-               if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
-                       return false;
-               }
-
-               try {
-                       // Not own constructor property must be Object
-                       if ( obj.constructor &&
-                               !core_hasOwn.call(obj, "constructor") &&
-                               !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
-                               return false;
-                       }
-               } catch ( e ) {
-                       // IE8,9 Will throw exceptions on certain host objects #9897
-                       return false;
-               }
-
-               // Own properties are enumerated firstly, so to speed up,
-               // if last one is own, then all properties are own.
-
-               var key;
-               for ( key in obj ) {}
-
-               return key === undefined || core_hasOwn.call( obj, key );
-       },
-
-       isEmptyObject: function( obj ) {
-               var name;
-               for ( name in obj ) {
-                       return false;
-               }
-               return true;
-       },
-
-       error: function( msg ) {
-               throw new Error( msg );
-       },
-
-       // data: string of html
-       // context (optional): If specified, the fragment will be created in this context, defaults to document
-       // scripts (optional): If true, will include scripts passed in the html string
-       parseHTML: function( data, context, scripts ) {
-               var parsed;
-               if ( !data || typeof data !== "string" ) {
-                       return null;
-               }
-               if ( typeof context === "boolean" ) {
-                       scripts = context;
-                       context = 0;
-               }
-               context = context || document;
-
-               // Single tag
-               if ( (parsed = rsingleTag.exec( data )) ) {
-                       return [ context.createElement( parsed[1] ) ];
-               }
-
-               parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );
-               return jQuery.merge( [],
-                       (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );
-       },
-
-       parseJSON: function( data ) {
-               if ( !data || typeof data !== "string") {
-                       return null;
-               }
-
-               // Make sure leading/trailing whitespace is removed (IE can't handle it)
-               data = jQuery.trim( data );
-
-               // Attempt to parse using the native JSON parser first
-               if ( window.JSON && window.JSON.parse ) {
-                       return window.JSON.parse( data );
-               }
-
-               // Make sure the incoming data is actual JSON
-               // Logic borrowed from http://json.org/json2.js
-               if ( rvalidchars.test( data.replace( rvalidescape, "@" )
-                       .replace( rvalidtokens, "]" )
-                       .replace( rvalidbraces, "")) ) {
-
-                       return ( new Function( "return " + data ) )();
-
-               }
-               jQuery.error( "Invalid JSON: " + data );
-       },
-
-       // Cross-browser xml parsing
-       parseXML: function( data ) {
-               var xml, tmp;
-               if ( !data || typeof data !== "string" ) {
-                       return null;
-               }
-               try {
-                       if ( window.DOMParser ) { // Standard
-                               tmp = new DOMParser();
-                               xml = tmp.parseFromString( data , "text/xml" );
-                       } else { // IE
-                               xml = new ActiveXObject( "Microsoft.XMLDOM" );
-                               xml.async = "false";
-                               xml.loadXML( data );
-                       }
-               } catch( e ) {
-                       xml = undefined;
-               }
-               if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
-                       jQuery.error( "Invalid XML: " + data );
-               }
-               return xml;
-       },
-
-       noop: function() {},
-
-       // Evaluates a script in a global context
-       // Workarounds based on findings by Jim Driscoll
-       // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
-       globalEval: function( data ) {
-               if ( data && core_rnotwhite.test( data ) ) {
-                       // We use execScript on Internet Explorer
-                       // We use an anonymous function so that context is window
-                       // rather than jQuery in Firefox
-                       ( window.execScript || function( data ) {
-                               window[ "eval" ].call( window, data );
-                       } )( data );
-               }
-       },
-
-       // Convert dashed to camelCase; used by the css and data modules
-       // Microsoft forgot to hump their vendor prefix (#9572)
-       camelCase: function( string ) {
-               return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
-       },
-
-       nodeName: function( elem, name ) {
-               return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
-       },
-
-       // args is for internal usage only
-       each: function( obj, callback, args ) {
-               var name,
-                       i = 0,
-                       length = obj.length,
-                       isObj = length === undefined || jQuery.isFunction( obj );
-
-               if ( args ) {
-                       if ( isObj ) {
-                               for ( name in obj ) {
-                                       if ( callback.apply( obj[ name ], args ) === false ) {
-                                               break;
-                                       }
-                               }
-                       } else {
-                               for ( ; i < length; ) {
-                                       if ( callback.apply( obj[ i++ ], args ) === false ) {
-                                               break;
-                                       }
-                               }
-                       }
-
-               // A special, fast, case for the most common use of each
-               } else {
-                       if ( isObj ) {
-                               for ( name in obj ) {
-                                       if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {
-                                               break;
-                                       }
-                               }
-                       } else {
-                               for ( ; i < length; ) {
-                                       if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {
-                                               break;
-                                       }
-                               }
-                       }
-               }
-
-               return obj;
-       },
-
-       // Use native String.trim function wherever possible
-       trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
-               function( text ) {
-                       return text == null ?
-                               "" :
-                               core_trim.call( text );
-               } :
-
-               // Otherwise use our own trimming functionality
-               function( text ) {
-                       return text == null ?
-                               "" :
-                               ( text + "" ).replace( rtrim, "" );
-               },
-
-       // results is for internal usage only
-       makeArray: function( arr, results ) {
-               var type,
-                       ret = results || [];
-
-               if ( arr != null ) {
-                       // The window, strings (and functions) also have 'length'
-                       // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
-                       type = jQuery.type( arr );
-
-                       if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) {
-                               core_push.call( ret, arr );
-                       } else {
-                               jQuery.merge( ret, arr );
-                       }
-               }
-
-               return ret;
-       },
-
-       inArray: function( elem, arr, i ) {
-               var len;
-
-               if ( arr ) {
-                       if ( core_indexOf ) {
-                               return core_indexOf.call( arr, elem, i );
-                       }
-
-                       len = arr.length;
-                       i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
-
-                       for ( ; i < len; i++ ) {
-                               // Skip accessing in sparse arrays
-                               if ( i in arr && arr[ i ] === elem ) {
-                                       return i;
-                               }
-                       }
-               }
-
-               return -1;
-       },
-
-       merge: function( first, second ) {
-               var l = second.length,
-                       i = first.length,
-                       j = 0;
-
-               if ( typeof l === "number" ) {
-                       for ( ; j < l; j++ ) {
-                               first[ i++ ] = second[ j ];
-                       }
-
-               } else {
-                       while ( second[j] !== undefined ) {
-                               first[ i++ ] = second[ j++ ];
-                       }
-               }
-
-               first.length = i;
-
-               return first;
-       },
-
-       grep: function( elems, callback, inv ) {
-               var retVal,
-                       ret = [],
-                       i = 0,
-                       length = elems.length;
-               inv = !!inv;
-
-               // Go through the array, only saving the items
-               // that pass the validator function
-               for ( ; i < length; i++ ) {
-                       retVal = !!callback( elems[ i ], i );
-                       if ( inv !== retVal ) {
-                               ret.push( elems[ i ] );
-                       }
-               }
-
-               return ret;
-       },
-
-       // arg is for internal usage only
-       map: function( elems, callback, arg ) {
-               var value, key,
-                       ret = [],
-                       i = 0,
-                       length = elems.length,
-                       // jquery objects are treated as arrays
-                       isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
-
-               // Go through the array, translating each of the items to their
-               if ( isArray ) {
-                       for ( ; i < length; i++ ) {
-                               value = callback( elems[ i ], i, arg );
-
-                               if ( value != null ) {
-                                       ret[ ret.length ] = value;
-                               }
-                       }
-
-               // Go through every key on the object,
-               } else {
-                       for ( key in elems ) {
-                               value = callback( elems[ key ], key, arg );
-
-                               if ( value != null ) {
-                                       ret[ ret.length ] = value;
-                               }
-                       }
-               }
-
-               // Flatten any nested arrays
-               return ret.concat.apply( [], ret );
-       },
-
-       // A global GUID counter for objects
-       guid: 1,
-
-       // Bind a function to a context, optionally partially applying any
-       // arguments.
-       proxy: function( fn, context ) {
-               var tmp, args, proxy;
-
-               if ( typeof context === "string" ) {
-                       tmp = fn[ context ];
-                       context = fn;
-                       fn = tmp;
-               }
-
-               // Quick check to determine if target is callable, in the spec
-               // this throws a TypeError, but we will just return undefined.
-               if ( !jQuery.isFunction( fn ) ) {
-                       return undefined;
-               }
-
-               // Simulated bind
-               args = core_slice.call( arguments, 2 );
-               proxy = function() {
-                       return fn.apply( context, args.concat( core_slice.call( arguments ) ) );
-               };
-
-               // Set the guid of unique handler to the same of original handler, so it can be removed
-               proxy.guid = fn.guid = fn.guid || jQuery.guid++;
-
-               return proxy;
-       },
-
-       // Multifunctional method to get and set values of a collection
-       // The value/s can optionally be executed if it's a function
-       access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
-               var exec,
-                       bulk = key == null,
-                       i = 0,
-                       length = elems.length;
-
-               // Sets many values
-               if ( key && typeof key === "object" ) {
-                       for ( i in key ) {
-                               jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
-                       }
-                       chainable = 1;
-
-               // Sets one value
-               } else if ( value !== undefined ) {
-                       // Optionally, function values get executed if exec is true
-                       exec = pass === undefined && jQuery.isFunction( value );
-
-                       if ( bulk ) {
-                               // Bulk operations only iterate when executing function values
-                               if ( exec ) {
-                                       exec = fn;
-                                       fn = function( elem, key, value ) {
-                                               return exec.call( jQuery( elem ), value );
-                                       };
-
-                               // Otherwise they run against the entire set
-                               } else {
-                                       fn.call( elems, value );
-                                       fn = null;
-                               }
-                       }
-
-                       if ( fn ) {
-                               for (; i < length; i++ ) {
-                                       fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
-                               }
-                       }
-
-                       chainable = 1;
-               }
-
-               return chainable ?
-                       elems :
-
-                       // Gets
-                       bulk ?
-                               fn.call( elems ) :
-                               length ? fn( elems[0], key ) : emptyGet;
-       },
-
-       now: function() {
-               return ( new Date() ).getTime();
-       }
-});
-
-jQuery.ready.promise = function( obj ) {
-       if ( !readyList ) {
-
-               readyList = jQuery.Deferred();
-
-               // Catch cases where $(document).ready() is called after the browser event has already occurred.
-               // we once tried to use readyState "interactive" here, but it caused issues like the one
-               // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
-               if ( document.readyState === "complete" ) {
-                       // Handle it asynchronously to allow scripts the opportunity to delay ready
-                       setTimeout( jQuery.ready, 1 );
-
-               // Standards-based browsers support DOMContentLoaded
-               } else if ( document.addEventListener ) {
-                       // Use the handy event callback
-                       document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
-
-                       // A fallback to window.onload, that will always work
-                       window.addEventListener( "load", jQuery.ready, false );
-
-               // If IE event model is used
-               } else {
-                       // Ensure firing before onload, maybe late but safe also for iframes
-                       document.attachEvent( "onreadystatechange", DOMContentLoaded );
-
-                       // A fallback to window.onload, that will always work
-                       window.attachEvent( "onload", jQuery.ready );
-
-                       // If IE and not a frame
-                       // continually check to see if the document is ready
-                       var top = false;
-
-                       try {
-                               top = window.frameElement == null && document.documentElement;
-                       } catch(e) {}
-
-                       if ( top && top.doScroll ) {
-                               (function doScrollCheck() {
-                                       if ( !jQuery.isReady ) {
-
-                                               try {
-                                                       // Use the trick by Diego Perini
-                                                       // http://javascript.nwbox.com/IEContentLoaded/
-                                                       top.doScroll("left");
-                                               } catch(e) {
-                                                       return setTimeout( doScrollCheck, 50 );
-                                               }
-
-                                               // and execute any waiting functions
-                                               jQuery.ready();
-                                       }
-                               })();
-                       }
-               }
-       }
-       return readyList.promise( obj );
-};
-
-// Populate the class2type map
-jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
-       class2type[ "[object " + name + "]" ] = name.toLowerCase();
-});
-
-// All jQuery objects should point back to these
-rootjQuery = jQuery(document);
-// String to Object options format cache
-var optionsCache = {};
-
-// Convert String-formatted options into Object-formatted ones and store in cache
-function createOptions( options ) {
-       var object = optionsCache[ options ] = {};
-       jQuery.each( options.split( core_rspace ), function( _, flag ) {
-               object[ flag ] = true;
-       });
-       return object;
-}
-
-/*
- * Create a callback list using the following parameters:
- *
- *     options: an optional list of space-separated options that will change how
- *                     the callback list behaves or a more traditional option object
- *
- * By default a callback list will act like an event callback list and can be
- * "fired" multiple times.
- *
- * Possible options:
- *
- *     once:                   will ensure the callback list can only be fired once (like a Deferred)
- *
- *     memory:                 will keep track of previous values and will call any callback added
- *                                     after the list has been fired right away with the latest "memorized"
- *                                     values (like a Deferred)
- *
- *     unique:                 will ensure a callback can only be added once (no duplicate in the list)
- *
- *     stopOnFalse:    interrupt callings when a callback returns false
- *
- */
-jQuery.Callbacks = function( options ) {
-
-       // Convert options from String-formatted to Object-formatted if needed
-       // (we check in cache first)
-       options = typeof options === "string" ?
-               ( optionsCache[ options ] || createOptions( options ) ) :
-               jQuery.extend( {}, options );
-
-       var // Last fire value (for non-forgettable lists)
-               memory,
-               // Flag to know if list was already fired
-               fired,
-               // Flag to know if list is currently firing
-               firing,
-               // First callback to fire (used internally by add and fireWith)
-               firingStart,
-               // End of the loop when firing
-               firingLength,
-               // Index of currently firing callback (modified by remove if needed)
-               firingIndex,
-               // Actual callback list
-               list = [],
-               // Stack of fire calls for repeatable lists
-               stack = !options.once && [],
-               // Fire callbacks
-               fire = function( data ) {
-                       memory = options.memory && data;
-                       fired = true;
-                       firingIndex = firingStart || 0;
-                       firingStart = 0;
-                       firingLength = list.length;
-                       firing = true;
-                       for ( ; list && firingIndex < firingLength; firingIndex++ ) {
-                               if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
-                                       memory = false; // To prevent further calls using add
-                                       break;
-                               }
-                       }
-                       firing = false;
-                       if ( list ) {
-                               if ( stack ) {
-                                       if ( stack.length ) {
-                                               fire( stack.shift() );
-                                       }
-                               } else if ( memory ) {
-                                       list = [];
-                               } else {
-                                       self.disable();
-                               }
-                       }
-               },
-               // Actual Callbacks object
-               self = {
-                       // Add a callback or a collection of callbacks to the list
-                       add: function() {
-                               if ( list ) {
-                                       // First, we save the current length
-                                       var start = list.length;
-                                       (function add( args ) {
-                                               jQuery.each( args, function( _, arg ) {
-                                                       var type = jQuery.type( arg );
-                                                       if ( type === "function" ) {
-                                                               if ( !options.unique || !self.has( arg ) ) {
-                                                                       list.push( arg );
-                                                               }
-                                                       } else if ( arg && arg.length && type !== "string" ) {
-                                                               // Inspect recursively
-                                                               add( arg );
-                                                       }
-                                               });
-                                       })( arguments );
-                                       // Do we need to add the callbacks to the
-                                       // current firing batch?
-                                       if ( firing ) {
-                                               firingLength = list.length;
-                                       // With memory, if we're not firing then
-                                       // we should call right away
-                                       } else if ( memory ) {
-                                               firingStart = start;
-                                               fire( memory );
-                                       }
-                               }
-                               return this;
-                       },
-                       // Remove a callback from the list
-                       remove: function() {
-                               if ( list ) {
-                                       jQuery.each( arguments, function( _, arg ) {
-                                               var index;
-                                               while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
-                                                       list.splice( index, 1 );
-                                                       // Handle firing indexes
-                                                       if ( firing ) {
-                                                               if ( index <= firingLength ) {
-                                                                       firingLength--;
-                                                               }
-                                                               if ( index <= firingIndex ) {
-                                                                       firingIndex--;
-                                                               }
-                                                       }
-                                               }
-                                       });
-                               }
-                               return this;
-                       },
-                       // Control if a given callback is in the list
-                       has: function( fn ) {
-                               return jQuery.inArray( fn, list ) > -1;
-                       },
-                       // Remove all callbacks from the list
-                       empty: function() {
-                               list = [];
-                               return this;
-                       },
-                       // Have the list do nothing anymore
-                       disable: function() {
-                               list = stack = memory = undefined;
-                               return this;
-                       },
-                       // Is it disabled?
-                       disabled: function() {
-                               return !list;
-                       },
-                       // Lock the list in its current state
-                       lock: function() {
-                               stack = undefined;
-                               if ( !memory ) {
-                                       self.disable();
-                               }
-                               return this;
-                       },
-                       // Is it locked?
-                       locked: function() {
-                               return !stack;
-                       },
-                       // Call all callbacks with the given context and arguments
-                       fireWith: function( context, args ) {
-                               args = args || [];
-                               args = [ context, args.slice ? args.slice() : args ];
-                               if ( list && ( !fired || stack ) ) {
-                                       if ( firing ) {
-                                               stack.push( args );
-                                       } else {
-                                               fire( args );
-                                       }
-                               }
-                               return this;
-                       },
-                       // Call all the callbacks with the given arguments
-                       fire: function() {
-                               self.fireWith( this, arguments );
-                               return this;
-                       },
-                       // To know if the callbacks have already been called at least once
-                       fired: function() {
-                               return !!fired;
-                       }
-               };
-
-       return self;
-};
-jQuery.extend({
-
-       Deferred: function( func ) {
-               var tuples = [
-                               // action, add listener, listener list, final state
-                               [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
-                               [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
-                               [ "notify", "progress", jQuery.Callbacks("memory") ]
-                       ],
-                       state = "pending",
-                       promise = {
-                               state: function() {
-                                       return state;
-                               },
-                               always: function() {
-                                       deferred.done( arguments ).fail( arguments );
-                                       return this;
-                               },
-                               then: function( /* fnDone, fnFail, fnProgress */ ) {
-                                       var fns = arguments;
-                                       return jQuery.Deferred(function( newDefer ) {
-                                               jQuery.each( tuples, function( i, tuple ) {
-                                                       var action = tuple[ 0 ],
-                                                               fn = fns[ i ];
-                                                       // deferred[ done | fail | progress ] for forwarding actions to newDefer
-                                                       deferred[ tuple[1] ]( jQuery.isFunction( fn ) ?
-                                                               function() {
-                                                                       var returned = fn.apply( this, arguments );
-                                                                       if ( returned && jQuery.isFunction( returned.promise ) ) {
-                                                                               returned.promise()
-                                                                                       .done( newDefer.resolve )
-                                                                                       .fail( newDefer.reject )
-                                                                                       .progress( newDefer.notify );
-                                                                       } else {
-                                                                               newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
-                                                                       }
-                                                               } :
-                                                               newDefer[ action ]
-                                                       );
-                                               });
-                                               fns = null;
-                                       }).promise();
-                               },
-                               // Get a promise for this deferred
-                               // If obj is provided, the promise aspect is added to the object
-                               promise: function( obj ) {
-                                       return obj != null ? jQuery.extend( obj, promise ) : promise;
-                               }
-                       },
-                       deferred = {};
-
-               // Keep pipe for back-compat
-               promise.pipe = promise.then;
-
-               // Add list-specific methods
-               jQuery.each( tuples, function( i, tuple ) {
-                       var list = tuple[ 2 ],
-                               stateString = tuple[ 3 ];
-
-                       // promise[ done | fail | progress ] = list.add
-                       promise[ tuple[1] ] = list.add;
-
-                       // Handle state
-                       if ( stateString ) {
-                               list.add(function() {
-                                       // state = [ resolved | rejected ]
-                                       state = stateString;
-
-                               // [ reject_list | resolve_list ].disable; progress_list.lock
-                               }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
-                       }
-
-                       // deferred[ resolve | reject | notify ] = list.fire
-                       deferred[ tuple[0] ] = list.fire;
-                       deferred[ tuple[0] + "With" ] = list.fireWith;
-               });
-
-               // Make the deferred a promise
-               promise.promise( deferred );
-
-               // Call given func if any
-               if ( func ) {
-                       func.call( deferred, deferred );
-               }
-
-               // All done!
-               return deferred;
-       },
-
-       // Deferred helper
-       when: function( subordinate /* , ..., subordinateN */ ) {
-               var i = 0,
-                       resolveValues = core_slice.call( arguments ),
-                       length = resolveValues.length,
-
-                       // the count of uncompleted subordinates
-                       remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
-
-                       // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
-                       deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
-
-                       // Update function for both resolve and progress values
-                       updateFunc = function( i, contexts, values ) {
-                               return function( value ) {
-                                       contexts[ i ] = this;
-                                       values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
-                                       if( values === progressValues ) {
-                                               deferred.notifyWith( contexts, values );
-                                       } else if ( !( --remaining ) ) {
-                                               deferred.resolveWith( contexts, values );
-                                       }
-                               };
-                       },
-
-                       progressValues, progressContexts, resolveContexts;
-
-               // add listeners to Deferred subordinates; treat others as resolved
-               if ( length > 1 ) {
-                       progressValues = new Array( length );
-                       progressContexts = new Array( length );
-                       resolveContexts = new Array( length );
-                       for ( ; i < length; i++ ) {
-                               if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
-                                       resolveValues[ i ].promise()
-                                               .done( updateFunc( i, resolveContexts, resolveValues ) )
-                                               .fail( deferred.reject )
-                                               .progress( updateFunc( i, progressContexts, progressValues ) );
-                               } else {
-                                       --remaining;
-                               }
-                       }
-               }
-
-               // if we're not waiting on anything, resolve the master
-               if ( !remaining ) {
-                       deferred.resolveWith( resolveContexts, resolveValues );
-               }
-
-               return deferred.promise();
-       }
-});
-jQuery.support = (function() {
-
-       var support,
-               all,
-               a,
-               select,
-               opt,
-               input,
-               fragment,
-               eventName,
-               i,
-               isSupported,
-               clickFn,
-               div = document.createElement("div");
-
-       // Setup
-       div.setAttribute( "className", "t" );
-       div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
-
-       // Support tests won't run in some limited or non-browser environments
-       all = div.getElementsByTagName("*");
-       a = div.getElementsByTagName("a")[ 0 ];
-       if ( !all || !a || !all.length ) {
-               return {};
-       }
-
-       // First batch of tests
-       select = document.createElement("select");
-       opt = select.appendChild( document.createElement("option") );
-       input = div.getElementsByTagName("input")[ 0 ];
-
-       a.style.cssText = "top:1px;float:left;opacity:.5";
-       support = {
-               // IE strips leading whitespace when .innerHTML is used
-               leadingWhitespace: ( div.firstChild.nodeType === 3 ),
-
-               // Make sure that tbody elements aren't automatically inserted
-               // IE will insert them into empty tables
-               tbody: !div.getElementsByTagName("tbody").length,
-
-               // Make sure that link elements get serialized correctly by innerHTML
-               // This requires a wrapper element in IE
-               htmlSerialize: !!div.getElementsByTagName("link").length,
-
-               // Get the style information from getAttribute
-               // (IE uses .cssText instead)
-               style: /top/.test( a.getAttribute("style") ),
-
-               // Make sure that URLs aren't manipulated
-               // (IE normalizes it by default)
-               hrefNormalized: ( a.getAttribute("href") === "/a" ),
-
-               // Make sure that element opacity exists
-               // (IE uses filter instead)
-               // Use a regex to work around a WebKit issue. See #5145
-               opacity: /^0.5/.test( a.style.opacity ),
-
-               // Verify style float existence
-               // (IE uses styleFloat instead of cssFloat)
-               cssFloat: !!a.style.cssFloat,
-
-               // Make sure that if no value is specified for a checkbox
-               // that it defaults to "on".
-               // (WebKit defaults to "" instead)
-               checkOn: ( input.value === "on" ),
-
-               // Make sure that a selected-by-default option has a working selected property.
-               // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
-               optSelected: opt.selected,
-
-               // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
-               getSetAttribute: div.className !== "t",
-
-               // Tests for enctype support on a form (#6743)
-               enctype: !!document.createElement("form").enctype,
-
-               // Makes sure cloning an html5 element does not cause problems
-               // Where outerHTML is undefined, this still works
-               html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
-
-               // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
-               boxModel: ( document.compatMode === "CSS1Compat" ),
-
-               // Will be defined later
-               submitBubbles: true,
-               changeBubbles: true,
-               focusinBubbles: false,
-               deleteExpando: true,
-               noCloneEvent: true,
-               inlineBlockNeedsLayout: false,
-               shrinkWrapBlocks: false,
-               reliableMarginRight: true,
-               boxSizingReliable: true,
-               pixelPosition: false
-       };
-
-       // Make sure checked status is properly cloned
-       input.checked = true;
-       support.noCloneChecked = input.cloneNode( true ).checked;
-
-       // Make sure that the options inside disabled selects aren't marked as disabled
-       // (WebKit marks them as disabled)
-       select.disabled = true;
-       support.optDisabled = !opt.disabled;
-
-       // Test to see if it's possible to delete an expando from an element
-       // Fails in Internet Explorer
-       try {
-               delete div.test;
-       } catch( e ) {
-               support.deleteExpando = false;
-       }
-
-       if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
-               div.attachEvent( "onclick", clickFn = function() {
-                       // Cloning a node shouldn't copy over any
-                       // bound event handlers (IE does this)
-                       support.noCloneEvent = false;
-               });
-               div.cloneNode( true ).fireEvent("onclick");
-               div.detachEvent( "onclick", clickFn );
-       }
-
-       // Check if a radio maintains its value
-       // after being appended to the DOM
-       input = document.createElement("input");
-       input.value = "t";
-       input.setAttribute( "type", "radio" );
-       support.radioValue = input.value === "t";
-
-       input.setAttribute( "checked", "checked" );
-
-       // #11217 - WebKit loses check when the name is after the checked attribute
-       input.setAttribute( "name", "t" );
-
-       div.appendChild( input );
-       fragment = document.createDocumentFragment();
-       fragment.appendChild( div.lastChild );
-
-       // WebKit doesn't clone checked state correctly in fragments
-       support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
-
-       // Check if a disconnected checkbox will retain its checked
-       // value of true after appended to the DOM (IE6/7)
-       support.appendChecked = input.checked;
-
-       fragment.removeChild( input );
-       fragment.appendChild( div );
-
-       // Technique from Juriy Zaytsev
-       // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
-       // We only care about the case where non-standard event systems
-       // are used, namely in IE. Short-circuiting here helps us to
-       // avoid an eval call (in setAttribute) which can cause CSP
-       // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
-       if ( div.attachEvent ) {
-               for ( i in {
-                       submit: true,
-                       change: true,
-                       focusin: true
-               }) {
-                       eventName = "on" + i;
-                       isSupported = ( eventName in div );
-                       if ( !isSupported ) {
-                               div.setAttribute( eventName, "return;" );
-                               isSupported = ( typeof div[ eventName ] === "function" );
-                       }
-                       support[ i + "Bubbles" ] = isSupported;
-               }
-       }
-
-       // Run tests that need a body at doc ready
-       jQuery(function() {
-               var container, div, tds, marginDiv,
-                       divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;",
-                       body = document.getElementsByTagName("body")[0];
-
-               if ( !body ) {
-                       // Return for frameset docs that don't have a body
-                       return;
-               }
-
-               container = document.createElement("div");
-               container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px";
-               body.insertBefore( container, body.firstChild );
-
-               // Construct the test element
-               div = document.createElement("div");
-               container.appendChild( div );
-
-               // Check if table cells still have offsetWidth/Height when they are set
-               // to display:none and there are still other visible table cells in a
-               // table row; if so, offsetWidth/Height are not reliable for use when
-               // determining if an element has been hidden directly using
-               // display:none (it is still safe to use offsets if a parent element is
-               // hidden; don safety goggles and see bug #4512 for more information).
-               // (only IE 8 fails this test)
-               div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
-               tds = div.getElementsByTagName("td");
-               tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
-               isSupported = ( tds[ 0 ].offsetHeight === 0 );
-
-               tds[ 0 ].style.display = "";
-               tds[ 1 ].style.display = "none";
-
-               // Check if empty table cells still have offsetWidth/Height
-               // (IE <= 8 fail this test)
-               support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
-
-               // Check box-sizing and margin behavior
-               div.innerHTML = "";
-               div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
-               support.boxSizing = ( div.offsetWidth === 4 );
-               support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
-
-               // NOTE: To any future maintainer, we've window.getComputedStyle
-               // because jsdom on node.js will break without it.
-               if ( window.getComputedStyle ) {
-                       support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
-                       support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
-
-                       // Check if div with explicit width and no margin-right incorrectly
-                       // gets computed margin-right based on width of container. For more
-                       // info see bug #3333
-                       // Fails in WebKit before Feb 2011 nightlies
-                       // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
-                       marginDiv = document.createElement("div");
-                       marginDiv.style.cssText = div.style.cssText = divReset;
-                       marginDiv.style.marginRight = marginDiv.style.width = "0";
-                       div.style.width = "1px";
-                       div.appendChild( marginDiv );
-                       support.reliableMarginRight =
-                               !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
-               }
-
-               if ( typeof div.style.zoom !== "undefined" ) {
-                       // Check if natively block-level elements act like inline-block
-                       // elements when setting their display to 'inline' and giving
-                       // them layout
-                       // (IE < 8 does this)
-                       div.innerHTML = "";
-                       div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
-                       support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
-
-                       // Check if elements with layout shrink-wrap their children
-                       // (IE 6 does this)
-                       div.style.display = "block";
-                       div.style.overflow = "visible";
-                       div.innerHTML = "<div></div>";
-                       div.firstChild.style.width = "5px";
-                       support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
-
-                       container.style.zoom = 1;
-               }
-
-               // Null elements to avoid leaks in IE
-               body.removeChild( container );
-               container = div = tds = marginDiv = null;
-       });
-
-       // Null elements to avoid leaks in IE
-       fragment.removeChild( div );
-       all = a = select = opt = input = fragment = div = null;
-
-       return support;
-})();
-var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
-       rmultiDash = /([A-Z])/g;
-
-jQuery.extend({
-       cache: {},
-
-       deletedIds: [],
-
-       // Remove at next major release (1.9/2.0)
-       uuid: 0,
-
-       // Unique for each copy of jQuery on the page
-       // Non-digits removed to match rinlinejQuery
-       expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
-
-       // The following elements throw uncatchable exceptions if you
-       // attempt to add expando properties to them.
-       noData: {
-               "embed": true,
-               // Ban all objects except for Flash (which handle expandos)
-               "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
-               "applet": true
-       },
-
-       hasData: function( elem ) {
-               elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
-               return !!elem && !isEmptyDataObject( elem );
-       },
-
-       data: function( elem, name, data, pvt /* Internal Use Only */ ) {
-               if ( !jQuery.acceptData( elem ) ) {
-                       return;
-               }
-
-               var thisCache, ret,
-                       internalKey = jQuery.expando,
-                       getByName = typeof name === "string",
-
-                       // We have to handle DOM nodes and JS objects differently because IE6-7
-                       // can't GC object references properly across the DOM-JS boundary
-                       isNode = elem.nodeType,
-
-                       // Only DOM nodes need the global jQuery cache; JS object data is
-                       // attached directly to the object so GC can occur automatically
-                       cache = isNode ? jQuery.cache : elem,
-
-                       // Only defining an ID for JS objects if its cache already exists allows
-                       // the code to shortcut on the same path as a DOM node with no cache
-                       id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
-
-               // Avoid doing any more work than we need to when trying to get data on an
-               // object that has no data at all
-               if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
-                       return;
-               }
-
-               if ( !id ) {
-                       // Only DOM nodes need a new unique ID for each element since their data
-                       // ends up in the global cache
-                       if ( isNode ) {
-                               elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++;
-                       } else {
-                               id = internalKey;
-                       }
-               }
-
-               if ( !cache[ id ] ) {
-                       cache[ id ] = {};
-
-                       // Avoids exposing jQuery metadata on plain JS objects when the object
-                       // is serialized using JSON.stringify
-                       if ( !isNode ) {
-                               cache[ id ].toJSON = jQuery.noop;
-                       }
-               }
-
-               // An object can be passed to jQuery.data instead of a key/value pair; this gets
-               // shallow copied over onto the existing cache
-               if ( typeof name === "object" || typeof name === "function" ) {
-                       if ( pvt ) {
-                               cache[ id ] = jQuery.extend( cache[ id ], name );
-                       } else {
-                               cache[ id ].data = jQuery.extend( cache[ id ].data, name );
-                       }
-               }
-
-               thisCache = cache[ id ];
-
-               // jQuery data() is stored in a separate object inside the object's internal data
-               // cache in order to avoid key collisions between internal data and user-defined
-               // data.
-               if ( !pvt ) {
-                       if ( !thisCache.data ) {
-                               thisCache.data = {};
-                       }
-
-                       thisCache = thisCache.data;
-               }
-
-               if ( data !== undefined ) {
-                       thisCache[ jQuery.camelCase( name ) ] = data;
-               }
-
-               // Check for both converted-to-camel and non-converted data property names
-               // If a data property was specified
-               if ( getByName ) {
-
-                       // First Try to find as-is property data
-                       ret = thisCache[ name ];
-
-                       // Test for null|undefined property data
-                       if ( ret == null ) {
-
-                               // Try to find the camelCased property
-                               ret = thisCache[ jQuery.camelCase( name ) ];
-                       }
-               } else {
-                       ret = thisCache;
-               }
-
-               return ret;
-       },
-
-       removeData: function( elem, name, pvt /* Internal Use Only */ ) {
-               if ( !jQuery.acceptData( elem ) ) {
-                       return;
-               }
-
-               var thisCache, i, l,
-
-                       isNode = elem.nodeType,
-
-                       // See jQuery.data for more information
-                       cache = isNode ? jQuery.cache : elem,
-                       id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
-
-               // If there is already no cache entry for this object, there is no
-               // purpose in continuing
-               if ( !cache[ id ] ) {
-                       return;
-               }
-
-               if ( name ) {
-
-                       thisCache = pvt ? cache[ id ] : cache[ id ].data;
-
-                       if ( thisCache ) {
-
-                               // Support array or space separated string names for data keys
-                               if ( !jQuery.isArray( name ) ) {
-
-                                       // try the string as a key before any manipulation
-                                       if ( name in thisCache ) {
-                                               name = [ name ];
-                                       } else {
-
-                                               // split the camel cased version by spaces unless a key with the spaces exists
-                                               name = jQuery.camelCase( name );
-                                               if ( name in thisCache ) {
-                                                       name = [ name ];
-                                               } else {
-                                                       name = name.split(" ");
-                                               }
-                                       }
-                               }
-
-                               for ( i = 0, l = name.length; i < l; i++ ) {
-                                       delete thisCache[ name[i] ];
-                               }
-
-                               // If there is no data left in the cache, we want to continue
-                               // and let the cache object itself get destroyed
-                               if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
-                                       return;
-                               }
-                       }
-               }
-
-               // See jQuery.data for more information
-               if ( !pvt ) {
-                       delete cache[ id ].data;
-
-                       // Don't destroy the parent cache unless the internal data object
-                       // had been the only thing left in it
-                       if ( !isEmptyDataObject( cache[ id ] ) ) {
-                               return;
-                       }
-               }
-
-               // Destroy the cache
-               if ( isNode ) {
-                       jQuery.cleanData( [ elem ], true );
-
-               // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
-               } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
-                       delete cache[ id ];
-
-               // When all else fails, null
-               } else {
-                       cache[ id ] = null;
-               }
-       },
-
-       // For internal use only.
-       _data: function( elem, name, data ) {
-               return jQuery.data( elem, name, data, true );
-       },
-
-       // A method for determining if a DOM node can handle the data expando
-       acceptData: function( elem ) {
-               var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
-
-               // nodes accept data unless otherwise specified; rejection can be conditional
-               return !noData || noData !== true && elem.getAttribute("classid") === noData;
-       }
-});
-
-jQuery.fn.extend({
-       data: function( key, value ) {
-               var parts, part, attr, name, l,
-                       elem = this[0],
-                       i = 0,
-                       data = null;
-
-               // Gets all values
-               if ( key === undefined ) {
-                       if ( this.length ) {
-                               data = jQuery.data( elem );
-
-                               if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
-                                       attr = elem.attributes;
-                                       for ( l = attr.length; i < l; i++ ) {
-                                               name = attr[i].name;
-
-                                               if ( !name.indexOf( "data-" ) ) {
-                                                       name = jQuery.camelCase( name.substring(5) );
-
-                                                       dataAttr( elem, name, data[ name ] );
-                                               }
-                                       }
-                                       jQuery._data( elem, "parsedAttrs", true );
-                               }
-                       }
-
-                       return data;
-               }
-
-               // Sets multiple values
-               if ( typeof key === "object" ) {
-                       return this.each(function() {
-                               jQuery.data( this, key );
-                       });
-               }
-
-               parts = key.split( ".", 2 );
-               parts[1] = parts[1] ? "." + parts[1] : "";
-               part = parts[1] + "!";
-
-               return jQuery.access( this, function( value ) {
-
-                       if ( value === undefined ) {
-                               data = this.triggerHandler( "getData" + part, [ parts[0] ] );
-
-                               // Try to fetch any internally stored data first
-                               if ( data === undefined && elem ) {
-                                       data = jQuery.data( elem, key );
-                                       data = dataAttr( elem, key, data );
-                               }
-
-                               return data === undefined && parts[1] ?
-                                       this.data( parts[0] ) :
-                                       data;
-                       }
-
-                       parts[1] = value;
-                       this.each(function() {
-                               var self = jQuery( this );
-
-                               self.triggerHandler( "setData" + part, parts );
-                               jQuery.data( this, key, value );
-                               self.triggerHandler( "changeData" + part, parts );
-                       });
-               }, null, value, arguments.length > 1, null, false );
-       },
-
-       removeData: function( key ) {
-               return this.each(function() {
-                       jQuery.removeData( this, key );
-               });
-       }
-});
-
-function dataAttr( elem, key, data ) {
-       // If nothing was found internally, try to fetch any
-       // data from the HTML5 data-* attribute
-       if ( data === undefined && elem.nodeType === 1 ) {
-
-               var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
-
-               data = elem.getAttribute( name );
-
-               if ( typeof data === "string" ) {
-                       try {
-                               data = data === "true" ? true :
-                               data === "false" ? false :
-                               data === "null" ? null :
-                               // Only convert to a number if it doesn't change the string
-                               +data + "" === data ? +data :
-                               rbrace.test( data ) ? jQuery.parseJSON( data ) :
-                                       data;
-                       } catch( e ) {}
-
-                       // Make sure we set the data so it isn't changed later
-                       jQuery.data( elem, key, data );
-
-               } else {
-                       data = undefined;
-               }
-       }
-
-       return data;
-}
-
-// checks a cache object for emptiness
-function isEmptyDataObject( obj ) {
-       var name;
-       for ( name in obj ) {
-
-               // if the public data object is empty, the private is still empty
-               if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
-                       continue;
-               }
-               if ( name !== "toJSON" ) {
-                       return false;
-               }
-       }
-
-       return true;
-}
-jQuery.extend({
-       queue: function( elem, type, data ) {
-               var queue;
-
-               if ( elem ) {
-                       type = ( type || "fx" ) + "queue";
-                       queue = jQuery._data( elem, type );
-
-                       // Speed up dequeue by getting out quickly if this is just a lookup
-                       if ( data ) {
-                               if ( !queue || jQuery.isArray(data) ) {
-                                       queue = jQuery._data( elem, type, jQuery.makeArray(data) );
-                               } else {
-                                       queue.push( data );
-                               }
-                       }
-                       return queue || [];
-               }
-       },
-
-       dequeue: function( elem, type ) {
-               type = type || "fx";
-
-               var queue = jQuery.queue( elem, type ),
-                       startLength = queue.length,
-                       fn = queue.shift(),
-                       hooks = jQuery._queueHooks( elem, type ),
-                       next = function() {
-                               jQuery.dequeue( elem, type );
-                       };
-
-               // If the fx queue is dequeued, always remove the progress sentinel
-               if ( fn === "inprogress" ) {
-                       fn = queue.shift();
-                       startLength--;
-               }
-
-               if ( fn ) {
-
-                       // Add a progress sentinel to prevent the fx queue from being
-                       // automatically dequeued
-                       if ( type === "fx" ) {
-                               queue.unshift( "inprogress" );
-                       }
-
-                       // clear up the last queue stop function
-                       delete hooks.stop;
-                       fn.call( elem, next, hooks );
-               }
-
-               if ( !startLength && hooks ) {
-                       hooks.empty.fire();
-               }
-       },
-
-       // not intended for public consumption - generates a queueHooks object, or returns the current one
-       _queueHooks: function( elem, type ) {
-               var key = type + "queueHooks";
-               return jQuery._data( elem, key ) || jQuery._data( elem, key, {
-                       empty: jQuery.Callbacks("once memory").add(function() {
-                               jQuery.removeData( elem, type + "queue", true );
-                               jQuery.removeData( elem, key, true );
-                       })
-               });
-       }
-});
-
-jQuery.fn.extend({
-       queue: function( type, data ) {
-               var setter = 2;
-
-               if ( typeof type !== "string" ) {
-                       data = type;
-                       type = "fx";
-                       setter--;
-               }
-
-               if ( arguments.length < setter ) {
-                       return jQuery.queue( this[0], type );
-               }
-
-               return data === undefined ?
-                       this :
-                       this.each(function() {
-                               var queue = jQuery.queue( this, type, data );
-
-                               // ensure a hooks for this queue
-                               jQuery._queueHooks( this, type );
-
-                               if ( type === "fx" && queue[0] !== "inprogress" ) {
-                                       jQuery.dequeue( this, type );
-                               }
-                       });
-       },
-       dequeue: function( type ) {
-               return this.each(function() {
-                       jQuery.dequeue( this, type );
-               });
-       },
-       // Based off of the plugin by Clint Helfers, with permission.
-       // http://blindsignals.com/index.php/2009/07/jquery-delay/
-       delay: function( time, type ) {
-               time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
-               type = type || "fx";
-
-               return this.queue( type, function( next, hooks ) {
-                       var timeout = setTimeout( next, time );
-                       hooks.stop = function() {
-                               clearTimeout( timeout );
-                       };
-               });
-       },
-       clearQueue: function( type ) {
-               return this.queue( type || "fx", [] );
-       },
-       // Get a promise resolved when queues of a certain type
-       // are emptied (fx is the type by default)
-       promise: function( type, obj ) {
-               var tmp,
-                       count = 1,
-                       defer = jQuery.Deferred(),
-                       elements = this,
-                       i = this.length,
-                       resolve = function() {
-                               if ( !( --count ) ) {
-                                       defer.resolveWith( elements, [ elements ] );
-                               }
-                       };
-
-               if ( typeof type !== "string" ) {
-                       obj = type;
-                       type = undefined;
-               }
-               type = type || "fx";
-
-               while( i-- ) {
-                       tmp = jQuery._data( elements[ i ], type + "queueHooks" );
-                       if ( tmp && tmp.empty ) {
-                               count++;
-                               tmp.empty.add( resolve );
-                       }
-               }
-               resolve();
-               return defer.promise( obj );
-       }
-});
-var nodeHook, boolHook, fixSpecified,
-       rclass = /[\t\r\n]/g,
-       rreturn = /\r/g,
-       rtype = /^(?:button|input)$/i,
-       rfocusable = /^(?:button|input|object|select|textarea)$/i,
-       rclickable = /^a(?:rea|)$/i,
-       rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
-       getSetAttribute = jQuery.support.getSetAttribute;
-
-jQuery.fn.extend({
-       attr: function( name, value ) {
-               return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
-       },
-
-       removeAttr: function( name ) {
-               return this.each(function() {
-                       jQuery.removeAttr( this, name );
-               });
-       },
-
-       prop: function( name, value ) {
-               return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
-       },
-
-       removeProp: function( name ) {
-               name = jQuery.propFix[ name ] || name;
-               return this.each(function() {
-                       // try/catch handles cases where IE balks (such as removing a property on window)
-                       try {
-                               this[ name ] = undefined;
-                               delete this[ name ];
-                       } catch( e ) {}
-               });
-       },
-
-       addClass: function( value ) {
-               var classNames, i, l, elem,
-                       setClass, c, cl;
-
-               if ( jQuery.isFunction( value ) ) {
-                       return this.each(function( j ) {
-                               jQuery( this ).addClass( value.call(this, j, this.className) );
-                       });
-               }
-
-               if ( value && typeof value === "string" ) {
-                       classNames = value.split( core_rspace );
-
-                       for ( i = 0, l = this.length; i < l; i++ ) {
-                               elem = this[ i ];
-
-                               if ( elem.nodeType === 1 ) {
-                                       if ( !elem.className && classNames.length === 1 ) {
-                                               elem.className = value;
-
-                                       } else {
-                                               setClass = " " + elem.className + " ";
-
-                                               for ( c = 0, cl = classNames.length; c < cl; c++ ) {
-                                                       if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) {
-                                                               setClass += classNames[ c ] + " ";
-                                                       }
-                                               }
-                                               elem.className = jQuery.trim( setClass );
-                                       }
-                               }
-                       }
-               }
-
-               return this;
-       },
-
-       removeClass: function( value ) {
-               var removes, className, elem, c, cl, i, l;
-
-               if ( jQuery.isFunction( value ) ) {
-                       return this.each(function( j ) {
-                               jQuery( this ).removeClass( value.call(this, j, this.className) );
-                       });
-               }
-               if ( (value && typeof value === "string") || value === undefined ) {
-                       removes = ( value || "" ).split( core_rspace );
-
-                       for ( i = 0, l = this.length; i < l; i++ ) {
-                               elem = this[ i ];
-                               if ( elem.nodeType === 1 && elem.className ) {
-
-                                       className = (" " + elem.className + " ").replace( rclass, " " );
-
-                                       // loop over each item in the removal list
-                                       for ( c = 0, cl = removes.length; c < cl; c++ ) {
-                                               // Remove until there is nothing to remove,
-                                               while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) {
-                                                       className = className.replace( " " + removes[ c ] + " " , " " );
-                                               }
-                                       }
-                                       elem.className = value ? jQuery.trim( className ) : "";
-                               }
-                       }
-               }
-
-               return this;
-       },
-
-       toggleClass: function( value, stateVal ) {
-               var type = typeof value,
-                       isBool = typeof stateVal === "boolean";
-
-               if ( jQuery.isFunction( value ) ) {
-                       return this.each(function( i ) {
-                               jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
-                       });
-               }
-
-               return this.each(function() {
-                       if ( type === "string" ) {
-                               // toggle individual class names
-                               var className,
-                                       i = 0,
-                                       self = jQuery( this ),
-                                       state = stateVal,
-                                       classNames = value.split( core_rspace );
-
-                               while ( (className = classNames[ i++ ]) ) {
-                                       // check each className given, space separated list
-                                       state = isBool ? state : !self.hasClass( className );
-                                       self[ state ? "addClass" : "removeClass" ]( className );
-                               }
-
-                       } else if ( type === "undefined" || type === "boolean" ) {
-                               if ( this.className ) {
-                                       // store className if set
-                                       jQuery._data( this, "__className__", this.className );
-                               }
-
-                               // toggle whole className
-                               this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
-                       }
-               });
-       },
-
-       hasClass: function( selector ) {
-               var className = " " + selector + " ",
-                       i = 0,
-                       l = this.length;
-               for ( ; i < l; i++ ) {
-                       if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
-                               return true;
-                       }
-               }
-
-               return false;
-       },
-
-       val: function( value ) {
-               var hooks, ret, isFunction,
-                       elem = this[0];
-
-               if ( !arguments.length ) {
-                       if ( elem ) {
-                               hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
-
-                               if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
-                                       return ret;
-                               }
-
-                               ret = elem.value;
-
-                               return typeof ret === "string" ?
-                                       // handle most common string cases
-                                       ret.replace(rreturn, "") :
-                                       // handle cases where value is null/undef or number
-                                       ret == null ? "" : ret;
-                       }
-
-                       return;
-               }
-
-               isFunction = jQuery.isFunction( value );
-
-               return this.each(function( i ) {
-                       var val,
-                               self = jQuery(this);
-
-                       if ( this.nodeType !== 1 ) {
-                               return;
-                       }
-
-                       if ( isFunction ) {
-                               val = value.call( this, i, self.val() );
-                       } else {
-                               val = value;
-                       }
-
-                       // Treat null/undefined as ""; convert numbers to string
-                       if ( val == null ) {
-                               val = "";
-                       } else if ( typeof val === "number" ) {
-                               val += "";
-                       } else if ( jQuery.isArray( val ) ) {
-                               val = jQuery.map(val, function ( value ) {
-                                       return value == null ? "" : value + "";
-                               });
-                       }
-
-                       hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
-
-                       // If set returns undefined, fall back to normal setting
-                       if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
-                               this.value = val;
-                       }
-               });
-       }
-});
-
-jQuery.extend({
-       valHooks: {
-               option: {
-                       get: function( elem ) {
-                               // attributes.value is undefined in Blackberry 4.7 but
-                               // uses .value. See #6932
-                               var val = elem.attributes.value;
-                               return !val || val.specified ? elem.value : elem.text;
-                       }
-               },
-               select: {
-                       get: function( elem ) {
-                               var value, option,
-                                       options = elem.options,
-                                       index = elem.selectedIndex,
-                                       one = elem.type === "select-one" || index < 0,
-                                       values = one ? null : [],
-                                       max = one ? index + 1 : options.length,
-                                       i = index < 0 ?
-                                               max :
-                                               one ? index : 0;
-
-                               // Loop through all the selected options
-                               for ( ; i < max; i++ ) {
-                                       option = options[ i ];
-
-                                       // oldIE doesn't update selected after form reset (#2551)
-                                       if ( ( option.selected || i === index ) &&
-                                                       // Don't return options that are disabled or in a disabled optgroup
-                                                       ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
-                                                       ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
-
-                                               // Get the specific value for the option
-                                               value = jQuery( option ).val();
-
-                                               // We don't need an array for one selects
-                                               if ( one ) {
-                                                       return value;
-                                               }
-
-                                               // Multi-Selects return an array
-                                               values.push( value );
-                                       }
-                               }
-
-                               return values;
-                       },
-
-                       set: function( elem, value ) {
-                               var values = jQuery.makeArray( value );
-
-                               jQuery(elem).find("option").each(function() {
-                                       this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
-                               });
-
-                               if ( !values.length ) {
-                                       elem.selectedIndex = -1;
-                               }
-                               return values;
-                       }
-               }
-       },
-
-       // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9
-       attrFn: {},
-
-       attr: function( elem, name, value, pass ) {
-               var ret, hooks, notxml,
-                       nType = elem.nodeType;
-
-               // don't get/set attributes on text, comment and attribute nodes
-               if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
-                       return;
-               }
-
-               if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
-                       return jQuery( elem )[ name ]( value );
-               }
-
-               // Fallback to prop when attributes are not supported
-               if ( typeof elem.getAttribute === "undefined" ) {
-                       return jQuery.prop( elem, name, value );
-               }
-
-               notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-
-               // All attributes are lowercase
-               // Grab necessary hook if one is defined
-               if ( notxml ) {
-                       name = name.toLowerCase();
-                       hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
-               }
-
-               if ( value !== undefined ) {
-
-                       if ( value === null ) {
-                               jQuery.removeAttr( elem, name );
-                               return;
-
-                       } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
-                               return ret;
-
-                       } else {
-                               elem.setAttribute( name, value + "" );
-                               return value;
-                       }
-
-               } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
-                       return ret;
-
-               } else {
-
-                       ret = elem.getAttribute( name );
-
-                       // Non-existent attributes return null, we normalize to undefined
-                       return ret === null ?
-                               undefined :
-                               ret;
-               }
-       },
-
-       removeAttr: function( elem, value ) {
-               var propName, attrNames, name, isBool,
-                       i = 0;
-
-               if ( value && elem.nodeType === 1 ) {
-
-                       attrNames = value.split( core_rspace );
-
-                       for ( ; i < attrNames.length; i++ ) {
-                               name = attrNames[ i ];
-
-                               if ( name ) {
-                                       propName = jQuery.propFix[ name ] || name;
-                                       isBool = rboolean.test( name );
-
-                                       // See #9699 for explanation of this approach (setting first, then removal)
-                                       // Do not do this for boolean attributes (see #10870)
-                                       if ( !isBool ) {
-                                               jQuery.attr( elem, name, "" );
-                                       }
-                                       elem.removeAttribute( getSetAttribute ? name : propName );
-
-                                       // Set corresponding property to false for boolean attributes
-                                       if ( isBool && propName in elem ) {
-                                               elem[ propName ] = false;
-                                       }
-                               }
-                       }
-               }
-       },
-
-       attrHooks: {
-               type: {
-                       set: function( elem, value ) {
-                               // We can't allow the type property to be changed (since it causes problems in IE)
-                               if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
-                                       jQuery.error( "type property can't be changed" );
-                               } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
-                                       // Setting the type on a radio button after the value resets the value in IE6-9
-                                       // Reset value to it's default in case type is set after value
-                                       // This is for element creation
-                                       var val = elem.value;
-                                       elem.setAttribute( "type", value );
-                                       if ( val ) {
-                                               elem.value = val;
-                                       }
-                                       return value;
-                               }
-                       }
-               },
-               // Use the value property for back compat
-               // Use the nodeHook for button elements in IE6/7 (#1954)
-               value: {
-                       get: function( elem, name ) {
-                               if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
-                                       return nodeHook.get( elem, name );
-                               }
-                               return name in elem ?
-                                       elem.value :
-                                       null;
-                       },
-                       set: function( elem, value, name ) {
-                               if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
-                                       return nodeHook.set( elem, value, name );
-                               }
-                               // Does not return so that setAttribute is also used
-                               elem.value = value;
-                       }
-               }
-       },
-
-       propFix: {
-               tabindex: "tabIndex",
-               readonly: "readOnly",
-               "for": "htmlFor",
-               "class": "className",
-               maxlength: "maxLength",
-               cellspacing: "cellSpacing",
-               cellpadding: "cellPadding",
-               rowspan: "rowSpan",
-               colspan: "colSpan",
-               usemap: "useMap",
-               frameborder: "frameBorder",
-               contenteditable: "contentEditable"
-       },
-
-       prop: function( elem, name, value ) {
-               var ret, hooks, notxml,
-                       nType = elem.nodeType;
-
-               // don't get/set properties on text, comment and attribute nodes
-               if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
-                       return;
-               }
-
-               notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-
-               if ( notxml ) {
-                       // Fix name and attach hooks
-                       name = jQuery.propFix[ name ] || name;
-                       hooks = jQuery.propHooks[ name ];
-               }
-
-               if ( value !== undefined ) {
-                       if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
-                               return ret;
-
-                       } else {
-                               return ( elem[ name ] = value );
-                       }
-
-               } else {
-                       if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
-                               return ret;
-
-                       } else {
-                               return elem[ name ];
-                       }
-               }
-       },
-
-       propHooks: {
-               tabIndex: {
-                       get: function( elem ) {
-                               // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
-                               // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
-                               var attributeNode = elem.getAttributeNode("tabindex");
-
-                               return attributeNode && attributeNode.specified ?
-                                       parseInt( attributeNode.value, 10 ) :
-                                       rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
-                                               0 :
-                                               undefined;
-                       }
-               }
-       }
-});
-
-// Hook for boolean attributes
-boolHook = {
-       get: function( elem, name ) {
-               // Align boolean attributes with corresponding properties
-               // Fall back to attribute presence where some booleans are not supported
-               var attrNode,
-                       property = jQuery.prop( elem, name );
-               return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
-                       name.toLowerCase() :
-                       undefined;
-       },
-       set: function( elem, value, name ) {
-               var propName;
-               if ( value === false ) {
-                       // Remove boolean attributes when set to false
-                       jQuery.removeAttr( elem, name );
-               } else {
-                       // value is true since we know at this point it's type boolean and not false
-                       // Set boolean attributes to the same name and set the DOM property
-                       propName = jQuery.propFix[ name ] || name;
-                       if ( propName in elem ) {
-                               // Only set the IDL specifically if it already exists on the element
-                               elem[ propName ] = true;
-                       }
-
-                       elem.setAttribute( name, name.toLowerCase() );
-               }
-               return name;
-       }
-};
-
-// IE6/7 do not support getting/setting some attributes with get/setAttribute
-if ( !getSetAttribute ) {
-
-       fixSpecified = {
-               name: true,
-               id: true,
-               coords: true
-       };
-
-       // Use this for any attribute in IE6/7
-       // This fixes almost every IE6/7 issue
-       nodeHook = jQuery.valHooks.button = {
-               get: function( elem, name ) {
-                       var ret;
-                       ret = elem.getAttributeNode( name );
-                       return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ?
-                               ret.value :
-                               undefined;
-               },
-               set: function( elem, value, name ) {
-                       // Set the existing or create a new attribute node
-                       var ret = elem.getAttributeNode( name );
-                       if ( !ret ) {
-                               ret = document.createAttribute( name );
-                               elem.setAttributeNode( ret );
-                       }
-                       return ( ret.value = value + "" );
-               }
-       };
-
-       // Set width and height to auto instead of 0 on empty string( Bug #8150 )
-       // This is for removals
-       jQuery.each([ "width", "height" ], function( i, name ) {
-               jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
-                       set: function( elem, value ) {
-                               if ( value === "" ) {
-                                       elem.setAttribute( name, "auto" );
-                                       return value;
-                               }
-                       }
-               });
-       });
-
-       // Set contenteditable to false on removals(#10429)
-       // Setting to empty string throws an error as an invalid value
-       jQuery.attrHooks.contenteditable = {
-               get: nodeHook.get,
-               set: function( elem, value, name ) {
-                       if ( value === "" ) {
-                               value = "false";
-                       }
-                       nodeHook.set( elem, value, name );
-               }
-       };
-}
-
-
-// Some attributes require a special call on IE
-if ( !jQuery.support.hrefNormalized ) {
-       jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
-               jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
-                       get: function( elem ) {
-                               var ret = elem.getAttribute( name, 2 );
-                               return ret === null ? undefined : ret;
-                       }
-               });
-       });
-}
-
-if ( !jQuery.support.style ) {
-       jQuery.attrHooks.style = {
-               get: function( elem ) {
-                       // Return undefined in the case of empty string
-                       // Normalize to lowercase since IE uppercases css property names
-                       return elem.style.cssText.toLowerCase() || undefined;
-               },
-               set: function( elem, value ) {
-                       return ( elem.style.cssText = value + "" );
-               }
-       };
-}
-
-// Safari mis-reports the default selected property of an option
-// Accessing the parent's selectedIndex property fixes it
-if ( !jQuery.support.optSelected ) {
-       jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
-               get: function( elem ) {
-                       var parent = elem.parentNode;
-
-                       if ( parent ) {
-                               parent.selectedIndex;
-
-                               // Make sure that it also works with optgroups, see #5701
-                               if ( parent.parentNode ) {
-                                       parent.parentNode.selectedIndex;
-                               }
-                       }
-                       return null;
-               }
-       });
-}
-
-// IE6/7 call enctype encoding
-if ( !jQuery.support.enctype ) {
-       jQuery.propFix.enctype = "encoding";
-}
-
-// Radios and checkboxes getter/setter
-if ( !jQuery.support.checkOn ) {
-       jQuery.each([ "radio", "checkbox" ], function() {
-               jQuery.valHooks[ this ] = {
-                       get: function( elem ) {
-                               // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
-                               return elem.getAttribute("value") === null ? "on" : elem.value;
-                       }
-               };
-       });
-}
-jQuery.each([ "radio", "checkbox" ], function() {
-       jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
-               set: function( elem, value ) {
-                       if ( jQuery.isArray( value ) ) {
-                               return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
-                       }
-               }
-       });
-});
-var rformElems = /^(?:textarea|input|select)$/i,
-       rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/,
-       rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
-       rkeyEvent = /^key/,
-       rmouseEvent = /^(?:mouse|contextmenu)|click/,
-       rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
-       hoverHack = function( events ) {
-               return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
-       };
-
-/*
- * Helper functions for managing events -- not part of the public interface.
- * Props to Dean Edwards' addEvent library for many of the ideas.
- */
-jQuery.event = {
-
-       add: function( elem, types, handler, data, selector ) {
-
-               var elemData, eventHandle, events,
-                       t, tns, type, namespaces, handleObj,
-                       handleObjIn, handlers, special;
-
-               // Don't attach events to noData or text/comment nodes (allow plain objects tho)
-               if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
-                       return;
-               }
-
-               // Caller can pass in an object of custom data in lieu of the handler
-               if ( handler.handler ) {
-                       handleObjIn = handler;
-                       handler = handleObjIn.handler;
-                       selector = handleObjIn.selector;
-               }
-
-               // Make sure that the handler has a unique ID, used to find/remove it later
-               if ( !handler.guid ) {
-                       handler.guid = jQuery.guid++;
-               }
-
-               // Init the element's event structure and main handler, if this is the first
-               events = elemData.events;
-               if ( !events ) {
-                       elemData.events = events = {};
-               }
-               eventHandle = elemData.handle;
-               if ( !eventHandle ) {
-                       elemData.handle = eventHandle = function( e ) {
-                               // Discard the second event of a jQuery.event.trigger() and
-                               // when an event is called after a page has unloaded
-                               return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
-                                       jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
-                                       undefined;
-                       };
-                       // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
-                       eventHandle.elem = elem;
-               }
-
-               // Handle multiple events separated by a space
-               // jQuery(...).bind("mouseover mouseout", fn);
-               types = jQuery.trim( hoverHack(types) ).split( " " );
-               for ( t = 0; t < types.length; t++ ) {
-
-                       tns = rtypenamespace.exec( types[t] ) || [];
-                       type = tns[1];
-                       namespaces = ( tns[2] || "" ).split( "." ).sort();
-
-                       // If event changes its type, use the special event handlers for the changed type
-                       special = jQuery.event.special[ type ] || {};
-
-                       // If selector defined, determine special event api type, otherwise given type
-                       type = ( selector ? special.delegateType : special.bindType ) || type;
-
-                       // Update special based on newly reset type
-                       special = jQuery.event.special[ type ] || {};
-
-                       // handleObj is passed to all event handlers
-                       handleObj = jQuery.extend({
-                               type: type,
-                               origType: tns[1],
-                               data: data,
-                               handler: handler,
-                               guid: handler.guid,
-                               selector: selector,
-                               needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
-                               namespace: namespaces.join(".")
-                       }, handleObjIn );
-
-                       // Init the event handler queue if we're the first
-                       handlers = events[ type ];
-                       if ( !handlers ) {
-                               handlers = events[ type ] = [];
-                               handlers.delegateCount = 0;
-
-                               // Only use addEventListener/attachEvent if the special events handler returns false
-                               if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
-                                       // Bind the global event handler to the element
-                                       if ( elem.addEventListener ) {
-                                               elem.addEventListener( type, eventHandle, false );
-
-                                       } else if ( elem.attachEvent ) {
-                                               elem.attachEvent( "on" + type, eventHandle );
-                                       }
-                               }
-                       }
-
-                       if ( special.add ) {
-                               special.add.call( elem, handleObj );
-
-                               if ( !handleObj.handler.guid ) {
-                                       handleObj.handler.guid = handler.guid;
-                               }
-                       }
-
-                       // Add to the element's handler list, delegates in front
-                       if ( selector ) {
-                               handlers.splice( handlers.delegateCount++, 0, handleObj );
-                       } else {
-                               handlers.push( handleObj );
-                       }
-
-                       // Keep track of which events have ever been used, for event optimization
-                       jQuery.event.global[ type ] = true;
-               }
-
-               // Nullify elem to prevent memory leaks in IE
-               elem = null;
-       },
-
-       global: {},
-
-       // Detach an event or set of events from an element
-       remove: function( elem, types, handler, selector, mappedTypes ) {
-
-               var t, tns, type, origType, namespaces, origCount,
-                       j, events, special, eventType, handleObj,
-                       elemData = jQuery.hasData( elem ) && jQuery._data( elem );
-
-               if ( !elemData || !(events = elemData.events) ) {
-                       return;
-               }
-
-               // Once for each type.namespace in types; type may be omitted
-               types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
-               for ( t = 0; t < types.length; t++ ) {
-                       tns = rtypenamespace.exec( types[t] ) || [];
-                       type = origType = tns[1];
-                       namespaces = tns[2];
-
-                       // Unbind all events (on this namespace, if provided) for the element
-                       if ( !type ) {
-                               for ( type in events ) {
-                                       jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
-                               }
-                               continue;
-                       }
-
-                       special = jQuery.event.special[ type ] || {};
-                       type = ( selector? special.delegateType : special.bindType ) || type;
-                       eventType = events[ type ] || [];
-                       origCount = eventType.length;
-                       namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
-
-                       // Remove matching events
-                       for ( j = 0; j < eventType.length; j++ ) {
-                               handleObj = eventType[ j ];
-
-                               if ( ( mappedTypes || origType === handleObj.origType ) &&
-                                        ( !handler || handler.guid === handleObj.guid ) &&
-                                        ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
-                                        ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
-                                       eventType.splice( j--, 1 );
-
-                                       if ( handleObj.selector ) {
-                                               eventType.delegateCount--;
-                                       }
-                                       if ( special.remove ) {
-                                               special.remove.call( elem, handleObj );
-                                       }
-                               }
-                       }
-
-                       // Remove generic event handler if we removed something and no more handlers exist
-                       // (avoids potential for endless recursion during removal of special event handlers)
-                       if ( eventType.length === 0 && origCount !== eventType.length ) {
-                               if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
-                                       jQuery.removeEvent( elem, type, elemData.handle );
-                               }
-
-                               delete events[ type ];
-                       }
-               }
-
-               // Remove the expando if it's no longer used
-               if ( jQuery.isEmptyObject( events ) ) {
-                       delete elemData.handle;
-
-                       // removeData also checks for emptiness and clears the expando if empty
-                       // so use it instead of delete
-                       jQuery.removeData( elem, "events", true );
-               }
-       },
-
-       // Events that are safe to short-circuit if no handlers are attached.
-       // Native DOM events should not be added, they may have inline handlers.
-       customEvent: {
-               "getData": true,
-               "setData": true,
-               "changeData": true
-       },
-
-       trigger: function( event, data, elem, onlyHandlers ) {
-               // Don't do events on text and comment nodes
-               if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
-                       return;
-               }
-
-               // Event object or event type
-               var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType,
-                       type = event.type || event,
-                       namespaces = [];
-
-               // focus/blur morphs to focusin/out; ensure we're not firing them right now
-               if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
-                       return;
-               }
-
-               if ( type.indexOf( "!" ) >= 0 ) {
-                       // Exclusive events trigger only for the exact event (no namespaces)
-                       type = type.slice(0, -1);
-                       exclusive = true;
-               }
-
-               if ( type.indexOf( "." ) >= 0 ) {
-                       // Namespaced trigger; create a regexp to match event type in handle()
-                       namespaces = type.split(".");
-                       type = namespaces.shift();
-                       namespaces.sort();
-               }
-
-               if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
-                       // No jQuery handlers for this event type, and it can't have inline handlers
-                       return;
-               }
-
-               // Caller can pass in an Event, Object, or just an event type string
-               event = typeof event === "object" ?
-                       // jQuery.Event object
-                       event[ jQuery.expando ] ? event :
-                       // Object literal
-                       new jQuery.Event( type, event ) :
-                       // Just the event type (string)
-                       new jQuery.Event( type );
-
-               event.type = type;
-               event.isTrigger = true;
-               event.exclusive = exclusive;
-               event.namespace = namespaces.join( "." );
-               event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
-               ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
-
-               // Handle a global trigger
-               if ( !elem ) {
-
-                       // TODO: Stop taunting the data cache; remove global events and always attach to document
-                       cache = jQuery.cache;
-                       for ( i in cache ) {
-                               if ( cache[ i ].events && cache[ i ].events[ type ] ) {
-                                       jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
-                               }
-                       }
-                       return;
-               }
-
-               // Clean up the event in case it is being reused
-               event.result = undefined;
-               if ( !event.target ) {
-                       event.target = elem;
-               }
-
-               // Clone any incoming data and prepend the event, creating the handler arg list
-               data = data != null ? jQuery.makeArray( data ) : [];
-               data.unshift( event );
-
-               // Allow special events to draw outside the lines
-               special = jQuery.event.special[ type ] || {};
-               if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
-                       return;
-               }
-
-               // Determine event propagation path in advance, per W3C events spec (#9951)
-               // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
-               eventPath = [[ elem, special.bindType || type ]];
-               if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
-
-                       bubbleType = special.delegateType || type;
-                       cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
-                       for ( old = elem; cur; cur = cur.parentNode ) {
-                               eventPath.push([ cur, bubbleType ]);
-                               old = cur;
-                       }
-
-                       // Only add window if we got to document (e.g., not plain obj or detached DOM)
-                       if ( old === (elem.ownerDocument || document) ) {
-                               eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
-                       }
-               }
-
-               // Fire handlers on the event path
-               for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
-
-                       cur = eventPath[i][0];
-                       event.type = eventPath[i][1];
-
-                       handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
-                       if ( handle ) {
-                               handle.apply( cur, data );
-                       }
-                       // Note that this is a bare JS function and not a jQuery handler
-                       handle = ontype && cur[ ontype ];
-                       if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
-                               event.preventDefault();
-                       }
-               }
-               event.type = type;
-
-               // If nobody prevented the default action, do it now
-               if ( !onlyHandlers && !event.isDefaultPrevented() ) {
-
-                       if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
-                               !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
-
-                               // Call a native DOM method on the target with the same name name as the event.
-                               // Can't use an .isFunction() check here because IE6/7 fails that test.
-                               // Don't do default actions on window, that's where global variables be (#6170)
-                               // IE<9 dies on focus/blur to hidden element (#1486)
-                               if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
-
-                                       // Don't re-trigger an onFOO event when we call its FOO() method
-                                       old = elem[ ontype ];
-
-                                       if ( old ) {
-                                               elem[ ontype ] = null;
-                                       }
-
-                                       // Prevent re-triggering of the same event, since we already bubbled it above
-                                       jQuery.event.triggered = type;
-                                       elem[ type ]();
-                                       jQuery.event.triggered = undefined;
-
-                                       if ( old ) {
-                                               elem[ ontype ] = old;
-                                       }
-                               }
-                       }
-               }
-
-               return event.result;
-       },
-
-       dispatch: function( event ) {
-
-               // Make a writable jQuery.Event from the native event object
-               event = jQuery.event.fix( event || window.event );
-
-               var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related,
-                       handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
-                       delegateCount = handlers.delegateCount,
-                       args = core_slice.call( arguments ),
-                       run_all = !event.exclusive && !event.namespace,
-                       special = jQuery.event.special[ event.type ] || {},
-                       handlerQueue = [];
-
-               // Use the fix-ed jQuery.Event rather than the (read-only) native event
-               args[0] = event;
-               event.delegateTarget = this;
-
-               // Call the preDispatch hook for the mapped type, and let it bail if desired
-               if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
-                       return;
-               }
-
-               // Determine handlers that should run if there are delegated events
-               // Avoid non-left-click bubbling in Firefox (#3861)
-               if ( delegateCount && !(event.button && event.type === "click") ) {
-
-                       for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
-
-                               // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764)
-                               if ( cur.disabled !== true || event.type !== "click" ) {
-                                       selMatch = {};
-                                       matches = [];
-                                       for ( i = 0; i < delegateCount; i++ ) {
-                                               handleObj = handlers[ i ];
-                                               sel = handleObj.selector;
-
-                                               if ( selMatch[ sel ] === undefined ) {
-                                                       selMatch[ sel ] = handleObj.needsContext ?
-                                                               jQuery( sel, this ).index( cur ) >= 0 :
-                                                               jQuery.find( sel, this, null, [ cur ] ).length;
-                                               }
-                                               if ( selMatch[ sel ] ) {
-                                                       matches.push( handleObj );
-                                               }
-                                       }
-                                       if ( matches.length ) {
-                                               handlerQueue.push({ elem: cur, matches: matches });
-                                       }
-                               }
-                       }
-               }
-
-               // Add the remaining (directly-bound) handlers
-               if ( handlers.length > delegateCount ) {
-                       handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
-               }
-
-               // Run delegates first; they may want to stop propagation beneath us
-               for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
-                       matched = handlerQueue[ i ];
-                       event.currentTarget = matched.elem;
-
-                       for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
-                               handleObj = matched.matches[ j ];
-
-                               // Triggered event must either 1) be non-exclusive and have no namespace, or
-                               // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
-                               if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
-
-                                       event.data = handleObj.data;
-                                       event.handleObj = handleObj;
-
-                                       ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
-                                                       .apply( matched.elem, args );
-
-                                       if ( ret !== undefined ) {
-                                               event.result = ret;
-                                               if ( ret === false ) {
-                                                       event.preventDefault();
-                                                       event.stopPropagation();
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               // Call the postDispatch hook for the mapped type
-               if ( special.postDispatch ) {
-                       special.postDispatch.call( this, event );
-               }
-
-               return event.result;
-       },
-
-       // Includes some event props shared by KeyEvent and MouseEvent
-       // *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
-       props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
-
-       fixHooks: {},
-
-       keyHooks: {
-               props: "char charCode key keyCode".split(" "),
-               filter: function( event, original ) {
-
-                       // Add which for key events
-                       if ( event.which == null ) {
-                               event.which = original.charCode != null ? original.charCode : original.keyCode;
-                       }
-
-                       return event;
-               }
-       },
-
-       mouseHooks: {
-               props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
-               filter: function( event, original ) {
-                       var eventDoc, doc, body,
-                               button = original.button,
-                               fromElement = original.fromElement;
-
-                       // Calculate pageX/Y if missing and clientX/Y available
-                       if ( event.pageX == null && original.clientX != null ) {
-                               eventDoc = event.target.ownerDocument || document;
-                               doc = eventDoc.documentElement;
-                               body = eventDoc.body;
-
-                               event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
-                               event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
-                       }
-
-                       // Add relatedTarget, if necessary
-                       if ( !event.relatedTarget && fromElement ) {
-                               event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
-                       }
-
-                       // Add which for click: 1 === left; 2 === middle; 3 === right
-                       // Note: button is not normalized, so don't use it
-                       if ( !event.which && button !== undefined ) {
-                               event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
-                       }
-
-                       return event;
-               }
-       },
-
-       fix: function( event ) {
-               if ( event[ jQuery.expando ] ) {
-                       return event;
-               }
-
-               // Create a writable copy of the event object and normalize some properties
-               var i, prop,
-                       originalEvent = event,
-                       fixHook = jQuery.event.fixHooks[ event.type ] || {},
-                       copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
-
-               event = jQuery.Event( originalEvent );
-
-               for ( i = copy.length; i; ) {
-                       prop = copy[ --i ];
-                       event[ prop ] = originalEvent[ prop ];
-               }
-
-               // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
-               if ( !event.target ) {
-                       event.target = originalEvent.srcElement || document;
-               }
-
-               // Target should not be a text node (#504, Safari)
-               if ( event.target.nodeType === 3 ) {
-                       event.target = event.target.parentNode;
-               }
-
-               // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8)
-               event.metaKey = !!event.metaKey;
-
-               return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
-       },
-
-       special: {
-               load: {
-                       // Prevent triggered image.load events from bubbling to window.load
-                       noBubble: true
-               },
-
-               focus: {
-                       delegateType: "focusin"
-               },
-               blur: {
-                       delegateType: "focusout"
-               },
-
-               beforeunload: {
-                       setup: function( data, namespaces, eventHandle ) {
-                               // We only want to do this special case on windows
-                               if ( jQuery.isWindow( this ) ) {
-                                       this.onbeforeunload = eventHandle;
-                               }
-                       },
-
-                       teardown: function( namespaces, eventHandle ) {
-                               if ( this.onbeforeunload === eventHandle ) {
-                                       this.onbeforeunload = null;
-                               }
-                       }
-               }
-       },
-
-       simulate: function( type, elem, event, bubble ) {
-               // Piggyback on a donor event to simulate a different one.
-               // Fake originalEvent to avoid donor's stopPropagation, but if the
-               // simulated event prevents default then we do the same on the donor.
-               var e = jQuery.extend(
-                       new jQuery.Event(),
-                       event,
-                       { type: type,
-                               isSimulated: true,
-                               originalEvent: {}
-                       }
-               );
-               if ( bubble ) {
-                       jQuery.event.trigger( e, null, elem );
-               } else {
-                       jQuery.event.dispatch.call( elem, e );
-               }
-               if ( e.isDefaultPrevented() ) {
-                       event.preventDefault();
-               }
-       }
-};
-
-// Some plugins are using, but it's undocumented/deprecated and will be removed.
-// The 1.7 special event interface should provide all the hooks needed now.
-jQuery.event.handle = jQuery.event.dispatch;
-
-jQuery.removeEvent = document.removeEventListener ?
-       function( elem, type, handle ) {
-               if ( elem.removeEventListener ) {
-                       elem.removeEventListener( type, handle, false );
-               }
-       } :
-       function( elem, type, handle ) {
-               var name = "on" + type;
-
-               if ( elem.detachEvent ) {
-
-                       // #8545, #7054, preventing memory leaks for custom events in IE6-8
-                       // detachEvent needed property on element, by name of that event, to properly expose it to GC
-                       if ( typeof elem[ name ] === "undefined" ) {
-                               elem[ name ] = null;
-                       }
-
-                       elem.detachEvent( name, handle );
-               }
-       };
-
-jQuery.Event = function( src, props ) {
-       // Allow instantiation without the 'new' keyword
-       if ( !(this instanceof jQuery.Event) ) {
-               return new jQuery.Event( src, props );
-       }
-
-       // Event object
-       if ( src && src.type ) {
-               this.originalEvent = src;
-               this.type = src.type;
-
-               // Events bubbling up the document may have been marked as prevented
-               // by a handler lower down the tree; reflect the correct value.
-               this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
-                       src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
-
-       // Event type
-       } else {
-               this.type = src;
-       }
-
-       // Put explicitly provided properties onto the event object
-       if ( props ) {
-               jQuery.extend( this, props );
-       }
-
-       // Create a timestamp if incoming event doesn't have one
-       this.timeStamp = src && src.timeStamp || jQuery.now();
-
-       // Mark it as fixed
-       this[ jQuery.expando ] = true;
-};
-
-function returnFalse() {
-       return false;
-}
-function returnTrue() {
-       return true;
-}
-
-// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
-// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
-jQuery.Event.prototype = {
-       preventDefault: function() {
-               this.isDefaultPrevented = returnTrue;
-
-               var e = this.originalEvent;
-               if ( !e ) {
-                       return;
-               }
-
-               // if preventDefault exists run it on the original event
-               if ( e.preventDefault ) {
-                       e.preventDefault();
-
-               // otherwise set the returnValue property of the original event to false (IE)
-               } else {
-                       e.returnValue = false;
-               }
-       },
-       stopPropagation: function() {
-               this.isPropagationStopped = returnTrue;
-
-               var e = this.originalEvent;
-               if ( !e ) {
-                       return;
-               }
-               // if stopPropagation exists run it on the original event
-               if ( e.stopPropagation ) {
-                       e.stopPropagation();
-               }
-               // otherwise set the cancelBubble property of the original event to true (IE)
-               e.cancelBubble = true;
-       },
-       stopImmediatePropagation: function() {
-               this.isImmediatePropagationStopped = returnTrue;
-               this.stopPropagation();
-       },
-       isDefaultPrevented: returnFalse,
-       isPropagationStopped: returnFalse,
-       isImmediatePropagationStopped: returnFalse
-};
-
-// Create mouseenter/leave events using mouseover/out and event-time checks
-jQuery.each({
-       mouseenter: "mouseover",
-       mouseleave: "mouseout"
-}, function( orig, fix ) {
-       jQuery.event.special[ orig ] = {
-               delegateType: fix,
-               bindType: fix,
-
-               handle: function( event ) {
-                       var ret,
-                               target = this,
-                               related = event.relatedTarget,
-                               handleObj = event.handleObj,
-                               selector = handleObj.selector;
-
-                       // For mousenter/leave call the handler if related is outside the target.
-                       // NB: No relatedTarget if the mouse left/entered the browser window
-                       if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
-                               event.type = handleObj.origType;
-                               ret = handleObj.handler.apply( this, arguments );
-                               event.type = fix;
-                       }
-                       return ret;
-               }
-       };
-});
-
-// IE submit delegation
-if ( !jQuery.support.submitBubbles ) {
-
-       jQuery.event.special.submit = {
-               setup: function() {
-                       // Only need this for delegated form submit events
-                       if ( jQuery.nodeName( this, "form" ) ) {
-                               return false;
-                       }
-
-                       // Lazy-add a submit handler when a descendant form may potentially be submitted
-                       jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
-                               // Node name check avoids a VML-related crash in IE (#9807)
-                               var elem = e.target,
-                                       form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
-                               if ( form && !jQuery._data( form, "_submit_attached" ) ) {
-                                       jQuery.event.add( form, "submit._submit", function( event ) {
-                                               event._submit_bubble = true;
-                                       });
-                                       jQuery._data( form, "_submit_attached", true );
-                               }
-                       });
-                       // return undefined since we don't need an event listener
-               },
-
-               postDispatch: function( event ) {
-                       // If form was submitted by the user, bubble the event up the tree
-                       if ( event._submit_bubble ) {
-                               delete event._submit_bubble;
-                               if ( this.parentNode && !event.isTrigger ) {
-                                       jQuery.event.simulate( "submit", this.parentNode, event, true );
-                               }
-                       }
-               },
-
-               teardown: function() {
-                       // Only need this for delegated form submit events
-                       if ( jQuery.nodeName( this, "form" ) ) {
-                               return false;
-                       }
-
-                       // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
-                       jQuery.event.remove( this, "._submit" );
-               }
-       };
-}
-
-// IE change delegation and checkbox/radio fix
-if ( !jQuery.support.changeBubbles ) {
-
-       jQuery.event.special.change = {
-
-               setup: function() {
-
-                       if ( rformElems.test( this.nodeName ) ) {
-                               // IE doesn't fire change on a check/radio until blur; trigger it on click
-                               // after a propertychange. Eat the blur-change in special.change.handle.
-                               // This still fires onchange a second time for check/radio after blur.
-                               if ( this.type === "checkbox" || this.type === "radio" ) {
-                                       jQuery.event.add( this, "propertychange._change", function( event ) {
-                                               if ( event.originalEvent.propertyName === "checked" ) {
-                                                       this._just_changed = true;
-                                               }
-                                       });
-                                       jQuery.event.add( this, "click._change", function( event ) {
-                                               if ( this._just_changed && !event.isTrigger ) {
-                                                       this._just_changed = false;
-                                               }
-                                               // Allow triggered, simulated change events (#11500)
-                                               jQuery.event.simulate( "change", this, event, true );
-                                       });
-                               }
-                               return false;
-                       }
-                       // Delegated event; lazy-add a change handler on descendant inputs
-                       jQuery.event.add( this, "beforeactivate._change", function( e ) {
-                               var elem = e.target;
-
-                               if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "_change_attached" ) ) {
-                                       jQuery.event.add( elem, "change._change", function( event ) {
-                                               if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
-                                                       jQuery.event.simulate( "change", this.parentNode, event, true );
-                                               }
-                                       });
-                                       jQuery._data( elem, "_change_attached", true );
-                               }
-                       });
-               },
-
-               handle: function( event ) {
-                       var elem = event.target;
-
-                       // Swallow native change events from checkbox/radio, we already triggered them above
-                       if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
-                               return event.handleObj.handler.apply( this, arguments );
-                       }
-               },
-
-               teardown: function() {
-                       jQuery.event.remove( this, "._change" );
-
-                       return !rformElems.test( this.nodeName );
-               }
-       };
-}
-
-// Create "bubbling" focus and blur events
-if ( !jQuery.support.focusinBubbles ) {
-       jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
-
-               // Attach a single capturing handler while someone wants focusin/focusout
-               var attaches = 0,
-                       handler = function( event ) {
-                               jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
-                       };
-
-               jQuery.event.special[ fix ] = {
-                       setup: function() {
-                               if ( attaches++ === 0 ) {
-                                       document.addEventListener( orig, handler, true );
-                               }
-                       },
-                       teardown: function() {
-                               if ( --attaches === 0 ) {
-                                       document.removeEventListener( orig, handler, true );
-                               }
-                       }
-               };
-       });
-}
-
-jQuery.fn.extend({
-
-       on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
-               var origFn, type;
-
-               // Types can be a map of types/handlers
-               if ( typeof types === "object" ) {
-                       // ( types-Object, selector, data )
-                       if ( typeof selector !== "string" ) { // && selector != null
-                               // ( types-Object, data )
-                               data = data || selector;
-                               selector = undefined;
-                       }
-                       for ( type in types ) {
-                               this.on( type, selector, data, types[ type ], one );
-                       }
-                       return this;
-               }
-
-               if ( data == null && fn == null ) {
-                       // ( types, fn )
-                       fn = selector;
-                       data = selector = undefined;
-               } else if ( fn == null ) {
-                       if ( typeof selector === "string" ) {
-                               // ( types, selector, fn )
-                               fn = data;
-                               data = undefined;
-                       } else {
-                               // ( types, data, fn )
-                               fn = data;
-                               data = selector;
-                               selector = undefined;
-                       }
-               }
-               if ( fn === false ) {
-                       fn = returnFalse;
-               } else if ( !fn ) {
-                       return this;
-               }
-
-               if ( one === 1 ) {
-                       origFn = fn;
-                       fn = function( event ) {
-                               // Can use an empty set, since event contains the info
-                               jQuery().off( event );
-                               return origFn.apply( this, arguments );
-                       };
-                       // Use same guid so caller can remove using origFn
-                       fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
-               }
-               return this.each( function() {
-                       jQuery.event.add( this, types, fn, data, selector );
-               });
-       },
-       one: function( types, selector, data, fn ) {
-               return this.on( types, selector, data, fn, 1 );
-       },
-       off: function( types, selector, fn ) {
-               var handleObj, type;
-               if ( types && types.preventDefault && types.handleObj ) {
-                       // ( event )  dispatched jQuery.Event
-                       handleObj = types.handleObj;
-                       jQuery( types.delegateTarget ).off(
-                               handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
-                               handleObj.selector,
-                               handleObj.handler
-                       );
-                       return this;
-               }
-               if ( typeof types === "object" ) {
-                       // ( types-object [, selector] )
-                       for ( type in types ) {
-                               this.off( type, selector, types[ type ] );
-                       }
-                       return this;
-               }
-               if ( selector === false || typeof selector === "function" ) {
-                       // ( types [, fn] )
-                       fn = selector;
-                       selector = undefined;
-               }
-               if ( fn === false ) {
-                       fn = returnFalse;
-               }
-               return this.each(function() {
-                       jQuery.event.remove( this, types, fn, selector );
-               });
-       },
-
-       bind: function( types, data, fn ) {
-               return this.on( types, null, data, fn );
-       },
-       unbind: function( types, fn ) {
-               return this.off( types, null, fn );
-       },
-
-       live: function( types, data, fn ) {
-               jQuery( this.context ).on( types, this.selector, data, fn );
-               return this;
-       },
-       die: function( types, fn ) {
-               jQuery( this.context ).off( types, this.selector || "**", fn );
-               return this;
-       },
-
-       delegate: function( selector, types, data, fn ) {
-               return this.on( types, selector, data, fn );
-       },
-       undelegate: function( selector, types, fn ) {
-               // ( namespace ) or ( selector, types [, fn] )
-               return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
-       },
-
-       trigger: function( type, data ) {
-               return this.each(function() {
-                       jQuery.event.trigger( type, data, this );
-               });
-       },
-       triggerHandler: function( type, data ) {
-               if ( this[0] ) {
-                       return jQuery.event.trigger( type, data, this[0], true );
-               }
-       },
-
-       toggle: function( fn ) {
-               // Save reference to arguments for access in closure
-               var args = arguments,
-                       guid = fn.guid || jQuery.guid++,
-                       i = 0,
-                       toggler = function( event ) {
-                               // Figure out which function to execute
-                               var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
-                               jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
-
-                               // Make sure that clicks stop
-                               event.preventDefault();
-
-                               // and execute the function
-                               return args[ lastToggle ].apply( this, arguments ) || false;
-                       };
-
-               // link all the functions, so any of them can unbind this click handler
-               toggler.guid = guid;
-               while ( i < args.length ) {
-                       args[ i++ ].guid = guid;
-               }
-
-               return this.click( toggler );
-       },
-
-       hover: function( fnOver, fnOut ) {
-               return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
-       }
-});
-
-jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
-       "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
-       "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
-
-       // Handle event binding
-       jQuery.fn[ name ] = function( data, fn ) {
-               if ( fn == null ) {
-                       fn = data;
-                       data = null;
-               }
-
-               return arguments.length > 0 ?
-                       this.on( name, null, data, fn ) :
-                       this.trigger( name );
-       };
-
-       if ( rkeyEvent.test( name ) ) {
-               jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
-       }
-
-       if ( rmouseEvent.test( name ) ) {
-               jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
-       }
-});
-/*!\r
- * Sizzle CSS Selector Engine\r
- * Copyright 2012 jQuery Foundation and other contributors\r
- * Released under the MIT license\r
- * http://sizzlejs.com/\r
- */\r
-(function( window, undefined ) {\r
-\r
-var cachedruns,\r
-       assertGetIdNotName,\r
-       Expr,\r
-       getText,\r
-       isXML,\r
-       contains,\r
-       compile,\r
-       sortOrder,\r
-       hasDuplicate,\r
-       outermostContext,\r
-\r
-       baseHasDuplicate = true,\r
-       strundefined = "undefined",\r
-\r
-       expando = ( "sizcache" + Math.random() ).replace( ".", "" ),\r
-\r
-       Token = String,\r
-       document = window.document,\r
-       docElem = document.documentElement,\r
-       dirruns = 0,\r
-       done = 0,\r
-       pop = [].pop,\r
-       push = [].push,\r
-       slice = [].slice,\r
-       // Use a stripped-down indexOf if a native one is unavailable\r
-       indexOf = [].indexOf || function( elem ) {\r
-               var i = 0,\r
-                       len = this.length;\r
-               for ( ; i < len; i++ ) {\r
-                       if ( this[i] === elem ) {\r
-                               return i;\r
-                       }\r
-               }\r
-               return -1;\r
-       },\r
-\r
-       // Augment a function for special use by Sizzle\r
-       markFunction = function( fn, value ) {\r
-               fn[ expando ] = value == null || value;\r
-               return fn;\r
-       },\r
-\r
-       createCache = function() {\r
-               var cache = {},\r
-                       keys = [];\r
-\r
-               return markFunction(function( key, value ) {\r
-                       // Only keep the most recent entries\r
-                       if ( keys.push( key ) > Expr.cacheLength ) {\r
-                               delete cache[ keys.shift() ];\r
-                       }\r
-\r
-                       // Retrieve with (key + " ") to avoid collision with native Object.prototype properties (see Issue #157)\r
-                       return (cache[ key + " " ] = value);\r
-               }, cache );\r
-       },\r
-\r
-       classCache = createCache(),\r
-       tokenCache = createCache(),\r
-       compilerCache = createCache(),\r
-\r
-       // Regex\r
-\r
-       // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\r
-       whitespace = "[\\x20\\t\\r\\n\\f]",\r
-       // http://www.w3.org/TR/css3-syntax/#characters\r
-       characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",\r
-\r
-       // Loosely modeled on CSS identifier characters\r
-       // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)\r
-       // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\r
-       identifier = characterEncoding.replace( "w", "w#" ),\r
-\r
-       // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\r
-       operators = "([*^$|!~]?=)",\r
-       attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +\r
-               "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",\r
-\r
-       // Prefer arguments not in parens/brackets,\r
-       //   then attribute selectors and non-pseudos (denoted by :),\r
-       //   then anything else\r
-       // These preferences are here to reduce the number of selectors\r
-       //   needing tokenize in the PSEUDO preFilter\r
-       pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)",\r
-\r
-       // For matchExpr.POS and matchExpr.needsContext\r
-       pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +\r
-               "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)",\r
-\r
-       // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\r
-       rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),\r
-\r
-       rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),\r
-       rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),\r
-       rpseudo = new RegExp( pseudos ),\r
-\r
-       // Easily-parseable/retrievable ID or TAG or CLASS selectors\r
-       rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,\r
-\r
-       rnot = /^:not/,\r
-       rsibling = /[\x20\t\r\n\f]*[+~]/,\r
-       rendsWithNot = /:not\($/,\r
-\r
-       rheader = /h\d/i,\r
-       rinputs = /input|select|textarea|button/i,\r
-\r
-       rbackslash = /\\(?!\\)/g,\r
-\r
-       matchExpr = {\r
-               "ID": new RegExp( "^#(" + characterEncoding + ")" ),\r
-               "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),\r
-               "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),\r
-               "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),\r
-               "ATTR": new RegExp( "^" + attributes ),\r
-               "PSEUDO": new RegExp( "^" + pseudos ),\r
-               "POS": new RegExp( pos, "i" ),\r
-               "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace +\r
-                       "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +\r
-                       "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),\r
-               // For use in libraries implementing .is()\r
-               "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" )\r
-       },\r
-\r
-       // Support\r
-\r
-       // Used for testing something on an element\r
-       assert = function( fn ) {\r
-               var div = document.createElement("div");\r
-\r
-               try {\r
-                       return fn( div );\r
-               } catch (e) {\r
-                       return false;\r
-               } finally {\r
-                       // release memory in IE\r
-                       div = null;\r
-               }\r
-       },\r
-\r
-       // Check if getElementsByTagName("*") returns only elements\r
-       assertTagNameNoComments = assert(function( div ) {\r
-               div.appendChild( document.createComment("") );\r
-               return !div.getElementsByTagName("*").length;\r
-       }),\r
-\r
-       // Check if getAttribute returns normalized href attributes\r
-       assertHrefNotNormalized = assert(function( div ) {\r
-               div.innerHTML = "<a href='#'></a>";\r
-               return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&\r
-                       div.firstChild.getAttribute("href") === "#";\r
-       }),\r
-\r
-       // Check if attributes should be retrieved by attribute nodes\r
-       assertAttributes = assert(function( div ) {\r
-               div.innerHTML = "<select></select>";\r
-               var type = typeof div.lastChild.getAttribute("multiple");\r
-               // IE8 returns a string for some attributes even when not present\r
-               return type !== "boolean" && type !== "string";\r
-       }),\r
-\r
-       // Check if getElementsByClassName can be trusted\r
-       assertUsableClassName = assert(function( div ) {\r
-               // Opera can't find a second classname (in 9.6)\r
-               div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";\r
-               if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {\r
-                       return false;\r
-               }\r
-\r
-               // Safari 3.2 caches class attributes and doesn't catch changes\r
-               div.lastChild.className = "e";\r
-               return div.getElementsByClassName("e").length === 2;\r
-       }),\r
-\r
-       // Check if getElementById returns elements by name\r
-       // Check if getElementsByName privileges form controls or returns elements by ID\r
-       assertUsableName = assert(function( div ) {\r
-               // Inject content\r
-               div.id = expando + 0;\r
-               div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";\r
-               docElem.insertBefore( div, docElem.firstChild );\r
-\r
-               // Test\r
-               var pass = document.getElementsByName &&\r
-                       // buggy browsers will return fewer than the correct 2\r
-                       document.getElementsByName( expando ).length === 2 +\r
-                       // buggy browsers will return more than the correct 0\r
-                       document.getElementsByName( expando + 0 ).length;\r
-               assertGetIdNotName = !document.getElementById( expando );\r
-\r
-               // Cleanup\r
-               docElem.removeChild( div );\r
-\r
-               return pass;\r
-       });\r
-\r
-// If slice is not available, provide a backup\r
-try {\r
-       slice.call( docElem.childNodes, 0 )[0].nodeType;\r
-} catch ( e ) {\r
-       slice = function( i ) {\r
-               var elem,\r
-                       results = [];\r
-               for ( ; (elem = this[i]); i++ ) {\r
-                       results.push( elem );\r
-               }\r
-               return results;\r
-       };\r
-}\r
-\r
-function Sizzle( selector, context, results, seed ) {\r
-       results = results || [];\r
-       context = context || document;\r
-       var match, elem, xml, m,\r
-               nodeType = context.nodeType;\r
-\r
-       if ( !selector || typeof selector !== "string" ) {\r
-               return results;\r
-       }\r
-\r
-       if ( nodeType !== 1 && nodeType !== 9 ) {\r
-               return [];\r
-       }\r
-\r
-       xml = isXML( context );\r
-\r
-       if ( !xml && !seed ) {\r
-               if ( (match = rquickExpr.exec( selector )) ) {\r
-                       // Speed-up: Sizzle("#ID")\r
-                       if ( (m = match[1]) ) {\r
-                               if ( nodeType === 9 ) {\r
-                                       elem = context.getElementById( m );\r
-                                       // Check parentNode to catch when Blackberry 4.6 returns\r
-                                       // nodes that are no longer in the document #6963\r
-                                       if ( elem && elem.parentNode ) {\r
-                                               // Handle the case where IE, Opera, and Webkit return items\r
-                                               // by name instead of ID\r
-                                               if ( elem.id === m ) {\r
-                                                       results.push( elem );\r
-                                                       return results;\r
-                                               }\r
-                                       } else {\r
-                                               return results;\r
-                                       }\r
-                               } else {\r
-                                       // Context is not a document\r
-                                       if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\r
-                                               contains( context, elem ) && elem.id === m ) {\r
-                                               results.push( elem );\r
-                                               return results;\r
-                                       }\r
-                               }\r
-\r
-                       // Speed-up: Sizzle("TAG")\r
-                       } else if ( match[2] ) {\r
-                               push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );\r
-                               return results;\r
-\r
-                       // Speed-up: Sizzle(".CLASS")\r
-                       } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) {\r
-                               push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );\r
-                               return results;\r
-                       }\r
-               }\r
-       }\r
-\r
-       // All others\r
-       return select( selector.replace( rtrim, "$1" ), context, results, seed, xml );\r
-}\r
-\r
-Sizzle.matches = function( expr, elements ) {\r
-       return Sizzle( expr, null, null, elements );\r
-};\r
-\r
-Sizzle.matchesSelector = function( elem, expr ) {\r
-       return Sizzle( expr, null, null, [ elem ] ).length > 0;\r
-};\r
-\r
-// Returns a function to use in pseudos for input types\r
-function createInputPseudo( type ) {\r
-       return function( elem ) {\r
-               var name = elem.nodeName.toLowerCase();\r
-               return name === "input" && elem.type === type;\r
-       };\r
-}\r
-\r
-// Returns a function to use in pseudos for buttons\r
-function createButtonPseudo( type ) {\r
-       return function( elem ) {\r
-               var name = elem.nodeName.toLowerCase();\r
-               return (name === "input" || name === "button") && elem.type === type;\r
-       };\r
-}\r
-\r
-// Returns a function to use in pseudos for positionals\r
-function createPositionalPseudo( fn ) {\r
-       return markFunction(function( argument ) {\r
-               argument = +argument;\r
-               return markFunction(function( seed, matches ) {\r
-                       var j,\r
-                               matchIndexes = fn( [], seed.length, argument ),\r
-                               i = matchIndexes.length;\r
-\r
-                       // Match elements found at the specified indexes\r
-                       while ( i-- ) {\r
-                               if ( seed[ (j = matchIndexes[i]) ] ) {\r
-                                       seed[j] = !(matches[j] = seed[j]);\r
-                               }\r
-                       }\r
-               });\r
-       });\r
-}\r
-\r
-/**\r
- * Utility function for retrieving the text value of an array of DOM nodes\r
- * @param {Array|Element} elem\r
- */\r
-getText = Sizzle.getText = function( elem ) {\r
-       var node,\r
-               ret = "",\r
-               i = 0,\r
-               nodeType = elem.nodeType;\r
-\r
-       if ( nodeType ) {\r
-               if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\r
-                       // Use textContent for elements\r
-                       // innerText usage removed for consistency of new lines (see #11153)\r
-                       if ( typeof elem.textContent === "string" ) {\r
-                               return elem.textContent;\r
-                       } else {\r
-                               // Traverse its children\r
-                               for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\r
-                                       ret += getText( elem );\r
-                               }\r
-                       }\r
-               } else if ( nodeType === 3 || nodeType === 4 ) {\r
-                       return elem.nodeValue;\r
-               }\r
-               // Do not include comment or processing instruction nodes\r
-       } else {\r
-\r
-               // If no nodeType, this is expected to be an array\r
-               for ( ; (node = elem[i]); i++ ) {\r
-                       // Do not traverse comment nodes\r
-                       ret += getText( node );\r
-               }\r
-       }\r
-       return ret;\r
-};\r
-\r
-isXML = Sizzle.isXML = function( elem ) {\r
-       // documentElement is verified for cases where it doesn't yet exist\r
-       // (such as loading iframes in IE - #4833)\r
-       var documentElement = elem && (elem.ownerDocument || elem).documentElement;\r
-       return documentElement ? documentElement.nodeName !== "HTML" : false;\r
-};\r
-\r
-// Element contains another\r
-contains = Sizzle.contains = docElem.contains ?\r
-       function( a, b ) {\r
-               var adown = a.nodeType === 9 ? a.documentElement : a,\r
-                       bup = b && b.parentNode;\r
-               return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );\r
-       } :\r
-       docElem.compareDocumentPosition ?\r
-       function( a, b ) {\r
-               return b && !!( a.compareDocumentPosition( b ) & 16 );\r
-       } :\r
-       function( a, b ) {\r
-               while ( (b = b.parentNode) ) {\r
-                       if ( b === a ) {\r
-                               return true;\r
-                       }\r
-               }\r
-               return false;\r
-       };\r
-\r
-Sizzle.attr = function( elem, name ) {\r
-       var val,\r
-               xml = isXML( elem );\r
-\r
-       if ( !xml ) {\r
-               name = name.toLowerCase();\r
-       }\r
-       if ( (val = Expr.attrHandle[ name ]) ) {\r
-               return val( elem );\r
-       }\r
-       if ( xml || assertAttributes ) {\r
-               return elem.getAttribute( name );\r
-       }\r
-       val = elem.getAttributeNode( name );\r
-       return val ?\r
-               typeof elem[ name ] === "boolean" ?\r
-                       elem[ name ] ? name : null :\r
-                       val.specified ? val.value : null :\r
-               null;\r
-};\r
-\r
-Expr = Sizzle.selectors = {\r
-\r
-       // Can be adjusted by the user\r
-       cacheLength: 50,\r
-\r
-       createPseudo: markFunction,\r
-\r
-       match: matchExpr,\r
-\r
-       // IE6/7 return a modified href\r
-       attrHandle: assertHrefNotNormalized ?\r
-               {} :\r
-               {\r
-                       "href": function( elem ) {\r
-                               return elem.getAttribute( "href", 2 );\r
-                       },\r
-                       "type": function( elem ) {\r
-                               return elem.getAttribute("type");\r
-                       }\r
-               },\r
-\r
-       find: {\r
-               "ID": assertGetIdNotName ?\r
-                       function( id, context, xml ) {\r
-                               if ( typeof context.getElementById !== strundefined && !xml ) {\r
-                                       var m = context.getElementById( id );\r
-                                       // Check parentNode to catch when Blackberry 4.6 returns\r
-                                       // nodes that are no longer in the document #6963\r
-                                       return m && m.parentNode ? [m] : [];\r
-                               }\r
-                       } :\r
-                       function( id, context, xml ) {\r
-                               if ( typeof context.getElementById !== strundefined && !xml ) {\r
-                                       var m = context.getElementById( id );\r
-\r
-                                       return m ?\r
-                                               m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?\r
-                                                       [m] :\r
-                                                       undefined :\r
-                                               [];\r
-                               }\r
-                       },\r
-\r
-               "TAG": assertTagNameNoComments ?\r
-                       function( tag, context ) {\r
-                               if ( typeof context.getElementsByTagName !== strundefined ) {\r
-                                       return context.getElementsByTagName( tag );\r
-                               }\r
-                       } :\r
-                       function( tag, context ) {\r
-                               var results = context.getElementsByTagName( tag );\r
-\r
-                               // Filter out possible comments\r
-                               if ( tag === "*" ) {\r
-                                       var elem,\r
-                                               tmp = [],\r
-                                               i = 0;\r
-\r
-                                       for ( ; (elem = results[i]); i++ ) {\r
-                                               if ( elem.nodeType === 1 ) {\r
-                                                       tmp.push( elem );\r
-                                               }\r
-                                       }\r
-\r
-                                       return tmp;\r
-                               }\r
-                               return results;\r
-                       },\r
-\r
-               "NAME": assertUsableName && function( tag, context ) {\r
-                       if ( typeof context.getElementsByName !== strundefined ) {\r
-                               return context.getElementsByName( name );\r
-                       }\r
-               },\r
-\r
-               "CLASS": assertUsableClassName && function( className, context, xml ) {\r
-                       if ( typeof context.getElementsByClassName !== strundefined && !xml ) {\r
-                               return context.getElementsByClassName( className );\r
-                       }\r
-               }\r
-       },\r
-\r
-       relative: {\r
-               ">": { dir: "parentNode", first: true },\r
-               " ": { dir: "parentNode" },\r
-               "+": { dir: "previousSibling", first: true },\r
-               "~": { dir: "previousSibling" }\r
-       },\r
-\r
-       preFilter: {\r
-               "ATTR": function( match ) {\r
-                       match[1] = match[1].replace( rbackslash, "" );\r
-\r
-                       // Move the given value to match[3] whether quoted or unquoted\r
-                       match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" );\r
-\r
-                       if ( match[2] === "~=" ) {\r
-                               match[3] = " " + match[3] + " ";\r
-                       }\r
-\r
-                       return match.slice( 0, 4 );\r
-               },\r
-\r
-               "CHILD": function( match ) {\r
-                       /* matches from matchExpr["CHILD"]\r
-                               1 type (only|nth|...)\r
-                               2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)\r
-                               3 xn-component of xn+y argument ([+-]?\d*n|)\r
-                               4 sign of xn-component\r
-                               5 x of xn-component\r
-                               6 sign of y-component\r
-                               7 y of y-component\r
-                       */\r
-                       match[1] = match[1].toLowerCase();\r
-\r
-                       if ( match[1] === "nth" ) {\r
-                               // nth-child requires argument\r
-                               if ( !match[2] ) {\r
-                                       Sizzle.error( match[0] );\r
-                               }\r
-\r
-                               // numeric x and y parameters for Expr.filter.CHILD\r
-                               // remember that false/true cast respectively to 0/1\r
-                               match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) );\r
-                               match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" );\r
-\r
-                       // other types prohibit arguments\r
-                       } else if ( match[2] ) {\r
-                               Sizzle.error( match[0] );\r
-                       }\r
-\r
-                       return match;\r
-               },\r
-\r
-               "PSEUDO": function( match ) {\r
-                       var unquoted, excess;\r
-                       if ( matchExpr["CHILD"].test( match[0] ) ) {\r
-                               return null;\r
-                       }\r
-\r
-                       if ( match[3] ) {\r
-                               match[2] = match[3];\r
-                       } else if ( (unquoted = match[4]) ) {\r
-                               // Only check arguments that contain a pseudo\r
-                               if ( rpseudo.test(unquoted) &&\r
-                                       // Get excess from tokenize (recursively)\r
-                                       (excess = tokenize( unquoted, true )) &&\r
-                                       // advance to the next closing parenthesis\r
-                                       (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {\r
-\r
-                                       // excess is a negative index\r
-                                       unquoted = unquoted.slice( 0, excess );\r
-                                       match[0] = match[0].slice( 0, excess );\r
-                               }\r
-                               match[2] = unquoted;\r
-                       }\r
-\r
-                       // Return only captures needed by the pseudo filter method (type and argument)\r
-                       return match.slice( 0, 3 );\r
-               }\r
-       },\r
-\r
-       filter: {\r
-               "ID": assertGetIdNotName ?\r
-                       function( id ) {\r
-                               id = id.replace( rbackslash, "" );\r
-                               return function( elem ) {\r
-                                       return elem.getAttribute("id") === id;\r
-                               };\r
-                       } :\r
-                       function( id ) {\r
-                               id = id.replace( rbackslash, "" );\r
-                               return function( elem ) {\r
-                                       var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");\r
-                                       return node && node.value === id;\r
-                               };\r
-                       },\r
-\r
-               "TAG": function( nodeName ) {\r
-                       if ( nodeName === "*" ) {\r
-                               return function() { return true; };\r
-                       }\r
-                       nodeName = nodeName.replace( rbackslash, "" ).toLowerCase();\r
-\r
-                       return function( elem ) {\r
-                               return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\r
-                       };\r
-               },\r
-\r
-               "CLASS": function( className ) {\r
-                       var pattern = classCache[ expando ][ className + " " ];\r
-\r
-                       return pattern ||\r
-                               (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&\r
-                               classCache( className, function( elem ) {\r
-                                       return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );\r
-                               });\r
-               },\r
-\r
-               "ATTR": function( name, operator, check ) {\r
-                       return function( elem, context ) {\r
-                               var result = Sizzle.attr( elem, name );\r
-\r
-                               if ( result == null ) {\r
-                                       return operator === "!=";\r
-                               }\r
-                               if ( !operator ) {\r
-                                       return true;\r
-                               }\r
-\r
-                               result += "";\r
-\r
-                               return operator === "=" ? result === check :\r
-                                       operator === "!=" ? result !== check :\r
-                                       operator === "^=" ? check && result.indexOf( check ) === 0 :\r
-                                       operator === "*=" ? check && result.indexOf( check ) > -1 :\r
-                                       operator === "$=" ? check && result.substr( result.length - check.length ) === check :\r
-                                       operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :\r
-                                       operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" :\r
-                                       false;\r
-                       };\r
-               },\r
-\r
-               "CHILD": function( type, argument, first, last ) {\r
-\r
-                       if ( type === "nth" ) {\r
-                               return function( elem ) {\r
-                                       var node, diff,\r
-                                               parent = elem.parentNode;\r
-\r
-                                       if ( first === 1 && last === 0 ) {\r
-                                               return true;\r
-                                       }\r
-\r
-                                       if ( parent ) {\r
-                                               diff = 0;\r
-                                               for ( node = parent.firstChild; node; node = node.nextSibling ) {\r
-                                                       if ( node.nodeType === 1 ) {\r
-                                                               diff++;\r
-                                                               if ( elem === node ) {\r
-                                                                       break;\r
-                                                               }\r
-                                                       }\r
-                                               }\r
-                                       }\r
-\r
-                                       // Incorporate the offset (or cast to NaN), then check against cycle size\r
-                                       diff -= last;\r
-                                       return diff === first || ( diff % first === 0 && diff / first >= 0 );\r
-                               };\r
-                       }\r
-\r
-                       return function( elem ) {\r
-                               var node = elem;\r
-\r
-                               switch ( type ) {\r
-                                       case "only":\r
-                                       case "first":\r
-                                               while ( (node = node.previousSibling) ) {\r
-                                                       if ( node.nodeType === 1 ) {\r
-                                                               return false;\r
-                                                       }\r
-                                               }\r
-\r
-                                               if ( type === "first" ) {\r
-                                                       return true;\r
-                                               }\r
-\r
-                                               node = elem;\r
-\r
-                                               /* falls through */\r
-                                       case "last":\r
-                                               while ( (node = node.nextSibling) ) {\r
-                                                       if ( node.nodeType === 1 ) {\r
-                                                               return false;\r
-                                                       }\r
-                                               }\r
-\r
-                                               return true;\r
-                               }\r
-                       };\r
-               },\r
-\r
-               "PSEUDO": function( pseudo, argument ) {\r
-                       // pseudo-class names are case-insensitive\r
-                       // http://www.w3.org/TR/selectors/#pseudo-classes\r
-                       // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\r
-                       // Remember that setFilters inherits from pseudos\r
-                       var args,\r
-                               fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\r
-                                       Sizzle.error( "unsupported pseudo: " + pseudo );\r
-\r
-                       // The user may use createPseudo to indicate that\r
-                       // arguments are needed to create the filter function\r
-                       // just as Sizzle does\r
-                       if ( fn[ expando ] ) {\r
-                               return fn( argument );\r
-                       }\r
-\r
-                       // But maintain support for old signatures\r
-                       if ( fn.length > 1 ) {\r
-                               args = [ pseudo, pseudo, "", argument ];\r
-                               return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\r
-                                       markFunction(function( seed, matches ) {\r
-                                               var idx,\r
-                                                       matched = fn( seed, argument ),\r
-                                                       i = matched.length;\r
-                                               while ( i-- ) {\r
-                                                       idx = indexOf.call( seed, matched[i] );\r
-                                                       seed[ idx ] = !( matches[ idx ] = matched[i] );\r
-                                               }\r
-                                       }) :\r
-                                       function( elem ) {\r
-                                               return fn( elem, 0, args );\r
-                                       };\r
-                       }\r
-\r
-                       return fn;\r
-               }\r
-       },\r
-\r
-       pseudos: {\r
-               "not": markFunction(function( selector ) {\r
-                       // Trim the selector passed to compile\r
-                       // to avoid treating leading and trailing\r
-                       // spaces as combinators\r
-                       var input = [],\r
-                               results = [],\r
-                               matcher = compile( selector.replace( rtrim, "$1" ) );\r
-\r
-                       return matcher[ expando ] ?\r
-                               markFunction(function( seed, matches, context, xml ) {\r
-                                       var elem,\r
-                                               unmatched = matcher( seed, null, xml, [] ),\r
-                                               i = seed.length;\r
-\r
-                                       // Match elements unmatched by `matcher`\r
-                                       while ( i-- ) {\r
-                                               if ( (elem = unmatched[i]) ) {\r
-                                                       seed[i] = !(matches[i] = elem);\r
-                                               }\r
-                                       }\r
-                               }) :\r
-                               function( elem, context, xml ) {\r
-                                       input[0] = elem;\r
-                                       matcher( input, null, xml, results );\r
-                                       return !results.pop();\r
-                               };\r
-               }),\r
-\r
-               "has": markFunction(function( selector ) {\r
-                       return function( elem ) {\r
-                               return Sizzle( selector, elem ).length > 0;\r
-                       };\r
-               }),\r
-\r
-               "contains": markFunction(function( text ) {\r
-                       return function( elem ) {\r
-                               return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\r
-                       };\r
-               }),\r
-\r
-               "enabled": function( elem ) {\r
-                       return elem.disabled === false;\r
-               },\r
-\r
-               "disabled": function( elem ) {\r
-                       return elem.disabled === true;\r
-               },\r
-\r
-               "checked": function( elem ) {\r
-                       // In CSS3, :checked should return both checked and selected elements\r
-                       // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\r
-                       var nodeName = elem.nodeName.toLowerCase();\r
-                       return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);\r
-               },\r
-\r
-               "selected": function( elem ) {\r
-                       // Accessing this property makes selected-by-default\r
-                       // options in Safari work properly\r
-                       if ( elem.parentNode ) {\r
-                               elem.parentNode.selectedIndex;\r
-                       }\r
-\r
-                       return elem.selected === true;\r
-               },\r
-\r
-               "parent": function( elem ) {\r
-                       return !Expr.pseudos["empty"]( elem );\r
-               },\r
-\r
-               "empty": function( elem ) {\r
-                       // http://www.w3.org/TR/selectors/#empty-pseudo\r
-                       // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),\r
-                       //   not comment, processing instructions, or others\r
-                       // Thanks to Diego Perini for the nodeName shortcut\r
-                       //   Greater than "@" means alpha characters (specifically not starting with "#" or "?")\r
-                       var nodeType;\r
-                       elem = elem.firstChild;\r
-                       while ( elem ) {\r
-                               if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) {\r
-                                       return false;\r
-                               }\r
-                               elem = elem.nextSibling;\r
-                       }\r
-                       return true;\r
-               },\r
-\r
-               "header": function( elem ) {\r
-                       return rheader.test( elem.nodeName );\r
-               },\r
-\r
-               "text": function( elem ) {\r
-                       var type, attr;\r
-                       // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\r
-                       // use getAttribute instead to test this case\r
-                       return elem.nodeName.toLowerCase() === "input" &&\r
-                               (type = elem.type) === "text" &&\r
-                               ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type );\r
-               },\r
-\r
-               // Input types\r
-               "radio": createInputPseudo("radio"),\r
-               "checkbox": createInputPseudo("checkbox"),\r
-               "file": createInputPseudo("file"),\r
-               "password": createInputPseudo("password"),\r
-               "image": createInputPseudo("image"),\r
-\r
-               "submit": createButtonPseudo("submit"),\r
-               "reset": createButtonPseudo("reset"),\r
-\r
-               "button": function( elem ) {\r
-                       var name = elem.nodeName.toLowerCase();\r
-                       return name === "input" && elem.type === "button" || name === "button";\r
-               },\r
-\r
-               "input": function( elem ) {\r
-                       return rinputs.test( elem.nodeName );\r
-               },\r
-\r
-               "focus": function( elem ) {\r
-                       var doc = elem.ownerDocument;\r
-                       return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\r
-               },\r
-\r
-               "active": function( elem ) {\r
-                       return elem === elem.ownerDocument.activeElement;\r
-               },\r
-\r
-               // Positional types\r
-               "first": createPositionalPseudo(function() {\r
-                       return [ 0 ];\r
-               }),\r
-\r
-               "last": createPositionalPseudo(function( matchIndexes, length ) {\r
-                       return [ length - 1 ];\r
-               }),\r
-\r
-               "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {\r
-                       return [ argument < 0 ? argument + length : argument ];\r
-               }),\r
-\r
-               "even": createPositionalPseudo(function( matchIndexes, length ) {\r
-                       for ( var i = 0; i < length; i += 2 ) {\r
-                               matchIndexes.push( i );\r
-                       }\r
-                       return matchIndexes;\r
-               }),\r
-\r
-               "odd": createPositionalPseudo(function( matchIndexes, length ) {\r
-                       for ( var i = 1; i < length; i += 2 ) {\r
-                               matchIndexes.push( i );\r
-                       }\r
-                       return matchIndexes;\r
-               }),\r
-\r
-               "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {\r
-                       for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) {\r
-                               matchIndexes.push( i );\r
-                       }\r
-                       return matchIndexes;\r
-               }),\r
-\r
-               "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {\r
-                       for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) {\r
-                               matchIndexes.push( i );\r
-                       }\r
-                       return matchIndexes;\r
-               })\r
-       }\r
-};\r
-\r
-function siblingCheck( a, b, ret ) {\r
-       if ( a === b ) {\r
-               return ret;\r
-       }\r
-\r
-       var cur = a.nextSibling;\r
-\r
-       while ( cur ) {\r
-               if ( cur === b ) {\r
-                       return -1;\r
-               }\r
-\r
-               cur = cur.nextSibling;\r
-       }\r
-\r
-       return 1;\r
-}\r
-\r
-sortOrder = docElem.compareDocumentPosition ?\r
-       function( a, b ) {\r
-               if ( a === b ) {\r
-                       hasDuplicate = true;\r
-                       return 0;\r
-               }\r
-\r
-               return ( !a.compareDocumentPosition || !b.compareDocumentPosition ?\r
-                       a.compareDocumentPosition :\r
-                       a.compareDocumentPosition(b) & 4\r
-               ) ? -1 : 1;\r
-       } :\r
-       function( a, b ) {\r
-               // The nodes are identical, we can exit early\r
-               if ( a === b ) {\r
-                       hasDuplicate = true;\r
-                       return 0;\r
-\r
-               // Fallback to using sourceIndex (in IE) if it's available on both nodes\r
-               } else if ( a.sourceIndex && b.sourceIndex ) {\r
-                       return a.sourceIndex - b.sourceIndex;\r
-               }\r
-\r
-               var al, bl,\r
-                       ap = [],\r
-                       bp = [],\r
-                       aup = a.parentNode,\r
-                       bup = b.parentNode,\r
-                       cur = aup;\r
-\r
-               // If the nodes are siblings (or identical) we can do a quick check\r
-               if ( aup === bup ) {\r
-                       return siblingCheck( a, b );\r
-\r
-               // If no parents were found then the nodes are disconnected\r
-               } else if ( !aup ) {\r
-                       return -1;\r
-\r
-               } else if ( !bup ) {\r
-                       return 1;\r
-               }\r
-\r
-               // Otherwise they're somewhere else in the tree so we need\r
-               // to build up a full list of the parentNodes for comparison\r
-               while ( cur ) {\r
-                       ap.unshift( cur );\r
-                       cur = cur.parentNode;\r
-               }\r
-\r
-               cur = bup;\r
-\r
-               while ( cur ) {\r
-                       bp.unshift( cur );\r
-                       cur = cur.parentNode;\r
-               }\r
-\r
-               al = ap.length;\r
-               bl = bp.length;\r
-\r
-               // Start walking down the tree looking for a discrepancy\r
-               for ( var i = 0; i < al && i < bl; i++ ) {\r
-                       if ( ap[i] !== bp[i] ) {\r
-                               return siblingCheck( ap[i], bp[i] );\r
-                       }\r
-               }\r
-\r
-               // We ended someplace up the tree so do a sibling check\r
-               return i === al ?\r
-                       siblingCheck( a, bp[i], -1 ) :\r
-                       siblingCheck( ap[i], b, 1 );\r
-       };\r
-\r
-// Always assume the presence of duplicates if sort doesn't\r
-// pass them to our comparison function (as in Google Chrome).\r
-[0, 0].sort( sortOrder );\r
-baseHasDuplicate = !hasDuplicate;\r
-\r
-// Document sorting and removing duplicates\r
-Sizzle.uniqueSort = function( results ) {\r
-       var elem,\r
-               duplicates = [],\r
-               i = 1,\r
-               j = 0;\r
-\r
-       hasDuplicate = baseHasDuplicate;\r
-       results.sort( sortOrder );\r
-\r
-       if ( hasDuplicate ) {\r
-               for ( ; (elem = results[i]); i++ ) {\r
-                       if ( elem === results[ i - 1 ] ) {\r
-                               j = duplicates.push( i );\r
-                       }\r
-               }\r
-               while ( j-- ) {\r
-                       results.splice( duplicates[ j ], 1 );\r
-               }\r
-       }\r
-\r
-       return results;\r
-};\r
-\r
-Sizzle.error = function( msg ) {\r
-       throw new Error( "Syntax error, unrecognized expression: " + msg );\r
-};\r
-\r
-function tokenize( selector, parseOnly ) {\r
-       var matched, match, tokens, type,\r
-               soFar, groups, preFilters,\r
-               cached = tokenCache[ expando ][ selector + " " ];\r
-\r
-       if ( cached ) {\r
-               return parseOnly ? 0 : cached.slice( 0 );\r
-       }\r
-\r
-       soFar = selector;\r
-       groups = [];\r
-       preFilters = Expr.preFilter;\r
-\r
-       while ( soFar ) {\r
-\r
-               // Comma and first run\r
-               if ( !matched || (match = rcomma.exec( soFar )) ) {\r
-                       if ( match ) {\r
-                               // Don't consume trailing commas as valid\r
-                               soFar = soFar.slice( match[0].length ) || soFar;\r
-                       }\r
-                       groups.push( tokens = [] );\r
-               }\r
-\r
-               matched = false;\r
-\r
-               // Combinators\r
-               if ( (match = rcombinators.exec( soFar )) ) {\r
-                       tokens.push( matched = new Token( match.shift() ) );\r
-                       soFar = soFar.slice( matched.length );\r
-\r
-                       // Cast descendant combinators to space\r
-                       matched.type = match[0].replace( rtrim, " " );\r
-               }\r
-\r
-               // Filters\r
-               for ( type in Expr.filter ) {\r
-                       if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\r
-                               (match = preFilters[ type ]( match ))) ) {\r
-\r
-                               tokens.push( matched = new Token( match.shift() ) );\r
-                               soFar = soFar.slice( matched.length );\r
-                               matched.type = type;\r
-                               matched.matches = match;\r
-                       }\r
-               }\r
-\r
-               if ( !matched ) {\r
-                       break;\r
-               }\r
-       }\r
-\r
-       // Return the length of the invalid excess\r
-       // if we're just parsing\r
-       // Otherwise, throw an error or return tokens\r
-       return parseOnly ?\r
-               soFar.length :\r
-               soFar ?\r
-                       Sizzle.error( selector ) :\r
-                       // Cache the tokens\r
-                       tokenCache( selector, groups ).slice( 0 );\r
-}\r
-\r
-function addCombinator( matcher, combinator, base ) {\r
-       var dir = combinator.dir,\r
-               checkNonElements = base && combinator.dir === "parentNode",\r
-               doneName = done++;\r
-\r
-       return combinator.first ?\r
-               // Check against closest ancestor/preceding element\r
-               function( elem, context, xml ) {\r
-                       while ( (elem = elem[ dir ]) ) {\r
-                               if ( checkNonElements || elem.nodeType === 1  ) {\r
-                                       return matcher( elem, context, xml );\r
-                               }\r
-                       }\r
-               } :\r
-\r
-               // Check against all ancestor/preceding elements\r
-               function( elem, context, xml ) {\r
-                       // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\r
-                       if ( !xml ) {\r
-                               var cache,\r
-                                       dirkey = dirruns + " " + doneName + " ",\r
-                                       cachedkey = dirkey + cachedruns;\r
-                               while ( (elem = elem[ dir ]) ) {\r
-                                       if ( checkNonElements || elem.nodeType === 1 ) {\r
-                                               if ( (cache = elem[ expando ]) === cachedkey ) {\r
-                                                       return elem.sizset;\r
-                                               } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) {\r
-                                                       if ( elem.sizset ) {\r
-                                                               return elem;\r
-                                                       }\r
-                                               } else {\r
-                                                       elem[ expando ] = cachedkey;\r
-                                                       if ( matcher( elem, context, xml ) ) {\r
-                                                               elem.sizset = true;\r
-                                                               return elem;\r
-                                                       }\r
-                                                       elem.sizset = false;\r
-                                               }\r
-                                       }\r
-                               }\r
-                       } else {\r
-                               while ( (elem = elem[ dir ]) ) {\r
-                                       if ( checkNonElements || elem.nodeType === 1 ) {\r
-                                               if ( matcher( elem, context, xml ) ) {\r
-                                                       return elem;\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-               };\r
-}\r
-\r
-function elementMatcher( matchers ) {\r
-       return matchers.length > 1 ?\r
-               function( elem, context, xml ) {\r
-                       var i = matchers.length;\r
-                       while ( i-- ) {\r
-                               if ( !matchers[i]( elem, context, xml ) ) {\r
-                                       return false;\r
-                               }\r
-                       }\r
-                       return true;\r
-               } :\r
-               matchers[0];\r
-}\r
-\r
-function condense( unmatched, map, filter, context, xml ) {\r
-       var elem,\r
-               newUnmatched = [],\r
-               i = 0,\r
-               len = unmatched.length,\r
-               mapped = map != null;\r
-\r
-       for ( ; i < len; i++ ) {\r
-               if ( (elem = unmatched[i]) ) {\r
-                       if ( !filter || filter( elem, context, xml ) ) {\r
-                               newUnmatched.push( elem );\r
-                               if ( mapped ) {\r
-                                       map.push( i );\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       return newUnmatched;\r
-}\r
-\r
-function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\r
-       if ( postFilter && !postFilter[ expando ] ) {\r
-               postFilter = setMatcher( postFilter );\r
-       }\r
-       if ( postFinder && !postFinder[ expando ] ) {\r
-               postFinder = setMatcher( postFinder, postSelector );\r
-       }\r
-       return markFunction(function( seed, results, context, xml ) {\r
-               var temp, i, elem,\r
-                       preMap = [],\r
-                       postMap = [],\r
-                       preexisting = results.length,\r
-\r
-                       // Get initial elements from seed or context\r
-                       elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),\r
-\r
-                       // Prefilter to get matcher input, preserving a map for seed-results synchronization\r
-                       matcherIn = preFilter && ( seed || !selector ) ?\r
-                               condense( elems, preMap, preFilter, context, xml ) :\r
-                               elems,\r
-\r
-                       matcherOut = matcher ?\r
-                               // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\r
-                               postFinder || ( seed ? preFilter : preexisting || postFilter ) ?\r
-\r
-                                       // ...intermediate processing is necessary\r
-                                       [] :\r
-\r
-                                       // ...otherwise use results directly\r
-                                       results :\r
-                               matcherIn;\r
-\r
-               // Find primary matches\r
-               if ( matcher ) {\r
-                       matcher( matcherIn, matcherOut, context, xml );\r
-               }\r
-\r
-               // Apply postFilter\r
-               if ( postFilter ) {\r
-                       temp = condense( matcherOut, postMap );\r
-                       postFilter( temp, [], context, xml );\r
-\r
-                       // Un-match failing elements by moving them back to matcherIn\r
-                       i = temp.length;\r
-                       while ( i-- ) {\r
-                               if ( (elem = temp[i]) ) {\r
-                                       matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\r
-                               }\r
-                       }\r
-               }\r
-\r
-               if ( seed ) {\r
-                       if ( postFinder || preFilter ) {\r
-                               if ( postFinder ) {\r
-                                       // Get the final matcherOut by condensing this intermediate into postFinder contexts\r
-                                       temp = [];\r
-                                       i = matcherOut.length;\r
-                                       while ( i-- ) {\r
-                                               if ( (elem = matcherOut[i]) ) {\r
-                                                       // Restore matcherIn since elem is not yet a final match\r
-                                                       temp.push( (matcherIn[i] = elem) );\r
-                                               }\r
-                                       }\r
-                                       postFinder( null, (matcherOut = []), temp, xml );\r
-                               }\r
-\r
-                               // Move matched elements from seed to results to keep them synchronized\r
-                               i = matcherOut.length;\r
-                               while ( i-- ) {\r
-                                       if ( (elem = matcherOut[i]) &&\r
-                                               (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {\r
-\r
-                                               seed[temp] = !(results[temp] = elem);\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-               // Add elements to results, through postFinder if defined\r
-               } else {\r
-                       matcherOut = condense(\r
-                               matcherOut === results ?\r
-                                       matcherOut.splice( preexisting, matcherOut.length ) :\r
-                                       matcherOut\r
-                       );\r
-                       if ( postFinder ) {\r
-                               postFinder( null, results, matcherOut, xml );\r
-                       } else {\r
-                               push.apply( results, matcherOut );\r
-                       }\r
-               }\r
-       });\r
-}\r
-\r
-function matcherFromTokens( tokens ) {\r
-       var checkContext, matcher, j,\r
-               len = tokens.length,\r
-               leadingRelative = Expr.relative[ tokens[0].type ],\r
-               implicitRelative = leadingRelative || Expr.relative[" "],\r
-               i = leadingRelative ? 1 : 0,\r
-\r
-               // The foundational matcher ensures that elements are reachable from top-level context(s)\r
-               matchContext = addCombinator( function( elem ) {\r
-                       return elem === checkContext;\r
-               }, implicitRelative, true ),\r
-               matchAnyContext = addCombinator( function( elem ) {\r
-                       return indexOf.call( checkContext, elem ) > -1;\r
-               }, implicitRelative, true ),\r
-               matchers = [ function( elem, context, xml ) {\r
-                       return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\r
-                               (checkContext = context).nodeType ?\r
-                                       matchContext( elem, context, xml ) :\r
-                                       matchAnyContext( elem, context, xml ) );\r
-               } ];\r
-\r
-       for ( ; i < len; i++ ) {\r
-               if ( (matcher = Expr.relative[ tokens[i].type ]) ) {\r
-                       matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];\r
-               } else {\r
-                       matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\r
-\r
-                       // Return special upon seeing a positional matcher\r
-                       if ( matcher[ expando ] ) {\r
-                               // Find the next relative operator (if any) for proper handling\r
-                               j = ++i;\r
-                               for ( ; j < len; j++ ) {\r
-                                       if ( Expr.relative[ tokens[j].type ] ) {\r
-                                               break;\r
-                                       }\r
-                               }\r
-                               return setMatcher(\r
-                                       i > 1 && elementMatcher( matchers ),\r
-                                       i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ),\r
-                                       matcher,\r
-                                       i < j && matcherFromTokens( tokens.slice( i, j ) ),\r
-                                       j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\r
-                                       j < len && tokens.join("")\r
-                               );\r
-                       }\r
-                       matchers.push( matcher );\r
-               }\r
-       }\r
-\r
-       return elementMatcher( matchers );\r
-}\r
-\r
-function matcherFromGroupMatchers( elementMatchers, setMatchers ) {\r
-       var bySet = setMatchers.length > 0,\r
-               byElement = elementMatchers.length > 0,\r
-               superMatcher = function( seed, context, xml, results, expandContext ) {\r
-                       var elem, j, matcher,\r
-                               setMatched = [],\r
-                               matchedCount = 0,\r
-                               i = "0",\r
-                               unmatched = seed && [],\r
-                               outermost = expandContext != null,\r
-                               contextBackup = outermostContext,\r
-                               // We must always have either seed elements or context\r
-                               elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),\r
-                               // Nested matchers should use non-integer dirruns\r
-                               dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);\r
-\r
-                       if ( outermost ) {\r
-                               outermostContext = context !== document && context;\r
-                               cachedruns = superMatcher.el;\r
-                       }\r
-\r
-                       // Add elements passing elementMatchers directly to results\r
-                       for ( ; (elem = elems[i]) != null; i++ ) {\r
-                               if ( byElement && elem ) {\r
-                                       for ( j = 0; (matcher = elementMatchers[j]); j++ ) {\r
-                                               if ( matcher( elem, context, xml ) ) {\r
-                                                       results.push( elem );\r
-                                                       break;\r
-                                               }\r
-                                       }\r
-                                       if ( outermost ) {\r
-                                               dirruns = dirrunsUnique;\r
-                                               cachedruns = ++superMatcher.el;\r
-                                       }\r
-                               }\r
-\r
-                               // Track unmatched elements for set filters\r
-                               if ( bySet ) {\r
-                                       // They will have gone through all possible matchers\r
-                                       if ( (elem = !matcher && elem) ) {\r
-                                               matchedCount--;\r
-                                       }\r
-\r
-                                       // Lengthen the array for every element, matched or not\r
-                                       if ( seed ) {\r
-                                               unmatched.push( elem );\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       // Apply set filters to unmatched elements\r
-                       matchedCount += i;\r
-                       if ( bySet && i !== matchedCount ) {\r
-                               for ( j = 0; (matcher = setMatchers[j]); j++ ) {\r
-                                       matcher( unmatched, setMatched, context, xml );\r
-                               }\r
-\r
-                               if ( seed ) {\r
-                                       // Reintegrate element matches to eliminate the need for sorting\r
-                                       if ( matchedCount > 0 ) {\r
-                                               while ( i-- ) {\r
-                                                       if ( !(unmatched[i] || setMatched[i]) ) {\r
-                                                               setMatched[i] = pop.call( results );\r
-                                                       }\r
-                                               }\r
-                                       }\r
-\r
-                                       // Discard index placeholder values to get only actual matches\r
-                                       setMatched = condense( setMatched );\r
-                               }\r
-\r
-                               // Add matches to results\r
-                               push.apply( results, setMatched );\r
-\r
-                               // Seedless set matches succeeding multiple successful matchers stipulate sorting\r
-                               if ( outermost && !seed && setMatched.length > 0 &&\r
-                                       ( matchedCount + setMatchers.length ) > 1 ) {\r
-\r
-                                       Sizzle.uniqueSort( results );\r
-                               }\r
-                       }\r
-\r
-                       // Override manipulation of globals by nested matchers\r
-                       if ( outermost ) {\r
-                               dirruns = dirrunsUnique;\r
-                               outermostContext = contextBackup;\r
-                       }\r
-\r
-                       return unmatched;\r
-               };\r
-\r
-       superMatcher.el = 0;\r
-       return bySet ?\r
-               markFunction( superMatcher ) :\r
-               superMatcher;\r
-}\r
-\r
-compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {\r
-       var i,\r
-               setMatchers = [],\r
-               elementMatchers = [],\r
-               cached = compilerCache[ expando ][ selector + " " ];\r
-\r
-       if ( !cached ) {\r
-               // Generate a function of recursive functions that can be used to check each element\r
-               if ( !group ) {\r
-                       group = tokenize( selector );\r
-               }\r
-               i = group.length;\r
-               while ( i-- ) {\r
-                       cached = matcherFromTokens( group[i] );\r
-                       if ( cached[ expando ] ) {\r
-                               setMatchers.push( cached );\r
-                       } else {\r
-                               elementMatchers.push( cached );\r
-                       }\r
-               }\r
-\r
-               // Cache the compiled function\r
-               cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\r
-       }\r
-       return cached;\r
-};\r
-\r
-function multipleContexts( selector, contexts, results ) {\r
-       var i = 0,\r
-               len = contexts.length;\r
-       for ( ; i < len; i++ ) {\r
-               Sizzle( selector, contexts[i], results );\r
-       }\r
-       return results;\r
-}\r
-\r
-function select( selector, context, results, seed, xml ) {\r
-       var i, tokens, token, type, find,\r
-               match = tokenize( selector ),\r
-               j = match.length;\r
-\r
-       if ( !seed ) {\r
-               // Try to minimize operations if there is only one group\r
-               if ( match.length === 1 ) {\r
-\r
-                       // Take a shortcut and set the context if the root selector is an ID\r
-                       tokens = match[0] = match[0].slice( 0 );\r
-                       if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&\r
-                                       context.nodeType === 9 && !xml &&\r
-                                       Expr.relative[ tokens[1].type ] ) {\r
-\r
-                               context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0];\r
-                               if ( !context ) {\r
-                                       return results;\r
-                               }\r
-\r
-                               selector = selector.slice( tokens.shift().length );\r
-                       }\r
-\r
-                       // Fetch a seed set for right-to-left matching\r
-                       for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) {\r
-                               token = tokens[i];\r
-\r
-                               // Abort if we hit a combinator\r
-                               if ( Expr.relative[ (type = token.type) ] ) {\r
-                                       break;\r
-                               }\r
-                               if ( (find = Expr.find[ type ]) ) {\r
-                                       // Search, expanding context for leading sibling combinators\r
-                                       if ( (seed = find(\r
-                                               token.matches[0].replace( rbackslash, "" ),\r
-                                               rsibling.test( tokens[0].type ) && context.parentNode || context,\r
-                                               xml\r
-                                       )) ) {\r
-\r
-                                               // If seed is empty or no tokens remain, we can return early\r
-                                               tokens.splice( i, 1 );\r
-                                               selector = seed.length && tokens.join("");\r
-                                               if ( !selector ) {\r
-                                                       push.apply( results, slice.call( seed, 0 ) );\r
-                                                       return results;\r
-                                               }\r
-\r
-                                               break;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       // Compile and execute a filtering function\r
-       // Provide `match` to avoid retokenization if we modified the selector above\r
-       compile( selector, match )(\r
-               seed,\r
-               context,\r
-               xml,\r
-               results,\r
-               rsibling.test( selector )\r
-       );\r
-       return results;\r
-}\r
-\r
-if ( document.querySelectorAll ) {\r
-       (function() {\r
-               var disconnectedMatch,\r
-                       oldSelect = select,\r
-                       rescape = /'|\\/g,\r
-                       rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,\r
-\r
-                       // qSa(:focus) reports false when true (Chrome 21), no need to also add to buggyMatches since matches checks buggyQSA\r
-                       // A support test would require too much code (would include document ready)\r
-                       rbuggyQSA = [ ":focus" ],\r
-\r
-                       // matchesSelector(:active) reports false when true (IE9/Opera 11.5)\r
-                       // A support test would require too much code (would include document ready)\r
-                       // just skip matchesSelector for :active\r
-                       rbuggyMatches = [ ":active" ],\r
-                       matches = docElem.matchesSelector ||\r
-                               docElem.mozMatchesSelector ||\r
-                               docElem.webkitMatchesSelector ||\r
-                               docElem.oMatchesSelector ||\r
-                               docElem.msMatchesSelector;\r
-\r
-               // Build QSA regex\r
-               // Regex strategy adopted from Diego Perini\r
-               assert(function( div ) {\r
-                       // Select is set to empty string on purpose\r
-                       // This is to test IE's treatment of not explictly\r
-                       // setting a boolean content attribute,\r
-                       // since its presence should be enough\r
-                       // http://bugs.jquery.com/ticket/12359\r
-                       div.innerHTML = "<select><option selected=''></option></select>";\r
-\r
-                       // IE8 - Some boolean attributes are not treated correctly\r
-                       if ( !div.querySelectorAll("[selected]").length ) {\r
-                               rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );\r
-                       }\r
-\r
-                       // Webkit/Opera - :checked should return selected option elements\r
-                       // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\r
-                       // IE8 throws error here (do not put tests after this one)\r
-                       if ( !div.querySelectorAll(":checked").length ) {\r
-                               rbuggyQSA.push(":checked");\r
-                       }\r
-               });\r
-\r
-               assert(function( div ) {\r
-\r
-                       // Opera 10-12/IE9 - ^= $= *= and empty values\r
-                       // Should not select anything\r
-                       div.innerHTML = "<p test=''></p>";\r
-                       if ( div.querySelectorAll("[test^='']").length ) {\r
-                               rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );\r
-                       }\r
-\r
-                       // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\r
-                       // IE8 throws error here (do not put tests after this one)\r
-                       div.innerHTML = "<input type='hidden'/>";\r
-                       if ( !div.querySelectorAll(":enabled").length ) {\r
-                               rbuggyQSA.push(":enabled", ":disabled");\r
-                       }\r
-               });\r
-\r
-               // rbuggyQSA always contains :focus, so no need for a length check\r
-               rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") );\r
-\r
-               select = function( selector, context, results, seed, xml ) {\r
-                       // Only use querySelectorAll when not filtering,\r
-                       // when this is not xml,\r
-                       // and when no QSA bugs apply\r
-                       if ( !seed && !xml && !rbuggyQSA.test( selector ) ) {\r
-                               var groups, i,\r
-                                       old = true,\r
-                                       nid = expando,\r
-                                       newContext = context,\r
-                                       newSelector = context.nodeType === 9 && selector;\r
-\r
-                               // qSA works strangely on Element-rooted queries\r
-                               // We can work around this by specifying an extra ID on the root\r
-                               // and working up from there (Thanks to Andrew Dupont for the technique)\r
-                               // IE 8 doesn't work on object elements\r
-                               if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {\r
-                                       groups = tokenize( selector );\r
-\r
-                                       if ( (old = context.getAttribute("id")) ) {\r
-                                               nid = old.replace( rescape, "\\$&" );\r
-                                       } else {\r
-                                               context.setAttribute( "id", nid );\r
-                                       }\r
-                                       nid = "[id='" + nid + "'] ";\r
-\r
-                                       i = groups.length;\r
-                                       while ( i-- ) {\r
-                                               groups[i] = nid + groups[i].join("");\r
-                                       }\r
-                                       newContext = rsibling.test( selector ) && context.parentNode || context;\r
-                                       newSelector = groups.join(",");\r
-                               }\r
-\r
-                               if ( newSelector ) {\r
-                                       try {\r
-                                               push.apply( results, slice.call( newContext.querySelectorAll(\r
-                                                       newSelector\r
-                                               ), 0 ) );\r
-                                               return results;\r
-                                       } catch(qsaError) {\r
-                                       } finally {\r
-                                               if ( !old ) {\r
-                                                       context.removeAttribute("id");\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       return oldSelect( selector, context, results, seed, xml );\r
-               };\r
-\r
-               if ( matches ) {\r
-                       assert(function( div ) {\r
-                               // Check to see if it's possible to do matchesSelector\r
-                               // on a disconnected node (IE 9)\r
-                               disconnectedMatch = matches.call( div, "div" );\r
-\r
-                               // This should fail with an exception\r
-                               // Gecko does not error, returns false instead\r
-                               try {\r
-                                       matches.call( div, "[test!='']:sizzle" );\r
-                                       rbuggyMatches.push( "!=", pseudos );\r
-                               } catch ( e ) {}\r
-                       });\r
-\r
-                       // rbuggyMatches always contains :active and :focus, so no need for a length check\r
-                       rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") );\r
-\r
-                       Sizzle.matchesSelector = function( elem, expr ) {\r
-                               // Make sure that attribute selectors are quoted\r
-                               expr = expr.replace( rattributeQuotes, "='$1']" );\r
-\r
-                               // rbuggyMatches always contains :active, so no need for an existence check\r
-                               if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && !rbuggyQSA.test( expr ) ) {\r
-                                       try {\r
-                                               var ret = matches.call( elem, expr );\r
-\r
-                                               // IE 9's matchesSelector returns false on disconnected nodes\r
-                                               if ( ret || disconnectedMatch ||\r
-                                                               // As well, disconnected nodes are said to be in a document\r
-                                                               // fragment in IE 9\r
-                                                               elem.document && elem.document.nodeType !== 11 ) {\r
-                                                       return ret;\r
-                                               }\r
-                                       } catch(e) {}\r
-                               }\r
-\r
-                               return Sizzle( expr, null, null, [ elem ] ).length > 0;\r
-                       };\r
-               }\r
-       })();\r
-}\r
-\r
-// Deprecated\r
-Expr.pseudos["nth"] = Expr.pseudos["eq"];\r
-\r
-// Back-compat\r
-function setFilters() {}\r
-Expr.filters = setFilters.prototype = Expr.pseudos;\r
-Expr.setFilters = new setFilters();\r
-\r
-// Override sizzle attribute retrieval
-Sizzle.attr = jQuery.attr;
-jQuery.find = Sizzle;
-jQuery.expr = Sizzle.selectors;
-jQuery.expr[":"] = jQuery.expr.pseudos;
-jQuery.unique = Sizzle.uniqueSort;
-jQuery.text = Sizzle.getText;
-jQuery.isXMLDoc = Sizzle.isXML;
-jQuery.contains = Sizzle.contains;
-\r
-\r
-})( window );\r
-var runtil = /Until$/,
-       rparentsprev = /^(?:parents|prev(?:Until|All))/,
-       isSimple = /^.[^:#\[\.,]*$/,
-       rneedsContext = jQuery.expr.match.needsContext,
-       // methods guaranteed to produce a unique set when starting from a unique set
-       guaranteedUnique = {
-               children: true,
-               contents: true,
-               next: true,
-               prev: true
-       };
-
-jQuery.fn.extend({
-       find: function( selector ) {
-               var i, l, length, n, r, ret,
-                       self = this;
-
-               if ( typeof selector !== "string" ) {
-                       return jQuery( selector ).filter(function() {
-                               for ( i = 0, l = self.length; i < l; i++ ) {
-                                       if ( jQuery.contains( self[ i ], this ) ) {
-                                               return true;
-                                       }
-                               }
-                       });
-               }
-
-               ret = this.pushStack( "", "find", selector );
-
-               for ( i = 0, l = this.length; i < l; i++ ) {
-                       length = ret.length;
-                       jQuery.find( selector, this[i], ret );
-
-                       if ( i > 0 ) {
-                               // Make sure that the results are unique
-                               for ( n = length; n < ret.length; n++ ) {
-                                       for ( r = 0; r < length; r++ ) {
-                                               if ( ret[r] === ret[n] ) {
-                                                       ret.splice(n--, 1);
-                                                       break;
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               return ret;
-       },
-
-       has: function( target ) {
-               var i,
-                       targets = jQuery( target, this ),
-                       len = targets.length;
-
-               return this.filter(function() {
-                       for ( i = 0; i < len; i++ ) {
-                               if ( jQuery.contains( this, targets[i] ) ) {
-                                       return true;
-                               }
-                       }
-               });
-       },
-
-       not: function( selector ) {
-               return this.pushStack( winnow(this, selector, false), "not", selector);
-       },
-
-       filter: function( selector ) {
-               return this.pushStack( winnow(this, selector, true), "filter", selector );
-       },
-
-       is: function( selector ) {
-               return !!selector && (
-                       typeof selector === "string" ?
-                               // If this is a positional/relative selector, check membership in the returned set
-                               // so $("p:first").is("p:last") won't return true for a doc with two "p".
-                               rneedsContext.test( selector ) ?
-                                       jQuery( selector, this.context ).index( this[0] ) >= 0 :
-                                       jQuery.filter( selector, this ).length > 0 :
-                               this.filter( selector ).length > 0 );
-       },
-
-       closest: function( selectors, context ) {
-               var cur,
-                       i = 0,
-                       l = this.length,
-                       ret = [],
-                       pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
-                               jQuery( selectors, context || this.context ) :
-                               0;
-
-               for ( ; i < l; i++ ) {
-                       cur = this[i];
-
-                       while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
-                               if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
-                                       ret.push( cur );
-                                       break;
-                               }
-                               cur = cur.parentNode;
-                       }
-               }
-
-               ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
-
-               return this.pushStack( ret, "closest", selectors );
-       },
-
-       // Determine the position of an element within
-       // the matched set of elements
-       index: function( elem ) {
-
-               // No argument, return index in parent
-               if ( !elem ) {
-                       return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
-               }
-
-               // index in selector
-               if ( typeof elem === "string" ) {
-                       return jQuery.inArray( this[0], jQuery( elem ) );
-               }
-
-               // Locate the position of the desired element
-               return jQuery.inArray(
-                       // If it receives a jQuery object, the first element is used
-                       elem.jquery ? elem[0] : elem, this );
-       },
-
-       add: function( selector, context ) {
-               var set = typeof selector === "string" ?
-                               jQuery( selector, context ) :
-                               jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
-                       all = jQuery.merge( this.get(), set );
-
-               return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
-                       all :
-                       jQuery.unique( all ) );
-       },
-
-       addBack: function( selector ) {
-               return this.add( selector == null ?
-                       this.prevObject : this.prevObject.filter(selector)
-               );
-       }
-});
-
-jQuery.fn.andSelf = jQuery.fn.addBack;
-
-// A painfully simple check to see if an element is disconnected
-// from a document (should be improved, where feasible).
-function isDisconnected( node ) {
-       return !node || !node.parentNode || node.parentNode.nodeType === 11;
-}
-
-function sibling( cur, dir ) {
-       do {
-               cur = cur[ dir ];
-       } while ( cur && cur.nodeType !== 1 );
-
-       return cur;
-}
-
-jQuery.each({
-       parent: function( elem ) {
-               var parent = elem.parentNode;
-               return parent && parent.nodeType !== 11 ? parent : null;
-       },
-       parents: function( elem ) {
-               return jQuery.dir( elem, "parentNode" );
-       },
-       parentsUntil: function( elem, i, until ) {
-               return jQuery.dir( elem, "parentNode", until );
-       },
-       next: function( elem ) {
-               return sibling( elem, "nextSibling" );
-       },
-       prev: function( elem ) {
-               return sibling( elem, "previousSibling" );
-       },
-       nextAll: function( elem ) {
-               return jQuery.dir( elem, "nextSibling" );
-       },
-       prevAll: function( elem ) {
-               return jQuery.dir( elem, "previousSibling" );
-       },
-       nextUntil: function( elem, i, until ) {
-               return jQuery.dir( elem, "nextSibling", until );
-       },
-       prevUntil: function( elem, i, until ) {
-               return jQuery.dir( elem, "previousSibling", until );
-       },
-       siblings: function( elem ) {
-               return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
-       },
-       children: function( elem ) {
-               return jQuery.sibling( elem.firstChild );
-       },
-       contents: function( elem ) {
-               return jQuery.nodeName( elem, "iframe" ) ?
-                       elem.contentDocument || elem.contentWindow.document :
-                       jQuery.merge( [], elem.childNodes );
-       }
-}, function( name, fn ) {
-       jQuery.fn[ name ] = function( until, selector ) {
-               var ret = jQuery.map( this, fn, until );
-
-               if ( !runtil.test( name ) ) {
-                       selector = until;
-               }
-
-               if ( selector && typeof selector === "string" ) {
-                       ret = jQuery.filter( selector, ret );
-               }
-
-               ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
-
-               if ( this.length > 1 && rparentsprev.test( name ) ) {
-                       ret = ret.reverse();
-               }
-
-               return this.pushStack( ret, name, core_slice.call( arguments ).join(",") );
-       };
-});
-
-jQuery.extend({
-       filter: function( expr, elems, not ) {
-               if ( not ) {
-                       expr = ":not(" + expr + ")";
-               }
-
-               return elems.length === 1 ?
-                       jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
-                       jQuery.find.matches(expr, elems);
-       },
-
-       dir: function( elem, dir, until ) {
-               var matched = [],
-                       cur = elem[ dir ];
-
-               while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
-                       if ( cur.nodeType === 1 ) {
-                               matched.push( cur );
-                       }
-                       cur = cur[dir];
-               }
-               return matched;
-       },
-
-       sibling: function( n, elem ) {
-               var r = [];
-
-               for ( ; n; n = n.nextSibling ) {
-                       if ( n.nodeType === 1 && n !== elem ) {
-                               r.push( n );
-                       }
-               }
-
-               return r;
-       }
-});
-
-// Implement the identical functionality for filter and not
-function winnow( elements, qualifier, keep ) {
-
-       // Can't pass null or undefined to indexOf in Firefox 4
-       // Set to 0 to skip string check
-       qualifier = qualifier || 0;
-
-       if ( jQuery.isFunction( qualifier ) ) {
-               return jQuery.grep(elements, function( elem, i ) {
-                       var retVal = !!qualifier.call( elem, i, elem );
-                       return retVal === keep;
-               });
-
-       } else if ( qualifier.nodeType ) {
-               return jQuery.grep(elements, function( elem, i ) {
-                       return ( elem === qualifier ) === keep;
-               });
-
-       } else if ( typeof qualifier === "string" ) {
-               var filtered = jQuery.grep(elements, function( elem ) {
-                       return elem.nodeType === 1;
-               });
-
-               if ( isSimple.test( qualifier ) ) {
-                       return jQuery.filter(qualifier, filtered, !keep);
-               } else {
-                       qualifier = jQuery.filter( qualifier, filtered );
-               }
-       }
-
-       return jQuery.grep(elements, function( elem, i ) {
-               return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
-       });
-}
-function createSafeFragment( document ) {
-       var list = nodeNames.split( "|" ),
-       safeFrag = document.createDocumentFragment();
-
-       if ( safeFrag.createElement ) {
-               while ( list.length ) {
-                       safeFrag.createElement(
-                               list.pop()
-                       );
-               }
-       }
-       return safeFrag;
-}
-
-var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
-               "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
-       rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
-       rleadingWhitespace = /^\s+/,
-       rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
-       rtagName = /<([\w:]+)/,
-       rtbody = /<tbody/i,
-       rhtml = /<|&#?\w+;/,
-       rnoInnerhtml = /<(?:script|style|link)/i,
-       rnocache = /<(?:script|object|embed|option|style)/i,
-       rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
-       rcheckableType = /^(?:checkbox|radio)$/,
-       // checked="checked" or checked
-       rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
-       rscriptType = /\/(java|ecma)script/i,
-       rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,
-       wrapMap = {
-               option: [ 1, "<select multiple='multiple'>", "</select>" ],
-               legend: [ 1, "<fieldset>", "</fieldset>" ],
-               thead: [ 1, "<table>", "</table>" ],
-               tr: [ 2, "<table><tbody>", "</tbody></table>" ],
-               td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
-               col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
-               area: [ 1, "<map>", "</map>" ],
-               _default: [ 0, "", "" ]
-       },
-       safeFragment = createSafeFragment( document ),
-       fragmentDiv = safeFragment.appendChild( document.createElement("div") );
-
-wrapMap.optgroup = wrapMap.option;
-wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
-wrapMap.th = wrapMap.td;
-
-// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
-// unless wrapped in a div with non-breaking characters in front of it.
-if ( !jQuery.support.htmlSerialize ) {
-       wrapMap._default = [ 1, "X<div>", "</div>" ];
-}
-
-jQuery.fn.extend({
-       text: function( value ) {
-               return jQuery.access( this, function( value ) {
-                       return value === undefined ?
-                               jQuery.text( this ) :
-                               this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
-               }, null, value, arguments.length );
-       },
-
-       wrapAll: function( html ) {
-               if ( jQuery.isFunction( html ) ) {
-                       return this.each(function(i) {
-                               jQuery(this).wrapAll( html.call(this, i) );
-                       });
-               }
-
-               if ( this[0] ) {
-                       // The elements to wrap the target around
-                       var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
-
-                       if ( this[0].parentNode ) {
-                               wrap.insertBefore( this[0] );
-                       }
-
-                       wrap.map(function() {
-                               var elem = this;
-
-                               while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
-                                       elem = elem.firstChild;
-                               }
-
-                               return elem;
-                       }).append( this );
-               }
-
-               return this;
-       },
-
-       wrapInner: function( html ) {
-               if ( jQuery.isFunction( html ) ) {
-                       return this.each(function(i) {
-                               jQuery(this).wrapInner( html.call(this, i) );
-                       });
-               }
-
-               return this.each(function() {
-                       var self = jQuery( this ),
-                               contents = self.contents();
-
-                       if ( contents.length ) {
-                               contents.wrapAll( html );
-
-                       } else {
-                               self.append( html );
-                       }
-               });
-       },
-
-       wrap: function( html ) {
-               var isFunction = jQuery.isFunction( html );
-
-               return this.each(function(i) {
-                       jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
-               });
-       },
-
-       unwrap: function() {
-               return this.parent().each(function() {
-                       if ( !jQuery.nodeName( this, "body" ) ) {
-                               jQuery( this ).replaceWith( this.childNodes );
-                       }
-               }).end();
-       },
-
-       append: function() {
-               return this.domManip(arguments, true, function( elem ) {
-                       if ( this.nodeType === 1 || this.nodeType === 11 ) {
-                               this.appendChild( elem );
-                       }
-               });
-       },
-
-       prepend: function() {
-               return this.domManip(arguments, true, function( elem ) {
-                       if ( this.nodeType === 1 || this.nodeType === 11 ) {
-                               this.insertBefore( elem, this.firstChild );
-                       }
-               });
-       },
-
-       before: function() {
-               if ( !isDisconnected( this[0] ) ) {
-                       return this.domManip(arguments, false, function( elem ) {
-                               this.parentNode.insertBefore( elem, this );
-                       });
-               }
-
-               if ( arguments.length ) {
-                       var set = jQuery.clean( arguments );
-                       return this.pushStack( jQuery.merge( set, this ), "before", this.selector );
-               }
-       },
-
-       after: function() {
-               if ( !isDisconnected( this[0] ) ) {
-                       return this.domManip(arguments, false, function( elem ) {
-                               this.parentNode.insertBefore( elem, this.nextSibling );
-                       });
-               }
-
-               if ( arguments.length ) {
-                       var set = jQuery.clean( arguments );
-                       return this.pushStack( jQuery.merge( this, set ), "after", this.selector );
-               }
-       },
-
-       // keepData is for internal use only--do not document
-       remove: function( selector, keepData ) {
-               var elem,
-                       i = 0;
-
-               for ( ; (elem = this[i]) != null; i++ ) {
-                       if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
-                               if ( !keepData && elem.nodeType === 1 ) {
-                                       jQuery.cleanData( elem.getElementsByTagName("*") );
-                                       jQuery.cleanData( [ elem ] );
-                               }
-
-                               if ( elem.parentNode ) {
-                                       elem.parentNode.removeChild( elem );
-                               }
-                       }
-               }
-
-               return this;
-       },
-
-       empty: function() {
-               var elem,
-                       i = 0;
-
-               for ( ; (elem = this[i]) != null; i++ ) {
-                       // Remove element nodes and prevent memory leaks
-                       if ( elem.nodeType === 1 ) {
-                               jQuery.cleanData( elem.getElementsByTagName("*") );
-                       }
-
-                       // Remove any remaining nodes
-                       while ( elem.firstChild ) {
-                               elem.removeChild( elem.firstChild );
-                       }
-               }
-
-               return this;
-       },
-
-       clone: function( dataAndEvents, deepDataAndEvents ) {
-               dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
-               deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
-
-               return this.map( function () {
-                       return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
-               });
-       },
-
-       html: function( value ) {
-               return jQuery.access( this, function( value ) {
-                       var elem = this[0] || {},
-                               i = 0,
-                               l = this.length;
-
-                       if ( value === undefined ) {
-                               return elem.nodeType === 1 ?
-                                       elem.innerHTML.replace( rinlinejQuery, "" ) :
-                                       undefined;
-                       }
-
-                       // See if we can take a shortcut and just use innerHTML
-                       if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
-                               ( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&
-                               ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
-                               !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
-
-                               value = value.replace( rxhtmlTag, "<$1></$2>" );
-
-                               try {
-                                       for (; i < l; i++ ) {
-                                               // Remove element nodes and prevent memory leaks
-                                               elem = this[i] || {};
-                                               if ( elem.nodeType === 1 ) {
-                                                       jQuery.cleanData( elem.getElementsByTagName( "*" ) );
-                                                       elem.innerHTML = value;
-                                               }
-                                       }
-
-                                       elem = 0;
-
-                               // If using innerHTML throws an exception, use the fallback method
-                               } catch(e) {}
-                       }
-
-                       if ( elem ) {
-                               this.empty().append( value );
-                       }
-               }, null, value, arguments.length );
-       },
-
-       replaceWith: function( value ) {
-               if ( !isDisconnected( this[0] ) ) {
-                       // Make sure that the elements are removed from the DOM before they are inserted
-                       // this can help fix replacing a parent with child elements
-                       if ( jQuery.isFunction( value ) ) {
-                               return this.each(function(i) {
-                                       var self = jQuery(this), old = self.html();
-                                       self.replaceWith( value.call( this, i, old ) );
-                               });
-                       }
-
-                       if ( typeof value !== "string" ) {
-                               value = jQuery( value ).detach();
-                       }
-
-                       return this.each(function() {
-                               var next = this.nextSibling,
-                                       parent = this.parentNode;
-
-                               jQuery( this ).remove();
-
-                               if ( next ) {
-                                       jQuery(next).before( value );
-                               } else {
-                                       jQuery(parent).append( value );
-                               }
-                       });
-               }
-
-               return this.length ?
-                       this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
-                       this;
-       },
-
-       detach: function( selector ) {
-               return this.remove( selector, true );
-       },
-
-       domManip: function( args, table, callback ) {
-
-               // Flatten any nested arrays
-               args = [].concat.apply( [], args );
-
-               var results, first, fragment, iNoClone,
-                       i = 0,
-                       value = args[0],
-                       scripts = [],
-                       l = this.length;
-
-               // We can't cloneNode fragments that contain checked, in WebKit
-               if ( !jQuery.support.checkClone && l > 1 && typeof value === "string" && rchecked.test( value ) ) {
-                       return this.each(function() {
-                               jQuery(this).domManip( args, table, callback );
-                       });
-               }
-
-               if ( jQuery.isFunction(value) ) {
-                       return this.each(function(i) {
-                               var self = jQuery(this);
-                               args[0] = value.call( this, i, table ? self.html() : undefined );
-                               self.domManip( args, table, callback );
-                       });
-               }
-
-               if ( this[0] ) {
-                       results = jQuery.buildFragment( args, this, scripts );
-                       fragment = results.fragment;
-                       first = fragment.firstChild;
-
-                       if ( fragment.childNodes.length === 1 ) {
-                               fragment = first;
-                       }
-
-                       if ( first ) {
-                               table = table && jQuery.nodeName( first, "tr" );
-
-                               // Use the original fragment for the last item instead of the first because it can end up
-                               // being emptied incorrectly in certain situations (#8070).
-                               // Fragments from the fragment cache must always be cloned and never used in place.
-                               for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) {
-                                       callback.call(
-                                               table && jQuery.nodeName( this[i], "table" ) ?
-                                                       findOrAppend( this[i], "tbody" ) :
-                                                       this[i],
-                                               i === iNoClone ?
-                                                       fragment :
-                                                       jQuery.clone( fragment, true, true )
-                                       );
-                               }
-                       }
-
-                       // Fix #11809: Avoid leaking memory
-                       fragment = first = null;
-
-                       if ( scripts.length ) {
-                               jQuery.each( scripts, function( i, elem ) {
-                                       if ( elem.src ) {
-                                               if ( jQuery.ajax ) {
-                                                       jQuery.ajax({
-                                                               url: elem.src,
-                                                               type: "GET",
-                                                               dataType: "script",
-                                                               async: false,
-                                                               global: false,
-                                                               "throws": true
-                                                       });
-                                               } else {
-                                                       jQuery.error("no ajax");
-                                               }
-                                       } else {
-                                               jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "" ) );
-                                       }
-
-                                       if ( elem.parentNode ) {
-                                               elem.parentNode.removeChild( elem );
-                                       }
-                               });
-                       }
-               }
-
-               return this;
-       }
-});
-
-function findOrAppend( elem, tag ) {
-       return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
-}
-
-function cloneCopyEvent( src, dest ) {
-
-       if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
-               return;
-       }
-
-       var type, i, l,
-               oldData = jQuery._data( src ),
-               curData = jQuery._data( dest, oldData ),
-               events = oldData.events;
-
-       if ( events ) {
-               delete curData.handle;
-               curData.events = {};
-
-               for ( type in events ) {
-                       for ( i = 0, l = events[ type ].length; i < l; i++ ) {
-                               jQuery.event.add( dest, type, events[ type ][ i ] );
-                       }
-               }
-       }
-
-       // make the cloned public data object a copy from the original
-       if ( curData.data ) {
-               curData.data = jQuery.extend( {}, curData.data );
-       }
-}
-
-function cloneFixAttributes( src, dest ) {
-       var nodeName;
-
-       // We do not need to do anything for non-Elements
-       if ( dest.nodeType !== 1 ) {
-               return;
-       }
-
-       // clearAttributes removes the attributes, which we don't want,
-       // but also removes the attachEvent events, which we *do* want
-       if ( dest.clearAttributes ) {
-               dest.clearAttributes();
-       }
-
-       // mergeAttributes, in contrast, only merges back on the
-       // original attributes, not the events
-       if ( dest.mergeAttributes ) {
-               dest.mergeAttributes( src );
-       }
-
-       nodeName = dest.nodeName.toLowerCase();
-
-       if ( nodeName === "object" ) {
-               // IE6-10 improperly clones children of object elements using classid.
-               // IE10 throws NoModificationAllowedError if parent is null, #12132.
-               if ( dest.parentNode ) {
-                       dest.outerHTML = src.outerHTML;
-               }
-
-               // This path appears unavoidable for IE9. When cloning an object
-               // element in IE9, the outerHTML strategy above is not sufficient.
-               // If the src has innerHTML and the destination does not,
-               // copy the src.innerHTML into the dest.innerHTML. #10324
-               if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) {
-                       dest.innerHTML = src.innerHTML;
-               }
-
-       } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
-               // IE6-8 fails to persist the checked state of a cloned checkbox
-               // or radio button. Worse, IE6-7 fail to give the cloned element
-               // a checked appearance if the defaultChecked value isn't also set
-
-               dest.defaultChecked = dest.checked = src.checked;
-
-               // IE6-7 get confused and end up setting the value of a cloned
-               // checkbox/radio button to an empty string instead of "on"
-               if ( dest.value !== src.value ) {
-                       dest.value = src.value;
-               }
-
-       // IE6-8 fails to return the selected option to the default selected
-       // state when cloning options
-       } else if ( nodeName === "option" ) {
-               dest.selected = src.defaultSelected;
-
-       // IE6-8 fails to set the defaultValue to the correct value when
-       // cloning other types of input fields
-       } else if ( nodeName === "input" || nodeName === "textarea" ) {
-               dest.defaultValue = src.defaultValue;
-
-       // IE blanks contents when cloning scripts
-       } else if ( nodeName === "script" && dest.text !== src.text ) {
-               dest.text = src.text;
-       }
-
-       // Event data gets referenced instead of copied if the expando
-       // gets copied too
-       dest.removeAttribute( jQuery.expando );
-}
-
-jQuery.buildFragment = function( args, context, scripts ) {
-       var fragment, cacheable, cachehit,
-               first = args[ 0 ];
-
-       // Set context from what may come in as undefined or a jQuery collection or a node
-       // Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 &
-       // also doubles as fix for #8950 where plain objects caused createDocumentFragment exception
-       context = context || document;
-       context = !context.nodeType && context[0] || context;
-       context = context.ownerDocument || context;
-
-       // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
-       // Cloning options loses the selected state, so don't cache them
-       // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
-       // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
-       // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
-       if ( args.length === 1 && typeof first === "string" && first.length < 512 && context === document &&
-               first.charAt(0) === "<" && !rnocache.test( first ) &&
-               (jQuery.support.checkClone || !rchecked.test( first )) &&
-               (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
-
-               // Mark cacheable and look for a hit
-               cacheable = true;
-               fragment = jQuery.fragments[ first ];
-               cachehit = fragment !== undefined;
-       }
-
-       if ( !fragment ) {
-               fragment = context.createDocumentFragment();
-               jQuery.clean( args, context, fragment, scripts );
-
-               // Update the cache, but only store false
-               // unless this is a second parsing of the same content
-               if ( cacheable ) {
-                       jQuery.fragments[ first ] = cachehit && fragment;
-               }
-       }
-
-       return { fragment: fragment, cacheable: cacheable };
-};
-
-jQuery.fragments = {};
-
-jQuery.each({
-       appendTo: "append",
-       prependTo: "prepend",
-       insertBefore: "before",
-       insertAfter: "after",
-       replaceAll: "replaceWith"
-}, function( name, original ) {
-       jQuery.fn[ name ] = function( selector ) {
-               var elems,
-                       i = 0,
-                       ret = [],
-                       insert = jQuery( selector ),
-                       l = insert.length,
-                       parent = this.length === 1 && this[0].parentNode;
-
-               if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) {
-                       insert[ original ]( this[0] );
-                       return this;
-               } else {
-                       for ( ; i < l; i++ ) {
-                               elems = ( i > 0 ? this.clone(true) : this ).get();
-                               jQuery( insert[i] )[ original ]( elems );
-                               ret = ret.concat( elems );
-                       }
-
-                       return this.pushStack( ret, name, insert.selector );
-               }
-       };
-});
-
-function getAll( elem ) {
-       if ( typeof elem.getElementsByTagName !== "undefined" ) {
-               return elem.getElementsByTagName( "*" );
-
-       } else if ( typeof elem.querySelectorAll !== "undefined" ) {
-               return elem.querySelectorAll( "*" );
-
-       } else {
-               return [];
-       }
-}
-
-// Used in clean, fixes the defaultChecked property
-function fixDefaultChecked( elem ) {
-       if ( rcheckableType.test( elem.type ) ) {
-               elem.defaultChecked = elem.checked;
-       }
-}
-
-jQuery.extend({
-       clone: function( elem, dataAndEvents, deepDataAndEvents ) {
-               var srcElements,
-                       destElements,
-                       i,
-                       clone;
-
-               if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
-                       clone = elem.cloneNode( true );
-
-               // IE<=8 does not properly clone detached, unknown element nodes
-               } else {
-                       fragmentDiv.innerHTML = elem.outerHTML;
-                       fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
-               }
-
-               if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
-                               (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
-                       // IE copies events bound via attachEvent when using cloneNode.
-                       // Calling detachEvent on the clone will also remove the events
-                       // from the original. In order to get around this, we use some
-                       // proprietary methods to clear the events. Thanks to MooTools
-                       // guys for this hotness.
-
-                       cloneFixAttributes( elem, clone );
-
-                       // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
-                       srcElements = getAll( elem );
-                       destElements = getAll( clone );
-
-                       // Weird iteration because IE will replace the length property
-                       // with an element if you are cloning the body and one of the
-                       // elements on the page has a name or id of "length"
-                       for ( i = 0; srcElements[i]; ++i ) {
-                               // Ensure that the destination node is not null; Fixes #9587
-                               if ( destElements[i] ) {
-                                       cloneFixAttributes( srcElements[i], destElements[i] );
-                               }
-                       }
-               }
-
-               // Copy the events from the original to the clone
-               if ( dataAndEvents ) {
-                       cloneCopyEvent( elem, clone );
-
-                       if ( deepDataAndEvents ) {
-                               srcElements = getAll( elem );
-                               destElements = getAll( clone );
-
-                               for ( i = 0; srcElements[i]; ++i ) {
-                                       cloneCopyEvent( srcElements[i], destElements[i] );
-                               }
-                       }
-               }
-
-               srcElements = destElements = null;
-
-               // Return the cloned set
-               return clone;
-       },
-
-       clean: function( elems, context, fragment, scripts ) {
-               var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags,
-                       safe = context === document && safeFragment,
-                       ret = [];
-
-               // Ensure that context is a document
-               if ( !context || typeof context.createDocumentFragment === "undefined" ) {
-                       context = document;
-               }
-
-               // Use the already-created safe fragment if context permits
-               for ( i = 0; (elem = elems[i]) != null; i++ ) {
-                       if ( typeof elem === "number" ) {
-                               elem += "";
-                       }
-
-                       if ( !elem ) {
-                               continue;
-                       }
-
-                       // Convert html string into DOM nodes
-                       if ( typeof elem === "string" ) {
-                               if ( !rhtml.test( elem ) ) {
-                                       elem = context.createTextNode( elem );
-                               } else {
-                                       // Ensure a safe container in which to render the html
-                                       safe = safe || createSafeFragment( context );
-                                       div = context.createElement("div");
-                                       safe.appendChild( div );
-
-                                       // Fix "XHTML"-style tags in all browsers
-                                       elem = elem.replace(rxhtmlTag, "<$1></$2>");
-
-                                       // Go to html and back, then peel off extra wrappers
-                                       tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
-                                       wrap = wrapMap[ tag ] || wrapMap._default;
-                                       depth = wrap[0];
-                                       div.innerHTML = wrap[1] + elem + wrap[2];
-
-                                       // Move to the right depth
-                                       while ( depth-- ) {
-                                               div = div.lastChild;
-                                       }
-
-                                       // Remove IE's autoinserted <tbody> from table fragments
-                                       if ( !jQuery.support.tbody ) {
-
-                                               // String was a <table>, *may* have spurious <tbody>
-                                               hasBody = rtbody.test(elem);
-                                                       tbody = tag === "table" && !hasBody ?
-                                                               div.firstChild && div.firstChild.childNodes :
-
-                                                               // String was a bare <thead> or <tfoot>
-                                                               wrap[1] === "<table>" && !hasBody ?
-                                                                       div.childNodes :
-                                                                       [];
-
-                                               for ( j = tbody.length - 1; j >= 0 ; --j ) {
-                                                       if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
-                                                               tbody[ j ].parentNode.removeChild( tbody[ j ] );
-                                                       }
-                                               }
-                                       }
-
-                                       // IE completely kills leading whitespace when innerHTML is used
-                                       if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
-                                               div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
-                                       }
-
-                                       elem = div.childNodes;
-
-                                       // Take out of fragment container (we need a fresh div each time)
-                                       div.parentNode.removeChild( div );
-                               }
-                       }
-
-                       if ( elem.nodeType ) {
-                               ret.push( elem );
-                       } else {
-                               jQuery.merge( ret, elem );
-                       }
-               }
-
-               // Fix #11356: Clear elements from safeFragment
-               if ( div ) {
-                       elem = div = safe = null;
-               }
-
-               // Reset defaultChecked for any radios and checkboxes
-               // about to be appended to the DOM in IE 6/7 (#8060)
-               if ( !jQuery.support.appendChecked ) {
-                       for ( i = 0; (elem = ret[i]) != null; i++ ) {
-                               if ( jQuery.nodeName( elem, "input" ) ) {
-                                       fixDefaultChecked( elem );
-                               } else if ( typeof elem.getElementsByTagName !== "undefined" ) {
-                                       jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
-                               }
-                       }
-               }
-
-               // Append elements to a provided document fragment
-               if ( fragment ) {
-                       // Special handling of each script element
-                       handleScript = function( elem ) {
-                               // Check if we consider it executable
-                               if ( !elem.type || rscriptType.test( elem.type ) ) {
-                                       // Detach the script and store it in the scripts array (if provided) or the fragment
-                                       // Return truthy to indicate that it has been handled
-                                       return scripts ?
-                                               scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
-                                               fragment.appendChild( elem );
-                               }
-                       };
-
-                       for ( i = 0; (elem = ret[i]) != null; i++ ) {
-                               // Check if we're done after handling an executable script
-                               if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
-                                       // Append to fragment and handle embedded scripts
-                                       fragment.appendChild( elem );
-                                       if ( typeof elem.getElementsByTagName !== "undefined" ) {
-                                               // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
-                                               jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
-
-                                               // Splice the scripts into ret after their former ancestor and advance our index beyond them
-                                               ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
-                                               i += jsTags.length;
-                                       }
-                               }
-                       }
-               }
-
-               return ret;
-       },
-
-       cleanData: function( elems, /* internal */ acceptData ) {
-               var data, id, elem, type,
-                       i = 0,
-                       internalKey = jQuery.expando,
-                       cache = jQuery.cache,
-                       deleteExpando = jQuery.support.deleteExpando,
-                       special = jQuery.event.special;
-
-               for ( ; (elem = elems[i]) != null; i++ ) {
-
-                       if ( acceptData || jQuery.acceptData( elem ) ) {
-
-                               id = elem[ internalKey ];
-                               data = id && cache[ id ];
-
-                               if ( data ) {
-                                       if ( data.events ) {
-                                               for ( type in data.events ) {
-                                                       if ( special[ type ] ) {
-                                                               jQuery.event.remove( elem, type );
-
-                                                       // This is a shortcut to avoid jQuery.event.remove's overhead
-                                                       } else {
-                                                               jQuery.removeEvent( elem, type, data.handle );
-                                                       }
-                                               }
-                                       }
-
-                                       // Remove cache only if it was not already removed by jQuery.event.remove
-                                       if ( cache[ id ] ) {
-
-                                               delete cache[ id ];
-
-                                               // IE does not allow us to delete expando properties from nodes,
-                                               // nor does it have a removeAttribute function on Document nodes;
-                                               // we must handle all of these cases
-                                               if ( deleteExpando ) {
-                                                       delete elem[ internalKey ];
-
-                                               } else if ( elem.removeAttribute ) {
-                                                       elem.removeAttribute( internalKey );
-
-                                               } else {
-                                                       elem[ internalKey ] = null;
-                                               }
-
-                                               jQuery.deletedIds.push( id );
-                                       }
-                               }
-                       }
-               }
-       }
-});
-// Limit scope pollution from any deprecated API
-(function() {
-
-var matched, browser;
-
-// Use of jQuery.browser is frowned upon.
-// More details: http://api.jquery.com/jQuery.browser
-// jQuery.uaMatch maintained for back-compat
-jQuery.uaMatch = function( ua ) {
-       ua = ua.toLowerCase();
-
-       var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
-               /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
-               /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
-               /(msie) ([\w.]+)/.exec( ua ) ||
-               ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
-               [];
-
-       return {
-               browser: match[ 1 ] || "",
-               version: match[ 2 ] || "0"
-       };
-};
-
-matched = jQuery.uaMatch( navigator.userAgent );
-browser = {};
-
-if ( matched.browser ) {
-       browser[ matched.browser ] = true;
-       browser.version = matched.version;
-}
-
-// Chrome is Webkit, but Webkit is also Safari.
-if ( browser.chrome ) {
-       browser.webkit = true;
-} else if ( browser.webkit ) {
-       browser.safari = true;
-}
-
-jQuery.browser = browser;
-
-jQuery.sub = function() {
-       function jQuerySub( selector, context ) {
-               return new jQuerySub.fn.init( selector, context );
-       }
-       jQuery.extend( true, jQuerySub, this );
-       jQuerySub.superclass = this;
-       jQuerySub.fn = jQuerySub.prototype = this();
-       jQuerySub.fn.constructor = jQuerySub;
-       jQuerySub.sub = this.sub;
-       jQuerySub.fn.init = function init( selector, context ) {
-               if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
-                       context = jQuerySub( context );
-               }
-
-               return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
-       };
-       jQuerySub.fn.init.prototype = jQuerySub.fn;
-       var rootjQuerySub = jQuerySub(document);
-       return jQuerySub;
-};
-
-})();
-var curCSS, iframe, iframeDoc,
-       ralpha = /alpha\([^)]*\)/i,
-       ropacity = /opacity=([^)]*)/,
-       rposition = /^(top|right|bottom|left)$/,
-       // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
-       // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
-       rdisplayswap = /^(none|table(?!-c[ea]).+)/,
-       rmargin = /^margin/,
-       rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
-       rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
-       rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ),
-       elemdisplay = { BODY: "block" },
-
-       cssShow = { position: "absolute", visibility: "hidden", display: "block" },
-       cssNormalTransform = {
-               letterSpacing: 0,
-               fontWeight: 400
-       },
-
-       cssExpand = [ "Top", "Right", "Bottom", "Left" ],
-       cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
-
-       eventsToggle = jQuery.fn.toggle;
-
-// return a css property mapped to a potentially vendor prefixed property
-function vendorPropName( style, name ) {
-
-       // shortcut for names that are not vendor prefixed
-       if ( name in style ) {
-               return name;
-       }
-
-       // check for vendor prefixed names
-       var capName = name.charAt(0).toUpperCase() + name.slice(1),
-               origName = name,
-               i = cssPrefixes.length;
-
-       while ( i-- ) {
-               name = cssPrefixes[ i ] + capName;
-               if ( name in style ) {
-                       return name;
-               }
-       }
-
-       return origName;
-}
-
-function isHidden( elem, el ) {
-       elem = el || elem;
-       return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
-}
-
-function showHide( elements, show ) {
-       var elem, display,
-               values = [],
-               index = 0,
-               length = elements.length;
-
-       for ( ; index < length; index++ ) {
-               elem = elements[ index ];
-               if ( !elem.style ) {
-                       continue;
-               }
-               values[ index ] = jQuery._data( elem, "olddisplay" );
-               if ( show ) {
-                       // Reset the inline display of this element to learn if it is
-                       // being hidden by cascaded rules or not
-                       if ( !values[ index ] && elem.style.display === "none" ) {
-                               elem.style.display = "";
-                       }
-
-                       // Set elements which have been overridden with display: none
-                       // in a stylesheet to whatever the default browser style is
-                       // for such an element
-                       if ( elem.style.display === "" && isHidden( elem ) ) {
-                               values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
-                       }
-               } else {
-                       display = curCSS( elem, "display" );
-
-                       if ( !values[ index ] && display !== "none" ) {
-                               jQuery._data( elem, "olddisplay", display );
-                       }
-               }
-       }
-
-       // Set the display of most of the elements in a second loop
-       // to avoid the constant reflow
-       for ( index = 0; index < length; index++ ) {
-               elem = elements[ index ];
-               if ( !elem.style ) {
-                       continue;
-               }
-               if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
-                       elem.style.display = show ? values[ index ] || "" : "none";
-               }
-       }
-
-       return elements;
-}
-
-jQuery.fn.extend({
-       css: function( name, value ) {
-               return jQuery.access( this, function( elem, name, value ) {
-                       return value !== undefined ?
-                               jQuery.style( elem, name, value ) :
-                               jQuery.css( elem, name );
-               }, name, value, arguments.length > 1 );
-       },
-       show: function() {
-               return showHide( this, true );
-       },
-       hide: function() {
-               return showHide( this );
-       },
-       toggle: function( state, fn2 ) {
-               var bool = typeof state === "boolean";
-
-               if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {
-                       return eventsToggle.apply( this, arguments );
-               }
-
-               return this.each(function() {
-                       if ( bool ? state : isHidden( this ) ) {
-                               jQuery( this ).show();
-                       } else {
-                               jQuery( this ).hide();
-                       }
-               });
-       }
-});
-
-jQuery.extend({
-       // Add in style property hooks for overriding the default
-       // behavior of getting and setting a style property
-       cssHooks: {
-               opacity: {
-                       get: function( elem, computed ) {
-                               if ( computed ) {
-                                       // We should always get a number back from opacity
-                                       var ret = curCSS( elem, "opacity" );
-                                       return ret === "" ? "1" : ret;
-
-                               }
-                       }
-               }
-       },
-
-       // Exclude the following css properties to add px
-       cssNumber: {
-               "fillOpacity": true,
-               "fontWeight": true,
-               "lineHeight": true,
-               "opacity": true,
-               "orphans": true,
-               "widows": true,
-               "zIndex": true,
-               "zoom": true
-       },
-
-       // Add in properties whose names you wish to fix before
-       // setting or getting the value
-       cssProps: {
-               // normalize float css property
-               "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
-       },
-
-       // Get and set the style property on a DOM Node
-       style: function( elem, name, value, extra ) {
-               // Don't set styles on text and comment nodes
-               if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
-                       return;
-               }
-
-               // Make sure that we're working with the right name
-               var ret, type, hooks,
-                       origName = jQuery.camelCase( name ),
-                       style = elem.style;
-
-               name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
-
-               // gets hook for the prefixed version
-               // followed by the unprefixed version
-               hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
-
-               // Check if we're setting a value
-               if ( value !== undefined ) {
-                       type = typeof value;
-
-                       // convert relative number strings (+= or -=) to relative numbers. #7345
-                       if ( type === "string" && (ret = rrelNum.exec( value )) ) {
-                               value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
-                               // Fixes bug #9237
-                               type = "number";
-                       }
-
-                       // Make sure that NaN and null values aren't set. See: #7116
-                       if ( value == null || type === "number" && isNaN( value ) ) {
-                               return;
-                       }
-
-                       // If a number was passed in, add 'px' to the (except for certain CSS properties)
-                       if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
-                               value += "px";
-                       }
-
-                       // If a hook was provided, use that value, otherwise just set the specified value
-                       if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
-                               // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
-                               // Fixes bug #5509
-                               try {
-                                       style[ name ] = value;
-                               } catch(e) {}
-                       }
-
-               } else {
-                       // If a hook was provided get the non-computed value from there
-                       if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
-                               return ret;
-                       }
-
-                       // Otherwise just get the value from the style object
-                       return style[ name ];
-               }
-       },
-
-       css: function( elem, name, numeric, extra ) {
-               var val, num, hooks,
-                       origName = jQuery.camelCase( name );
-
-               // Make sure that we're working with the right name
-               name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
-
-               // gets hook for the prefixed version
-               // followed by the unprefixed version
-               hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
-
-               // If a hook was provided get the computed value from there
-               if ( hooks && "get" in hooks ) {
-                       val = hooks.get( elem, true, extra );
-               }
-
-               // Otherwise, if a way to get the computed value exists, use that
-               if ( val === undefined ) {
-                       val = curCSS( elem, name );
-               }
-
-               //convert "normal" to computed value
-               if ( val === "normal" && name in cssNormalTransform ) {
-                       val = cssNormalTransform[ name ];
-               }
-
-               // Return, converting to number if forced or a qualifier was provided and val looks numeric
-               if ( numeric || extra !== undefined ) {
-                       num = parseFloat( val );
-                       return numeric || jQuery.isNumeric( num ) ? num || 0 : val;
-               }
-               return val;
-       },
-
-       // A method for quickly swapping in/out CSS properties to get correct calculations
-       swap: function( elem, options, callback ) {
-               var ret, name,
-                       old = {};
-
-               // Remember the old values, and insert the new ones
-               for ( name in options ) {
-                       old[ name ] = elem.style[ name ];
-                       elem.style[ name ] = options[ name ];
-               }
-
-               ret = callback.call( elem );
-
-               // Revert the old values
-               for ( name in options ) {
-                       elem.style[ name ] = old[ name ];
-               }
-
-               return ret;
-       }
-});
-
-// NOTE: To any future maintainer, we've window.getComputedStyle
-// because jsdom on node.js will break without it.
-if ( window.getComputedStyle ) {
-       curCSS = function( elem, name ) {
-               var ret, width, minWidth, maxWidth,
-                       computed = window.getComputedStyle( elem, null ),
-                       style = elem.style;
-
-               if ( computed ) {
-
-                       // getPropertyValue is only needed for .css('filter') in IE9, see #12537
-                       ret = computed.getPropertyValue( name ) || computed[ name ];
-
-                       if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
-                               ret = jQuery.style( elem, name );
-                       }
-
-                       // A tribute to the "awesome hack by Dean Edwards"
-                       // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
-                       // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
-                       // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
-                       if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
-                               width = style.width;
-                               minWidth = style.minWidth;
-                               maxWidth = style.maxWidth;
-
-                               style.minWidth = style.maxWidth = style.width = ret;
-                               ret = computed.width;
-
-                               style.width = width;
-                               style.minWidth = minWidth;
-                               style.maxWidth = maxWidth;
-                       }
-               }
-
-               return ret;
-       };
-} else if ( document.documentElement.currentStyle ) {
-       curCSS = function( elem, name ) {
-               var left, rsLeft,
-                       ret = elem.currentStyle && elem.currentStyle[ name ],
-                       style = elem.style;
-
-               // Avoid setting ret to empty string here
-               // so we don't default to auto
-               if ( ret == null && style && style[ name ] ) {
-                       ret = style[ name ];
-               }
-
-               // From the awesome hack by Dean Edwards
-               // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
-
-               // If we're not dealing with a regular pixel number
-               // but a number that has a weird ending, we need to convert it to pixels
-               // but not position css attributes, as those are proportional to the parent element instead
-               // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
-               if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
-
-                       // Remember the original values
-                       left = style.left;
-                       rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
-
-                       // Put in the new values to get a computed value out
-                       if ( rsLeft ) {
-                               elem.runtimeStyle.left = elem.currentStyle.left;
-                       }
-                       style.left = name === "fontSize" ? "1em" : ret;
-                       ret = style.pixelLeft + "px";
-
-                       // Revert the changed values
-                       style.left = left;
-                       if ( rsLeft ) {
-                               elem.runtimeStyle.left = rsLeft;
-                       }
-               }
-
-               return ret === "" ? "auto" : ret;
-       };
-}
-
-function setPositiveNumber( elem, value, subtract ) {
-       var matches = rnumsplit.exec( value );
-       return matches ?
-                       Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
-                       value;
-}
-
-function augmentWidthOrHeight( elem, name, extra, isBorderBox ) {
-       var i = extra === ( isBorderBox ? "border" : "content" ) ?
-               // If we already have the right measurement, avoid augmentation
-               4 :
-               // Otherwise initialize for horizontal or vertical properties
-               name === "width" ? 1 : 0,
-
-               val = 0;
-
-       for ( ; i < 4; i += 2 ) {
-               // both box models exclude margin, so add it if we want it
-               if ( extra === "margin" ) {
-                       // we use jQuery.css instead of curCSS here
-                       // because of the reliableMarginRight CSS hook!
-                       val += jQuery.css( elem, extra + cssExpand[ i ], true );
-               }
-
-               // From this point on we use curCSS for maximum performance (relevant in animations)
-               if ( isBorderBox ) {
-                       // border-box includes padding, so remove it if we want content
-                       if ( extra === "content" ) {
-                               val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
-                       }
-
-                       // at this point, extra isn't border nor margin, so remove border
-                       if ( extra !== "margin" ) {
-                               val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
-                       }
-               } else {
-                       // at this point, extra isn't content, so add padding
-                       val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
-
-                       // at this point, extra isn't content nor padding, so add border
-                       if ( extra !== "padding" ) {
-                               val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
-                       }
-               }
-       }
-
-       return val;
-}
-
-function getWidthOrHeight( elem, name, extra ) {
-
-       // Start with offset property, which is equivalent to the border-box value
-       var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
-               valueIsBorderBox = true,
-               isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box";
-
-       // some non-html elements return undefined for offsetWidth, so check for null/undefined
-       // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
-       // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
-       if ( val <= 0 || val == null ) {
-               // Fall back to computed then uncomputed css if necessary
-               val = curCSS( elem, name );
-               if ( val < 0 || val == null ) {
-                       val = elem.style[ name ];
-               }
-
-               // Computed unit is not pixels. Stop here and return.
-               if ( rnumnonpx.test(val) ) {
-                       return val;
-               }
-
-               // we need the check for style in case a browser which returns unreliable values
-               // for getComputedStyle silently falls back to the reliable elem.style
-               valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
-
-               // Normalize "", auto, and prepare for extra
-               val = parseFloat( val ) || 0;
-       }
-
-       // use the active box-sizing model to add/subtract irrelevant styles
-       return ( val +
-               augmentWidthOrHeight(
-                       elem,
-                       name,
-                       extra || ( isBorderBox ? "border" : "content" ),
-                       valueIsBorderBox
-               )
-       ) + "px";
-}
-
-
-// Try to determine the default display value of an element
-function css_defaultDisplay( nodeName ) {
-       if ( elemdisplay[ nodeName ] ) {
-               return elemdisplay[ nodeName ];
-       }
-
-       var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ),
-               display = elem.css("display");
-       elem.remove();
-
-       // If the simple way fails,
-       // get element's real default display by attaching it to a temp iframe
-       if ( display === "none" || display === "" ) {
-               // Use the already-created iframe if possible
-               iframe = document.body.appendChild(
-                       iframe || jQuery.extend( document.createElement("iframe"), {
-                               frameBorder: 0,
-                               width: 0,
-                               height: 0
-                       })
-               );
-
-               // Create a cacheable copy of the iframe document on first call.
-               // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
-               // document to it; WebKit & Firefox won't allow reusing the iframe document.
-               if ( !iframeDoc || !iframe.createElement ) {
-                       iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
-                       iframeDoc.write("<!doctype html><html><body>");
-                       iframeDoc.close();
-               }
-
-               elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) );
-
-               display = curCSS( elem, "display" );
-               document.body.removeChild( iframe );
-       }
-
-       // Store the correct default display
-       elemdisplay[ nodeName ] = display;
-
-       return display;
-}
-
-jQuery.each([ "height", "width" ], function( i, name ) {
-       jQuery.cssHooks[ name ] = {
-               get: function( elem, computed, extra ) {
-                       if ( computed ) {
-                               // certain elements can have dimension info if we invisibly show them
-                               // however, it must have a current display style that would benefit from this
-                               if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, "display" ) ) ) {
-                                       return jQuery.swap( elem, cssShow, function() {
-                                               return getWidthOrHeight( elem, name, extra );
-                                       });
-                               } else {
-                                       return getWidthOrHeight( elem, name, extra );
-                               }
-                       }
-               },
-
-               set: function( elem, value, extra ) {
-                       return setPositiveNumber( elem, value, extra ?
-                               augmentWidthOrHeight(
-                                       elem,
-                                       name,
-                                       extra,
-                                       jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"
-                               ) : 0
-                       );
-               }
-       };
-});
-
-if ( !jQuery.support.opacity ) {
-       jQuery.cssHooks.opacity = {
-               get: function( elem, computed ) {
-                       // IE uses filters for opacity
-                       return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
-                               ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
-                               computed ? "1" : "";
-               },
-
-               set: function( elem, value ) {
-                       var style = elem.style,
-                               currentStyle = elem.currentStyle,
-                               opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
-                               filter = currentStyle && currentStyle.filter || style.filter || "";
-
-                       // IE has trouble with opacity if it does not have layout
-                       // Force it by setting the zoom level
-                       style.zoom = 1;
-
-                       // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
-                       if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
-                               style.removeAttribute ) {
-
-                               // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
-                               // if "filter:" is present at all, clearType is disabled, we want to avoid this
-                               // style.removeAttribute is IE Only, but so apparently is this code path...
-                               style.removeAttribute( "filter" );
-
-                               // if there there is no filter style applied in a css rule, we are done
-                               if ( currentStyle && !currentStyle.filter ) {
-                                       return;
-                               }
-                       }
-
-                       // otherwise, set new filter values
-                       style.filter = ralpha.test( filter ) ?
-                               filter.replace( ralpha, opacity ) :
-                               filter + " " + opacity;
-               }
-       };
-}
-
-// These hooks cannot be added until DOM ready because the support test
-// for it is not run until after DOM ready
-jQuery(function() {
-       if ( !jQuery.support.reliableMarginRight ) {
-               jQuery.cssHooks.marginRight = {
-                       get: function( elem, computed ) {
-                               // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
-                               // Work around by temporarily setting element display to inline-block
-                               return jQuery.swap( elem, { "display": "inline-block" }, function() {
-                                       if ( computed ) {
-                                               return curCSS( elem, "marginRight" );
-                                       }
-                               });
-                       }
-               };
-       }
-
-       // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
-       // getComputedStyle returns percent when specified for top/left/bottom/right
-       // rather than make the css module depend on the offset module, we just check for it here
-       if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
-               jQuery.each( [ "top", "left" ], function( i, prop ) {
-                       jQuery.cssHooks[ prop ] = {
-                               get: function( elem, computed ) {
-                                       if ( computed ) {
-                                               var ret = curCSS( elem, prop );
-                                               // if curCSS returns percentage, fallback to offset
-                                               return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + "px" : ret;
-                                       }
-                               }
-                       };
-               });
-       }
-
-});
-
-if ( jQuery.expr && jQuery.expr.filters ) {
-       jQuery.expr.filters.hidden = function( elem ) {
-               return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none");
-       };
-
-       jQuery.expr.filters.visible = function( elem ) {
-               return !jQuery.expr.filters.hidden( elem );
-       };
-}
-
-// These hooks are used by animate to expand properties
-jQuery.each({
-       margin: "",
-       padding: "",
-       border: "Width"
-}, function( prefix, suffix ) {
-       jQuery.cssHooks[ prefix + suffix ] = {
-               expand: function( value ) {
-                       var i,
-
-                               // assumes a single number if not a string
-                               parts = typeof value === "string" ? value.split(" ") : [ value ],
-                               expanded = {};
-
-                       for ( i = 0; i < 4; i++ ) {
-                               expanded[ prefix + cssExpand[ i ] + suffix ] =
-                                       parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
-                       }
-
-                       return expanded;
-               }
-       };
-
-       if ( !rmargin.test( prefix ) ) {
-               jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
-       }
-});
-var r20 = /%20/g,
-       rbracket = /\[\]$/,
-       rCRLF = /\r?\n/g,
-       rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
-       rselectTextarea = /^(?:select|textarea)/i;
-
-jQuery.fn.extend({
-       serialize: function() {
-               return jQuery.param( this.serializeArray() );
-       },
-       serializeArray: function() {
-               return this.map(function(){
-                       return this.elements ? jQuery.makeArray( this.elements ) : this;
-               })
-               .filter(function(){
-                       return this.name && !this.disabled &&
-                               ( this.checked || rselectTextarea.test( this.nodeName ) ||
-                                       rinput.test( this.type ) );
-               })
-               .map(function( i, elem ){
-                       var val = jQuery( this ).val();
-
-                       return val == null ?
-                               null :
-                               jQuery.isArray( val ) ?
-                                       jQuery.map( val, function( val, i ){
-                                               return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
-                                       }) :
-                                       { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
-               }).get();
-       }
-});
-
-//Serialize an array of form elements or a set of
-//key/values into a query string
-jQuery.param = function( a, traditional ) {
-       var prefix,
-               s = [],
-               add = function( key, value ) {
-                       // If value is a function, invoke it and return its value
-                       value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
-                       s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
-               };
-
-       // Set traditional to true for jQuery <= 1.3.2 behavior.
-       if ( traditional === undefined ) {
-               traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
-       }
-
-       // If an array was passed in, assume that it is an array of form elements.
-       if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
-               // Serialize the form elements
-               jQuery.each( a, function() {
-                       add( this.name, this.value );
-               });
-
-       } else {
-               // If traditional, encode the "old" way (the way 1.3.2 or older
-               // did it), otherwise encode params recursively.
-               for ( prefix in a ) {
-                       buildParams( prefix, a[ prefix ], traditional, add );
-               }
-       }
-
-       // Return the resulting serialization
-       return s.join( "&" ).replace( r20, "+" );
-};
-
-function buildParams( prefix, obj, traditional, add ) {
-       var name;
-
-       if ( jQuery.isArray( obj ) ) {
-               // Serialize array item.
-               jQuery.each( obj, function( i, v ) {
-                       if ( traditional || rbracket.test( prefix ) ) {
-                               // Treat each array item as a scalar.
-                               add( prefix, v );
-
-                       } else {
-                               // If array item is non-scalar (array or object), encode its
-                               // numeric index to resolve deserialization ambiguity issues.
-                               // Note that rack (as of 1.0.0) can't currently deserialize
-                               // nested arrays properly, and attempting to do so may cause
-                               // a server error. Possible fixes are to modify rack's
-                               // deserialization algorithm or to provide an option or flag
-                               // to force array serialization to be shallow.
-                               buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
-                       }
-               });
-
-       } else if ( !traditional && jQuery.type( obj ) === "object" ) {
-               // Serialize object item.
-               for ( name in obj ) {
-                       buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
-               }
-
-       } else {
-               // Serialize scalar item.
-               add( prefix, obj );
-       }
-}
-var
-       // Document location
-       ajaxLocParts,
-       ajaxLocation,
-
-       rhash = /#.*$/,
-       rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
-       // #7653, #8125, #8152: local protocol detection
-       rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
-       rnoContent = /^(?:GET|HEAD)$/,
-       rprotocol = /^\/\//,
-       rquery = /\?/,
-       rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
-       rts = /([?&])_=[^&]*/,
-       rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
-
-       // Keep a copy of the old load method
-       _load = jQuery.fn.load,
-
-       /* Prefilters
-        * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
-        * 2) These are called:
-        *    - BEFORE asking for a transport
-        *    - AFTER param serialization (s.data is a string if s.processData is true)
-        * 3) key is the dataType
-        * 4) the catchall symbol "*" can be used
-        * 5) execution will start with transport dataType and THEN continue down to "*" if needed
-        */
-       prefilters = {},
-
-       /* Transports bindings
-        * 1) key is the dataType
-        * 2) the catchall symbol "*" can be used
-        * 3) selection will start with transport dataType and THEN go to "*" if needed
-        */
-       transports = {},
-
-       // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
-       allTypes = ["*/"] + ["*"];
-
-// #8138, IE may throw an exception when accessing
-// a field from window.location if document.domain has been set
-try {
-       ajaxLocation = location.href;
-} catch( e ) {
-       // Use the href attribute of an A element
-       // since IE will modify it given document.location
-       ajaxLocation = document.createElement( "a" );
-       ajaxLocation.href = "";
-       ajaxLocation = ajaxLocation.href;
-}
-
-// Segment location into parts
-ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
-
-// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
-function addToPrefiltersOrTransports( structure ) {
-
-       // dataTypeExpression is optional and defaults to "*"
-       return function( dataTypeExpression, func ) {
-
-               if ( typeof dataTypeExpression !== "string" ) {
-                       func = dataTypeExpression;
-                       dataTypeExpression = "*";
-               }
-
-               var dataType, list, placeBefore,
-                       dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ),
-                       i = 0,
-                       length = dataTypes.length;
-
-               if ( jQuery.isFunction( func ) ) {
-                       // For each dataType in the dataTypeExpression
-                       for ( ; i < length; i++ ) {
-                               dataType = dataTypes[ i ];
-                               // We control if we're asked to add before
-                               // any existing element
-                               placeBefore = /^\+/.test( dataType );
-                               if ( placeBefore ) {
-                                       dataType = dataType.substr( 1 ) || "*";
-                               }
-                               list = structure[ dataType ] = structure[ dataType ] || [];
-                               // then we add to the structure accordingly
-                               list[ placeBefore ? "unshift" : "push" ]( func );
-                       }
-               }
-       };
-}
-
-// Base inspection function for prefilters and transports
-function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
-               dataType /* internal */, inspected /* internal */ ) {
-
-       dataType = dataType || options.dataTypes[ 0 ];
-       inspected = inspected || {};
-
-       inspected[ dataType ] = true;
-
-       var selection,
-               list = structure[ dataType ],
-               i = 0,
-               length = list ? list.length : 0,
-               executeOnly = ( structure === prefilters );
-
-       for ( ; i < length && ( executeOnly || !selection ); i++ ) {
-               selection = list[ i ]( options, originalOptions, jqXHR );
-               // If we got redirected to another dataType
-               // we try there if executing only and not done already
-               if ( typeof selection === "string" ) {
-                       if ( !executeOnly || inspected[ selection ] ) {
-                               selection = undefined;
-                       } else {
-                               options.dataTypes.unshift( selection );
-                               selection = inspectPrefiltersOrTransports(
-                                               structure, options, originalOptions, jqXHR, selection, inspected );
-                       }
-               }
-       }
-       // If we're only executing or nothing was selected
-       // we try the catchall dataType if not done already
-       if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
-               selection = inspectPrefiltersOrTransports(
-                               structure, options, originalOptions, jqXHR, "*", inspected );
-       }
-       // unnecessary when only executing (prefilters)
-       // but it'll be ignored by the caller in that case
-       return selection;
-}
-
-// A special extend for ajax options
-// that takes "flat" options (not to be deep extended)
-// Fixes #9887
-function ajaxExtend( target, src ) {
-       var key, deep,
-               flatOptions = jQuery.ajaxSettings.flatOptions || {};
-       for ( key in src ) {
-               if ( src[ key ] !== undefined ) {
-                       ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
-               }
-       }
-       if ( deep ) {
-               jQuery.extend( true, target, deep );
-       }
-}
-
-jQuery.fn.load = function( url, params, callback ) {
-       if ( typeof url !== "string" && _load ) {
-               return _load.apply( this, arguments );
-       }
-
-       // Don't do a request if no elements are being requested
-       if ( !this.length ) {
-               return this;
-       }
-
-       var selector, type, response,
-               self = this,
-               off = url.indexOf(" ");
-
-       if ( off >= 0 ) {
-               selector = url.slice( off, url.length );
-               url = url.slice( 0, off );
-       }
-
-       // If it's a function
-       if ( jQuery.isFunction( params ) ) {
-
-               // We assume that it's the callback
-               callback = params;
-               params = undefined;
-
-       // Otherwise, build a param string
-       } else if ( params && typeof params === "object" ) {
-               type = "POST";
-       }
-
-       // Request the remote document
-       jQuery.ajax({
-               url: url,
-
-               // if "type" variable is undefined, then "GET" method will be used
-               type: type,
-               dataType: "html",
-               data: params,
-               complete: function( jqXHR, status ) {
-                       if ( callback ) {
-                               self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
-                       }
-               }
-       }).done(function( responseText ) {
-
-               // Save response for use in complete callback
-               response = arguments;
-
-               // See if a selector was specified
-               self.html( selector ?
-
-                       // Create a dummy div to hold the results
-                       jQuery("<div>")
-
-                               // inject the contents of the document in, removing the scripts
-                               // to avoid any 'Permission Denied' errors in IE
-                               .append( responseText.replace( rscript, "" ) )
-
-                               // Locate the specified elements
-                               .find( selector ) :
-
-                       // If not, just inject the full result
-                       responseText );
-
-       });
-
-       return this;
-};
-
-// Attach a bunch of functions for handling common AJAX events
-jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
-       jQuery.fn[ o ] = function( f ){
-               return this.on( o, f );
-       };
-});
-
-jQuery.each( [ "get", "post" ], function( i, method ) {
-       jQuery[ method ] = function( url, data, callback, type ) {
-               // shift arguments if data argument was omitted
-               if ( jQuery.isFunction( data ) ) {
-                       type = type || callback;
-                       callback = data;
-                       data = undefined;
-               }
-
-               return jQuery.ajax({
-                       type: method,
-                       url: url,
-                       data: data,
-                       success: callback,
-                       dataType: type
-               });
-       };
-});
-
-jQuery.extend({
-
-       getScript: function( url, callback ) {
-               return jQuery.get( url, undefined, callback, "script" );
-       },
-
-       getJSON: function( url, data, callback ) {
-               return jQuery.get( url, data, callback, "json" );
-       },
-
-       // Creates a full fledged settings object into target
-       // with both ajaxSettings and settings fields.
-       // If target is omitted, writes into ajaxSettings.
-       ajaxSetup: function( target, settings ) {
-               if ( settings ) {
-                       // Building a settings object
-                       ajaxExtend( target, jQuery.ajaxSettings );
-               } else {
-                       // Extending ajaxSettings
-                       settings = target;
-                       target = jQuery.ajaxSettings;
-               }
-               ajaxExtend( target, settings );
-               return target;
-       },
-
-       ajaxSettings: {
-               url: ajaxLocation,
-               isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
-               global: true,
-               type: "GET",
-               contentType: "application/x-www-form-urlencoded; charset=UTF-8",
-               processData: true,
-               async: true,
-               /*
-               timeout: 0,
-               data: null,
-               dataType: null,
-               username: null,
-               password: null,
-               cache: null,
-               throws: false,
-               traditional: false,
-               headers: {},
-               */
-
-               accepts: {
-                       xml: "application/xml, text/xml",
-                       html: "text/html",
-                       text: "text/plain",
-                       json: "application/json, text/javascript",
-                       "*": allTypes
-               },
-
-               contents: {
-                       xml: /xml/,
-                       html: /html/,
-                       json: /json/
-               },
-
-               responseFields: {
-                       xml: "responseXML",
-                       text: "responseText"
-               },
-
-               // List of data converters
-               // 1) key format is "source_type destination_type" (a single space in-between)
-               // 2) the catchall symbol "*" can be used for source_type
-               converters: {
-
-                       // Convert anything to text
-                       "* text": window.String,
-
-                       // Text to html (true = no transformation)
-                       "text html": true,
-
-                       // Evaluate text as a json expression
-                       "text json": jQuery.parseJSON,
-
-                       // Parse text as xml
-                       "text xml": jQuery.parseXML
-               },
-
-               // For options that shouldn't be deep extended:
-               // you can add your own custom options here if
-               // and when you create one that shouldn't be
-               // deep extended (see ajaxExtend)
-               flatOptions: {
-                       context: true,
-                       url: true
-               }
-       },
-
-       ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
-       ajaxTransport: addToPrefiltersOrTransports( transports ),
-
-       // Main method
-       ajax: function( url, options ) {
-
-               // If url is an object, simulate pre-1.5 signature
-               if ( typeof url === "object" ) {
-                       options = url;
-                       url = undefined;
-               }
-
-               // Force options to be an object
-               options = options || {};
-
-               var // ifModified key
-                       ifModifiedKey,
-                       // Response headers
-                       responseHeadersString,
-                       responseHeaders,
-                       // transport
-                       transport,
-                       // timeout handle
-                       timeoutTimer,
-                       // Cross-domain detection vars
-                       parts,
-                       // To know if global events are to be dispatched
-                       fireGlobals,
-                       // Loop variable
-                       i,
-                       // Create the final options object
-                       s = jQuery.ajaxSetup( {}, options ),
-                       // Callbacks context
-                       callbackContext = s.context || s,
-                       // Context for global events
-                       // It's the callbackContext if one was provided in the options
-                       // and if it's a DOM node or a jQuery collection
-                       globalEventContext = callbackContext !== s &&
-                               ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
-                                               jQuery( callbackContext ) : jQuery.event,
-                       // Deferreds
-                       deferred = jQuery.Deferred(),
-                       completeDeferred = jQuery.Callbacks( "once memory" ),
-                       // Status-dependent callbacks
-                       statusCode = s.statusCode || {},
-                       // Headers (they are sent all at once)
-                       requestHeaders = {},
-                       requestHeadersNames = {},
-                       // The jqXHR state
-                       state = 0,
-                       // Default abort message
-                       strAbort = "canceled",
-                       // Fake xhr
-                       jqXHR = {
-
-                               readyState: 0,
-
-                               // Caches the header
-                               setRequestHeader: function( name, value ) {
-                                       if ( !state ) {
-                                               var lname = name.toLowerCase();
-                                               name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
-                                               requestHeaders[ name ] = value;
-                                       }
-                                       return this;
-                               },
-
-                               // Raw string
-                               getAllResponseHeaders: function() {
-                                       return state === 2 ? responseHeadersString : null;
-                               },
-
-                               // Builds headers hashtable if needed
-                               getResponseHeader: function( key ) {
-                                       var match;
-                                       if ( state === 2 ) {
-                                               if ( !responseHeaders ) {
-                                                       responseHeaders = {};
-                                                       while( ( match = rheaders.exec( responseHeadersString ) ) ) {
-                                                               responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
-                                                       }
-                                               }
-                                               match = responseHeaders[ key.toLowerCase() ];
-                                       }
-                                       return match === undefined ? null : match;
-                               },
-
-                               // Overrides response content-type header
-                               overrideMimeType: function( type ) {
-                                       if ( !state ) {
-                                               s.mimeType = type;
-                                       }
-                                       return this;
-                               },
-
-                               // Cancel the request
-                               abort: function( statusText ) {
-                                       statusText = statusText || strAbort;
-                                       if ( transport ) {
-                                               transport.abort( statusText );
-                                       }
-                                       done( 0, statusText );
-                                       return this;
-                               }
-                       };
-
-               // Callback for when everything is done
-               // It is defined here because jslint complains if it is declared
-               // at the end of the function (which would be more logical and readable)
-               function done( status, nativeStatusText, responses, headers ) {
-                       var isSuccess, success, error, response, modified,
-                               statusText = nativeStatusText;
-
-                       // Called once
-                       if ( state === 2 ) {
-                               return;
-                       }
-
-                       // State is "done" now
-                       state = 2;
-
-                       // Clear timeout if it exists
-                       if ( timeoutTimer ) {
-                               clearTimeout( timeoutTimer );
-                       }
-
-                       // Dereference transport for early garbage collection
-                       // (no matter how long the jqXHR object will be used)
-                       transport = undefined;
-
-                       // Cache response headers
-                       responseHeadersString = headers || "";
-
-                       // Set readyState
-                       jqXHR.readyState = status > 0 ? 4 : 0;
-
-                       // Get response data
-                       if ( responses ) {
-                               response = ajaxHandleResponses( s, jqXHR, responses );
-                       }
-
-                       // If successful, handle type chaining
-                       if ( status >= 200 && status < 300 || status === 304 ) {
-
-                               // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
-                               if ( s.ifModified ) {
-
-                                       modified = jqXHR.getResponseHeader("Last-Modified");
-                                       if ( modified ) {
-                                               jQuery.lastModified[ ifModifiedKey ] = modified;
-                                       }
-                                       modified = jqXHR.getResponseHeader("Etag");
-                                       if ( modified ) {
-                                               jQuery.etag[ ifModifiedKey ] = modified;
-                                       }
-                               }
-
-                               // If not modified
-                               if ( status === 304 ) {
-
-                                       statusText = "notmodified";
-                                       isSuccess = true;
-
-                               // If we have data
-                               } else {
-
-                                       isSuccess = ajaxConvert( s, response );
-                                       statusText = isSuccess.state;
-                                       success = isSuccess.data;
-                                       error = isSuccess.error;
-                                       isSuccess = !error;
-                               }
-                       } else {
-                               // We extract error from statusText
-                               // then normalize statusText and status for non-aborts
-                               error = statusText;
-                               if ( !statusText || status ) {
-                                       statusText = "error";
-                                       if ( status < 0 ) {
-                                               status = 0;
-                                       }
-                               }
-                       }
-
-                       // Set data for the fake xhr object
-                       jqXHR.status = status;
-                       jqXHR.statusText = ( nativeStatusText || statusText ) + "";
-
-                       // Success/Error
-                       if ( isSuccess ) {
-                               deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
-                       } else {
-                               deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
-                       }
-
-                       // Status-dependent callbacks
-                       jqXHR.statusCode( statusCode );
-                       statusCode = undefined;
-
-                       if ( fireGlobals ) {
-                               globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
-                                               [ jqXHR, s, isSuccess ? success : error ] );
-                       }
-
-                       // Complete
-                       completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
-
-                       if ( fireGlobals ) {
-                               globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
-                               // Handle the global AJAX counter
-                               if ( !( --jQuery.active ) ) {
-                                       jQuery.event.trigger( "ajaxStop" );
-                               }
-                       }
-               }
-
-               // Attach deferreds
-               deferred.promise( jqXHR );
-               jqXHR.success = jqXHR.done;
-               jqXHR.error = jqXHR.fail;
-               jqXHR.complete = completeDeferred.add;
-
-               // Status-dependent callbacks
-               jqXHR.statusCode = function( map ) {
-                       if ( map ) {
-                               var tmp;
-                               if ( state < 2 ) {
-                                       for ( tmp in map ) {
-                                               statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
-                                       }
-                               } else {
-                                       tmp = map[ jqXHR.status ];
-                                       jqXHR.always( tmp );
-                               }
-                       }
-                       return this;
-               };
-
-               // Remove hash character (#7531: and string promotion)
-               // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
-               // We also use the url parameter if available
-               s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
-
-               // Extract dataTypes list
-               s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace );
-
-               // A cross-domain request is in order when we have a protocol:host:port mismatch
-               if ( s.crossDomain == null ) {
-                       parts = rurl.exec( s.url.toLowerCase() );
-                       s.crossDomain = !!( parts &&
-                               ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
-                                       ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
-                                               ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
-                       );
-               }
-
-               // Convert data if not already a string
-               if ( s.data && s.processData && typeof s.data !== "string" ) {
-                       s.data = jQuery.param( s.data, s.traditional );
-               }
-
-               // Apply prefilters
-               inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
-
-               // If request was aborted inside a prefilter, stop there
-               if ( state === 2 ) {
-                       return jqXHR;
-               }
-
-               // We can fire global events as of now if asked to
-               fireGlobals = s.global;
-
-               // Uppercase the type
-               s.type = s.type.toUpperCase();
-
-               // Determine if request has content
-               s.hasContent = !rnoContent.test( s.type );
-
-               // Watch for a new set of requests
-               if ( fireGlobals && jQuery.active++ === 0 ) {
-                       jQuery.event.trigger( "ajaxStart" );
-               }
-
-               // More options handling for requests with no content
-               if ( !s.hasContent ) {
-
-                       // If data is available, append data to url
-                       if ( s.data ) {
-                               s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
-                               // #9682: remove data so that it's not used in an eventual retry
-                               delete s.data;
-                       }
-
-                       // Get ifModifiedKey before adding the anti-cache parameter
-                       ifModifiedKey = s.url;
-
-                       // Add anti-cache in url if needed
-                       if ( s.cache === false ) {
-
-                               var ts = jQuery.now(),
-                                       // try replacing _= if it is there
-                                       ret = s.url.replace( rts, "$1_=" + ts );
-
-                               // if nothing was replaced, add timestamp to the end
-                               s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
-                       }
-               }
-
-               // Set the correct header, if data is being sent
-               if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
-                       jqXHR.setRequestHeader( "Content-Type", s.contentType );
-               }
-
-               // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
-               if ( s.ifModified ) {
-                       ifModifiedKey = ifModifiedKey || s.url;
-                       if ( jQuery.lastModified[ ifModifiedKey ] ) {
-                               jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
-                       }
-                       if ( jQuery.etag[ ifModifiedKey ] ) {
-                               jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
-                       }
-               }
-
-               // Set the Accepts header for the server, depending on the dataType
-               jqXHR.setRequestHeader(
-                       "Accept",
-                       s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
-                               s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
-                               s.accepts[ "*" ]
-               );
-
-               // Check for headers option
-               for ( i in s.headers ) {
-                       jqXHR.setRequestHeader( i, s.headers[ i ] );
-               }
-
-               // Allow custom headers/mimetypes and early abort
-               if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
-                               // Abort if not done already and return
-                               return jqXHR.abort();
-
-               }
-
-               // aborting is no longer a cancellation
-               strAbort = "abort";
-
-               // Install callbacks on deferreds
-               for ( i in { success: 1, error: 1, complete: 1 } ) {
-                       jqXHR[ i ]( s[ i ] );
-               }
-
-               // Get transport
-               transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
-
-               // If no transport, we auto-abort
-               if ( !transport ) {
-                       done( -1, "No Transport" );
-               } else {
-                       jqXHR.readyState = 1;
-                       // Send global event
-                       if ( fireGlobals ) {
-                               globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
-                       }
-                       // Timeout
-                       if ( s.async && s.timeout > 0 ) {
-                               timeoutTimer = setTimeout( function(){
-                                       jqXHR.abort( "timeout" );
-                               }, s.timeout );
-                       }
-
-                       try {
-                               state = 1;
-                               transport.send( requestHeaders, done );
-                       } catch (e) {
-                               // Propagate exception as error if not done
-                               if ( state < 2 ) {
-                                       done( -1, e );
-                               // Simply rethrow otherwise
-                               } else {
-                                       throw e;
-                               }
-                       }
-               }
-
-               return jqXHR;
-       },
-
-       // Counter for holding the number of active queries
-       active: 0,
-
-       // Last-Modified header cache for next request
-       lastModified: {},
-       etag: {}
-
-});
-
-/* Handles responses to an ajax request:
- * - sets all responseXXX fields accordingly
- * - finds the right dataType (mediates between content-type and expected dataType)
- * - returns the corresponding response
- */
-function ajaxHandleResponses( s, jqXHR, responses ) {
-
-       var ct, type, finalDataType, firstDataType,
-               contents = s.contents,
-               dataTypes = s.dataTypes,
-               responseFields = s.responseFields;
-
-       // Fill responseXXX fields
-       for ( type in responseFields ) {
-               if ( type in responses ) {
-                       jqXHR[ responseFields[type] ] = responses[ type ];
-               }
-       }
-
-       // Remove auto dataType and get content-type in the process
-       while( dataTypes[ 0 ] === "*" ) {
-               dataTypes.shift();
-               if ( ct === undefined ) {
-                       ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
-               }
-       }
-
-       // Check if we're dealing with a known content-type
-       if ( ct ) {
-               for ( type in contents ) {
-                       if ( contents[ type ] && contents[ type ].test( ct ) ) {
-                               dataTypes.unshift( type );
-                               break;
-                       }
-               }
-       }
-
-       // Check to see if we have a response for the expected dataType
-       if ( dataTypes[ 0 ] in responses ) {
-               finalDataType = dataTypes[ 0 ];
-       } else {
-               // Try convertible dataTypes
-               for ( type in responses ) {
-                       if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
-                               finalDataType = type;
-                               break;
-                       }
-                       if ( !firstDataType ) {
-                               firstDataType = type;
-                       }
-               }
-               // Or just use first one
-               finalDataType = finalDataType || firstDataType;
-       }
-
-       // If we found a dataType
-       // We add the dataType to the list if needed
-       // and return the corresponding response
-       if ( finalDataType ) {
-               if ( finalDataType !== dataTypes[ 0 ] ) {
-                       dataTypes.unshift( finalDataType );
-               }
-               return responses[ finalDataType ];
-       }
-}
-
-// Chain conversions given the request and the original response
-function ajaxConvert( s, response ) {
-
-       var conv, conv2, current, tmp,
-               // Work with a copy of dataTypes in case we need to modify it for conversion
-               dataTypes = s.dataTypes.slice(),
-               prev = dataTypes[ 0 ],
-               converters = {},
-               i = 0;
-
-       // Apply the dataFilter if provided
-       if ( s.dataFilter ) {
-               response = s.dataFilter( response, s.dataType );
-       }
-
-       // Create converters map with lowercased keys
-       if ( dataTypes[ 1 ] ) {
-               for ( conv in s.converters ) {
-                       converters[ conv.toLowerCase() ] = s.converters[ conv ];
-               }
-       }
-
-       // Convert to each sequential dataType, tolerating list modification
-       for ( ; (current = dataTypes[++i]); ) {
-
-               // There's only work to do if current dataType is non-auto
-               if ( current !== "*" ) {
-
-                       // Convert response if prev dataType is non-auto and differs from current
-                       if ( prev !== "*" && prev !== current ) {
-
-                               // Seek a direct converter
-                               conv = converters[ prev + " " + current ] || converters[ "* " + current ];
-
-                               // If none found, seek a pair
-                               if ( !conv ) {
-                                       for ( conv2 in converters ) {
-
-                                               // If conv2 outputs current
-                                               tmp = conv2.split(" ");
-                                               if ( tmp[ 1 ] === current ) {
-
-                                                       // If prev can be converted to accepted input
-                                                       conv = converters[ prev + " " + tmp[ 0 ] ] ||
-                                                               converters[ "* " + tmp[ 0 ] ];
-                                                       if ( conv ) {
-                                                               // Condense equivalence converters
-                                                               if ( conv === true ) {
-                                                                       conv = converters[ conv2 ];
-
-                                                               // Otherwise, insert the intermediate dataType
-                                                               } else if ( converters[ conv2 ] !== true ) {
-                                                                       current = tmp[ 0 ];
-                                                                       dataTypes.splice( i--, 0, current );
-                                                               }
-
-                                                               break;
-                                                       }
-                                               }
-                                       }
-                               }
-
-                               // Apply converter (if not an equivalence)
-                               if ( conv !== true ) {
-
-                                       // Unless errors are allowed to bubble, catch and return them
-                                       if ( conv && s["throws"] ) {
-                                               response = conv( response );
-                                       } else {
-                                               try {
-                                                       response = conv( response );
-                                               } catch ( e ) {
-                                                       return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
-                                               }
-                                       }
-                               }
-                       }
-
-                       // Update prev for next iteration
-                       prev = current;
-               }
-       }
-
-       return { state: "success", data: response };
-}
-var oldCallbacks = [],
-       rquestion = /\?/,
-       rjsonp = /(=)\?(?=&|$)|\?\?/,
-       nonce = jQuery.now();
-
-// Default jsonp settings
-jQuery.ajaxSetup({
-       jsonp: "callback",
-       jsonpCallback: function() {
-               var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
-               this[ callback ] = true;
-               return callback;
-       }
-});
-
-// Detect, normalize options and install callbacks for jsonp requests
-jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
-
-       var callbackName, overwritten, responseContainer,
-               data = s.data,
-               url = s.url,
-               hasCallback = s.jsonp !== false,
-               replaceInUrl = hasCallback && rjsonp.test( url ),
-               replaceInData = hasCallback && !replaceInUrl && typeof data === "string" &&
-                       !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") &&
-                       rjsonp.test( data );
-
-       // Handle iff the expected data type is "jsonp" or we have a parameter to set
-       if ( s.dataTypes[ 0 ] === "jsonp" || replaceInUrl || replaceInData ) {
-
-               // Get callback name, remembering preexisting value associated with it
-               callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
-                       s.jsonpCallback() :
-                       s.jsonpCallback;
-               overwritten = window[ callbackName ];
-
-               // Insert callback into url or form data
-               if ( replaceInUrl ) {
-                       s.url = url.replace( rjsonp, "$1" + callbackName );
-               } else if ( replaceInData ) {
-                       s.data = data.replace( rjsonp, "$1" + callbackName );
-               } else if ( hasCallback ) {
-                       s.url += ( rquestion.test( url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
-               }
-
-               // Use data converter to retrieve json after script execution
-               s.converters["script json"] = function() {
-                       if ( !responseContainer ) {
-                               jQuery.error( callbackName + " was not called" );
-                       }
-                       return responseContainer[ 0 ];
-               };
-
-               // force json dataType
-               s.dataTypes[ 0 ] = "json";
-
-               // Install callback
-               window[ callbackName ] = function() {
-                       responseContainer = arguments;
-               };
-
-               // Clean-up function (fires after converters)
-               jqXHR.always(function() {
-                       // Restore preexisting value
-                       window[ callbackName ] = overwritten;
-
-                       // Save back as free
-                       if ( s[ callbackName ] ) {
-                               // make sure that re-using the options doesn't screw things around
-                               s.jsonpCallback = originalSettings.jsonpCallback;
-
-                               // save the callback name for future use
-                               oldCallbacks.push( callbackName );
-                       }
-
-                       // Call if it was a function and we have a response
-                       if ( responseContainer && jQuery.isFunction( overwritten ) ) {
-                               overwritten( responseContainer[ 0 ] );
-                       }
-
-                       responseContainer = overwritten = undefined;
-               });
-
-               // Delegate to script
-               return "script";
-       }
-});
-// Install script dataType
-jQuery.ajaxSetup({
-       accepts: {
-               script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
-       },
-       contents: {
-               script: /javascript|ecmascript/
-       },
-       converters: {
-               "text script": function( text ) {
-                       jQuery.globalEval( text );
-                       return text;
-               }
-       }
-});
-
-// Handle cache's special case and global
-jQuery.ajaxPrefilter( "script", function( s ) {
-       if ( s.cache === undefined ) {
-               s.cache = false;
-       }
-       if ( s.crossDomain ) {
-               s.type = "GET";
-               s.global = false;
-       }
-});
-
-// Bind script tag hack transport
-jQuery.ajaxTransport( "script", function(s) {
-
-       // This transport only deals with cross domain requests
-       if ( s.crossDomain ) {
-
-               var script,
-                       head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
-
-               return {
-
-                       send: function( _, callback ) {
-
-                               script = document.createElement( "script" );
-
-                               script.async = "async";
-
-                               if ( s.scriptCharset ) {
-                                       script.charset = s.scriptCharset;
-                               }
-
-                               script.src = s.url;
-
-                               // Attach handlers for all browsers
-                               script.onload = script.onreadystatechange = function( _, isAbort ) {
-
-                                       if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
-
-                                               // Handle memory leak in IE
-                                               script.onload = script.onreadystatechange = null;
-
-                                               // Remove the script
-                                               if ( head && script.parentNode ) {
-                                                       head.removeChild( script );
-                                               }
-
-                                               // Dereference the script
-                                               script = undefined;
-
-                                               // Callback if not abort
-                                               if ( !isAbort ) {
-                                                       callback( 200, "success" );
-                                               }
-                                       }
-                               };
-                               // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
-                               // This arises when a base node is used (#2709 and #4378).
-                               head.insertBefore( script, head.firstChild );
-                       },
-
-                       abort: function() {
-                               if ( script ) {
-                                       script.onload( 0, 1 );
-                               }
-                       }
-               };
-       }
-});
-var xhrCallbacks,
-       // #5280: Internet Explorer will keep connections alive if we don't abort on unload
-       xhrOnUnloadAbort = window.ActiveXObject ? function() {
-               // Abort all pending requests
-               for ( var key in xhrCallbacks ) {
-                       xhrCallbacks[ key ]( 0, 1 );
-               }
-       } : false,
-       xhrId = 0;
-
-// Functions to create xhrs
-function createStandardXHR() {
-       try {
-               return new window.XMLHttpRequest();
-       } catch( e ) {}
-}
-
-function createActiveXHR() {
-       try {
-               return new window.ActiveXObject( "Microsoft.XMLHTTP" );
-       } catch( e ) {}
-}
-
-// Create the request object
-// (This is still attached to ajaxSettings for backward compatibility)
-jQuery.ajaxSettings.xhr = window.ActiveXObject ?
-       /* Microsoft failed to properly
-        * implement the XMLHttpRequest in IE7 (can't request local files),
-        * so we use the ActiveXObject when it is available
-        * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
-        * we need a fallback.
-        */
-       function() {
-               return !this.isLocal && createStandardXHR() || createActiveXHR();
-       } :
-       // For all other browsers, use the standard XMLHttpRequest object
-       createStandardXHR;
-
-// Determine support properties
-(function( xhr ) {
-       jQuery.extend( jQuery.support, {
-               ajax: !!xhr,
-               cors: !!xhr && ( "withCredentials" in xhr )
-       });
-})( jQuery.ajaxSettings.xhr() );
-
-// Create transport if the browser can provide an xhr
-if ( jQuery.support.ajax ) {
-
-       jQuery.ajaxTransport(function( s ) {
-               // Cross domain only allowed if supported through XMLHttpRequest
-               if ( !s.crossDomain || jQuery.support.cors ) {
-
-                       var callback;
-
-                       return {
-                               send: function( headers, complete ) {
-
-                                       // Get a new xhr
-                                       var handle, i,
-                                               xhr = s.xhr();
-
-                                       // Open the socket
-                                       // Passing null username, generates a login popup on Opera (#2865)
-                                       if ( s.username ) {
-                                               xhr.open( s.type, s.url, s.async, s.username, s.password );
-                                       } else {
-                                               xhr.open( s.type, s.url, s.async );
-                                       }
-
-                                       // Apply custom fields if provided
-                                       if ( s.xhrFields ) {
-                                               for ( i in s.xhrFields ) {
-                                                       xhr[ i ] = s.xhrFields[ i ];
-                                               }
-                                       }
-
-                                       // Override mime type if needed
-                                       if ( s.mimeType && xhr.overrideMimeType ) {
-                                               xhr.overrideMimeType( s.mimeType );
-                                       }
-
-                                       // X-Requested-With header
-                                       // For cross-domain requests, seeing as conditions for a preflight are
-                                       // akin to a jigsaw puzzle, we simply never set it to be sure.
-                                       // (it can always be set on a per-request basis or even using ajaxSetup)
-                                       // For same-domain requests, won't change header if already provided.
-                                       if ( !s.crossDomain && !headers["X-Requested-With"] ) {
-                                               headers[ "X-Requested-With" ] = "XMLHttpRequest";
-                                       }
-
-                                       // Need an extra try/catch for cross domain requests in Firefox 3
-                                       try {
-                                               for ( i in headers ) {
-                                                       xhr.setRequestHeader( i, headers[ i ] );
-                                               }
-                                       } catch( _ ) {}
-
-                                       // Do send the request
-                                       // This may raise an exception which is actually
-                                       // handled in jQuery.ajax (so no try/catch here)
-                                       xhr.send( ( s.hasContent && s.data ) || null );
-
-                                       // Listener
-                                       callback = function( _, isAbort ) {
-
-                                               var status,
-                                                       statusText,
-                                                       responseHeaders,
-                                                       responses,
-                                                       xml;
-
-                                               // Firefox throws exceptions when accessing properties
-                                               // of an xhr when a network error occurred
-                                               // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
-                                               try {
-
-                                                       // Was never called and is aborted or complete
-                                                       if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
-
-                                                               // Only called once
-                                                               callback = undefined;
-
-                                                               // Do not keep as active anymore
-                                                               if ( handle ) {
-                                                                       xhr.onreadystatechange = jQuery.noop;
-                                                                       if ( xhrOnUnloadAbort ) {
-                                                                               delete xhrCallbacks[ handle ];
-                                                                       }
-                                                               }
-
-                                                               // If it's an abort
-                                                               if ( isAbort ) {
-                                                                       // Abort it manually if needed
-                                                                       if ( xhr.readyState !== 4 ) {
-                                                                               xhr.abort();
-                                                                       }
-                                                               } else {
-                                                                       status = xhr.status;
-                                                                       responseHeaders = xhr.getAllResponseHeaders();
-                                                                       responses = {};
-                                                                       xml = xhr.responseXML;
-
-                                                                       // Construct response list
-                                                                       if ( xml && xml.documentElement /* #4958 */ ) {
-                                                                               responses.xml = xml;
-                                                                       }
-
-                                                                       // When requesting binary data, IE6-9 will throw an exception
-                                                                       // on any attempt to access responseText (#11426)
-                                                                       try {
-                                                                               responses.text = xhr.responseText;
-                                                                       } catch( e ) {
-                                                                       }
-
-                                                                       // Firefox throws an exception when accessing
-                                                                       // statusText for faulty cross-domain requests
-                                                                       try {
-                                                                               statusText = xhr.statusText;
-                                                                       } catch( e ) {
-                                                                               // We normalize with Webkit giving an empty statusText
-                                                                               statusText = "";
-                                                                       }
-
-                                                                       // Filter status for non standard behaviors
-
-                                                                       // If the request is local and we have data: assume a success
-                                                                       // (success with no data won't get notified, that's the best we
-                                                                       // can do given current implementations)
-                                                                       if ( !status && s.isLocal && !s.crossDomain ) {
-                                                                               status = responses.text ? 200 : 404;
-                                                                       // IE - #1450: sometimes returns 1223 when it should be 204
-                                                                       } else if ( status === 1223 ) {
-                                                                               status = 204;
-                                                                       }
-                                                               }
-                                                       }
-                                               } catch( firefoxAccessException ) {
-                                                       if ( !isAbort ) {
-                                                               complete( -1, firefoxAccessException );
-                                                       }
-                                               }
-
-                                               // Call complete if needed
-                                               if ( responses ) {
-                                                       complete( status, statusText, responses, responseHeaders );
-                                               }
-                                       };
-
-                                       if ( !s.async ) {
-                                               // if we're in sync mode we fire the callback
-                                               callback();
-                                       } else if ( xhr.readyState === 4 ) {
-                                               // (IE6 & IE7) if it's in cache and has been
-                                               // retrieved directly we need to fire the callback
-                                               setTimeout( callback, 0 );
-                                       } else {
-                                               handle = ++xhrId;
-                                               if ( xhrOnUnloadAbort ) {
-                                                       // Create the active xhrs callbacks list if needed
-                                                       // and attach the unload handler
-                                                       if ( !xhrCallbacks ) {
-                                                               xhrCallbacks = {};
-                                                               jQuery( window ).unload( xhrOnUnloadAbort );
-                                                       }
-                                                       // Add to list of active xhrs callbacks
-                                                       xhrCallbacks[ handle ] = callback;
-                                               }
-                                               xhr.onreadystatechange = callback;
-                                       }
-                               },
-
-                               abort: function() {
-                                       if ( callback ) {
-                                               callback(0,1);
-                                       }
-                               }
-                       };
-               }
-       });
-}
-var fxNow, timerId,
-       rfxtypes = /^(?:toggle|show|hide)$/,
-       rfxnum = new RegExp( "^(?:([-+])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
-       rrun = /queueHooks$/,
-       animationPrefilters = [ defaultPrefilter ],
-       tweeners = {
-               "*": [function( prop, value ) {
-                       var end, unit,
-                               tween = this.createTween( prop, value ),
-                               parts = rfxnum.exec( value ),
-                               target = tween.cur(),
-                               start = +target || 0,
-                               scale = 1,
-                               maxIterations = 20;
-
-                       if ( parts ) {
-                               end = +parts[2];
-                               unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
-
-                               // We need to compute starting value
-                               if ( unit !== "px" && start ) {
-                                       // Iteratively approximate from a nonzero starting point
-                                       // Prefer the current property, because this process will be trivial if it uses the same units
-                                       // Fallback to end or a simple constant
-                                       start = jQuery.css( tween.elem, prop, true ) || end || 1;
-
-                                       do {
-                                               // If previous iteration zeroed out, double until we get *something*
-                                               // Use a string for doubling factor so we don't accidentally see scale as unchanged below
-                                               scale = scale || ".5";
-
-                                               // Adjust and apply
-                                               start = start / scale;
-                                               jQuery.style( tween.elem, prop, start + unit );
-
-                                       // Update scale, tolerating zero or NaN from tween.cur()
-                                       // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
-                                       } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
-                               }
-
-                               tween.unit = unit;
-                               tween.start = start;
-                               // If a +=/-= token was provided, we're doing a relative animation
-                               tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
-                       }
-                       return tween;
-               }]
-       };
-
-// Animations created synchronously will run synchronously
-function createFxNow() {
-       setTimeout(function() {
-               fxNow = undefined;
-       }, 0 );
-       return ( fxNow = jQuery.now() );
-}
-
-function createTweens( animation, props ) {
-       jQuery.each( props, function( prop, value ) {
-               var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
-                       index = 0,
-                       length = collection.length;
-               for ( ; index < length; index++ ) {
-                       if ( collection[ index ].call( animation, prop, value ) ) {
-
-                               // we're done with this property
-                               return;
-                       }
-               }
-       });
-}
-
-function Animation( elem, properties, options ) {
-       var result,
-               index = 0,
-               tweenerIndex = 0,
-               length = animationPrefilters.length,
-               deferred = jQuery.Deferred().always( function() {
-                       // don't match elem in the :animated selector
-                       delete tick.elem;
-               }),
-               tick = function() {
-                       var currentTime = fxNow || createFxNow(),
-                               remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
-                               // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
-                               temp = remaining / animation.duration || 0,
-                               percent = 1 - temp,
-                               index = 0,
-                               length = animation.tweens.length;
-
-                       for ( ; index < length ; index++ ) {
-                               animation.tweens[ index ].run( percent );
-                       }
-
-                       deferred.notifyWith( elem, [ animation, percent, remaining ]);
-
-                       if ( percent < 1 && length ) {
-                               return remaining;
-                       } else {
-                               deferred.resolveWith( elem, [ animation ] );
-                               return false;
-                       }
-               },
-               animation = deferred.promise({
-                       elem: elem,
-                       props: jQuery.extend( {}, properties ),
-                       opts: jQuery.extend( true, { specialEasing: {} }, options ),
-                       originalProperties: properties,
-                       originalOptions: options,
-                       startTime: fxNow || createFxNow(),
-                       duration: options.duration,
-                       tweens: [],
-                       createTween: function( prop, end, easing ) {
-                               var tween = jQuery.Tween( elem, animation.opts, prop, end,
-                                               animation.opts.specialEasing[ prop ] || animation.opts.easing );
-                               animation.tweens.push( tween );
-                               return tween;
-                       },
-                       stop: function( gotoEnd ) {
-                               var index = 0,
-                                       // if we are going to the end, we want to run all the tweens
-                                       // otherwise we skip this part
-                                       length = gotoEnd ? animation.tweens.length : 0;
-
-                               for ( ; index < length ; index++ ) {
-                                       animation.tweens[ index ].run( 1 );
-                               }
-
-                               // resolve when we played the last frame
-                               // otherwise, reject
-                               if ( gotoEnd ) {
-                                       deferred.resolveWith( elem, [ animation, gotoEnd ] );
-                               } else {
-                                       deferred.rejectWith( elem, [ animation, gotoEnd ] );
-                               }
-                               return this;
-                       }
-               }),
-               props = animation.props;
-
-       propFilter( props, animation.opts.specialEasing );
-
-       for ( ; index < length ; index++ ) {
-               result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
-               if ( result ) {
-                       return result;
-               }
-       }
-
-       createTweens( animation, props );
-
-       if ( jQuery.isFunction( animation.opts.start ) ) {
-               animation.opts.start.call( elem, animation );
-       }
-
-       jQuery.fx.timer(
-               jQuery.extend( tick, {
-                       anim: animation,
-                       queue: animation.opts.queue,
-                       elem: elem
-               })
-       );
-
-       // attach callbacks from options
-       return animation.progress( animation.opts.progress )
-               .done( animation.opts.done, animation.opts.complete )
-               .fail( animation.opts.fail )
-               .always( animation.opts.always );
-}
-
-function propFilter( props, specialEasing ) {
-       var index, name, easing, value, hooks;
-
-       // camelCase, specialEasing and expand cssHook pass
-       for ( index in props ) {
-               name = jQuery.camelCase( index );
-               easing = specialEasing[ name ];
-               value = props[ index ];
-               if ( jQuery.isArray( value ) ) {
-                       easing = value[ 1 ];
-                       value = props[ index ] = value[ 0 ];
-               }
-
-               if ( index !== name ) {
-                       props[ name ] = value;
-                       delete props[ index ];
-               }
-
-               hooks = jQuery.cssHooks[ name ];
-               if ( hooks && "expand" in hooks ) {
-                       value = hooks.expand( value );
-                       delete props[ name ];
-
-                       // not quite $.extend, this wont overwrite keys already present.
-                       // also - reusing 'index' from above because we have the correct "name"
-                       for ( index in value ) {
-                               if ( !( index in props ) ) {
-                                       props[ index ] = value[ index ];
-                                       specialEasing[ index ] = easing;
-                               }
-                       }
-               } else {
-                       specialEasing[ name ] = easing;
-               }
-       }
-}
-
-jQuery.Animation = jQuery.extend( Animation, {
-
-       tweener: function( props, callback ) {
-               if ( jQuery.isFunction( props ) ) {
-                       callback = props;
-                       props = [ "*" ];
-               } else {
-                       props = props.split(" ");
-               }
-
-               var prop,
-                       index = 0,
-                       length = props.length;
-
-               for ( ; index < length ; index++ ) {
-                       prop = props[ index ];
-                       tweeners[ prop ] = tweeners[ prop ] || [];
-                       tweeners[ prop ].unshift( callback );
-               }
-       },
-
-       prefilter: function( callback, prepend ) {
-               if ( prepend ) {
-                       animationPrefilters.unshift( callback );
-               } else {
-                       animationPrefilters.push( callback );
-               }
-       }
-});
-
-function defaultPrefilter( elem, props, opts ) {
-       var index, prop, value, length, dataShow, toggle, tween, hooks, oldfire,
-               anim = this,
-               style = elem.style,
-               orig = {},
-               handled = [],
-               hidden = elem.nodeType && isHidden( elem );
-
-       // handle queue: false promises
-       if ( !opts.queue ) {
-               hooks = jQuery._queueHooks( elem, "fx" );
-               if ( hooks.unqueued == null ) {
-                       hooks.unqueued = 0;
-                       oldfire = hooks.empty.fire;
-                       hooks.empty.fire = function() {
-                               if ( !hooks.unqueued ) {
-                                       oldfire();
-                               }
-                       };
-               }
-               hooks.unqueued++;
-
-               anim.always(function() {
-                       // doing this makes sure that the complete handler will be called
-                       // before this completes
-                       anim.always(function() {
-                               hooks.unqueued--;
-                               if ( !jQuery.queue( elem, "fx" ).length ) {
-                                       hooks.empty.fire();
-                               }
-                       });
-               });
-       }
-
-       // height/width overflow pass
-       if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
-               // Make sure that nothing sneaks out
-               // Record all 3 overflow attributes because IE does not
-               // change the overflow attribute when overflowX and
-               // overflowY are set to the same value
-               opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
-
-               // Set display property to inline-block for height/width
-               // animations on inline elements that are having width/height animated
-               if ( jQuery.css( elem, "display" ) === "inline" &&
-                               jQuery.css( elem, "float" ) === "none" ) {
-
-                       // inline-level elements accept inline-block;
-                       // block-level elements need to be inline with layout
-                       if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
-                               style.display = "inline-block";
-
-                       } else {
-                               style.zoom = 1;
-                       }
-               }
-       }
-
-       if ( opts.overflow ) {
-               style.overflow = "hidden";
-               if ( !jQuery.support.shrinkWrapBlocks ) {
-                       anim.done(function() {
-                               style.overflow = opts.overflow[ 0 ];
-                               style.overflowX = opts.overflow[ 1 ];
-                               style.overflowY = opts.overflow[ 2 ];
-                       });
-               }
-       }
-
-
-       // show/hide pass
-       for ( index in props ) {
-               value = props[ index ];
-               if ( rfxtypes.exec( value ) ) {
-                       delete props[ index ];
-                       toggle = toggle || value === "toggle";
-                       if ( value === ( hidden ? "hide" : "show" ) ) {
-                               continue;
-                       }
-                       handled.push( index );
-               }
-       }
-
-       length = handled.length;
-       if ( length ) {
-               dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
-               if ( "hidden" in dataShow ) {
-                       hidden = dataShow.hidden;
-               }
-
-               // store state if its toggle - enables .stop().toggle() to "reverse"
-               if ( toggle ) {
-                       dataShow.hidden = !hidden;
-               }
-               if ( hidden ) {
-                       jQuery( elem ).show();
-               } else {
-                       anim.done(function() {
-                               jQuery( elem ).hide();
-                       });
-               }
-               anim.done(function() {
-                       var prop;
-                       jQuery.removeData( elem, "fxshow", true );
-                       for ( prop in orig ) {
-                               jQuery.style( elem, prop, orig[ prop ] );
-                       }
-               });
-               for ( index = 0 ; index < length ; index++ ) {
-                       prop = handled[ index ];
-                       tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
-                       orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
-
-                       if ( !( prop in dataShow ) ) {
-                               dataShow[ prop ] = tween.start;
-                               if ( hidden ) {
-                                       tween.end = tween.start;
-                                       tween.start = prop === "width" || prop === "height" ? 1 : 0;
-                               }
-                       }
-               }
-       }
-}
-
-function Tween( elem, options, prop, end, easing ) {
-       return new Tween.prototype.init( elem, options, prop, end, easing );
-}
-jQuery.Tween = Tween;
-
-Tween.prototype = {
-       constructor: Tween,
-       init: function( elem, options, prop, end, easing, unit ) {
-               this.elem = elem;
-               this.prop = prop;
-               this.easing = easing || "swing";
-               this.options = options;
-               this.start = this.now = this.cur();
-               this.end = end;
-               this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
-       },
-       cur: function() {
-               var hooks = Tween.propHooks[ this.prop ];
-
-               return hooks && hooks.get ?
-                       hooks.get( this ) :
-                       Tween.propHooks._default.get( this );
-       },
-       run: function( percent ) {
-               var eased,
-                       hooks = Tween.propHooks[ this.prop ];
-
-               if ( this.options.duration ) {
-                       this.pos = eased = jQuery.easing[ this.easing ](
-                               percent, this.options.duration * percent, 0, 1, this.options.duration
-                       );
-               } else {
-                       this.pos = eased = percent;
-               }
-               this.now = ( this.end - this.start ) * eased + this.start;
-
-               if ( this.options.step ) {
-                       this.options.step.call( this.elem, this.now, this );
-               }
-
-               if ( hooks && hooks.set ) {
-                       hooks.set( this );
-               } else {
-                       Tween.propHooks._default.set( this );
-               }
-               return this;
-       }
-};
-
-Tween.prototype.init.prototype = Tween.prototype;
-
-Tween.propHooks = {
-       _default: {
-               get: function( tween ) {
-                       var result;
-
-                       if ( tween.elem[ tween.prop ] != null &&
-                               (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
-                               return tween.elem[ tween.prop ];
-                       }
-
-                       // passing any value as a 4th parameter to .css will automatically
-                       // attempt a parseFloat and fallback to a string if the parse fails
-                       // so, simple values such as "10px" are parsed to Float.
-                       // complex values such as "rotate(1rad)" are returned as is.
-                       result = jQuery.css( tween.elem, tween.prop, false, "" );
-                       // Empty strings, null, undefined and "auto" are converted to 0.
-                       return !result || result === "auto" ? 0 : result;
-               },
-               set: function( tween ) {
-                       // use step hook for back compat - use cssHook if its there - use .style if its
-                       // available and use plain properties where available
-                       if ( jQuery.fx.step[ tween.prop ] ) {
-                               jQuery.fx.step[ tween.prop ]( tween );
-                       } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
-                               jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
-                       } else {
-                               tween.elem[ tween.prop ] = tween.now;
-                       }
-               }
-       }
-};
-
-// Remove in 2.0 - this supports IE8's panic based approach
-// to setting things on disconnected nodes
-
-Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
-       set: function( tween ) {
-               if ( tween.elem.nodeType && tween.elem.parentNode ) {
-                       tween.elem[ tween.prop ] = tween.now;
-               }
-       }
-};
-
-jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
-       var cssFn = jQuery.fn[ name ];
-       jQuery.fn[ name ] = function( speed, easing, callback ) {
-               return speed == null || typeof speed === "boolean" ||
-                       // special check for .toggle( handler, handler, ... )
-                       ( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ?
-                       cssFn.apply( this, arguments ) :
-                       this.animate( genFx( name, true ), speed, easing, callback );
-       };
-});
-
-jQuery.fn.extend({
-       fadeTo: function( speed, to, easing, callback ) {
-
-               // show any hidden elements after setting opacity to 0
-               return this.filter( isHidden ).css( "opacity", 0 ).show()
-
-                       // animate to the value specified
-                       .end().animate({ opacity: to }, speed, easing, callback );
-       },
-       animate: function( prop, speed, easing, callback ) {
-               var empty = jQuery.isEmptyObject( prop ),
-                       optall = jQuery.speed( speed, easing, callback ),
-                       doAnimation = function() {
-                               // Operate on a copy of prop so per-property easing won't be lost
-                               var anim = Animation( this, jQuery.extend( {}, prop ), optall );
-
-                               // Empty animations resolve immediately
-                               if ( empty ) {
-                                       anim.stop( true );
-                               }
-                       };
-
-               return empty || optall.queue === false ?
-                       this.each( doAnimation ) :
-                       this.queue( optall.queue, doAnimation );
-       },
-       stop: function( type, clearQueue, gotoEnd ) {
-               var stopQueue = function( hooks ) {
-                       var stop = hooks.stop;
-                       delete hooks.stop;
-                       stop( gotoEnd );
-               };
-
-               if ( typeof type !== "string" ) {
-                       gotoEnd = clearQueue;
-                       clearQueue = type;
-                       type = undefined;
-               }
-               if ( clearQueue && type !== false ) {
-                       this.queue( type || "fx", [] );
-               }
-
-               return this.each(function() {
-                       var dequeue = true,
-                               index = type != null && type + "queueHooks",
-                               timers = jQuery.timers,
-                               data = jQuery._data( this );
-
-                       if ( index ) {
-                               if ( data[ index ] && data[ index ].stop ) {
-                                       stopQueue( data[ index ] );
-                               }
-                       } else {
-                               for ( index in data ) {
-                                       if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
-                                               stopQueue( data[ index ] );
-                                       }
-                               }
-                       }
-
-                       for ( index = timers.length; index--; ) {
-                               if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
-                                       timers[ index ].anim.stop( gotoEnd );
-                                       dequeue = false;
-                                       timers.splice( index, 1 );
-                               }
-                       }
-
-                       // start the next in the queue if the last step wasn't forced
-                       // timers currently will call their complete callbacks, which will dequeue
-                       // but only if they were gotoEnd
-                       if ( dequeue || !gotoEnd ) {
-                               jQuery.dequeue( this, type );
-                       }
-               });
-       }
-});
-
-// Generate parameters to create a standard animation
-function genFx( type, includeWidth ) {
-       var which,
-               attrs = { height: type },
-               i = 0;
-
-       // if we include width, step value is 1 to do all cssExpand values,
-       // if we don't include width, step value is 2 to skip over Left and Right
-       includeWidth = includeWidth? 1 : 0;
-       for( ; i < 4 ; i += 2 - includeWidth ) {
-               which = cssExpand[ i ];
-               attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
-       }
-
-       if ( includeWidth ) {
-               attrs.opacity = attrs.width = type;
-       }
-
-       return attrs;
-}
-
-// Generate shortcuts for custom animations
-jQuery.each({
-       slideDown: genFx("show"),
-       slideUp: genFx("hide"),
-       slideToggle: genFx("toggle"),
-       fadeIn: { opacity: "show" },
-       fadeOut: { opacity: "hide" },
-       fadeToggle: { opacity: "toggle" }
-}, function( name, props ) {
-       jQuery.fn[ name ] = function( speed, easing, callback ) {
-               return this.animate( props, speed, easing, callback );
-       };
-});
-
-jQuery.speed = function( speed, easing, fn ) {
-       var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
-               complete: fn || !fn && easing ||
-                       jQuery.isFunction( speed ) && speed,
-               duration: speed,
-               easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
-       };
-
-       opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
-               opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
-
-       // normalize opt.queue - true/undefined/null -> "fx"
-       if ( opt.queue == null || opt.queue === true ) {
-               opt.queue = "fx";
-       }
-
-       // Queueing
-       opt.old = opt.complete;
-
-       opt.complete = function() {
-               if ( jQuery.isFunction( opt.old ) ) {
-                       opt.old.call( this );
-               }
-
-               if ( opt.queue ) {
-                       jQuery.dequeue( this, opt.queue );
-               }
-       };
-
-       return opt;
-};
-
-jQuery.easing = {
-       linear: function( p ) {
-               return p;
-       },
-       swing: function( p ) {
-               return 0.5 - Math.cos( p*Math.PI ) / 2;
-       }
-};
-
-jQuery.timers = [];
-jQuery.fx = Tween.prototype.init;
-jQuery.fx.tick = function() {
-       var timer,
-               timers = jQuery.timers,
-               i = 0;
-
-       fxNow = jQuery.now();
-
-       for ( ; i < timers.length; i++ ) {
-               timer = timers[ i ];
-               // Checks the timer has not already been removed
-               if ( !timer() && timers[ i ] === timer ) {
-                       timers.splice( i--, 1 );
-               }
-       }
-
-       if ( !timers.length ) {
-               jQuery.fx.stop();
-       }
-       fxNow = undefined;
-};
-
-jQuery.fx.timer = function( timer ) {
-       if ( timer() && jQuery.timers.push( timer ) && !timerId ) {
-               timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
-       }
-};
-
-jQuery.fx.interval = 13;
-
-jQuery.fx.stop = function() {
-       clearInterval( timerId );
-       timerId = null;
-};
-
-jQuery.fx.speeds = {
-       slow: 600,
-       fast: 200,
-       // Default speed
-       _default: 400
-};
-
-// Back Compat <1.8 extension point
-jQuery.fx.step = {};
-
-if ( jQuery.expr && jQuery.expr.filters ) {
-       jQuery.expr.filters.animated = function( elem ) {
-               return jQuery.grep(jQuery.timers, function( fn ) {
-                       return elem === fn.elem;
-               }).length;
-       };
-}
-var rroot = /^(?:body|html)$/i;
-
-jQuery.fn.offset = function( options ) {
-       if ( arguments.length ) {
-               return options === undefined ?
-                       this :
-                       this.each(function( i ) {
-                               jQuery.offset.setOffset( this, options, i );
-                       });
-       }
-
-       var docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft,
-               box = { top: 0, left: 0 },
-               elem = this[ 0 ],
-               doc = elem && elem.ownerDocument;
-
-       if ( !doc ) {
-               return;
-       }
-
-       if ( (body = doc.body) === elem ) {
-               return jQuery.offset.bodyOffset( elem );
-       }
-
-       docElem = doc.documentElement;
-
-       // Make sure it's not a disconnected DOM node
-       if ( !jQuery.contains( docElem, elem ) ) {
-               return box;
-       }
-
-       // If we don't have gBCR, just use 0,0 rather than error
-       // BlackBerry 5, iOS 3 (original iPhone)
-       if ( typeof elem.getBoundingClientRect !== "undefined" ) {
-               box = elem.getBoundingClientRect();
-       }
-       win = getWindow( doc );
-       clientTop  = docElem.clientTop  || body.clientTop  || 0;
-       clientLeft = docElem.clientLeft || body.clientLeft || 0;
-       scrollTop  = win.pageYOffset || docElem.scrollTop;
-       scrollLeft = win.pageXOffset || docElem.scrollLeft;
-       return {
-               top: box.top  + scrollTop  - clientTop,
-               left: box.left + scrollLeft - clientLeft
-       };
-};
-
-jQuery.offset = {
-
-       bodyOffset: function( body ) {
-               var top = body.offsetTop,
-                       left = body.offsetLeft;
-
-               if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
-                       top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
-                       left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
-               }
-
-               return { top: top, left: left };
-       },
-
-       setOffset: function( elem, options, i ) {
-               var position = jQuery.css( elem, "position" );
-
-               // set position first, in-case top/left are set even on static elem
-               if ( position === "static" ) {
-                       elem.style.position = "relative";
-               }
-
-               var curElem = jQuery( elem ),
-                       curOffset = curElem.offset(),
-                       curCSSTop = jQuery.css( elem, "top" ),
-                       curCSSLeft = jQuery.css( elem, "left" ),
-                       calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
-                       props = {}, curPosition = {}, curTop, curLeft;
-
-               // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
-               if ( calculatePosition ) {
-                       curPosition = curElem.position();
-                       curTop = curPosition.top;
-                       curLeft = curPosition.left;
-               } else {
-                       curTop = parseFloat( curCSSTop ) || 0;
-                       curLeft = parseFloat( curCSSLeft ) || 0;
-               }
-
-               if ( jQuery.isFunction( options ) ) {
-                       options = options.call( elem, i, curOffset );
-               }
-
-               if ( options.top != null ) {
-                       props.top = ( options.top - curOffset.top ) + curTop;
-               }
-               if ( options.left != null ) {
-                       props.left = ( options.left - curOffset.left ) + curLeft;
-               }
-
-               if ( "using" in options ) {
-                       options.using.call( elem, props );
-               } else {
-                       curElem.css( props );
-               }
-       }
-};
-
-
-jQuery.fn.extend({
-
-       position: function() {
-               if ( !this[0] ) {
-                       return;
-               }
-
-               var elem = this[0],
-
-               // Get *real* offsetParent
-               offsetParent = this.offsetParent(),
-
-               // Get correct offsets
-               offset       = this.offset(),
-               parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
-
-               // Subtract element margins
-               // note: when an element has margin: auto the offsetLeft and marginLeft
-               // are the same in Safari causing offset.left to incorrectly be 0
-               offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
-               offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
-
-               // Add offsetParent borders
-               parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
-               parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
-
-               // Subtract the two offsets
-               return {
-                       top:  offset.top  - parentOffset.top,
-                       left: offset.left - parentOffset.left
-               };
-       },
-
-       offsetParent: function() {
-               return this.map(function() {
-                       var offsetParent = this.offsetParent || document.body;
-                       while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
-                               offsetParent = offsetParent.offsetParent;
-                       }
-                       return offsetParent || document.body;
-               });
-       }
-});
-
-
-// Create scrollLeft and scrollTop methods
-jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
-       var top = /Y/.test( prop );
-
-       jQuery.fn[ method ] = function( val ) {
-               return jQuery.access( this, function( elem, method, val ) {
-                       var win = getWindow( elem );
-
-                       if ( val === undefined ) {
-                               return win ? (prop in win) ? win[ prop ] :
-                                       win.document.documentElement[ method ] :
-                                       elem[ method ];
-                       }
-
-                       if ( win ) {
-                               win.scrollTo(
-                                       !top ? val : jQuery( win ).scrollLeft(),
-                                        top ? val : jQuery( win ).scrollTop()
-                               );
-
-                       } else {
-                               elem[ method ] = val;
-                       }
-               }, method, val, arguments.length, null );
-       };
-});
-
-function getWindow( elem ) {
-       return jQuery.isWindow( elem ) ?
-               elem :
-               elem.nodeType === 9 ?
-                       elem.defaultView || elem.parentWindow :
-                       false;
-}
-// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
-jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
-       jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
-               // margin is only for outerHeight, outerWidth
-               jQuery.fn[ funcName ] = function( margin, value ) {
-                       var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
-                               extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
-
-                       return jQuery.access( this, function( elem, type, value ) {
-                               var doc;
-
-                               if ( jQuery.isWindow( elem ) ) {
-                                       // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
-                                       // isn't a whole lot we can do. See pull request at this URL for discussion:
-                                       // https://github.com/jquery/jquery/pull/764
-                                       return elem.document.documentElement[ "client" + name ];
-                               }
-
-                               // Get document width or height
-                               if ( elem.nodeType === 9 ) {
-                                       doc = elem.documentElement;
-
-                                       // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
-                                       // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
-                                       return Math.max(
-                                               elem.body[ "scroll" + name ], doc[ "scroll" + name ],
-                                               elem.body[ "offset" + name ], doc[ "offset" + name ],
-                                               doc[ "client" + name ]
-                                       );
-                               }
-
-                               return value === undefined ?
-                                       // Get width or height on the element, requesting but not forcing parseFloat
-                                       jQuery.css( elem, type, value, extra ) :
-
-                                       // Set width or height on the element
-                                       jQuery.style( elem, type, value, extra );
-                       }, type, chainable ? margin : undefined, chainable, null );
-               };
-       });
-});
-// Expose jQuery to the global object
-window.jQuery = window.$ = jQuery;
-
-// Expose jQuery as an AMD module, but only for AMD loaders that
-// understand the issues with loading multiple versions of jQuery
-// in a page that all might call define(). The loader will indicate
-// they have special allowances for multiple jQuery versions by
-// specifying define.amd.jQuery = true. Register as a named module,
-// since jQuery can be concatenated with other files that may use define,
-// but not use a proper concatenation script that understands anonymous
-// AMD modules. A named AMD is safest and most robust way to register.
-// Lowercase jquery is used because AMD module names are derived from
-// file names, and jQuery is normally delivered in a lowercase file name.
-// Do this after creating the global so that if an AMD module wants to call
-// noConflict to hide this version of jQuery, it will work.
-if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
-       define( "jquery", [], function () { return jQuery; } );
-}
-
-})( window );
diff --git a/resources/jquery/jquery.json.js b/resources/jquery/jquery.json.js
deleted file mode 100644 (file)
index 75953f4..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * jQuery JSON plugin 2.4.0
- *
- * @author Brantley Harris, 2009-2011
- * @author Timo Tijhof, 2011-2012
- * @source This plugin is heavily influenced by MochiKit's serializeJSON, which is
- *         copyrighted 2005 by Bob Ippolito.
- * @source Brantley Harris wrote this plugin. It is based somewhat on the JSON.org
- *         website's http://www.json.org/json2.js, which proclaims:
- *         "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that
- *         I uphold.
- * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
- */
-(function ($) {
-       'use strict';
-
-       var escape = /["\\\x00-\x1f\x7f-\x9f]/g,
-               meta = {
-                       '\b': '\\b',
-                       '\t': '\\t',
-                       '\n': '\\n',
-                       '\f': '\\f',
-                       '\r': '\\r',
-                       '"' : '\\"',
-                       '\\': '\\\\'
-               },
-               hasOwn = Object.prototype.hasOwnProperty;
-
-       /**
-        * jQuery.toJSON
-        * Converts the given argument into a JSON representation.
-        *
-        * @param o {Mixed} The json-serializable *thing* to be converted
-        *
-        * If an object has a toJSON prototype, that will be used to get the representation.
-        * Non-integer/string keys are skipped in the object, as are keys that point to a
-        * function.
-        *
-        */
-       $.toJSON = typeof JSON === 'object' && JSON.stringify ? JSON.stringify : function (o) {
-               if (o === null) {
-                       return 'null';
-               }
-
-               var pairs, k, name, val,
-                       type = $.type(o);
-
-               if (type === 'undefined') {
-                       return undefined;
-               }
-
-               // Also covers instantiated Number and Boolean objects,
-               // which are typeof 'object' but thanks to $.type, we
-               // catch them here. I don't know whether it is right
-               // or wrong that instantiated primitives are not
-               // exported to JSON as an {"object":..}.
-               // We choose this path because that's what the browsers did.
-               if (type === 'number' || type === 'boolean') {
-                       return String(o);
-               }
-               if (type === 'string') {
-                       return $.quoteString(o);
-               }
-               if (typeof o.toJSON === 'function') {
-                       return $.toJSON(o.toJSON());
-               }
-               if (type === 'date') {
-                       var month = o.getUTCMonth() + 1,
-                               day = o.getUTCDate(),
-                               year = o.getUTCFullYear(),
-                               hours = o.getUTCHours(),
-                               minutes = o.getUTCMinutes(),
-                               seconds = o.getUTCSeconds(),
-                               milli = o.getUTCMilliseconds();
-
-                       if (month < 10) {
-                               month = '0' + month;
-                       }
-                       if (day < 10) {
-                               day = '0' + day;
-                       }
-                       if (hours < 10) {
-                               hours = '0' + hours;
-                       }
-                       if (minutes < 10) {
-                               minutes = '0' + minutes;
-                       }
-                       if (seconds < 10) {
-                               seconds = '0' + seconds;
-                       }
-                       if (milli < 100) {
-                               milli = '0' + milli;
-                       }
-                       if (milli < 10) {
-                               milli = '0' + milli;
-                       }
-                       return '"' + year + '-' + month + '-' + day + 'T' +
-                               hours + ':' + minutes + ':' + seconds +
-                               '.' + milli + 'Z"';
-               }
-
-               pairs = [];
-
-               if ($.isArray(o)) {
-                       for (k = 0; k < o.length; k++) {
-                               pairs.push($.toJSON(o[k]) || 'null');
-                       }
-                       return '[' + pairs.join(',') + ']';
-               }
-
-               // Any other object (plain object, RegExp, ..)
-               // Need to do typeof instead of $.type, because we also
-               // want to catch non-plain objects.
-               if (typeof o === 'object') {
-                       for (k in o) {
-                               // Only include own properties,
-                               // Filter out inherited prototypes
-                               if (hasOwn.call(o, k)) {
-                                       // Keys must be numerical or string. Skip others
-                                       type = typeof k;
-                                       if (type === 'number') {
-                                               name = '"' + k + '"';
-                                       } else if (type === 'string') {
-                                               name = $.quoteString(k);
-                                       } else {
-                                               continue;
-                                       }
-                                       type = typeof o[k];
-
-                                       // Invalid values like these return undefined
-                                       // from toJSON, however those object members
-                                       // shouldn't be included in the JSON string at all.
-                                       if (type !== 'function' && type !== 'undefined') {
-                                               val = $.toJSON(o[k]);
-                                               pairs.push(name + ':' + val);
-                                       }
-                               }
-                       }
-                       return '{' + pairs.join(',') + '}';
-               }
-       };
-
-       /**
-        * jQuery.evalJSON
-        * Evaluates a given json string.
-        *
-        * @param str {String}
-        */
-       $.evalJSON = typeof JSON === 'object' && JSON.parse ? JSON.parse : function (str) {
-               /*jshint evil: true */
-               return eval('(' + str + ')');
-       };
-
-       /**
-        * jQuery.secureEvalJSON
-        * Evals JSON in a way that is *more* secure.
-        *
-        * @param str {String}
-        */
-       $.secureEvalJSON = typeof JSON === 'object' && JSON.parse ? JSON.parse : function (str) {
-               var filtered =
-                       str
-                       .replace(/\\["\\\/bfnrtu]/g, '@')
-                       .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
-                       .replace(/(?:^|:|,)(?:\s*\[)+/g, '');
-
-               if (/^[\],:{}\s]*$/.test(filtered)) {
-                       /*jshint evil: true */
-                       return eval('(' + str + ')');
-               }
-               throw new SyntaxError('Error parsing JSON, source is not valid.');
-       };
-
-       /**
-        * jQuery.quoteString
-        * Returns a string-repr of a string, escaping quotes intelligently.
-        * Mostly a support function for toJSON.
-        * Examples:
-        * >>> jQuery.quoteString('apple')
-        * "apple"
-        *
-        * >>> jQuery.quoteString('"Where are we going?", she asked.')
-        * "\"Where are we going?\", she asked."
-        */
-       $.quoteString = function (str) {
-               if (str.match(escape)) {
-                       return '"' + str.replace(escape, function (a) {
-                               var c = meta[a];
-                               if (typeof c === 'string') {
-                                       return c;
-                               }
-                               c = a.charCodeAt();
-                               return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
-                       }) + '"';
-               }
-               return '"' + str + '"';
-       };
-
-}(jQuery));
diff --git a/resources/jquery/jquery.localize.js b/resources/jquery/jquery.localize.js
deleted file mode 100644 (file)
index f499e10..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/**
- * @class jQuery.plugin.localize
- */
-( function ( $, mw ) {
-
-/**
- * Gets a localized message, using parameters from options if present.
- * @ignore
- *
- * @param {Object} options
- * @param {string} key
- * @return {string} Localized message
- */
-function msg( options, key ) {
-       var args = options.params[key] || [];
-       // Format: mw.msg( key [, p1, p2, ...] )
-       args.unshift( options.prefix + ( options.keys[key] || key ) );
-       return mw.msg.apply( mw, args );
-}
-
-/**
- * Localizes a DOM selection by replacing <html:msg /> elements with localized text and adding
- * localized title and alt attributes to elements with title-msg and alt-msg attributes
- * respectively.
- *
- * Call on a selection of HTML which contains `<html:msg key="message-key" />` elements or elements
- * with title-msg="message-key", alt-msg="message-key" or placeholder-msg="message-key" attributes.
- * `<html:msg />` elements will be replaced with localized text, *-msg attributes will be replaced
- * with attributes that do not have the "-msg" suffix and contain a localized message.
- *
- * Example:
- *     // Messages: { 'title': 'Awesome', 'desc': 'Cat doing backflip' 'search' contains 'Search' }
- *     var html = '\
- *         <p>\
- *             <html:msg key="title" />\
- *             <img src="something.jpg" title-msg="title" alt-msg="desc" />\
- *             <input type="text" placeholder-msg="search" />\
- *         </p>';
- *     $( 'body' ).append( $( html ).localize() );
- *
- * Appends something like this to the body...
- *     <p>
- *         Awesome
- *         <img src="something.jpg" title="Awesome" alt="Cat doing backflip" />
- *         <input type="text" placeholder="Search" />
- *     </p>
- *
- * Arguments can be passed into uses of a message using the params property of the options object
- * given to .localize(). Multiple messages can be given parameters, because the params property is
- * an object keyed by the message key to apply the parameters to, each containing an array of
- * parameters to use. The limitation is that you can not use different parameters to individual uses
- * of a message in the same selection being localized - they will all recieve the same parameters.
- *
- * Example:
- *     // Messages: { 'easy-as': 'Easy as $1 $2 $3.' }
- *     var html = '<p><html:msg key="easy-as" /></p>';
- *     $( 'body' ).append( $( html ).localize( { 'params': { 'easy-as': ['a', 'b', 'c'] } } ) );
- *
- * Appends something like this to the body...
- *     <p>Easy as a, b, c</p>
- *
- * Raw HTML content can be used, instead of it being escaped as text. To do this, just use the raw
- * attribute on a msg element.
- *
- * Example:
- *     // Messages: { 'hello': '<b><i>Hello</i> $1!</b>' }
- *     var html = '\
- *         <p>\
- *             <!-- escaped: --><html:msg key="hello" />\
- *             <!-- raw: --><html:msg key="hello" raw />\
- *         </p>';
- *     $( 'body' ).append( $( html ).localize( { 'params': { 'hello': ['world'] } } ) );
- *
- * Appends something like this to the body...
- *     <p>
- *         <!-- escaped: -->&lt;b&gt;&lt;i&gt;Hello&lt;/i&gt; world!&lt;/b&gt;
- *         <!-- raw: --><b><i>Hello</i> world!</b>
- *     </p>
- *
- * Message keys can also be remapped, allowing the same generic template to be used with a variety
- * of messages. This is important for improving re-usability of templates.
- *
- * Example:
- *     // Messages: { 'good-afternoon': 'Good afternoon' }
- *     var html = '<p><html:msg key="greeting" /></p>';
- *     $( 'body' ).append( $( html ).localize( { 'keys': { 'greeting': 'good-afternoon' } } ) );
- *
- * Appends something like this to the body...
- *     <p>Good afternoon</p>
- *
- * Message keys can also be prefixed globally, which is handy when writing extensions, where by
- * convention all messages are prefixed with the extension's name.
- *
- * Example:
- *     // Messages: { 'teleportation-warning': 'You may not get there all in one piece.' }
- *     var html = '<p><html:msg key="warning" /></p>';
- *     $( 'body' ).append( $( html ).localize( { 'prefix': 'teleportation-' } ) );
- *
- * Appends something like this to the body...
- *     <p>You may not get there all in one piece.</p>
- *
- * @param {Object} options Map of options to be used while localizing
- * @param {string} options.prefix String to prepend to all message keys
- * @param {Object} options.keys Message key aliases, used for remapping keys to a template
- * @param {Object} options.params Lists of parameters to use with certain message keys
- * @return {jQuery}
- * @chainable
- */
-$.fn.localize = function ( options ) {
-       var $target = this,
-               attributes = ['title', 'alt', 'placeholder'];
-
-       // Extend options
-       options = $.extend( {
-               prefix: '',
-               keys: {},
-               params: {}
-       }, options );
-
-       // Elements
-       // Ok, so here's the story on this selector. In IE 6/7, searching for 'msg' turns up the
-       // 'html:msg', but searching for 'html:msg' doesn't. In later IE and other browsers, searching
-       // for 'html:msg' turns up the 'html:msg', but searching for 'msg' doesn't. So searching for
-       // both 'msg' and 'html:msg' seems to get the job done. This feels pretty icky, though.
-       $target.find( 'msg,html\\:msg' ).each( function () {
-               var $el = $(this);
-               // Escape by default
-               if ( $el.attr( 'raw' ) ) {
-                       $el.html( msg( options, $el.attr( 'key' ) ) );
-               } else {
-                       $el.text( msg( options, $el.attr( 'key' ) ) );
-               }
-               // Remove wrapper
-               $el.replaceWith( $el.html() );
-       } );
-
-       // Attributes
-       // Note: there's no way to prevent escaping of values being injected into attributes, this is
-       // on purpose, not a design flaw.
-       $.each( attributes, function ( i, attr ) {
-               var msgAttr = attr + '-msg';
-               $target.find( '[' + msgAttr + ']' ).each( function () {
-                       var $el = $(this);
-                       $el.attr( attr, msg( options, $el.attr( msgAttr ) ) ).removeAttr( msgAttr );
-               } );
-       } );
-
-       // HTML, Text for elements which cannot have children e.g. OPTION
-       $target.find( '[data-msg-text]' ).each( function () {
-               var $el = $( this );
-               $el.text( msg( options, $el.attr( 'data-msg-text' ) ) );
-       } );
-
-       $target.find( '[data-msg-html]' ).each( function () {
-               var $el = $( this );
-               $el.html( msg( options, $el.attr( 'data-msg-html' ) ) );
-       } );
-
-       return $target;
-};
-
-// Let IE know about the msg tag before it's used...
-document.createElement( 'msg' );
-
-/**
- * @class jQuery
- * @mixins jQuery.plugin.localize
- */
-
-}( jQuery, mediaWiki ) );
diff --git a/resources/jquery/jquery.makeCollapsible.css b/resources/jquery/jquery.makeCollapsible.css
deleted file mode 100644 (file)
index 55ea7c9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* See also jquery.makeCollapsible.js */
-.mw-collapsible-toggle {
-       float: right;
-       -moz-user-select: none;
-       -webkit-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
-}
-
-/* collapse links in captions should be inline */
-caption .mw-collapsible-toggle {
-       float: none;
-}
-
-/* list-items go as wide as their parent element, don't float them inside list items */
-li .mw-collapsible-toggle {
-       float: none;
-}
-
-/* the added list item should have no list-style */
-.mw-collapsible-toggle-li {
-       list-style: none;
-}
diff --git a/resources/jquery/jquery.makeCollapsible.js b/resources/jquery/jquery.makeCollapsible.js
deleted file mode 100644 (file)
index 01fde4c..0000000
+++ /dev/null
@@ -1,394 +0,0 @@
-/**
- * jQuery makeCollapsible
- *
- * This will enable collapsible-functionality on all passed elements.
- * - Will prevent binding twice to the same element.
- * - Initial state is expanded by default, this can be overriden by adding class
- *   "mw-collapsed" to the "mw-collapsible" element.
- * - Elements made collapsible have jQuery data "mw-made-collapsible" set to true.
- * - The inner content is wrapped in a "div.mw-collapsible-content" (except for tables and lists).
- *
- * @author Krinkle, 2011-2012
- *
- * Dual license:
- * @license CC BY 3.0 <http://creativecommons.org/licenses/by/3.0>
- * @license GPL2 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
- */
-( function ( $, mw ) {
-       /**
-        * Handler for a click on a collapsible toggler.
-        *
-        * @param {jQuery} $collapsible
-        * @param {string} action The action this function will take ('expand' or 'collapse').
-        * @param {jQuery|null} [optional] $defaultToggle
-        * @param {Object|undefined} options
-        */
-       function toggleElement( $collapsible, action, $defaultToggle, options ) {
-               var $collapsibleContent, $containers, hookCallback;
-               options = options || {};
-
-               // Validate parameters
-
-               // $collapsible must be an instance of jQuery
-               if ( !$collapsible.jquery ) {
-                       return;
-               }
-               if ( action !== 'expand' && action !== 'collapse' ) {
-                       // action must be string with 'expand' or 'collapse'
-                       return;
-               }
-               if ( $defaultToggle === undefined ) {
-                       $defaultToggle = null;
-               }
-               if ( $defaultToggle !== null && !$defaultToggle.jquery ) {
-                       // is optional (may be undefined), but if defined it must be an instance of jQuery.
-                       // If it's not, abort right away.
-                       // After this $defaultToggle is either null or a valid jQuery instance.
-                       return;
-               }
-
-               // Trigger a custom event to allow callers to hook to the collapsing/expanding,
-               // allowing the module to be testable, and making it possible to
-               // e.g. implement persistence via cookies
-               $collapsible.trigger( action === 'expand' ? 'beforeExpand.mw-collapsible' : 'beforeCollapse.mw-collapsible' );
-               hookCallback = function () {
-                       $collapsible.trigger( action === 'expand' ? 'afterExpand.mw-collapsible' : 'afterCollapse.mw-collapsible' );
-               };
-
-               // Handle different kinds of elements
-
-               if ( !options.plainMode && $collapsible.is( 'table' ) ) {
-                       // Tables
-                       // If there is a caption, hide all rows; otherwise, only hide body rows
-                       if ( $collapsible.find( '> caption' ).length ) {
-                               $containers = $collapsible.find( '> * > tr' );
-                       } else {
-                               $containers = $collapsible.find( '> tbody > tr' );
-                       }
-                       if ( $defaultToggle ) {
-                               // Exclude table row containing togglelink
-                               $containers = $containers.not( $defaultToggle.closest( 'tr' ) );
-                       }
-
-                       if ( action === 'collapse' ) {
-                               // Hide all table rows of this table
-                               // Slide doesn't work with tables, but fade does as of jQuery 1.1.3
-                               // http://stackoverflow.com/questions/467336#920480
-                               if ( options.instantHide ) {
-                                       $containers.hide();
-                                       hookCallback();
-                               } else {
-                                       $containers.stop( true, true ).fadeOut().promise().done( hookCallback );
-                               }
-                       } else {
-                               $containers.stop( true, true ).fadeIn().promise().done( hookCallback );
-                       }
-
-               } else if ( !options.plainMode && ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) ) {
-                       // Lists
-                       $containers = $collapsible.find( '> li' );
-                       if ( $defaultToggle ) {
-                               // Exclude list-item containing togglelink
-                               $containers = $containers.not( $defaultToggle.parent() );
-                       }
-
-                       if ( action === 'collapse' ) {
-                               if ( options.instantHide ) {
-                                       $containers.hide();
-                                       hookCallback();
-                               } else {
-                                       $containers.stop( true, true ).slideUp().promise().done( hookCallback );
-                               }
-                       } else {
-                               $containers.stop( true, true ).slideDown().promise().done( hookCallback );
-                       }
-
-               } else {
-                       // Everything else: <div>, <p> etc.
-                       $collapsibleContent = $collapsible.find( '> .mw-collapsible-content' );
-
-                       // If a collapsible-content is defined, act on it
-                       if ( !options.plainMode && $collapsibleContent.length ) {
-                               if ( action === 'collapse' ) {
-                                       if ( options.instantHide ) {
-                                               $collapsibleContent.hide();
-                                               hookCallback();
-                                       } else {
-                                               $collapsibleContent.slideUp().promise().done( hookCallback );
-                                       }
-                               } else {
-                                       $collapsibleContent.slideDown().promise().done( hookCallback );
-                               }
-
-                       // Otherwise assume this is a customcollapse with a remote toggle
-                       // .. and there is no collapsible-content because the entire element should be toggled
-                       } else {
-                               if ( action === 'collapse' ) {
-                                       if ( options.instantHide ) {
-                                               $collapsible.hide();
-                                               hookCallback();
-                                       } else {
-                                               if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
-                                                       $collapsible.fadeOut().promise().done( hookCallback );
-                                               } else {
-                                                       $collapsible.slideUp().promise().done( hookCallback );
-                                               }
-                                       }
-                               } else {
-                                       if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
-                                               $collapsible.fadeIn().promise().done( hookCallback );
-                                       } else {
-                                               $collapsible.slideDown().promise().done( hookCallback );
-                                       }
-                               }
-                       }
-               }
-       }
-
-       /**
-        * Handles clicking/keypressing on the collapsible element toggle and other
-        * situations where a collapsible element is toggled (e.g. the initial
-        * toggle for collapsed ones).
-        *
-        * @param {jQuery} $toggle the clickable toggle itself
-        * @param {jQuery} $collapsible the collapsible element
-        * @param {jQuery.Event|null} e either the event or null if unavailable
-        * @param {Object|undefined} options
-        */
-       function togglingHandler( $toggle, $collapsible, e, options ) {
-               var wasCollapsed, $textContainer, collapseText, expandText;
-
-               if ( options === undefined ) {
-                       options = {};
-               }
-
-               if ( e ) {
-                       if ( e.type === 'click' && options.linksPassthru && $.nodeName( e.target, 'a' ) ) {
-                               // Don't fire if a link was clicked, if requested  (for premade togglers by default)
-                               return;
-                       } else if ( e.type === 'keypress' && e.which !== 13 && e.which !== 32 ) {
-                               // Only handle keypresses on the "Enter" or "Space" keys
-                               return;
-                       } else {
-                               e.preventDefault();
-                               e.stopPropagation();
-                       }
-               }
-
-               // This allows the element to be hidden on initial toggle without fiddling with the class
-               if ( options.wasCollapsed !== undefined ) {
-                       wasCollapsed = options.wasCollapsed;
-               } else {
-                       wasCollapsed = $collapsible.hasClass( 'mw-collapsed' );
-               }
-
-               // Toggle the state of the collapsible element (that is, expand or collapse)
-               $collapsible.toggleClass( 'mw-collapsed', !wasCollapsed );
-
-               // Toggle the mw-collapsible-toggle classes, if requested (for default and premade togglers by default)
-               if ( options.toggleClasses ) {
-                       $toggle
-                               .toggleClass( 'mw-collapsible-toggle-collapsed', !wasCollapsed )
-                               .toggleClass( 'mw-collapsible-toggle-expanded', wasCollapsed );
-               }
-
-               // Toggle the text ("Show"/"Hide"), if requested (for default togglers by default)
-               if ( options.toggleText ) {
-                       collapseText = options.toggleText.collapseText;
-                       expandText = options.toggleText.expandText;
-
-                       $textContainer = $toggle.find( '> a' );
-                       if ( !$textContainer.length ) {
-                               $textContainer = $toggle;
-                       }
-                       $textContainer.text( wasCollapsed ? collapseText : expandText );
-               }
-
-               // And finally toggle the element state itself
-               toggleElement( $collapsible, wasCollapsed ? 'expand' : 'collapse', $toggle, options );
-       }
-
-       /**
-        * Make any element collapsible.
-        *
-        * Supported options:
-        * - collapseText: text to be used for the toggler when clicking it would
-        *   collapse the element. Default: the 'data-collapsetext' attribute of
-        *   the collapsible element or the content of 'collapsible-collapse'
-        *   message.
-        * - expandText: text to be used for the toggler when clicking it would
-        *   expand the element. Default: the 'data-expandtext' attribute of
-        *   the collapsible element or the content of 'collapsible-expand'
-        *   message.
-        * - collapsed: boolean, whether to collapse immediately. By default
-        *   collapse only if the elements has the 'mw-collapsible' class.
-        * - $customTogglers: jQuerified list of elements to be used as togglers
-        *   for this collapsible element. By default, if the collapsible element
-        *   has an id attribute like 'mw-customcollapsible-XXX', elements with a
-        *   *class* of 'mw-customtoggle-XXX' are made togglers for it.
-        * - plainMode: boolean, whether to use a "plain mode" when making the
-        *   element collapsible - that is, hide entire tables and lists (instead
-        *   of hiding only all rows but first of tables, and hiding each list
-        *   item separately for lists) and don't wrap other elements in
-        *   div.mw-collapsible-content. May only be used with custom togglers.
-        */
-       $.fn.makeCollapsible = function ( options ) {
-               if ( options === undefined ) {
-                       options = {};
-               }
-
-               return this.each( function () {
-                       var $collapsible, collapseText, expandText, $caption, $toggle, actionHandler, buildDefaultToggleLink,
-                               premadeToggleHandler, $toggleLink, $firstItem, collapsibleId, $customTogglers, firstval;
-
-                       // Ensure class "mw-collapsible" is present in case .makeCollapsible()
-                       // is called on element(s) that don't have it yet.
-                       $collapsible = $( this ).addClass( 'mw-collapsible' );
-
-                       // Return if it has been enabled already.
-                       if ( $collapsible.data( 'mw-made-collapsible' ) ) {
-                               return;
-                       } else {
-                               $collapsible.data( 'mw-made-collapsible', true );
-                       }
-
-                       // Use custom text or default?
-                       collapseText = options.collapseText || $collapsible.attr( 'data-collapsetext' ) || mw.msg( 'collapsible-collapse' );
-                       expandText = options.expandText || $collapsible.attr( 'data-expandtext' ) || mw.msg( 'collapsible-expand' );
-
-                       // Default click/keypress handler and toggle link to use when none is present
-                       actionHandler = function ( e, opts ) {
-                               var defaultOpts = {
-                                       toggleClasses: true,
-                                       toggleText: { collapseText: collapseText, expandText: expandText }
-                               };
-                               opts = $.extend( defaultOpts, options, opts );
-                               togglingHandler( $( this ), $collapsible, e, opts );
-                       };
-                       // Default toggle link. Only build it when needed to avoid jQuery memory leaks (event data).
-                       buildDefaultToggleLink = function () {
-                               return $( '<a href="#"></a>' )
-                                       .text( collapseText )
-                                       .wrap( '<span class="mw-collapsible-toggle"></span>' )
-                                               .parent()
-                                               .prepend( '&nbsp;[' )
-                                               .append( ']&nbsp;' )
-                                               .on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
-                       };
-
-                       // Default handler for clicking on premade toggles
-                       premadeToggleHandler = function ( e, opts ) {
-                               var defaultOpts = { toggleClasses: true, linksPassthru: true };
-                               opts = $.extend( defaultOpts, options, opts );
-                               togglingHandler( $( this ), $collapsible, e, opts );
-                       };
-
-                       // Check if this element has a custom position for the toggle link
-                       // (ie. outside the container or deeper inside the tree)
-                       if ( options.$customTogglers ) {
-                               $customTogglers = $( options.$customTogglers );
-                       } else {
-                               collapsibleId = $collapsible.attr( 'id' ) || '';
-                               if ( collapsibleId.indexOf( 'mw-customcollapsible-' ) === 0 ) {
-                                       $customTogglers = $( '.' + collapsibleId.replace( 'mw-customcollapsible', 'mw-customtoggle' ) );
-                               }
-                       }
-
-                       // Add event handlers to custom togglers or create our own ones
-                       if ( $customTogglers && $customTogglers.length ) {
-                               actionHandler = function ( e, opts ) {
-                                       var defaultOpts = {};
-                                       opts = $.extend( defaultOpts, options, opts );
-                                       togglingHandler( $( this ), $collapsible, e, opts );
-                               };
-
-                               $toggleLink = $customTogglers;
-                               $toggleLink.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
-
-                       } else {
-                               // If this is not a custom case, do the default: wrap the
-                               // contents and add the toggle link. Different elements are
-                               // treated differently.
-                               if ( $collapsible.is( 'table' ) ) {
-
-                                       // If the table has a caption, collapse to the caption
-                                       // as opposed to the first row
-                                       $caption = $collapsible.find( '> caption' );
-                                       if ( $caption.length ) {
-                                               $toggle = $caption.find( '> .mw-collapsible-toggle' );
-
-                                               // If there is no toggle link, add it to the end of the caption
-                                               if ( !$toggle.length ) {
-                                                       $toggleLink = buildDefaultToggleLink().appendTo( $caption );
-                                               } else {
-                                                       actionHandler = premadeToggleHandler;
-                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
-                                               }
-                                       } else {
-                                               // The toggle-link will be in one the the cells (td or th) of the first row
-                                               $firstItem = $collapsible.find( 'tr:first th, tr:first td' );
-                                               $toggle = $firstItem.find( '> .mw-collapsible-toggle' );
-
-                                               // If theres no toggle link, add it to the last cell
-                                               if ( !$toggle.length ) {
-                                                       $toggleLink = buildDefaultToggleLink().prependTo( $firstItem.eq( -1 ) );
-                                               } else {
-                                                       actionHandler = premadeToggleHandler;
-                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
-                                               }
-                                       }
-
-                               } else if ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) {
-                                       // The toggle-link will be in the first list-item
-                                       $firstItem = $collapsible.find( 'li:first' );
-                                       $toggle = $firstItem.find( '> .mw-collapsible-toggle' );
-
-                                       // If theres no toggle link, add it
-                                       if ( !$toggle.length ) {
-                                               // Make sure the numeral order doesn't get messed up, force the first (soon to be second) item
-                                               // to be "1". Except if the value-attribute is already used.
-                                               // If no value was set WebKit returns "", Mozilla returns '-1', others return 0, null or undefined.
-                                               firstval = $firstItem.attr( 'value' );
-                                               if ( firstval === undefined || !firstval || firstval === '-1' || firstval === -1 ) {
-                                                       $firstItem.attr( 'value', '1' );
-                                               }
-                                               $toggleLink = buildDefaultToggleLink();
-                                               $toggleLink.wrap( '<li class="mw-collapsible-toggle-li"></li>' ).parent().prependTo( $collapsible );
-                                       } else {
-                                               actionHandler = premadeToggleHandler;
-                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
-                                       }
-
-                               } else { // <div>, <p> etc.
-
-                                       // The toggle-link will be the first child of the element
-                                       $toggle = $collapsible.find( '> .mw-collapsible-toggle' );
-
-                                       // If a direct child .content-wrapper does not exists, create it
-                                       if ( !$collapsible.find( '> .mw-collapsible-content' ).length ) {
-                                               $collapsible.wrapInner( '<div class="mw-collapsible-content"></div>' );
-                                       }
-
-                                       // If theres no toggle link, add it
-                                       if ( !$toggle.length ) {
-                                               $toggleLink = buildDefaultToggleLink().prependTo( $collapsible );
-                                       } else {
-                                               actionHandler = premadeToggleHandler;
-                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
-                                       }
-                               }
-                       }
-
-                       // Attributes for accessibility. This isn't necessary when the toggler is already
-                       // an <a> or a <button> etc., but it doesn't hurt either, and it's consistent.
-                       $toggleLink.prop( 'tabIndex', 0 );
-
-                       // Initial state
-                       if ( options.collapsed || $collapsible.hasClass( 'mw-collapsed' ) ) {
-                               // One toggler can hook to multiple elements, and one element can have
-                               // multiple togglers. This is the sanest way to handle that.
-                               actionHandler.call( $toggleLink.get( 0 ), null, { instantHide: true, wasCollapsed: false } );
-                       }
-               } );
-       };
-}( jQuery, mediaWiki ) );
diff --git a/resources/jquery/jquery.mockjax.js b/resources/jquery/jquery.mockjax.js
deleted file mode 100644 (file)
index 5f6e130..0000000
+++ /dev/null
@@ -1,382 +0,0 @@
-/*!
- * MockJax - jQuery Plugin to Mock Ajax requests
- *
- * Version:  1.4.0
- * Released: 2011-02-04
- * Source:   http://github.com/appendto/jquery-mockjax
- * Docs:     http://enterprisejquery.com/2010/07/mock-your-ajax-requests-with-mockjax-for-rapid-development
- * Plugin:   mockjax
- * Author:   Jonathan Sharp (http://jdsharp.com)
- * License:  MIT,GPL
- * 
- * Copyright (c) 2010 appendTo LLC.
- * Dual licensed under the MIT or GPL licenses.
- * http://appendto.com/open-source-licenses
- */
-(function($) {
-       var _ajax = $.ajax,
-               mockHandlers = [];
-       
-       function parseXML(xml) {
-               if ( window['DOMParser'] == undefined && window.ActiveXObject ) {
-                       DOMParser = function() { };
-                       DOMParser.prototype.parseFromString = function( xmlString ) {
-                               var doc = new ActiveXObject('Microsoft.XMLDOM');
-                       doc.async = 'false';
-                       doc.loadXML( xmlString );
-                               return doc;
-                       };
-               }
-               
-               try {
-                       var xmlDoc      = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
-                       if ( $.isXMLDoc( xmlDoc ) ) {
-                               var err = $('parsererror', xmlDoc);
-                               if ( err.length == 1 ) {
-                                       throw('Error: ' + $(xmlDoc).text() );
-                               }
-                       } else {
-                               throw('Unable to parse XML');
-                       }
-               } catch( e ) {
-                       var msg = ( e.name == undefined ? e : e.name + ': ' + e.message );
-                       $(document).trigger('xmlParseError', [ msg ]);
-                       return undefined;
-               }
-               return xmlDoc;
-       }
-       
-       $.extend({
-               ajax: function(origSettings) {
-                       var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings),
-                           mock = false;
-                       // Iterate over our mock handlers (in registration order) until we find
-                       // one that is willing to intercept the request
-                       $.each(mockHandlers, function(k, v) {
-                               if ( !mockHandlers[k] ) {
-                                       return;
-                               }
-                               var m = null;
-                               // If the mock was registered with a function, let the function decide if we 
-                               // want to mock this request
-                               if ( $.isFunction(mockHandlers[k]) ) {
-                                       m = mockHandlers[k](s);
-                               } else {
-                                       m = mockHandlers[k];
-                                       // Inspect the URL of the request and check if the mock handler's url 
-                                       // matches the url for this ajax request
-                                       if ( $.isFunction(m.url.test) ) {
-                                               // The user provided a regex for the url, test it
-                                               if ( !m.url.test( s.url ) ) {
-                                                       m = null;
-                                               }
-                                       } else {
-                                               // Look for a simple wildcard '*' or a direct URL match
-                                               var star = m.url.indexOf('*');
-                                               if ( ( m.url != '*' && m.url != s.url && star == -1 ) ||
-                                                       ( star > -1 && m.url.substr(0, star) != s.url.substr(0, star) ) ) {
-                                                        // The url we tested did not match the wildcard *
-                                                        m = null;
-                                               }
-                                       }
-                                       if ( m ) {
-                                               // Inspect the data submitted in the request (either POST body or GET query string)
-                                               if ( m.data && s.data ) {
-                                                       var identical = false;
-                                                       // Deep inspect the identity of the objects
-                                                       (function ident(mock, live) {
-                                                               // Test for situations where the data is a querystring (not an object)
-                                                               if (typeof live === 'string') {
-                                                                       // Querystring may be a regex
-                                                                       identical = $.isFunction( mock.test ) ? mock.test(live) : mock == live;
-                                                                       return identical;
-                                                               }
-                                                               $.each(mock, function(k, v) {
-                                                                       if ( live[k] === undefined ) {
-                                                                               identical = false;
-                                                                               return false;
-                                                                       } else {
-                                                                               identical = true;
-                                                                               if ( typeof live[k] == 'object' ) {
-                                                                                       return ident(mock[k], live[k]);
-                                                                               } else {
-                                                                                       if ( $.isFunction( mock[k].test ) ) {
-                                                                                               identical = mock[k].test(live[k]);
-                                                                                       } else {
-                                                                                               identical = ( mock[k] == live[k] );
-                                                                                       }
-                                                                                       return identical;
-                                                                               }
-                                                                       }
-                                                               });
-                                                       })(m.data, s.data);
-                                                       // They're not identical, do not mock this request
-                                                       if ( identical == false ) {
-                                                               m = null;
-                                                       }
-                                               }
-                                               // Inspect the request type
-                                               if ( m && m.type && m.type != s.type ) {
-                                                       // The request type doesn't match (GET vs. POST)
-                                                       m = null;
-                                               }
-                                       }
-                               }
-                               if ( m ) {
-                                       mock = true;
-
-                                       // Handle console logging
-                                       var c = $.extend({}, $.mockjaxSettings, m);
-                                       if ( c.log && $.isFunction(c.log) ) {
-                                               c.log('MOCK ' + s.type.toUpperCase() + ': ' + s.url, $.extend({}, s));
-                                       }
-                                       
-                                       var jsre = /=\?(&|$)/, jsc = (new Date()).getTime();
-
-                                       // Handle JSONP Parameter Callbacks, we need to replicate some of the jQuery core here
-                                       // because there isn't an easy hook for the cross domain script tag of jsonp
-                                       if ( s.dataType === "jsonp" ) {
-                                               if ( s.type.toUpperCase() === "GET" ) {
-                                                       if ( !jsre.test( s.url ) ) {
-                                                               s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
-                                                       }
-                                               } else if ( !s.data || !jsre.test(s.data) ) {
-                                                       s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
-                                               }
-                                               s.dataType = "json";
-                                       }
-                       
-                                       // Build temporary JSONP function
-                                       if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
-                                               jsonp = s.jsonpCallback || ("jsonp" + jsc++);
-                       
-                                               // Replace the =? sequence both in the query string and the data
-                                               if ( s.data ) {
-                                                       s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
-                                               }
-                       
-                                               s.url = s.url.replace(jsre, "=" + jsonp + "$1");
-                       
-                                               // We need to make sure
-                                               // that a JSONP style response is executed properly
-                                               s.dataType = "script";
-                       
-                                               // Handle JSONP-style loading
-                                               window[ jsonp ] = window[ jsonp ] || function( tmp ) {
-                                                       data = tmp;
-                                                       success();
-                                                       complete();
-                                                       // Garbage collect
-                                                       window[ jsonp ] = undefined;
-                       
-                                                       try {
-                                                               delete window[ jsonp ];
-                                                       } catch(e) {}
-                       
-                                                       if ( head ) {
-                                                               head.removeChild( script );
-                                                       }
-                                               };
-                                       }
-                                       
-                                       var rurl = /^(\w+:)?\/\/([^\/?#]+)/,
-                                               parts = rurl.exec( s.url ),
-                                               remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
-                                       
-                                       // Test if we are going to create a script tag (if so, intercept & mock)
-                                       if ( s.dataType === "script" && s.type.toUpperCase() === "GET" && remote ) {
-                                               // Synthesize the mock request for adding a script tag
-                                               var callbackContext = origSettings && origSettings.context || s;
-                                               
-                                               function success() {
-                                                       // If a local callback was specified, fire it and pass it the data
-                                                       if ( s.success ) {
-                                                               s.success.call( callbackContext, ( m.response ? m.response.toString() : m.responseText || ''), status, {} );
-                                                       }
-                               
-                                                       // Fire the global callback
-                                                       if ( s.global ) {
-                                                               trigger( "ajaxSuccess", [{}, s] );
-                                                       }
-                                               }
-                               
-                                               function complete() {
-                                                       // Process result
-                                                       if ( s.complete ) {
-                                                               s.complete.call( callbackContext, {} , status );
-                                                       }
-                               
-                                                       // The request was completed
-                                                       if ( s.global ) {
-                                                               trigger( "ajaxComplete", [{}, s] );
-                                                       }
-                               
-                                                       // Handle the global AJAX counter
-                                                       if ( s.global && ! --jQuery.active ) {
-                                                               jQuery.event.trigger( "ajaxStop" );
-                                                       }
-                                               }
-                                               
-                                               function trigger(type, args) {
-                                                       (s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
-                                               }
-                                               
-                                               if ( m.response && $.isFunction(m.response) ) {
-                                                       m.response(origSettings);
-                                               } else {
-                                                       $.globalEval(m.responseText);
-                                               }
-                                               success();
-                                               complete();
-                                               return false;
-                                       }
-                                       mock = _ajax.call($, $.extend(true, {}, origSettings, {
-                                               // Mock the XHR object
-                                               xhr: function() {
-                                                       // Extend with our default mockjax settings
-                                                       m = $.extend({}, $.mockjaxSettings, m);
-
-                                                       if ( m.contentType ) {
-                                                               m.headers['content-type'] = m.contentType;
-                                                       }
-
-                                                       // Return our mock xhr object
-                                                       return {
-                                                               status: m.status,
-                                                               readyState: 1,
-                                                               open: function() { },
-                                                               send: function() {
-                                                                       // This is a substitute for < 1.4 which lacks $.proxy
-                                                                       var process = (function(that) {
-                                                                               return function() {
-                                                                                       return (function() {
-                                                                                               // The request has returned
-                                                                                               this.status             = m.status;
-                                                                                               this.readyState         = 4;
-                                                                               
-                                                                                               // We have an executable function, call it to give 
-                                                                                               // the mock handler a chance to update it's data
-                                                                                               if ( $.isFunction(m.response) ) {
-                                                                                                       m.response(origSettings);
-                                                                                               }
-                                                                                               // Copy over our mock to our xhr object before passing control back to 
-                                                                                               // jQuery's onreadystatechange callback
-                                                                                               if ( s.dataType == 'json' && ( typeof m.responseText == 'object' ) ) {
-                                                                                                       this.responseText = JSON.stringify(m.responseText);
-                                                                                               } else if ( s.dataType == 'xml' ) {
-                                                                                                       if ( typeof m.responseXML == 'string' ) {
-                                                                                                               this.responseXML = parseXML(m.responseXML);
-                                                                                                       } else {
-                                                                                                               this.responseXML = m.responseXML;
-                                                                                                       }
-                                                                                               } else {
-                                                                                                       this.responseText = m.responseText;
-                                                                                               }
-                                                                                               // jQuery < 1.4 doesn't have onreadystate change for xhr
-                                                                                               if ( $.isFunction(this.onreadystatechange) ) {
-                                                                                                       this.onreadystatechange( m.isTimeout ? 'timeout' : undefined );
-                                                                                               }
-                                                                                       }).apply(that);
-                                                                               };
-                                                                       })(this);
-
-                                                                       if ( m.proxy ) {
-                                                                               // We're proxying this request and loading in an external file instead
-                                                                               _ajax({
-                                                                                       global: false,
-                                                                                       url: m.proxy,
-                                                                                       type: m.proxyType,
-                                                                                       data: m.data,
-                                                                                       dataType: s.dataType,
-                                                                                       complete: function(xhr, txt) {
-                                                                                               m.responseXML = xhr.responseXML;
-                                                                                               m.responseText = xhr.responseText;
-                                                                                               this.responseTimer = setTimeout(process, m.responseTime || 0);
-                                                                                       }
-                                                                               });
-                                                                       } else {
-                                                                               // type == 'POST' || 'GET' || 'DELETE'
-                                                                               if ( s.async === false ) {
-                                                                                       // TODO: Blocking delay
-                                                                                       process();
-                                                                               } else {
-                                                                                       this.responseTimer = setTimeout(process, m.responseTime || 50);
-                                                                               }
-                                                                       }
-                                                               },
-                                                               abort: function() {
-                                                                       clearTimeout(this.responseTimer);
-                                                               },
-                                                               setRequestHeader: function() { },
-                                                               getResponseHeader: function(header) {
-                                                                       // 'Last-modified', 'Etag', 'content-type' are all checked by jQuery
-                                                                       if ( m.headers && m.headers[header] ) {
-                                                                               // Return arbitrary headers
-                                                                               return m.headers[header];
-                                                                       } else if ( header.toLowerCase() == 'last-modified' ) {
-                                                                               return m.lastModified || (new Date()).toString();
-                                                                       } else if ( header.toLowerCase() == 'etag' ) {
-                                                                               return m.etag || '';
-                                                                       } else if ( header.toLowerCase() == 'content-type' ) {
-                                                                               return m.contentType || 'text/plain';
-                                                                       }
-                                                               },
-                                                               getAllResponseHeaders: function() {
-                                                                       var headers = '';
-                                                                       $.each(m.headers, function(k, v) {
-                                                                               headers += k + ': ' + v + "\n";
-                                                                       });
-                                                                       return headers;
-                                                               }
-                                                       };
-                                               }
-                                       }));
-                                       return false;
-                               }
-                       });
-                       // We don't have a mock request, trigger a normal request
-                       if ( !mock ) {
-                               return _ajax.apply($, arguments);
-                       } else {
-                               return mock;
-                       }
-               }
-       });
-
-       $.mockjaxSettings = {
-               //url:        null,
-               //type:       'GET',
-               log:          function(msg) {
-                               window['console'] && window.console.log && window.console.log(msg);
-                             },
-               status:       200,
-               responseTime: 500,
-               isTimeout:    false,
-               contentType:  'text/plain',
-               response:     '', 
-               responseText: '',
-               responseXML:  '',
-               proxy:        '',
-               proxyType:    'GET',
-               
-               lastModified: null,
-               etag:         '',
-               headers: {
-                       etag: 'IJF@H#@923uf8023hFO@I#H#',
-                       'content-type' : 'text/plain'
-               }
-       };
-
-       $.mockjax = function(settings) {
-               var i = mockHandlers.length;
-               mockHandlers[i] = settings;
-               return i;
-       };
-       $.mockjaxClear = function(i) {
-               if ( arguments.length == 1 ) {
-                       mockHandlers[i] = null;
-               } else {
-                       mockHandlers = [];
-               }
-       };
-})(jQuery);
diff --git a/resources/jquery/jquery.mw-jump.js b/resources/jquery/jquery.mw-jump.js
deleted file mode 100644 (file)
index e286834..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * JavaScript to show jump links to motor-impaired users when they are focused.
- */
-jQuery( function ( $ ) {
-
-       $( '.mw-jump' ).on( 'focus blur', 'a', function ( e ) {
-               // Confusingly jQuery leaves e.type as focusout for delegated blur events
-               if ( e.type === 'blur' || e.type === 'focusout' ) {
-                       $( this ).closest( '.mw-jump' ).css({ height: 0 });
-               } else {
-                       $( this ).closest( '.mw-jump' ).css({ height: 'auto' });
-               }
-       } );
-
-} );
diff --git a/resources/jquery/jquery.mwExtension.js b/resources/jquery/jquery.mwExtension.js
deleted file mode 100644 (file)
index 03c1c85..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * JavaScript backwards-compatibility alternatives and other convenience functions
- */
-( function ( $ ) {
-
-       $.extend({
-               trimLeft: function ( str ) {
-                       return str === null ? '' : str.toString().replace( /^\s+/, '' );
-               },
-               trimRight: function ( str ) {
-                       return str === null ?
-                                       '' : str.toString().replace( /\s+$/, '' );
-               },
-               ucFirst: function ( str ) {
-                       return str.charAt( 0 ).toUpperCase() + str.substr( 1 );
-               },
-               escapeRE: function ( str ) {
-                       return str.replace ( /([\\{}()|.?*+\-\^$\[\]])/g, '\\$1' );
-               },
-               isDomElement: function ( el ) {
-                       return !!el && !!el.nodeType;
-               },
-               isEmpty: function ( v ) {
-                       var key;
-                       if ( v === '' || v === 0 || v === '0' || v === null
-                               || v === false || v === undefined )
-                       {
-                               return true;
-                       }
-                       // the for-loop could potentially contain prototypes
-                       // to avoid that we check it's length first
-                       if ( v.length === 0 ) {
-                               return true;
-                       }
-                       if ( typeof v === 'object' ) {
-                               for ( key in v ) {
-                                       return false;
-                               }
-                               return true;
-                       }
-                       return false;
-               },
-               compareArray: function ( arrThis, arrAgainst ) {
-                       if ( arrThis.length !== arrAgainst.length ) {
-                               return false;
-                       }
-                       for ( var i = 0; i < arrThis.length; i++ ) {
-                               if ( $.isArray( arrThis[i] ) ) {
-                                       if ( !$.compareArray( arrThis[i], arrAgainst[i] ) ) {
-                                               return false;
-                                       }
-                               } else if ( arrThis[i] !== arrAgainst[i] ) {
-                                       return false;
-                               }
-                       }
-                       return true;
-               },
-               compareObject: function ( objectA, objectB ) {
-                       var prop, type;
-
-                       // Do a simple check if the types match
-                       if ( typeof objectA === typeof objectB ) {
-
-                               // Only loop over the contents if it really is an object
-                               if ( typeof objectA === 'object' ) {
-                                       // If they are aliases of the same object (ie. mw and mediaWiki) return now
-                                       if ( objectA === objectB ) {
-                                               return true;
-                                       } else {
-                                               // Iterate over each property
-                                               for ( prop in objectA ) {
-                                                       // Check if this property is also present in the other object
-                                                       if ( prop in objectB ) {
-                                                               // Compare the types of the properties
-                                                               type = typeof objectA[prop];
-                                                               if ( type === typeof objectB[prop] ) {
-                                                                       // Recursively check objects inside this one
-                                                                       switch ( type ) {
-                                                                               case 'object' :
-                                                                                       if ( !$.compareObject( objectA[prop], objectB[prop] ) ) {
-                                                                                               return false;
-                                                                                       }
-                                                                                       break;
-                                                                               case 'function' :
-                                                                                       // Functions need to be strings to compare them properly
-                                                                                       if ( objectA[prop].toString() !== objectB[prop].toString() ) {
-                                                                                               return false;
-                                                                                       }
-                                                                                       break;
-                                                                               default:
-                                                                                       // Strings, numbers
-                                                                                       if ( objectA[prop] !== objectB[prop] ) {
-                                                                                               return false;
-                                                                                       }
-                                                                                       break;
-                                                                       }
-                                                               } else {
-                                                                       return false;
-                                                               }
-                                                       } else {
-                                                               return false;
-                                                       }
-                                               }
-                                               // Check for properties in B but not in A
-                                               // This is about 15% faster (tested in Safari 5 and Firefox 3.6)
-                                               // ...than incrementing a count variable in the above and below loops
-                                               // See also: https://www.mediawiki.org/wiki/ResourceLoader/Default_modules/compareObject_test#Results
-                                               for ( prop in objectB ) {
-                                                       if ( !( prop in objectA ) ) {
-                                                               return false;
-                                                       }
-                                               }
-                                       }
-                               }
-                       } else {
-                               return false;
-                       }
-                       return true;
-               }
-       });
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.placeholder.js b/resources/jquery/jquery.placeholder.js
deleted file mode 100644 (file)
index 6f7ada3..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/**
- * HTML5 placeholder emulation for jQuery plugin
- *
- * This will automatically use the HTML5 placeholder attribute if supported, or emulate this behavior if not.
- *
- * This is a fork from Mathias Bynens' jquery.placeholder as of this commit
- * https://github.com/mathiasbynens/jquery-placeholder/blob/47f05d400e2dd16b59d144141a2cf54a9a77c502/jquery.placeholder.js
- *
- * @author Mathias Bynens <http://mathiasbynens.be/>
- * @author Trevor Parscal <tparscal@wikimedia.org>, 2012
- * @author Krinkle <krinklemail@gmail.com>, 2012
- * @author Alex Ivanov <alexivanov97@gmail.com>, 2013
- * @version 2.1.0
- * @license MIT
- */
-(function ($) {
-
-       var isInputSupported = 'placeholder' in document.createElement('input'),
-               isTextareaSupported = 'placeholder' in document.createElement('textarea'),
-               prototype = $.fn,
-               valHooks = $.valHooks,
-               propHooks = $.propHooks,
-               hooks,
-               placeholder;
-
-       if (isInputSupported && isTextareaSupported) {
-
-               placeholder = prototype.placeholder = function (text) {
-                       var hasArgs = arguments.length;
-
-                       if (hasArgs) {
-                               changePlaceholder.call(this, text);
-                       }
-
-                       return this;
-               };
-
-               placeholder.input = placeholder.textarea = true;
-
-       } else {
-
-               placeholder = prototype.placeholder = function (text) {
-                       var $this = this,
-                               hasArgs = arguments.length;
-
-                       if (hasArgs) {
-                               changePlaceholder.call(this, text);
-                       }
-
-                       $this
-                               .filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')
-                               .filter(function () {
-                                       return !$(this).data('placeholder-enabled');
-                               })
-                               .bind({
-                                       'focus.placeholder drop.placeholder': clearPlaceholder,
-                                       'blur.placeholder': setPlaceholder
-                               })
-                               .data('placeholder-enabled', true)
-                               .trigger('blur.placeholder');
-                       return $this;
-               };
-
-               placeholder.input = isInputSupported;
-               placeholder.textarea = isTextareaSupported;
-
-               hooks = {
-                       'get': function (element) {
-                               var $element = $(element),
-                                       $passwordInput = $element.data('placeholder-password');
-                               if ($passwordInput) {
-                                       return $passwordInput[0].value;
-                               }
-
-                               return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value;
-                       },
-                       'set': function (element, value) {
-                               var $element = $(element),
-                                       $passwordInput = $element.data('placeholder-password');
-                               if ($passwordInput) {
-                                       $passwordInput[0].value = value;
-                                       return value;
-                               }
-
-                               if (!$element.data('placeholder-enabled')) {
-                                       element.value = value;
-                                       return value;
-                               }
-                               if (!value) {
-                                       element.value = value;
-                                       // Issue #56: Setting the placeholder causes problems if the element continues to have focus.
-                                       if (element !== safeActiveElement()) {
-                                               // We can't use `triggerHandler` here because of dummy text/password inputs :(
-                                               setPlaceholder.call(element);
-                                       }
-                               } else if ($element.hasClass('placeholder')) {
-                                       if (!clearPlaceholder.call(element, true, value)) {
-                                               element.value = value;
-                                       }
-                               } else {
-                                       element.value = value;
-                               }
-                               // `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
-                               return $element;
-                       }
-               };
-
-               if (!isInputSupported) {
-                       valHooks.input = hooks;
-                       propHooks.value = hooks;
-               }
-               if (!isTextareaSupported) {
-                       valHooks.textarea = hooks;
-                       propHooks.value = hooks;
-               }
-
-               $(function () {
-                       // Look for forms
-                       $(document).delegate('form', 'submit.placeholder', function () {
-                               // Clear the placeholder values so they don't get submitted
-                               var $inputs = $('.placeholder', this).each(clearPlaceholder);
-                               setTimeout(function () {
-                                       $inputs.each(setPlaceholder);
-                               }, 10);
-                       });
-               });
-
-               // Clear placeholder values upon page reload
-               $(window).bind('beforeunload.placeholder', function () {
-                       $('.placeholder').each(function () {
-                               this.value = '';
-                       });
-               });
-
-       }
-
-       function args(elem) {
-               // Return an object of element attributes
-               var newAttrs = {},
-                       rinlinejQuery = /^jQuery\d+$/;
-               $.each(elem.attributes, function (i, attr) {
-                       if (attr.specified && !rinlinejQuery.test(attr.name)) {
-                               newAttrs[attr.name] = attr.value;
-                       }
-               });
-               return newAttrs;
-       }
-
-       function clearPlaceholder(event, value) {
-               var input = this,
-                       $input = $(input);
-               if (input.value === $input.attr('placeholder') && $input.hasClass('placeholder')) {
-                       if ($input.data('placeholder-password')) {
-                               $input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id'));
-                               // If `clearPlaceholder` was called from `$.valHooks.input.set`
-                               if (event === true) {
-                                       $input[0].value = value;
-                                       return value;
-                               }
-                               $input.focus();
-                       } else {
-                               input.value = '';
-                               $input.removeClass('placeholder');
-                               if (input === safeActiveElement()) {
-                                       input.select();
-                               }
-                       }
-               }
-       }
-
-       function setPlaceholder() {
-               var $replacement,
-                       input = this,
-                       $input = $(input),
-                       id = this.id;
-               if (!input.value) {
-                       if (input.type === 'password') {
-                               if (!$input.data('placeholder-textinput')) {
-                                       try {
-                                               $replacement = $input.clone().attr({ 'type': 'text' });
-                                       } catch(e) {
-                                               $replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' }));
-                                       }
-                                       $replacement
-                                               .removeAttr('name')
-                                               .data({
-                                                       'placeholder-password': $input,
-                                                       'placeholder-id': id
-                                               })
-                                               .bind('focus.placeholder drop.placeholder', clearPlaceholder);
-                                       $input
-                                               .data({
-                                                       'placeholder-textinput': $replacement,
-                                                       'placeholder-id': id
-                                               })
-                                               .before($replacement);
-                               }
-                               $input = $input.removeAttr('id').hide().prev().attr('id', id).show();
-                               // Note: `$input[0] != input` now!
-                       }
-                       $input.addClass('placeholder');
-                       $input[0].value = $input.attr('placeholder');
-               } else {
-                       $input.removeClass('placeholder');
-               }
-       }
-
-       function safeActiveElement() {
-               // Avoid IE9 `document.activeElement` of death
-               // https://github.com/mathiasbynens/jquery-placeholder/pull/99
-               try {
-                       return document.activeElement;
-               } catch (err) {}
-       }
-
-       function changePlaceholder(text) {
-               var hasArgs = arguments.length,
-                       $input = this;
-               if (hasArgs) {
-                       if ($input.attr('placeholder') !== text) {
-                               $input.prop('placeholder', text);
-                               if ($input.hasClass('placeholder')) {
-                                       $input[0].value = text;
-                               }
-                       }
-               }
-       }
-
-}(jQuery));
diff --git a/resources/jquery/jquery.qunit.completenessTest.js b/resources/jquery/jquery.qunit.completenessTest.js
deleted file mode 100644 (file)
index 86fcaea..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-/**
- * jQuery QUnit CompletenessTest 0.4
- *
- * Tests the completeness of test suites for object oriented javascript
- * libraries. Written to be used in environments with jQuery and QUnit.
- * Requires jQuery 1.7.2 or higher.
- *
- * Built for and tested with:
- * - Chrome 19
- * - Firefox 4
- * - Safari 5
- *
- * @author Timo Tijhof, 2011-2012
- */
-( function ( $ ) {
-       'use strict';
-
-       var util,
-               hasOwn = Object.prototype.hasOwnProperty,
-               log = (window.console && window.console.log)
-                       ? function () { return window.console.log.apply(window.console, arguments); }
-                       : function () {};
-
-       // Simplified version of a few jQuery methods, except that they don't
-       // call other jQuery methods. Required to be able to run the CompletenessTest
-       // on jQuery itself as well.
-       util = {
-               keys: Object.keys || function ( object ) {
-                       var key, keys = [];
-                       for ( key in object ) {
-                               if ( hasOwn.call( object, key ) ) {
-                                       keys.push( key );
-                               }
-                       }
-                       return keys;
-               },
-               extend: function () {
-                       var options, name, src, copy,
-                               target = arguments[0] || {},
-                               i = 1,
-                               length = arguments.length;
-
-                       for ( ; i < length; i++ ) {
-                               options = arguments[ i ];
-                               // Only deal with non-null/undefined values
-                               if ( options !== null && options !== undefined ) {
-                                       // Extend the base object
-                                       for ( name in options ) {
-                                               src = target[ name ];
-                                               copy = options[ name ];
-
-                                               // Prevent never-ending loop
-                                               if ( target === copy ) {
-                                                       continue;
-                                               }
-
-                                               if ( copy !== undefined ) {
-                                                       target[ name ] = copy;
-                                               }
-                                       }
-                               }
-                       }
-
-                       // Return the modified object
-                       return target;
-               },
-               each: function ( object, callback ) {
-                       var name;
-                       for ( name in object ) {
-                               if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
-                                       break;
-                               }
-                       }
-               },
-               // $.type and $.isEmptyObject are safe as is, they don't call
-               // other $.* methods. Still need to be derefenced into `util`
-               // since the CompletenessTest will overload them with spies.
-               type: $.type,
-               isEmptyObject: $.isEmptyObject
-       };
-
-       /**
-        * CompletenessTest
-        * @constructor
-        *
-        * @example
-        *  var myTester = new CompletenessTest( myLib );
-        * @param masterVariable {Object} The root variable that contains all object
-        *  members. CompletenessTest will recursively traverse objects and keep track
-        *  of all methods.
-        * @param ignoreFn {Function} Optionally pass a function to filter out certain
-        *  methods. Example: You may want to filter out instances of jQuery or some
-        *  other constructor. Otherwise "missingTests" will include all methods that
-        *  were not called from that instance.
-        */
-       function CompletenessTest( masterVariable, ignoreFn ) {
-
-               // Keep track in these objects. Keyed by strings with the
-               // method names (ie. 'my.foo', 'my.bar', etc.) values are boolean true.
-               this.injectionTracker = {};
-               this.methodCallTracker = {};
-               this.missingTests = {};
-
-               this.ignoreFn = undefined === ignoreFn ? function () { return false; } : ignoreFn;
-
-               // Lazy limit in case something weird happends (like recurse (part of) ourself).
-               this.lazyLimit = 2000;
-               this.lazyCounter = 0;
-
-               var that = this;
-
-               // Bind begin and end to QUnit.
-               QUnit.begin( function () {
-                       that.walkTheObject( null, masterVariable, masterVariable, [], CompletenessTest.ACTION_INJECT );
-                       log( 'CompletenessTest/walkTheObject/ACTION_INJECT', that );
-               });
-
-               QUnit.done( function () {
-                       that.populateMissingTests();
-                       log( 'CompletenessTest/populateMissingTests', that );
-
-                       var toolbar, testResults, cntTotal, cntCalled, cntMissing;
-
-                       cntTotal = util.keys( that.injectionTracker ).length;
-                       cntCalled = util.keys( that.methodCallTracker ).length;
-                       cntMissing = util.keys( that.missingTests ).length;
-
-                       function makeTestResults( blob, title, style ) {
-                               var elOutputWrapper, elTitle, elContainer, elList, elFoot;
-
-                               elTitle = document.createElement( 'strong' );
-                               elTitle.textContent = title || 'Values';
-
-                               elList = document.createElement( 'ul' );
-                               util.each( blob, function ( key ) {
-                                       var elItem = document.createElement( 'li' );
-                                       elItem.textContent = key;
-                                       elList.appendChild( elItem );
-                               });
-
-                               elFoot = document.createElement( 'p' );
-                               elFoot.innerHTML = '<em>&mdash; CompletenessTest</em>';
-
-                               elContainer = document.createElement( 'div' );
-                               elContainer.appendChild( elTitle );
-                               elContainer.appendChild( elList );
-                               elContainer.appendChild( elFoot );
-
-                               elOutputWrapper = document.getElementById( 'qunit-completenesstest' );
-                               if ( !elOutputWrapper ) {
-                                       elOutputWrapper = document.createElement( 'div' );
-                                       elOutputWrapper.id = 'qunit-completenesstest';
-                               }
-                               elOutputWrapper.appendChild( elContainer );
-
-                               util.each( style, function ( key, value ) {
-                                       elOutputWrapper.style[key] = value;
-                               });
-                               return elOutputWrapper;
-                       }
-
-                       if ( cntMissing === 0 ) {
-                               // Good
-                               testResults = makeTestResults(
-                                       {},
-                                       'Detected calls to ' + cntCalled + '/' + cntTotal + ' methods. No missing tests!',
-                                       {
-                                               backgroundColor: '#D2E0E6',
-                                               color: '#366097',
-                                               paddingTop: '1em',
-                                               paddingRight: '1em',
-                                               paddingBottom: '1em',
-                                               paddingLeft: '1em'
-                                       }
-                               );
-                       } else {
-                               // Bad
-                               testResults = makeTestResults(
-                                       that.missingTests,
-                                       'Detected calls to ' + cntCalled + '/' + cntTotal + ' methods. ' + cntMissing + ' methods not covered:',
-                                       {
-                                               backgroundColor: '#EE5757',
-                                               color: 'black',
-                                               paddingTop: '1em',
-                                               paddingRight: '1em',
-                                               paddingBottom: '1em',
-                                               paddingLeft: '1em'
-                                       }
-                               );
-                       }
-
-                       toolbar = document.getElementById( 'qunit-testrunner-toolbar' );
-                       if ( toolbar ) {
-                               toolbar.insertBefore( testResults, toolbar.firstChild );
-                       }
-               });
-
-               return this;
-       }
-
-       /* Static members */
-       CompletenessTest.ACTION_INJECT = 500;
-       CompletenessTest.ACTION_CHECK = 501;
-
-       /* Public methods */
-       CompletenessTest.fn = CompletenessTest.prototype = {
-
-               /**
-                * CompletenessTest.fn.walkTheObject
-                *
-                * This function recursively walks through the given object, calling itself as it goes.
-                * Depending on the action it either injects our listener into the methods, or
-                * reads from our tracker and records which methods have not been called by the test suite.
-                *
-                * @param currName {String|Null} Name of the given object member (Initially this is null).
-                * @param currVar {mixed} The variable to check (initially an object,
-                *  further down it could be anything).
-                * @param masterVariable {Object} Throughout our interation, always keep track of the master/root.
-                *  Initially this is the same as currVar.
-                * @param parentPathArray {Array} Array of names that indicate our breadcrumb path starting at
-                *  masterVariable. Not including currName.
-                * @param action {Number} What is this function supposed to do (ACTION_INJECT or ACTION_CHECK)
-                */
-               walkTheObject: function ( currName, currVar, masterVariable, parentPathArray, action ) {
-
-                       var key, value, tmpPathArray,
-                               type = util.type( currVar ),
-                               that = this;
-
-                       // Hard ignores
-                       if ( this.ignoreFn( currVar, that, parentPathArray ) ) {
-                               return null;
-                       }
-
-                       // Handle the lazy limit
-                       this.lazyCounter++;
-                       if ( this.lazyCounter > this.lazyLimit ) {
-                               log( 'CompletenessTest.fn.walkTheObject> Limit reached: ' + this.lazyCounter, parentPathArray );
-                               return null;
-                       }
-
-                       // Functions
-                       if ( type === 'function' ) {
-
-                               if ( !currVar.prototype || util.isEmptyObject( currVar.prototype ) ) {
-
-                                       if ( action === CompletenessTest.ACTION_INJECT ) {
-
-                                               that.injectionTracker[ parentPathArray.join( '.' ) ] = true;
-                                               that.injectCheck( masterVariable, parentPathArray, function () {
-                                                       that.methodCallTracker[ parentPathArray.join( '.' ) ] = true;
-                                               } );
-                                       }
-
-                               // We don't support checking object constructors yet...
-                               // ...we can check the prototypes fine, though.
-                               } else {
-                                       if ( action === CompletenessTest.ACTION_INJECT ) {
-
-                                               for ( key in currVar.prototype ) {
-                                                       if ( hasOwn.call( currVar.prototype, key ) ) {
-                                                               value = currVar.prototype[key];
-                                                               if ( key === 'constructor' ) {
-                                                                       continue;
-                                                               }
-
-                                                               // Clone and break reference to parentPathArray
-                                                               tmpPathArray = util.extend( [], parentPathArray );
-                                                               tmpPathArray.push( 'prototype' );
-                                                               tmpPathArray.push( key );
-
-                                                               that.walkTheObject( key, value, masterVariable, tmpPathArray, action );
-                                                       }
-                                               }
-
-                                       }
-                               }
-
-                       }
-
-                       // Recursively. After all, this is the *completeness* test
-                       if ( type === 'function' || type === 'object' ) {
-                               for ( key in currVar ) {
-                                       if ( hasOwn.call( currVar, key ) ) {
-                                               value = currVar[key];
-
-                                               // Clone and break reference to parentPathArray
-                                               tmpPathArray = util.extend( [], parentPathArray );
-                                               tmpPathArray.push( key );
-
-                                               that.walkTheObject( key, value, masterVariable, tmpPathArray, action );
-                                       }
-                               }
-                       }
-               },
-
-               populateMissingTests: function () {
-                       var ct = this;
-                       util.each( ct.injectionTracker, function ( key ) {
-                               ct.hasTest( key );
-                       });
-               },
-
-               /**
-                * CompletenessTest.fn.hasTest
-                *
-                * Checks if the given method name (ie. 'my.foo.bar')
-                * was called during the test suite (as far as the tracker knows).
-                * If not it adds it to missingTests.
-                *
-                * @param fnName {String}
-                * @return {Boolean}
-                */
-               hasTest: function ( fnName ) {
-                       if ( !( fnName in this.methodCallTracker ) ) {
-                               this.missingTests[fnName] = true;
-                               return false;
-                       }
-                       return true;
-               },
-
-               /**
-                * CompletenessTest.fn.injectCheck
-                *
-                * Injects a function (such as a spy that updates methodCallTracker when
-                * it's called) inside another function.
-                *
-                * @param masterVariable {Object}
-                * @param objectPathArray {Array}
-                * @param injectFn {Function}
-                */
-               injectCheck: function ( masterVariable, objectPathArray, injectFn ) {
-                       var i, len, prev, memberName, lastMember,
-                               curr = masterVariable;
-
-                       // Get the object in question through the path from the master variable,
-                       // We can't pass the value directly because we need to re-define the object
-                       // member and keep references to the parent object, member name and member
-                       // value at all times.
-                       for ( i = 0, len = objectPathArray.length; i < len; i++ ) {
-                               memberName = objectPathArray[i];
-
-                               prev = curr;
-                               curr = prev[memberName];
-                               lastMember = memberName;
-                       }
-
-                       // Objects are by reference, members (unless objects) are not.
-                       prev[lastMember] = function () {
-                               injectFn();
-                               return curr.apply( this, arguments );
-                       };
-               }
-       };
-
-       /* Expose */
-       window.CompletenessTest = CompletenessTest;
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.qunit.css b/resources/jquery/jquery.qunit.css
deleted file mode 100644 (file)
index d7fc0c8..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/**
- * QUnit v1.11.0 - A JavaScript Unit Testing Framework
- *
- * http://qunitjs.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- */
-
-/** Font Family and Sizes */
-
-#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
-       font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
-}
-
-#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
-#qunit-tests { font-size: smaller; }
-
-
-/** Resets */
-
-#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
-       margin: 0;
-       padding: 0;
-}
-
-
-/** Header */
-
-#qunit-header {
-       padding: 0.5em 0 0.5em 1em;
-
-       color: #8699a4;
-       background-color: #0d3349;
-
-       font-size: 1.5em;
-       line-height: 1em;
-       font-weight: normal;
-
-       border-radius: 5px 5px 0 0;
-       -moz-border-radius: 5px 5px 0 0;
-       -webkit-border-top-right-radius: 5px;
-       -webkit-border-top-left-radius: 5px;
-}
-
-#qunit-header a {
-       text-decoration: none;
-       color: #c2ccd1;
-}
-
-#qunit-header a:hover,
-#qunit-header a:focus {
-       color: #fff;
-}
-
-#qunit-testrunner-toolbar label {
-       display: inline-block;
-       padding: 0 .5em 0 .1em;
-}
-
-#qunit-banner {
-       height: 5px;
-}
-
-#qunit-testrunner-toolbar {
-       padding: 0.5em 0 0.5em 2em;
-       color: #5E740B;
-       background-color: #eee;
-       overflow: hidden;
-}
-
-#qunit-userAgent {
-       padding: 0.5em 0 0.5em 2.5em;
-       background-color: #2b81af;
-       color: #fff;
-       text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
-}
-
-#qunit-modulefilter-container {
-       float: right;
-}
-
-/** Tests: Pass/Fail */
-
-#qunit-tests {
-       list-style-position: inside;
-}
-
-#qunit-tests li {
-       padding: 0.4em 0.5em 0.4em 2.5em;
-       border-bottom: 1px solid #fff;
-       list-style-position: inside;
-}
-
-#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {
-       display: none;
-}
-
-#qunit-tests li strong {
-       cursor: pointer;
-}
-
-#qunit-tests li a {
-       padding: 0.5em;
-       color: #c2ccd1;
-       text-decoration: none;
-}
-#qunit-tests li a:hover,
-#qunit-tests li a:focus {
-       color: #000;
-}
-
-#qunit-tests li .runtime {
-       float: right;
-       font-size: smaller;
-}
-
-.qunit-assert-list {
-       margin-top: 0.5em;
-       padding: 0.5em;
-
-       background-color: #fff;
-
-       border-radius: 5px;
-       -moz-border-radius: 5px;
-       -webkit-border-radius: 5px;
-}
-
-.qunit-collapsed {
-       display: none;
-}
-
-#qunit-tests table {
-       border-collapse: collapse;
-       margin-top: .2em;
-}
-
-#qunit-tests th {
-       text-align: right;
-       vertical-align: top;
-       padding: 0 .5em 0 0;
-}
-
-#qunit-tests td {
-       vertical-align: top;
-}
-
-#qunit-tests pre {
-       margin: 0;
-       white-space: pre-wrap;
-       word-wrap: break-word;
-}
-
-#qunit-tests del {
-       background-color: #e0f2be;
-       color: #374e0c;
-       text-decoration: none;
-}
-
-#qunit-tests ins {
-       background-color: #ffcaca;
-       color: #500;
-       text-decoration: none;
-}
-
-/*** Test Counts */
-
-#qunit-tests b.counts                       { color: black; }
-#qunit-tests b.passed                       { color: #5E740B; }
-#qunit-tests b.failed                       { color: #710909; }
-
-#qunit-tests li li {
-       padding: 5px;
-       background-color: #fff;
-       border-bottom: none;
-       list-style-position: inside;
-}
-
-/*** Passing Styles */
-
-#qunit-tests li li.pass {
-       color: #3c510c;
-       background-color: #fff;
-       border-left: 10px solid #C6E746;
-}
-
-#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }
-#qunit-tests .pass .test-name               { color: #366097; }
-
-#qunit-tests .pass .test-actual,
-#qunit-tests .pass .test-expected           { color: #999999; }
-
-#qunit-banner.qunit-pass                    { background-color: #C6E746; }
-
-/*** Failing Styles */
-
-#qunit-tests li li.fail {
-       color: #710909;
-       background-color: #fff;
-       border-left: 10px solid #EE5757;
-       white-space: pre;
-}
-
-#qunit-tests > li:last-child {
-       border-radius: 0 0 5px 5px;
-       -moz-border-radius: 0 0 5px 5px;
-       -webkit-border-bottom-right-radius: 5px;
-       -webkit-border-bottom-left-radius: 5px;
-}
-
-#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }
-#qunit-tests .fail .test-name,
-#qunit-tests .fail .module-name             { color: #000000; }
-
-#qunit-tests .fail .test-actual             { color: #EE5757; }
-#qunit-tests .fail .test-expected           { color: green;   }
-
-#qunit-banner.qunit-fail                    { background-color: #EE5757; }
-
-
-/** Result */
-
-#qunit-testresult {
-       padding: 0.5em 0.5em 0.5em 2.5em;
-
-       color: #2b81af;
-       background-color: #D2E0E6;
-
-       border-bottom: 1px solid white;
-}
-#qunit-testresult .module-name {
-       font-weight: bold;
-}
-
-/** Fixture */
-
-#qunit-fixture {
-       position: absolute;
-       top: -10000px;
-       left: -10000px;
-       width: 1000px;
-       height: 1000px;
-}
diff --git a/resources/jquery/jquery.qunit.js b/resources/jquery/jquery.qunit.js
deleted file mode 100644 (file)
index 302545f..0000000
+++ /dev/null
@@ -1,2152 +0,0 @@
-/**
- * QUnit v1.11.0 - A JavaScript Unit Testing Framework
- *
- * http://qunitjs.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- */
-
-(function( window ) {
-
-var QUnit,
-       assert,
-       config,
-       onErrorFnPrev,
-       testId = 0,
-       fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
-       toString = Object.prototype.toString,
-       hasOwn = Object.prototype.hasOwnProperty,
-       // Keep a local reference to Date (GH-283)
-       Date = window.Date,
-       defined = {
-               setTimeout: typeof window.setTimeout !== "undefined",
-               sessionStorage: (function() {
-                       var x = "qunit-test-string";
-                       try {
-                               sessionStorage.setItem( x, x );
-                               sessionStorage.removeItem( x );
-                               return true;
-                       } catch( e ) {
-                               return false;
-                       }
-               }())
-       },
-       /**
-        * Provides a normalized error string, correcting an issue
-        * with IE 7 (and prior) where Error.prototype.toString is
-        * not properly implemented
-        *
-        * Based on http://es5.github.com/#x15.11.4.4
-        *
-        * @param {String|Error} error
-        * @return {String} error message
-        */
-       errorString = function( error ) {
-               var name, message,
-                       errorString = error.toString();
-               if ( errorString.substring( 0, 7 ) === "[object" ) {
-                       name = error.name ? error.name.toString() : "Error";
-                       message = error.message ? error.message.toString() : "";
-                       if ( name && message ) {
-                               return name + ": " + message;
-                       } else if ( name ) {
-                               return name;
-                       } else if ( message ) {
-                               return message;
-                       } else {
-                               return "Error";
-                       }
-               } else {
-                       return errorString;
-               }
-       },
-       /**
-        * Makes a clone of an object using only Array or Object as base,
-        * and copies over the own enumerable properties.
-        *
-        * @param {Object} obj
-        * @return {Object} New object with only the own properties (recursively).
-        */
-       objectValues = function( obj ) {
-               // Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.
-               /*jshint newcap: false */
-               var key, val,
-                       vals = QUnit.is( "array", obj ) ? [] : {};
-               for ( key in obj ) {
-                       if ( hasOwn.call( obj, key ) ) {
-                               val = obj[key];
-                               vals[key] = val === Object(val) ? objectValues(val) : val;
-                       }
-               }
-               return vals;
-       };
-
-function Test( settings ) {
-       extend( this, settings );
-       this.assertions = [];
-       this.testNumber = ++Test.count;
-}
-
-Test.count = 0;
-
-Test.prototype = {
-       init: function() {
-               var a, b, li,
-                       tests = id( "qunit-tests" );
-
-               if ( tests ) {
-                       b = document.createElement( "strong" );
-                       b.innerHTML = this.nameHtml;
-
-                       // `a` initialized at top of scope
-                       a = document.createElement( "a" );
-                       a.innerHTML = "Rerun";
-                       a.href = QUnit.url({ testNumber: this.testNumber });
-
-                       li = document.createElement( "li" );
-                       li.appendChild( b );
-                       li.appendChild( a );
-                       li.className = "running";
-                       li.id = this.id = "qunit-test-output" + testId++;
-
-                       tests.appendChild( li );
-               }
-       },
-       setup: function() {
-               if ( this.module !== config.previousModule ) {
-                       if ( config.previousModule ) {
-                               runLoggingCallbacks( "moduleDone", QUnit, {
-                                       name: config.previousModule,
-                                       failed: config.moduleStats.bad,
-                                       passed: config.moduleStats.all - config.moduleStats.bad,
-                                       total: config.moduleStats.all
-                               });
-                       }
-                       config.previousModule = this.module;
-                       config.moduleStats = { all: 0, bad: 0 };
-                       runLoggingCallbacks( "moduleStart", QUnit, {
-                               name: this.module
-                       });
-               } else if ( config.autorun ) {
-                       runLoggingCallbacks( "moduleStart", QUnit, {
-                               name: this.module
-                       });
-               }
-
-               config.current = this;
-
-               this.testEnvironment = extend({
-                       setup: function() {},
-                       teardown: function() {}
-               }, this.moduleTestEnvironment );
-
-               this.started = +new Date();
-               runLoggingCallbacks( "testStart", QUnit, {
-                       name: this.testName,
-                       module: this.module
-               });
-
-               // allow utility functions to access the current test environment
-               // TODO why??
-               QUnit.current_testEnvironment = this.testEnvironment;
-
-               if ( !config.pollution ) {
-                       saveGlobal();
-               }
-               if ( config.notrycatch ) {
-                       this.testEnvironment.setup.call( this.testEnvironment );
-                       return;
-               }
-               try {
-                       this.testEnvironment.setup.call( this.testEnvironment );
-               } catch( e ) {
-                       QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
-               }
-       },
-       run: function() {
-               config.current = this;
-
-               var running = id( "qunit-testresult" );
-
-               if ( running ) {
-                       running.innerHTML = "Running: <br/>" + this.nameHtml;
-               }
-
-               if ( this.async ) {
-                       QUnit.stop();
-               }
-
-               this.callbackStarted = +new Date();
-
-               if ( config.notrycatch ) {
-                       this.callback.call( this.testEnvironment, QUnit.assert );
-                       this.callbackRuntime = +new Date() - this.callbackStarted;
-                       return;
-               }
-
-               try {
-                       this.callback.call( this.testEnvironment, QUnit.assert );
-                       this.callbackRuntime = +new Date() - this.callbackStarted;
-               } catch( e ) {
-                       this.callbackRuntime = +new Date() - this.callbackStarted;
-
-                       QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
-                       // else next test will carry the responsibility
-                       saveGlobal();
-
-                       // Restart the tests if they're blocking
-                       if ( config.blocking ) {
-                               QUnit.start();
-                       }
-               }
-       },
-       teardown: function() {
-               config.current = this;
-               if ( config.notrycatch ) {
-                       if ( typeof this.callbackRuntime === "undefined" ) {
-                               this.callbackRuntime = +new Date() - this.callbackStarted;
-                       }
-                       this.testEnvironment.teardown.call( this.testEnvironment );
-                       return;
-               } else {
-                       try {
-                               this.testEnvironment.teardown.call( this.testEnvironment );
-                       } catch( e ) {
-                               QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
-                       }
-               }
-               checkPollution();
-       },
-       finish: function() {
-               config.current = this;
-               if ( config.requireExpects && this.expected === null ) {
-                       QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );
-               } else if ( this.expected !== null && this.expected !== this.assertions.length ) {
-                       QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );
-               } else if ( this.expected === null && !this.assertions.length ) {
-                       QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
-               }
-
-               var i, assertion, a, b, time, li, ol,
-                       test = this,
-                       good = 0,
-                       bad = 0,
-                       tests = id( "qunit-tests" );
-
-               this.runtime = +new Date() - this.started;
-               config.stats.all += this.assertions.length;
-               config.moduleStats.all += this.assertions.length;
-
-               if ( tests ) {
-                       ol = document.createElement( "ol" );
-                       ol.className = "qunit-assert-list";
-
-                       for ( i = 0; i < this.assertions.length; i++ ) {
-                               assertion = this.assertions[i];
-
-                               li = document.createElement( "li" );
-                               li.className = assertion.result ? "pass" : "fail";
-                               li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" );
-                               ol.appendChild( li );
-
-                               if ( assertion.result ) {
-                                       good++;
-                               } else {
-                                       bad++;
-                                       config.stats.bad++;
-                                       config.moduleStats.bad++;
-                               }
-                       }
-
-                       // store result when possible
-                       if ( QUnit.config.reorder && defined.sessionStorage ) {
-                               if ( bad ) {
-                                       sessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad );
-                               } else {
-                                       sessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName );
-                               }
-                       }
-
-                       if ( bad === 0 ) {
-                               addClass( ol, "qunit-collapsed" );
-                       }
-
-                       // `b` initialized at top of scope
-                       b = document.createElement( "strong" );
-                       b.innerHTML = this.nameHtml + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
-
-                       addEvent(b, "click", function() {
-                               var next = b.parentNode.lastChild,
-                                       collapsed = hasClass( next, "qunit-collapsed" );
-                               ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );
-                       });
-
-                       addEvent(b, "dblclick", function( e ) {
-                               var target = e && e.target ? e.target : window.event.srcElement;
-                               if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) {
-                                       target = target.parentNode;
-                               }
-                               if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
-                                       window.location = QUnit.url({ testNumber: test.testNumber });
-                               }
-                       });
-
-                       // `time` initialized at top of scope
-                       time = document.createElement( "span" );
-                       time.className = "runtime";
-                       time.innerHTML = this.runtime + " ms";
-
-                       // `li` initialized at top of scope
-                       li = id( this.id );
-                       li.className = bad ? "fail" : "pass";
-                       li.removeChild( li.firstChild );
-                       a = li.firstChild;
-                       li.appendChild( b );
-                       li.appendChild( a );
-                       li.appendChild( time );
-                       li.appendChild( ol );
-
-               } else {
-                       for ( i = 0; i < this.assertions.length; i++ ) {
-                               if ( !this.assertions[i].result ) {
-                                       bad++;
-                                       config.stats.bad++;
-                                       config.moduleStats.bad++;
-                               }
-                       }
-               }
-
-               runLoggingCallbacks( "testDone", QUnit, {
-                       name: this.testName,
-                       module: this.module,
-                       failed: bad,
-                       passed: this.assertions.length - bad,
-                       total: this.assertions.length,
-                       duration: this.runtime
-               });
-
-               QUnit.reset();
-
-               config.current = undefined;
-       },
-
-       queue: function() {
-               var bad,
-                       test = this;
-
-               synchronize(function() {
-                       test.init();
-               });
-               function run() {
-                       // each of these can by async
-                       synchronize(function() {
-                               test.setup();
-                       });
-                       synchronize(function() {
-                               test.run();
-                       });
-                       synchronize(function() {
-                               test.teardown();
-                       });
-                       synchronize(function() {
-                               test.finish();
-                       });
-               }
-
-               // `bad` initialized at top of scope
-               // defer when previous test run passed, if storage is available
-               bad = QUnit.config.reorder && defined.sessionStorage &&
-                                               +sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName );
-
-               if ( bad ) {
-                       run();
-               } else {
-                       synchronize( run, true );
-               }
-       }
-};
-
-// Root QUnit object.
-// `QUnit` initialized at top of scope
-QUnit = {
-
-       // call on start of module test to prepend name to all tests
-       module: function( name, testEnvironment ) {
-               config.currentModule = name;
-               config.currentModuleTestEnvironment = testEnvironment;
-               config.modules[name] = true;
-       },
-
-       asyncTest: function( testName, expected, callback ) {
-               if ( arguments.length === 2 ) {
-                       callback = expected;
-                       expected = null;
-               }
-
-               QUnit.test( testName, expected, callback, true );
-       },
-
-       test: function( testName, expected, callback, async ) {
-               var test,
-                       nameHtml = "<span class='test-name'>" + escapeText( testName ) + "</span>";
-
-               if ( arguments.length === 2 ) {
-                       callback = expected;
-                       expected = null;
-               }
-
-               if ( config.currentModule ) {
-                       nameHtml = "<span class='module-name'>" + escapeText( config.currentModule ) + "</span>: " + nameHtml;
-               }
-
-               test = new Test({
-                       nameHtml: nameHtml,
-                       testName: testName,
-                       expected: expected,
-                       async: async,
-                       callback: callback,
-                       module: config.currentModule,
-                       moduleTestEnvironment: config.currentModuleTestEnvironment,
-                       stack: sourceFromStacktrace( 2 )
-               });
-
-               if ( !validTest( test ) ) {
-                       return;
-               }
-
-               test.queue();
-       },
-
-       // Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
-       expect: function( asserts ) {
-               if (arguments.length === 1) {
-                       config.current.expected = asserts;
-               } else {
-                       return config.current.expected;
-               }
-       },
-
-       start: function( count ) {
-               // QUnit hasn't been initialized yet.
-               // Note: RequireJS (et al) may delay onLoad
-               if ( config.semaphore === undefined ) {
-                       QUnit.begin(function() {
-                               // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first
-                               setTimeout(function() {
-                                       QUnit.start( count );
-                               });
-                       });
-                       return;
-               }
-
-               config.semaphore -= count || 1;
-               // don't start until equal number of stop-calls
-               if ( config.semaphore > 0 ) {
-                       return;
-               }
-               // ignore if start is called more often then stop
-               if ( config.semaphore < 0 ) {
-                       config.semaphore = 0;
-                       QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) );
-                       return;
-               }
-               // A slight delay, to avoid any current callbacks
-               if ( defined.setTimeout ) {
-                       window.setTimeout(function() {
-                               if ( config.semaphore > 0 ) {
-                                       return;
-                               }
-                               if ( config.timeout ) {
-                                       clearTimeout( config.timeout );
-                               }
-
-                               config.blocking = false;
-                               process( true );
-                       }, 13);
-               } else {
-                       config.blocking = false;
-                       process( true );
-               }
-       },
-
-       stop: function( count ) {
-               config.semaphore += count || 1;
-               config.blocking = true;
-
-               if ( config.testTimeout && defined.setTimeout ) {
-                       clearTimeout( config.timeout );
-                       config.timeout = window.setTimeout(function() {
-                               QUnit.ok( false, "Test timed out" );
-                               config.semaphore = 1;
-                               QUnit.start();
-                       }, config.testTimeout );
-               }
-       }
-};
-
-// `assert` initialized at top of scope
-// Asssert helpers
-// All of these must either call QUnit.push() or manually do:
-// - runLoggingCallbacks( "log", .. );
-// - config.current.assertions.push({ .. });
-// We attach it to the QUnit object *after* we expose the public API,
-// otherwise `assert` will become a global variable in browsers (#341).
-assert = {
-       /**
-        * Asserts rough true-ish result.
-        * @name ok
-        * @function
-        * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
-        */
-       ok: function( result, msg ) {
-               if ( !config.current ) {
-                       throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) );
-               }
-               result = !!result;
-
-               var source,
-                       details = {
-                               module: config.current.module,
-                               name: config.current.testName,
-                               result: result,
-                               message: msg
-                       };
-
-               msg = escapeText( msg || (result ? "okay" : "failed" ) );
-               msg = "<span class='test-message'>" + msg + "</span>";
-
-               if ( !result ) {
-                       source = sourceFromStacktrace( 2 );
-                       if ( source ) {
-                               details.source = source;
-                               msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr></table>";
-                       }
-               }
-               runLoggingCallbacks( "log", QUnit, details );
-               config.current.assertions.push({
-                       result: result,
-                       message: msg
-               });
-       },
-
-       /**
-        * Assert that the first two arguments are equal, with an optional message.
-        * Prints out both actual and expected values.
-        * @name equal
-        * @function
-        * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
-        */
-       equal: function( actual, expected, message ) {
-               /*jshint eqeqeq:false */
-               QUnit.push( expected == actual, actual, expected, message );
-       },
-
-       /**
-        * @name notEqual
-        * @function
-        */
-       notEqual: function( actual, expected, message ) {
-               /*jshint eqeqeq:false */
-               QUnit.push( expected != actual, actual, expected, message );
-       },
-
-       /**
-        * @name propEqual
-        * @function
-        */
-       propEqual: function( actual, expected, message ) {
-               actual = objectValues(actual);
-               expected = objectValues(expected);
-               QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
-       },
-
-       /**
-        * @name notPropEqual
-        * @function
-        */
-       notPropEqual: function( actual, expected, message ) {
-               actual = objectValues(actual);
-               expected = objectValues(expected);
-               QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
-       },
-
-       /**
-        * @name deepEqual
-        * @function
-        */
-       deepEqual: function( actual, expected, message ) {
-               QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
-       },
-
-       /**
-        * @name notDeepEqual
-        * @function
-        */
-       notDeepEqual: function( actual, expected, message ) {
-               QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
-       },
-
-       /**
-        * @name strictEqual
-        * @function
-        */
-       strictEqual: function( actual, expected, message ) {
-               QUnit.push( expected === actual, actual, expected, message );
-       },
-
-       /**
-        * @name notStrictEqual
-        * @function
-        */
-       notStrictEqual: function( actual, expected, message ) {
-               QUnit.push( expected !== actual, actual, expected, message );
-       },
-
-       "throws": function( block, expected, message ) {
-               var actual,
-                       expectedOutput = expected,
-                       ok = false;
-
-               // 'expected' is optional
-               if ( typeof expected === "string" ) {
-                       message = expected;
-                       expected = null;
-               }
-
-               config.current.ignoreGlobalErrors = true;
-               try {
-                       block.call( config.current.testEnvironment );
-               } catch (e) {
-                       actual = e;
-               }
-               config.current.ignoreGlobalErrors = false;
-
-               if ( actual ) {
-                       // we don't want to validate thrown error
-                       if ( !expected ) {
-                               ok = true;
-                               expectedOutput = null;
-                       // expected is a regexp
-                       } else if ( QUnit.objectType( expected ) === "regexp" ) {
-                               ok = expected.test( errorString( actual ) );
-                       // expected is a constructor
-                       } else if ( actual instanceof expected ) {
-                               ok = true;
-                       // expected is a validation function which returns true is validation passed
-                       } else if ( expected.call( {}, actual ) === true ) {
-                               expectedOutput = null;
-                               ok = true;
-                       }
-
-                       QUnit.push( ok, actual, expectedOutput, message );
-               } else {
-                       QUnit.pushFailure( message, null, 'No exception was thrown.' );
-               }
-       }
-};
-
-/**
- * @deprecate since 1.8.0
- * Kept assertion helpers in root for backwards compatibility.
- */
-extend( QUnit, assert );
-
-/**
- * @deprecated since 1.9.0
- * Kept root "raises()" for backwards compatibility.
- * (Note that we don't introduce assert.raises).
- */
-QUnit.raises = assert[ "throws" ];
-
-/**
- * @deprecated since 1.0.0, replaced with error pushes since 1.3.0
- * Kept to avoid TypeErrors for undefined methods.
- */
-QUnit.equals = function() {
-       QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
-};
-QUnit.same = function() {
-       QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" );
-};
-
-// We want access to the constructor's prototype
-(function() {
-       function F() {}
-       F.prototype = QUnit;
-       QUnit = new F();
-       // Make F QUnit's constructor so that we can add to the prototype later
-       QUnit.constructor = F;
-}());
-
-/**
- * Config object: Maintain internal state
- * Later exposed as QUnit.config
- * `config` initialized at top of scope
- */
-config = {
-       // The queue of tests to run
-       queue: [],
-
-       // block until document ready
-       blocking: true,
-
-       // when enabled, show only failing tests
-       // gets persisted through sessionStorage and can be changed in UI via checkbox
-       hidepassed: false,
-
-       // by default, run previously failed tests first
-       // very useful in combination with "Hide passed tests" checked
-       reorder: true,
-
-       // by default, modify document.title when suite is done
-       altertitle: true,
-
-       // when enabled, all tests must call expect()
-       requireExpects: false,
-
-       // add checkboxes that are persisted in the query-string
-       // when enabled, the id is set to `true` as a `QUnit.config` property
-       urlConfig: [
-               {
-                       id: "noglobals",
-                       label: "Check for Globals",
-                       tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."
-               },
-               {
-                       id: "notrycatch",
-                       label: "No try-catch",
-                       tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."
-               }
-       ],
-
-       // Set of all modules.
-       modules: {},
-
-       // logging callback queues
-       begin: [],
-       done: [],
-       log: [],
-       testStart: [],
-       testDone: [],
-       moduleStart: [],
-       moduleDone: []
-};
-
-// Export global variables, unless an 'exports' object exists,
-// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
-if ( typeof exports === "undefined" ) {
-       extend( window, QUnit );
-
-       // Expose QUnit object
-       window.QUnit = QUnit;
-}
-
-// Initialize more QUnit.config and QUnit.urlParams
-(function() {
-       var i,
-               location = window.location || { search: "", protocol: "file:" },
-               params = location.search.slice( 1 ).split( "&" ),
-               length = params.length,
-               urlParams = {},
-               current;
-
-       if ( params[ 0 ] ) {
-               for ( i = 0; i < length; i++ ) {
-                       current = params[ i ].split( "=" );
-                       current[ 0 ] = decodeURIComponent( current[ 0 ] );
-                       // allow just a key to turn on a flag, e.g., test.html?noglobals
-                       current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
-                       urlParams[ current[ 0 ] ] = current[ 1 ];
-               }
-       }
-
-       QUnit.urlParams = urlParams;
-
-       // String search anywhere in moduleName+testName
-       config.filter = urlParams.filter;
-
-       // Exact match of the module name
-       config.module = urlParams.module;
-
-       config.testNumber = parseInt( urlParams.testNumber, 10 ) || null;
-
-       // Figure out if we're running the tests from a server or not
-       QUnit.isLocal = location.protocol === "file:";
-}());
-
-// Extend QUnit object,
-// these after set here because they should not be exposed as global functions
-extend( QUnit, {
-       assert: assert,
-
-       config: config,
-
-       // Initialize the configuration options
-       init: function() {
-               extend( config, {
-                       stats: { all: 0, bad: 0 },
-                       moduleStats: { all: 0, bad: 0 },
-                       started: +new Date(),
-                       updateRate: 1000,
-                       blocking: false,
-                       autostart: true,
-                       autorun: false,
-                       filter: "",
-                       queue: [],
-                       semaphore: 1
-               });
-
-               var tests, banner, result,
-                       qunit = id( "qunit" );
-
-               if ( qunit ) {
-                       qunit.innerHTML =
-                               "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
-                               "<h2 id='qunit-banner'></h2>" +
-                               "<div id='qunit-testrunner-toolbar'></div>" +
-                               "<h2 id='qunit-userAgent'></h2>" +
-                               "<ol id='qunit-tests'></ol>";
-               }
-
-               tests = id( "qunit-tests" );
-               banner = id( "qunit-banner" );
-               result = id( "qunit-testresult" );
-
-               if ( tests ) {
-                       tests.innerHTML = "";
-               }
-
-               if ( banner ) {
-                       banner.className = "";
-               }
-
-               if ( result ) {
-                       result.parentNode.removeChild( result );
-               }
-
-               if ( tests ) {
-                       result = document.createElement( "p" );
-                       result.id = "qunit-testresult";
-                       result.className = "result";
-                       tests.parentNode.insertBefore( result, tests );
-                       result.innerHTML = "Running...<br/>&nbsp;";
-               }
-       },
-
-       // Resets the test setup. Useful for tests that modify the DOM.
-       reset: function() {
-               var fixture = id( "qunit-fixture" );
-               if ( fixture ) {
-                       fixture.innerHTML = config.fixture;
-               }
-       },
-
-       // Trigger an event on an element.
-       // @example triggerEvent( document.body, "click" );
-       triggerEvent: function( elem, type, event ) {
-               if ( document.createEvent ) {
-                       event = document.createEvent( "MouseEvents" );
-                       event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
-                               0, 0, 0, 0, 0, false, false, false, false, 0, null);
-
-                       elem.dispatchEvent( event );
-               } else if ( elem.fireEvent ) {
-                       elem.fireEvent( "on" + type );
-               }
-       },
-
-       // Safe object type checking
-       is: function( type, obj ) {
-               return QUnit.objectType( obj ) === type;
-       },
-
-       objectType: function( obj ) {
-               if ( typeof obj === "undefined" ) {
-                               return "undefined";
-               // consider: typeof null === object
-               }
-               if ( obj === null ) {
-                               return "null";
-               }
-
-               var match = toString.call( obj ).match(/^\[object\s(.*)\]$/),
-                       type = match && match[1] || "";
-
-               switch ( type ) {
-                       case "Number":
-                               if ( isNaN(obj) ) {
-                                       return "nan";
-                               }
-                               return "number";
-                       case "String":
-                       case "Boolean":
-                       case "Array":
-                       case "Date":
-                       case "RegExp":
-                       case "Function":
-                               return type.toLowerCase();
-               }
-               if ( typeof obj === "object" ) {
-                       return "object";
-               }
-               return undefined;
-       },
-
-       push: function( result, actual, expected, message ) {
-               if ( !config.current ) {
-                       throw new Error( "assertion outside test context, was " + sourceFromStacktrace() );
-               }
-
-               var output, source,
-                       details = {
-                               module: config.current.module,
-                               name: config.current.testName,
-                               result: result,
-                               message: message,
-                               actual: actual,
-                               expected: expected
-                       };
-
-               message = escapeText( message ) || ( result ? "okay" : "failed" );
-               message = "<span class='test-message'>" + message + "</span>";
-               output = message;
-
-               if ( !result ) {
-                       expected = escapeText( QUnit.jsDump.parse(expected) );
-                       actual = escapeText( QUnit.jsDump.parse(actual) );
-                       output += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>";
-
-                       if ( actual !== expected ) {
-                               output += "<tr class='test-actual'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>";
-                               output += "<tr class='test-diff'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>";
-                       }
-
-                       source = sourceFromStacktrace();
-
-                       if ( source ) {
-                               details.source = source;
-                               output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
-                       }
-
-                       output += "</table>";
-               }
-
-               runLoggingCallbacks( "log", QUnit, details );
-
-               config.current.assertions.push({
-                       result: !!result,
-                       message: output
-               });
-       },
-
-       pushFailure: function( message, source, actual ) {
-               if ( !config.current ) {
-                       throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
-               }
-
-               var output,
-                       details = {
-                               module: config.current.module,
-                               name: config.current.testName,
-                               result: false,
-                               message: message
-                       };
-
-               message = escapeText( message ) || "error";
-               message = "<span class='test-message'>" + message + "</span>";
-               output = message;
-
-               output += "<table>";
-
-               if ( actual ) {
-                       output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>";
-               }
-
-               if ( source ) {
-                       details.source = source;
-                       output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
-               }
-
-               output += "</table>";
-
-               runLoggingCallbacks( "log", QUnit, details );
-
-               config.current.assertions.push({
-                       result: false,
-                       message: output
-               });
-       },
-
-       url: function( params ) {
-               params = extend( extend( {}, QUnit.urlParams ), params );
-               var key,
-                       querystring = "?";
-
-               for ( key in params ) {
-                       if ( !hasOwn.call( params, key ) ) {
-                               continue;
-                       }
-                       querystring += encodeURIComponent( key ) + "=" +
-                               encodeURIComponent( params[ key ] ) + "&";
-               }
-               return window.location.protocol + "//" + window.location.host +
-                       window.location.pathname + querystring.slice( 0, -1 );
-       },
-
-       extend: extend,
-       id: id,
-       addEvent: addEvent
-       // load, equiv, jsDump, diff: Attached later
-});
-
-/**
- * @deprecated: Created for backwards compatibility with test runner that set the hook function
- * into QUnit.{hook}, instead of invoking it and passing the hook function.
- * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.
- * Doing this allows us to tell if the following methods have been overwritten on the actual
- * QUnit object.
- */
-extend( QUnit.constructor.prototype, {
-
-       // Logging callbacks; all receive a single argument with the listed properties
-       // run test/logs.html for any related changes
-       begin: registerLoggingCallback( "begin" ),
-
-       // done: { failed, passed, total, runtime }
-       done: registerLoggingCallback( "done" ),
-
-       // log: { result, actual, expected, message }
-       log: registerLoggingCallback( "log" ),
-
-       // testStart: { name }
-       testStart: registerLoggingCallback( "testStart" ),
-
-       // testDone: { name, failed, passed, total, duration }
-       testDone: registerLoggingCallback( "testDone" ),
-
-       // moduleStart: { name }
-       moduleStart: registerLoggingCallback( "moduleStart" ),
-
-       // moduleDone: { name, failed, passed, total }
-       moduleDone: registerLoggingCallback( "moduleDone" )
-});
-
-if ( typeof document === "undefined" || document.readyState === "complete" ) {
-       config.autorun = true;
-}
-
-QUnit.load = function() {
-       runLoggingCallbacks( "begin", QUnit, {} );
-
-       // Initialize the config, saving the execution queue
-       var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
-               urlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,
-               numModules = 0,
-               moduleFilterHtml = "",
-               urlConfigHtml = "",
-               oldconfig = extend( {}, config );
-
-       QUnit.init();
-       extend(config, oldconfig);
-
-       config.blocking = false;
-
-       len = config.urlConfig.length;
-
-       for ( i = 0; i < len; i++ ) {
-               val = config.urlConfig[i];
-               if ( typeof val === "string" ) {
-                       val = {
-                               id: val,
-                               label: val,
-                               tooltip: "[no tooltip available]"
-                       };
-               }
-               config[ val.id ] = QUnit.urlParams[ val.id ];
-               urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
-                       "' name='" + escapeText( val.id ) +
-                       "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) +
-                       " title='" + escapeText( val.tooltip ) +
-                       "'><label for='qunit-urlconfig-" + escapeText( val.id ) +
-                       "' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
-       }
-
-       moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " +
-               ( config.module === undefined  ? "selected='selected'" : "" ) +
-               ">< All Modules ></option>";
-
-       for ( i in config.modules ) {
-               if ( config.modules.hasOwnProperty( i ) ) {
-                       numModules += 1;
-                       moduleFilterHtml += "<option value='" + escapeText( encodeURIComponent(i) ) + "' " +
-                               ( config.module === i ? "selected='selected'" : "" ) +
-                               ">" + escapeText(i) + "</option>";
-               }
-       }
-       moduleFilterHtml += "</select>";
-
-       // `userAgent` initialized at top of scope
-       userAgent = id( "qunit-userAgent" );
-       if ( userAgent ) {
-               userAgent.innerHTML = navigator.userAgent;
-       }
-
-       // `banner` initialized at top of scope
-       banner = id( "qunit-header" );
-       if ( banner ) {
-               banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "'>" + banner.innerHTML + "</a> ";
-       }
-
-       // `toolbar` initialized at top of scope
-       toolbar = id( "qunit-testrunner-toolbar" );
-       if ( toolbar ) {
-               // `filter` initialized at top of scope
-               filter = document.createElement( "input" );
-               filter.type = "checkbox";
-               filter.id = "qunit-filter-pass";
-
-               addEvent( filter, "click", function() {
-                       var tmp,
-                               ol = document.getElementById( "qunit-tests" );
-
-                       if ( filter.checked ) {
-                               ol.className = ol.className + " hidepass";
-                       } else {
-                               tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
-                               ol.className = tmp.replace( / hidepass /, " " );
-                       }
-                       if ( defined.sessionStorage ) {
-                               if (filter.checked) {
-                                       sessionStorage.setItem( "qunit-filter-passed-tests", "true" );
-                               } else {
-                                       sessionStorage.removeItem( "qunit-filter-passed-tests" );
-                               }
-                       }
-               });
-
-               if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) {
-                       filter.checked = true;
-                       // `ol` initialized at top of scope
-                       ol = document.getElementById( "qunit-tests" );
-                       ol.className = ol.className + " hidepass";
-               }
-               toolbar.appendChild( filter );
-
-               // `label` initialized at top of scope
-               label = document.createElement( "label" );
-               label.setAttribute( "for", "qunit-filter-pass" );
-               label.setAttribute( "title", "Only show tests and assertons that fail. Stored in sessionStorage." );
-               label.innerHTML = "Hide passed tests";
-               toolbar.appendChild( label );
-
-               urlConfigCheckboxesContainer = document.createElement("span");
-               urlConfigCheckboxesContainer.innerHTML = urlConfigHtml;
-               urlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName("input");
-               // For oldIE support:
-               // * Add handlers to the individual elements instead of the container
-               // * Use "click" instead of "change"
-               // * Fallback from event.target to event.srcElement
-               addEvents( urlConfigCheckboxes, "click", function( event ) {
-                       var params = {},
-                               target = event.target || event.srcElement;
-                       params[ target.name ] = target.checked ? true : undefined;
-                       window.location = QUnit.url( params );
-               });
-               toolbar.appendChild( urlConfigCheckboxesContainer );
-
-               if (numModules > 1) {
-                       moduleFilter = document.createElement( 'span' );
-                       moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
-                       moduleFilter.innerHTML = moduleFilterHtml;
-                       addEvent( moduleFilter.lastChild, "change", function() {
-                               var selectBox = moduleFilter.getElementsByTagName("select")[0],
-                                       selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
-
-                               window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
-                       });
-                       toolbar.appendChild(moduleFilter);
-               }
-       }
-
-       // `main` initialized at top of scope
-       main = id( "qunit-fixture" );
-       if ( main ) {
-               config.fixture = main.innerHTML;
-       }
-
-       if ( config.autostart ) {
-               QUnit.start();
-       }
-};
-
-addEvent( window, "load", QUnit.load );
-
-// `onErrorFnPrev` initialized at top of scope
-// Preserve other handlers
-onErrorFnPrev = window.onerror;
-
-// Cover uncaught exceptions
-// Returning true will surpress the default browser handler,
-// returning false will let it run.
-window.onerror = function ( error, filePath, linerNr ) {
-       var ret = false;
-       if ( onErrorFnPrev ) {
-               ret = onErrorFnPrev( error, filePath, linerNr );
-       }
-
-       // Treat return value as window.onerror itself does,
-       // Only do our handling if not surpressed.
-       if ( ret !== true ) {
-               if ( QUnit.config.current ) {
-                       if ( QUnit.config.current.ignoreGlobalErrors ) {
-                               return true;
-                       }
-                       QUnit.pushFailure( error, filePath + ":" + linerNr );
-               } else {
-                       QUnit.test( "global failure", extend( function() {
-                               QUnit.pushFailure( error, filePath + ":" + linerNr );
-                       }, { validTest: validTest } ) );
-               }
-               return false;
-       }
-
-       return ret;
-};
-
-function done() {
-       config.autorun = true;
-
-       // Log the last module results
-       if ( config.currentModule ) {
-               runLoggingCallbacks( "moduleDone", QUnit, {
-                       name: config.currentModule,
-                       failed: config.moduleStats.bad,
-                       passed: config.moduleStats.all - config.moduleStats.bad,
-                       total: config.moduleStats.all
-               });
-       }
-
-       var i, key,
-               banner = id( "qunit-banner" ),
-               tests = id( "qunit-tests" ),
-               runtime = +new Date() - config.started,
-               passed = config.stats.all - config.stats.bad,
-               html = [
-                       "Tests completed in ",
-                       runtime,
-                       " milliseconds.<br/>",
-                       "<span class='passed'>",
-                       passed,
-                       "</span> assertions of <span class='total'>",
-                       config.stats.all,
-                       "</span> passed, <span class='failed'>",
-                       config.stats.bad,
-                       "</span> failed."
-               ].join( "" );
-
-       if ( banner ) {
-               banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" );
-       }
-
-       if ( tests ) {
-               id( "qunit-testresult" ).innerHTML = html;
-       }
-
-       if ( config.altertitle && typeof document !== "undefined" && document.title ) {
-               // show ✖ for good, ✔ for bad suite result in title
-               // use escape sequences in case file gets loaded with non-utf-8-charset
-               document.title = [
-                       ( config.stats.bad ? "\u2716" : "\u2714" ),
-                       document.title.replace( /^[\u2714\u2716] /i, "" )
-               ].join( " " );
-       }
-
-       // clear own sessionStorage items if all tests passed
-       if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {
-               // `key` & `i` initialized at top of scope
-               for ( i = 0; i < sessionStorage.length; i++ ) {
-                       key = sessionStorage.key( i++ );
-                       if ( key.indexOf( "qunit-test-" ) === 0 ) {
-                               sessionStorage.removeItem( key );
-                       }
-               }
-       }
-
-       // scroll back to top to show results
-       if ( window.scrollTo ) {
-               window.scrollTo(0, 0);
-       }
-
-       runLoggingCallbacks( "done", QUnit, {
-               failed: config.stats.bad,
-               passed: passed,
-               total: config.stats.all,
-               runtime: runtime
-       });
-}
-
-/** @return Boolean: true if this test should be ran */
-function validTest( test ) {
-       var include,
-               filter = config.filter && config.filter.toLowerCase(),
-               module = config.module && config.module.toLowerCase(),
-               fullName = (test.module + ": " + test.testName).toLowerCase();
-
-       // Internally-generated tests are always valid
-       if ( test.callback && test.callback.validTest === validTest ) {
-               delete test.callback.validTest;
-               return true;
-       }
-
-       if ( config.testNumber ) {
-               return test.testNumber === config.testNumber;
-       }
-
-       if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
-               return false;
-       }
-
-       if ( !filter ) {
-               return true;
-       }
-
-       include = filter.charAt( 0 ) !== "!";
-       if ( !include ) {
-               filter = filter.slice( 1 );
-       }
-
-       // If the filter matches, we need to honour include
-       if ( fullName.indexOf( filter ) !== -1 ) {
-               return include;
-       }
-
-       // Otherwise, do the opposite
-       return !include;
-}
-
-// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)
-// Later Safari and IE10 are supposed to support error.stack as well
-// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
-function extractStacktrace( e, offset ) {
-       offset = offset === undefined ? 3 : offset;
-
-       var stack, include, i;
-
-       if ( e.stacktrace ) {
-               // Opera
-               return e.stacktrace.split( "\n" )[ offset + 3 ];
-       } else if ( e.stack ) {
-               // Firefox, Chrome
-               stack = e.stack.split( "\n" );
-               if (/^error$/i.test( stack[0] ) ) {
-                       stack.shift();
-               }
-               if ( fileName ) {
-                       include = [];
-                       for ( i = offset; i < stack.length; i++ ) {
-                               if ( stack[ i ].indexOf( fileName ) !== -1 ) {
-                                       break;
-                               }
-                               include.push( stack[ i ] );
-                       }
-                       if ( include.length ) {
-                               return include.join( "\n" );
-                       }
-               }
-               return stack[ offset ];
-       } else if ( e.sourceURL ) {
-               // Safari, PhantomJS
-               // hopefully one day Safari provides actual stacktraces
-               // exclude useless self-reference for generated Error objects
-               if ( /qunit.js$/.test( e.sourceURL ) ) {
-                       return;
-               }
-               // for actual exceptions, this is useful
-               return e.sourceURL + ":" + e.line;
-       }
-}
-function sourceFromStacktrace( offset ) {
-       try {
-               throw new Error();
-       } catch ( e ) {
-               return extractStacktrace( e, offset );
-       }
-}
-
-/**
- * Escape text for attribute or text content.
- */
-function escapeText( s ) {
-       if ( !s ) {
-               return "";
-       }
-       s = s + "";
-       // Both single quotes and double quotes (for attributes)
-       return s.replace( /['"<>&]/g, function( s ) {
-               switch( s ) {
-                       case '\'':
-                               return '&#039;';
-                       case '"':
-                               return '&quot;';
-                       case '<':
-                               return '&lt;';
-                       case '>':
-                               return '&gt;';
-                       case '&':
-                               return '&amp;';
-               }
-       });
-}
-
-function synchronize( callback, last ) {
-       config.queue.push( callback );
-
-       if ( config.autorun && !config.blocking ) {
-               process( last );
-       }
-}
-
-function process( last ) {
-       function next() {
-               process( last );
-       }
-       var start = new Date().getTime();
-       config.depth = config.depth ? config.depth + 1 : 1;
-
-       while ( config.queue.length && !config.blocking ) {
-               if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {
-                       config.queue.shift()();
-               } else {
-                       window.setTimeout( next, 13 );
-                       break;
-               }
-       }
-       config.depth--;
-       if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {
-               done();
-       }
-}
-
-function saveGlobal() {
-       config.pollution = [];
-
-       if ( config.noglobals ) {
-               for ( var key in window ) {
-                       // in Opera sometimes DOM element ids show up here, ignore them
-                       if ( !hasOwn.call( window, key ) || /^qunit-test-output/.test( key ) ) {
-                               continue;
-                       }
-                       config.pollution.push( key );
-               }
-       }
-}
-
-function checkPollution() {
-       var newGlobals,
-               deletedGlobals,
-               old = config.pollution;
-
-       saveGlobal();
-
-       newGlobals = diff( config.pollution, old );
-       if ( newGlobals.length > 0 ) {
-               QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") );
-       }
-
-       deletedGlobals = diff( old, config.pollution );
-       if ( deletedGlobals.length > 0 ) {
-               QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") );
-       }
-}
-
-// returns a new Array with the elements that are in a but not in b
-function diff( a, b ) {
-       var i, j,
-               result = a.slice();
-
-       for ( i = 0; i < result.length; i++ ) {
-               for ( j = 0; j < b.length; j++ ) {
-                       if ( result[i] === b[j] ) {
-                               result.splice( i, 1 );
-                               i--;
-                               break;
-                       }
-               }
-       }
-       return result;
-}
-
-function extend( a, b ) {
-       for ( var prop in b ) {
-               if ( b[ prop ] === undefined ) {
-                       delete a[ prop ];
-
-               // Avoid "Member not found" error in IE8 caused by setting window.constructor
-               } else if ( prop !== "constructor" || a !== window ) {
-                       a[ prop ] = b[ prop ];
-               }
-       }
-
-       return a;
-}
-
-/**
- * @param {HTMLElement} elem
- * @param {string} type
- * @param {Function} fn
- */
-function addEvent( elem, type, fn ) {
-       // Standards-based browsers
-       if ( elem.addEventListener ) {
-               elem.addEventListener( type, fn, false );
-       // IE
-       } else {
-               elem.attachEvent( "on" + type, fn );
-       }
-}
-
-/**
- * @param {Array|NodeList} elems
- * @param {string} type
- * @param {Function} fn
- */
-function addEvents( elems, type, fn ) {
-       var i = elems.length;
-       while ( i-- ) {
-               addEvent( elems[i], type, fn );
-       }
-}
-
-function hasClass( elem, name ) {
-       return (" " + elem.className + " ").indexOf(" " + name + " ") > -1;
-}
-
-function addClass( elem, name ) {
-       if ( !hasClass( elem, name ) ) {
-               elem.className += (elem.className ? " " : "") + name;
-       }
-}
-
-function removeClass( elem, name ) {
-       var set = " " + elem.className + " ";
-       // Class name may appear multiple times
-       while ( set.indexOf(" " + name + " ") > -1 ) {
-               set = set.replace(" " + name + " " , " ");
-       }
-       // If possible, trim it for prettiness, but not neccecarily
-       elem.className = window.jQuery ? jQuery.trim( set ) : ( set.trim ? set.trim() : set );
-}
-
-function id( name ) {
-       return !!( typeof document !== "undefined" && document && document.getElementById ) &&
-               document.getElementById( name );
-}
-
-function registerLoggingCallback( key ) {
-       return function( callback ) {
-               config[key].push( callback );
-       };
-}
-
-// Supports deprecated method of completely overwriting logging callbacks
-function runLoggingCallbacks( key, scope, args ) {
-       var i, callbacks;
-       if ( QUnit.hasOwnProperty( key ) ) {
-               QUnit[ key ].call(scope, args );
-       } else {
-               callbacks = config[ key ];
-               for ( i = 0; i < callbacks.length; i++ ) {
-                       callbacks[ i ].call( scope, args );
-               }
-       }
-}
-
-// Test for equality any JavaScript type.
-// Author: Philippe Rathé <prathe@gmail.com>
-QUnit.equiv = (function() {
-
-       // Call the o related callback with the given arguments.
-       function bindCallbacks( o, callbacks, args ) {
-               var prop = QUnit.objectType( o );
-               if ( prop ) {
-                       if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) {
-                               return callbacks[ prop ].apply( callbacks, args );
-                       } else {
-                               return callbacks[ prop ]; // or undefined
-                       }
-               }
-       }
-
-       // the real equiv function
-       var innerEquiv,
-               // stack to decide between skip/abort functions
-               callers = [],
-               // stack to avoiding loops from circular referencing
-               parents = [],
-
-               getProto = Object.getPrototypeOf || function ( obj ) {
-                       return obj.__proto__;
-               },
-               callbacks = (function () {
-
-                       // for string, boolean, number and null
-                       function useStrictEquality( b, a ) {
-                               /*jshint eqeqeq:false */
-                               if ( b instanceof a.constructor || a instanceof b.constructor ) {
-                                       // to catch short annotaion VS 'new' annotation of a
-                                       // declaration
-                                       // e.g. var i = 1;
-                                       // var j = new Number(1);
-                                       return a == b;
-                               } else {
-                                       return a === b;
-                               }
-                       }
-
-                       return {
-                               "string": useStrictEquality,
-                               "boolean": useStrictEquality,
-                               "number": useStrictEquality,
-                               "null": useStrictEquality,
-                               "undefined": useStrictEquality,
-
-                               "nan": function( b ) {
-                                       return isNaN( b );
-                               },
-
-                               "date": function( b, a ) {
-                                       return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf();
-                               },
-
-                               "regexp": function( b, a ) {
-                                       return QUnit.objectType( b ) === "regexp" &&
-                                               // the regex itself
-                                               a.source === b.source &&
-                                               // and its modifers
-                                               a.global === b.global &&
-                                               // (gmi) ...
-                                               a.ignoreCase === b.ignoreCase &&
-                                               a.multiline === b.multiline &&
-                                               a.sticky === b.sticky;
-                               },
-
-                               // - skip when the property is a method of an instance (OOP)
-                               // - abort otherwise,
-                               // initial === would have catch identical references anyway
-                               "function": function() {
-                                       var caller = callers[callers.length - 1];
-                                       return caller !== Object && typeof caller !== "undefined";
-                               },
-
-                               "array": function( b, a ) {
-                                       var i, j, len, loop;
-
-                                       // b could be an object literal here
-                                       if ( QUnit.objectType( b ) !== "array" ) {
-                                               return false;
-                                       }
-
-                                       len = a.length;
-                                       if ( len !== b.length ) {
-                                               // safe and faster
-                                               return false;
-                                       }
-
-                                       // track reference to avoid circular references
-                                       parents.push( a );
-                                       for ( i = 0; i < len; i++ ) {
-                                               loop = false;
-                                               for ( j = 0; j < parents.length; j++ ) {
-                                                       if ( parents[j] === a[i] ) {
-                                                               loop = true;// dont rewalk array
-                                                       }
-                                               }
-                                               if ( !loop && !innerEquiv(a[i], b[i]) ) {
-                                                       parents.pop();
-                                                       return false;
-                                               }
-                                       }
-                                       parents.pop();
-                                       return true;
-                               },
-
-                               "object": function( b, a ) {
-                                       var i, j, loop,
-                                               // Default to true
-                                               eq = true,
-                                               aProperties = [],
-                                               bProperties = [];
-
-                                       // comparing constructors is more strict than using
-                                       // instanceof
-                                       if ( a.constructor !== b.constructor ) {
-                                               // Allow objects with no prototype to be equivalent to
-                                               // objects with Object as their constructor.
-                                               if ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||
-                                                       ( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {
-                                                               return false;
-                                               }
-                                       }
-
-                                       // stack constructor before traversing properties
-                                       callers.push( a.constructor );
-                                       // track reference to avoid circular references
-                                       parents.push( a );
-
-                                       for ( i in a ) { // be strict: don't ensures hasOwnProperty
-                                                                       // and go deep
-                                               loop = false;
-                                               for ( j = 0; j < parents.length; j++ ) {
-                                                       if ( parents[j] === a[i] ) {
-                                                               // don't go down the same path twice
-                                                               loop = true;
-                                                       }
-                                               }
-                                               aProperties.push(i); // collect a's properties
-
-                                               if (!loop && !innerEquiv( a[i], b[i] ) ) {
-                                                       eq = false;
-                                                       break;
-                                               }
-                                       }
-
-                                       callers.pop(); // unstack, we are done
-                                       parents.pop();
-
-                                       for ( i in b ) {
-                                               bProperties.push( i ); // collect b's properties
-                                       }
-
-                                       // Ensures identical properties name
-                                       return eq && innerEquiv( aProperties.sort(), bProperties.sort() );
-                               }
-                       };
-               }());
-
-       innerEquiv = function() { // can take multiple arguments
-               var args = [].slice.apply( arguments );
-               if ( args.length < 2 ) {
-                       return true; // end transition
-               }
-
-               return (function( a, b ) {
-                       if ( a === b ) {
-                               return true; // catch the most you can
-                       } else if ( a === null || b === null || typeof a === "undefined" ||
-                                       typeof b === "undefined" ||
-                                       QUnit.objectType(a) !== QUnit.objectType(b) ) {
-                               return false; // don't lose time with error prone cases
-                       } else {
-                               return bindCallbacks(a, callbacks, [ b, a ]);
-                       }
-
-                       // apply transition with (1..n) arguments
-               }( args[0], args[1] ) && arguments.callee.apply( this, args.splice(1, args.length - 1 )) );
-       };
-
-       return innerEquiv;
-}());
-
-/**
- * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
- * http://flesler.blogspot.com Licensed under BSD
- * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
- *
- * @projectDescription Advanced and extensible data dumping for Javascript.
- * @version 1.0.0
- * @author Ariel Flesler
- * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
- */
-QUnit.jsDump = (function() {
-       function quote( str ) {
-               return '"' + str.toString().replace( /"/g, '\\"' ) + '"';
-       }
-       function literal( o ) {
-               return o + "";
-       }
-       function join( pre, arr, post ) {
-               var s = jsDump.separator(),
-                       base = jsDump.indent(),
-                       inner = jsDump.indent(1);
-               if ( arr.join ) {
-                       arr = arr.join( "," + s + inner );
-               }
-               if ( !arr ) {
-                       return pre + post;
-               }
-               return [ pre, inner + arr, base + post ].join(s);
-       }
-       function array( arr, stack ) {
-               var i = arr.length, ret = new Array(i);
-               this.up();
-               while ( i-- ) {
-                       ret[i] = this.parse( arr[i] , undefined , stack);
-               }
-               this.down();
-               return join( "[", ret, "]" );
-       }
-
-       var reName = /^function (\w+)/,
-               jsDump = {
-                       // type is used mostly internally, you can fix a (custom)type in advance
-                       parse: function( obj, type, stack ) {
-                               stack = stack || [ ];
-                               var inStack, res,
-                                       parser = this.parsers[ type || this.typeOf(obj) ];
-
-                               type = typeof parser;
-                               inStack = inArray( obj, stack );
-
-                               if ( inStack !== -1 ) {
-                                       return "recursion(" + (inStack - stack.length) + ")";
-                               }
-                               if ( type === "function" )  {
-                                       stack.push( obj );
-                                       res = parser.call( this, obj, stack );
-                                       stack.pop();
-                                       return res;
-                               }
-                               return ( type === "string" ) ? parser : this.parsers.error;
-                       },
-                       typeOf: function( obj ) {
-                               var type;
-                               if ( obj === null ) {
-                                       type = "null";
-                               } else if ( typeof obj === "undefined" ) {
-                                       type = "undefined";
-                               } else if ( QUnit.is( "regexp", obj) ) {
-                                       type = "regexp";
-                               } else if ( QUnit.is( "date", obj) ) {
-                                       type = "date";
-                               } else if ( QUnit.is( "function", obj) ) {
-                                       type = "function";
-                               } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) {
-                                       type = "window";
-                               } else if ( obj.nodeType === 9 ) {
-                                       type = "document";
-                               } else if ( obj.nodeType ) {
-                                       type = "node";
-                               } else if (
-                                       // native arrays
-                                       toString.call( obj ) === "[object Array]" ||
-                                       // NodeList objects
-                                       ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
-                               ) {
-                                       type = "array";
-                               } else if ( obj.constructor === Error.prototype.constructor ) {
-                                       type = "error";
-                               } else {
-                                       type = typeof obj;
-                               }
-                               return type;
-                       },
-                       separator: function() {
-                               return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&nbsp;" : " ";
-                       },
-                       // extra can be a number, shortcut for increasing-calling-decreasing
-                       indent: function( extra ) {
-                               if ( !this.multiline ) {
-                                       return "";
-                               }
-                               var chr = this.indentChar;
-                               if ( this.HTML ) {
-                                       chr = chr.replace( /\t/g, "   " ).replace( / /g, "&nbsp;" );
-                               }
-                               return new Array( this._depth_ + (extra||0) ).join(chr);
-                       },
-                       up: function( a ) {
-                               this._depth_ += a || 1;
-                       },
-                       down: function( a ) {
-                               this._depth_ -= a || 1;
-                       },
-                       setParser: function( name, parser ) {
-                               this.parsers[name] = parser;
-                       },
-                       // The next 3 are exposed so you can use them
-                       quote: quote,
-                       literal: literal,
-                       join: join,
-                       //
-                       _depth_: 1,
-                       // This is the list of parsers, to modify them, use jsDump.setParser
-                       parsers: {
-                               window: "[Window]",
-                               document: "[Document]",
-                               error: function(error) {
-                                       return "Error(\"" + error.message + "\")";
-                               },
-                               unknown: "[Unknown]",
-                               "null": "null",
-                               "undefined": "undefined",
-                               "function": function( fn ) {
-                                       var ret = "function",
-                                               // functions never have name in IE
-                                               name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
-
-                                       if ( name ) {
-                                               ret += " " + name;
-                                       }
-                                       ret += "( ";
-
-                                       ret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" );
-                                       return join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" );
-                               },
-                               array: array,
-                               nodelist: array,
-                               "arguments": array,
-                               object: function( map, stack ) {
-                                       var ret = [ ], keys, key, val, i;
-                                       QUnit.jsDump.up();
-                                       keys = [];
-                                       for ( key in map ) {
-                                               keys.push( key );
-                                       }
-                                       keys.sort();
-                                       for ( i = 0; i < keys.length; i++ ) {
-                                               key = keys[ i ];
-                                               val = map[ key ];
-                                               ret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) );
-                                       }
-                                       QUnit.jsDump.down();
-                                       return join( "{", ret, "}" );
-                               },
-                               node: function( node ) {
-                                       var len, i, val,
-                                               open = QUnit.jsDump.HTML ? "&lt;" : "<",
-                                               close = QUnit.jsDump.HTML ? "&gt;" : ">",
-                                               tag = node.nodeName.toLowerCase(),
-                                               ret = open + tag,
-                                               attrs = node.attributes;
-
-                                       if ( attrs ) {
-                                               for ( i = 0, len = attrs.length; i < len; i++ ) {
-                                                       val = attrs[i].nodeValue;
-                                                       // IE6 includes all attributes in .attributes, even ones not explicitly set.
-                                                       // Those have values like undefined, null, 0, false, "" or "inherit".
-                                                       if ( val && val !== "inherit" ) {
-                                                               ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" );
-                                                       }
-                                               }
-                                       }
-                                       ret += close;
-
-                                       // Show content of TextNode or CDATASection
-                                       if ( node.nodeType === 3 || node.nodeType === 4 ) {
-                                               ret += node.nodeValue;
-                                       }
-
-                                       return ret + open + "/" + tag + close;
-                               },
-                               // function calls it internally, it's the arguments part of the function
-                               functionArgs: function( fn ) {
-                                       var args,
-                                               l = fn.length;
-
-                                       if ( !l ) {
-                                               return "";
-                                       }
-
-                                       args = new Array(l);
-                                       while ( l-- ) {
-                                               // 97 is 'a'
-                                               args[l] = String.fromCharCode(97+l);
-                                       }
-                                       return " " + args.join( ", " ) + " ";
-                               },
-                               // object calls it internally, the key part of an item in a map
-                               key: quote,
-                               // function calls it internally, it's the content of the function
-                               functionCode: "[code]",
-                               // node calls it internally, it's an html attribute value
-                               attribute: quote,
-                               string: quote,
-                               date: quote,
-                               regexp: literal,
-                               number: literal,
-                               "boolean": literal
-                       },
-                       // if true, entities are escaped ( <, >, \t, space and \n )
-                       HTML: false,
-                       // indentation unit
-                       indentChar: "  ",
-                       // if true, items in a collection, are separated by a \n, else just a space.
-                       multiline: true
-               };
-
-       return jsDump;
-}());
-
-// from jquery.js
-function inArray( elem, array ) {
-       if ( array.indexOf ) {
-               return array.indexOf( elem );
-       }
-
-       for ( var i = 0, length = array.length; i < length; i++ ) {
-               if ( array[ i ] === elem ) {
-                       return i;
-               }
-       }
-
-       return -1;
-}
-
-/*
- * Javascript Diff Algorithm
- *  By John Resig (http://ejohn.org/)
- *  Modified by Chu Alan "sprite"
- *
- * Released under the MIT license.
- *
- * More Info:
- *  http://ejohn.org/projects/javascript-diff-algorithm/
- *
- * Usage: QUnit.diff(expected, actual)
- *
- * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
- */
-QUnit.diff = (function() {
-       /*jshint eqeqeq:false, eqnull:true */
-       function diff( o, n ) {
-               var i,
-                       ns = {},
-                       os = {};
-
-               for ( i = 0; i < n.length; i++ ) {
-                       if ( !hasOwn.call( ns, n[i] ) ) {
-                               ns[ n[i] ] = {
-                                       rows: [],
-                                       o: null
-                               };
-                       }
-                       ns[ n[i] ].rows.push( i );
-               }
-
-               for ( i = 0; i < o.length; i++ ) {
-                       if ( !hasOwn.call( os, o[i] ) ) {
-                               os[ o[i] ] = {
-                                       rows: [],
-                                       n: null
-                               };
-                       }
-                       os[ o[i] ].rows.push( i );
-               }
-
-               for ( i in ns ) {
-                       if ( !hasOwn.call( ns, i ) ) {
-                               continue;
-                       }
-                       if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {
-                               n[ ns[i].rows[0] ] = {
-                                       text: n[ ns[i].rows[0] ],
-                                       row: os[i].rows[0]
-                               };
-                               o[ os[i].rows[0] ] = {
-                                       text: o[ os[i].rows[0] ],
-                                       row: ns[i].rows[0]
-                               };
-                       }
-               }
-
-               for ( i = 0; i < n.length - 1; i++ ) {
-                       if ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
-                                               n[ i + 1 ] == o[ n[i].row + 1 ] ) {
-
-                               n[ i + 1 ] = {
-                                       text: n[ i + 1 ],
-                                       row: n[i].row + 1
-                               };
-                               o[ n[i].row + 1 ] = {
-                                       text: o[ n[i].row + 1 ],
-                                       row: i + 1
-                               };
-                       }
-               }
-
-               for ( i = n.length - 1; i > 0; i-- ) {
-                       if ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
-                                               n[ i - 1 ] == o[ n[i].row - 1 ]) {
-
-                               n[ i - 1 ] = {
-                                       text: n[ i - 1 ],
-                                       row: n[i].row - 1
-                               };
-                               o[ n[i].row - 1 ] = {
-                                       text: o[ n[i].row - 1 ],
-                                       row: i - 1
-                               };
-                       }
-               }
-
-               return {
-                       o: o,
-                       n: n
-               };
-       }
-
-       return function( o, n ) {
-               o = o.replace( /\s+$/, "" );
-               n = n.replace( /\s+$/, "" );
-
-               var i, pre,
-                       str = "",
-                       out = diff( o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/) ),
-                       oSpace = o.match(/\s+/g),
-                       nSpace = n.match(/\s+/g);
-
-               if ( oSpace == null ) {
-                       oSpace = [ " " ];
-               }
-               else {
-                       oSpace.push( " " );
-               }
-
-               if ( nSpace == null ) {
-                       nSpace = [ " " ];
-               }
-               else {
-                       nSpace.push( " " );
-               }
-
-               if ( out.n.length === 0 ) {
-                       for ( i = 0; i < out.o.length; i++ ) {
-                               str += "<del>" + out.o[i] + oSpace[i] + "</del>";
-                       }
-               }
-               else {
-                       if ( out.n[0].text == null ) {
-                               for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {
-                                       str += "<del>" + out.o[n] + oSpace[n] + "</del>";
-                               }
-                       }
-
-                       for ( i = 0; i < out.n.length; i++ ) {
-                               if (out.n[i].text == null) {
-                                       str += "<ins>" + out.n[i] + nSpace[i] + "</ins>";
-                               }
-                               else {
-                                       // `pre` initialized at top of scope
-                                       pre = "";
-
-                                       for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
-                                               pre += "<del>" + out.o[n] + oSpace[n] + "</del>";
-                                       }
-                                       str += " " + out.n[i].text + nSpace[i] + pre;
-                               }
-                       }
-               }
-
-               return str;
-       };
-}());
-
-// for CommonJS enviroments, export everything
-if ( typeof exports !== "undefined" ) {
-       extend( exports, QUnit );
-}
-
-// get at whatever the global object is, like window in browsers
-}( (function() {return this;}.call()) ));
diff --git a/resources/jquery/jquery.spinner.css b/resources/jquery/jquery.spinner.css
deleted file mode 100644 (file)
index a9e06db..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-.mw-spinner {
-       background-color: transparent;
-       background-position: center center;
-       background-repeat: no-repeat;
-}
-
-.mw-spinner-small {
-       /* @embed */
-       background-image: url(images/spinner.gif);
-       height: 20px;
-       width: 20px;
-       /* Avoid issues with .mw-spinner-block when floated without width. */
-       min-width: 20px;
-}
-
-.mw-spinner-large {
-       /* @embed */
-       background-image: url(images/spinner-large.gif);
-       height: 32px;
-       width: 32px;
-       /* Avoid issues with .mw-spinner-block when floated without width. */
-       min-width: 32px;
-}
-
-.mw-spinner-block {
-       display: block;
-       /* This overrides width from .mw-spinner-large / .mw-spinner-small,
-        * This is where the min-width kicks in.
-        */
-       width: 100%;
-}
-
-.mw-spinner-inline {
-       display: inline-block;
-       vertical-align: middle;
-
-       /* IE < 8 */
-       zoom: 1;
-       *display: inline;
-}
diff --git a/resources/jquery/jquery.spinner.js b/resources/jquery/jquery.spinner.js
deleted file mode 100644 (file)
index 073fb3d..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * jQuery Spinner
- *
- * Simple jQuery plugin to create, inject and remove spinners.
- *
- * @class jQuery.plugin.spinner
- */
-( function ( $ ) {
-
-       // Default options for new spinners,
-       // stored outside the function to share between calls.
-       var defaults = {
-               id: undefined,
-               size: 'small',
-               type: 'inline'
-       };
-
-       $.extend({
-               /**
-                * Create a spinner element
-                *
-                * The argument is an object with options used to construct the spinner (see below).
-                *
-                * It is a good practice to keep a reference to the created spinner to be able to remove it
-                * later. Alternatively, one can use the 'id' option and #removeSpinner (but make sure to choose
-                * an id that's unlikely to cause conflicts, e.g. with extensions, gadgets or user scripts).
-                *
-                * CSS classes used:
-                *
-                * - .mw-spinner for every spinner
-                * - .mw-spinner-small / .mw-spinner-large for size
-                * - .mw-spinner-block / .mw-spinner-inline for display types
-                *
-                * Example:
-                *
-                *     // Create a large spinner reserving all available horizontal space.
-                *     var $spinner = $.createSpinner({ size: 'large', type: 'block' });
-                *     // Insert above page content.
-                *     $( '#mw-content-text' ).prepend( $spinner );
-                *
-                *     // Place a small inline spinner next to the "Save" button
-                *     var $spinner = $.createSpinner({ size: 'small', type: 'inline' });
-                *     // Alternatively, just `$.createSpinner();` as these are the default options.
-                *     $( '#wpSave' ).after( $spinner );
-                *
-                *     // The following two are equivalent:
-                *     $.createSpinner( 'magic' );
-                *     $.createSpinner({ id: 'magic' });
-                *
-                * @static
-                * @inheritable
-                * @param {Object|string} [opts] Options. If a string is given, it will be treated as the value
-                *   of the `id` option. If an object is given, the possible option keys are:
-                * @param {string} [opts.id] If given, spinner will be given an id of "mw-spinner-{id}".
-                * @param {string} [opts.size='small'] 'small' or 'large' for a 20-pixel or 32-pixel spinner.
-                * @param {string} [opts.type='inline'] 'inline' or 'block'. Inline creates an inline-block with
-                *   width and height equal to spinner size. Block is a block-level element with width 100%,
-                *   height equal to spinner size.
-                * @return {jQuery}
-                */
-               createSpinner: function ( opts ) {
-                       if ( opts !== undefined && $.type( opts ) !== 'object' ) {
-                               opts = {
-                                       id: opts
-                               };
-                       }
-
-                       opts = $.extend( {}, defaults, opts );
-
-                       var $spinner = $( '<div>', { 'class': 'mw-spinner', 'title': '...' } );
-                       if ( opts.id !== undefined ) {
-                               $spinner.attr( 'id', 'mw-spinner-' + opts.id );
-                       }
-
-                       $spinner.addClass( opts.size === 'large' ? 'mw-spinner-large' : 'mw-spinner-small' );
-                       $spinner.addClass( opts.type === 'block' ? 'mw-spinner-block' : 'mw-spinner-inline' );
-
-                       return $spinner;
-               },
-
-               /**
-                * Remove a spinner element
-                *
-                * @static
-                * @inheritable
-                * @param {string} id Id of the spinner, as passed to #createSpinner
-                * @return {jQuery} The (now detached) spinner element
-                */
-               removeSpinner: function ( id ) {
-                       return $( '#mw-spinner-' + id ).remove();
-               }
-       });
-
-       /**
-        * Inject a spinner after each element in the collection
-        *
-        * Inserts spinner as siblings (not children) of the target elements.
-        * Collection contents remain unchanged.
-        *
-        * @param {Object|string} [opts] See #createSpinner
-        * @return {jQuery}
-        */
-       $.fn.injectSpinner = function ( opts ) {
-               return this.after( $.createSpinner( opts ) );
-       };
-
-       /**
-        * @class jQuery
-        * @mixins jQuery.plugin.spinner
-        */
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.suggestions.css b/resources/jquery/jquery.suggestions.css
deleted file mode 100644 (file)
index e0ba647..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/* suggestions plugin */
-
-.suggestions {
-       overflow: hidden;
-       position: absolute;
-       top: 0;
-       left: 0;
-       width: 0;
-       border: none;
-       z-index: 1099;
-       padding: 0;
-       margin: -1px -1px 0 0;
-}
-
-/* IGNORED BY IE6 */
-html > body .suggestions {
-       margin: -1px 0 0 0;
-}
-
-.suggestions-special {
-       position: relative;
-       background-color: white;
-       cursor: pointer;
-       border: solid 1px #aaaaaa;
-       padding: 0;
-       margin: 0;
-       margin-top: -2px;
-       display: none;
-       padding: 0.25em 0.25em;
-       line-height: 1.25em;
-}
-
-.suggestions-results {
-       background-color: white;
-       cursor: pointer;
-       border: solid 1px #aaaaaa;
-       padding: 0;
-       margin: 0;
-}
-
-.suggestions-result {
-       color: black;
-       margin: 0;
-       line-height: 1.5em;
-       padding: 0.01em 0.25em;
-       text-align: left;
-}
-
-.suggestions-result-current {
-       background-color: #4C59A6;
-       color: white;
-}
-
-.suggestions-special .special-label {
-       color: gray;
-       text-align: left;
-}
-
-.suggestions-special .special-query {
-       color: black;
-       font-style: italic;
-       text-align: left;
-}
-
-.suggestions-special .special-hover {
-       background-color: silver;
-}
-
-.suggestions-result-current .special-label,
-.suggestions-result-current .special-query {
-       color: white;
-}
-
-.autoellipsis-matched,
-.highlight {
-       font-weight: bold;
-}
diff --git a/resources/jquery/jquery.suggestions.js b/resources/jquery/jquery.suggestions.js
deleted file mode 100644 (file)
index f9a225f..0000000
+++ /dev/null
@@ -1,629 +0,0 @@
-/**
- * This plugin provides a generic way to add suggestions to a text box.
- *
- * Usage:
- *
- * Set options:
- *             $( '#textbox' ).suggestions( { option1: value1, option2: value2 } );
- *             $( '#textbox' ).suggestions( option, value );
- * Get option:
- *             value = $( '#textbox' ).suggestions( option );
- * Initialize:
- *             $( '#textbox' ).suggestions();
- *
- * Options:
- *
- * fetch(query): Callback that should fetch suggestions and set the suggestions property.
- *      Executed in the context of the textbox
- *             Type: Function
- * cancel: Callback function to call when any pending asynchronous suggestions fetches
- *      should be canceled. Executed in the context of the textbox
- *             Type: Function
- * special: Set of callbacks for rendering and selecting
- *             Type: Object of Functions 'render' and 'select'
- * result: Set of callbacks for rendering and selecting
- *             Type: Object of Functions 'render' and 'select'
- * $region: jQuery selection of element to place the suggestions below and match width of
- *             Type: jQuery Object, Default: $(this)
- * suggestions: Suggestions to display
- *             Type: Array of strings
- * maxRows: Maximum number of suggestions to display at one time
- *             Type: Number, Range: 1 - 100, Default: 7
- * delay: Number of ms to wait for the user to stop typing
- *             Type: Number, Range: 0 - 1200, Default: 120
- * submitOnClick: Whether to submit the form containing the textbox when a suggestion is clicked
- *             Type: Boolean, Default: false
- * maxExpandFactor: Maximum suggestions box width relative to the textbox width. If set
- *      to e.g. 2, the suggestions box will never be grown beyond 2 times the width of the textbox.
- *             Type: Number, Range: 1 - infinity, Default: 3
- * expandFrom: Which direction to offset the suggestion box from.
- *      Values 'start' and 'end' translate to left and right respectively depending on the
- *      directionality of the current document, according to $( 'html' ).css( 'direction' ).
- *      Type: String, default: 'auto', options: 'left', 'right', 'start', 'end', 'auto'.
- * positionFromLeft: Sets expandFrom=left, for backwards compatibility
- *             Type: Boolean, Default: true
- * highlightInput: Whether to hightlight matched portions of the input or not
- *             Type: Boolean, Default: false
- */
-( function ( $ ) {
-
-$.suggestions = {
-       /**
-        * Cancel any delayed maybeFetch() call and callback the context so
-        * they can cancel any async fetching if they use AJAX or something.
-        */
-       cancel: function ( context ) {
-               if ( context.data.timerID !== null ) {
-                       clearTimeout( context.data.timerID );
-               }
-               if ( $.isFunction( context.config.cancel ) ) {
-                       context.config.cancel.call( context.data.$textbox );
-               }
-       },
-
-       /**
-        * Hide the element with suggestions and clean up some state.
-        */
-       hide: function ( context ) {
-               // Remove any highlights, including on "special" items
-               context.data.$container.find( '.suggestions-result-current' ).removeClass( 'suggestions-result-current' );
-               // Hide the container
-               context.data.$container.hide();
-       },
-
-       /**
-        * Restore the text the user originally typed in the textbox, before it
-        * was overwritten by highlight(). This restores the value the currently
-        * displayed suggestions are based on, rather than the value just before
-        * highlight() overwrote it; the former is arguably slightly more sensible.
-        */
-       restore: function ( context ) {
-               context.data.$textbox.val( context.data.prevText );
-       },
-
-       /**
-        * Ask the user-specified callback for new suggestions. Any previous delayed
-        * call to this function still pending will be canceled. If the value in the
-        * textbox is empty or hasn't changed since the last time suggestions were fetched,
-        * this function does nothing.
-        * @param {Boolean} delayed Whether or not to delay this by the currently configured amount of time
-        */
-       update: function ( context, delayed ) {
-               // Only fetch if the value in the textbox changed and is not empty, or if the results were hidden
-               // if the textbox is empty then clear the result div, but leave other settings intouched
-               function maybeFetch() {
-                       if ( context.data.$textbox.val().length === 0 ) {
-                               $.suggestions.hide( context );
-                               context.data.prevText = '';
-                       } else if (
-                               context.data.$textbox.val() !== context.data.prevText ||
-                               !context.data.$container.is( ':visible' )
-                       ) {
-                               if ( typeof context.config.fetch === 'function' ) {
-                                       context.data.prevText = context.data.$textbox.val();
-                                       context.config.fetch.call( context.data.$textbox, context.data.$textbox.val() );
-                               }
-                       }
-               }
-
-               // Cancels any delayed maybeFetch call, and invokes context.config.cancel.
-               $.suggestions.cancel( context );
-
-               if ( delayed ) {
-                       // To avoid many started/aborted requests while typing, we're gonna take a short
-                       // break before trying to fetch data.
-                       context.data.timerID = setTimeout( maybeFetch, context.config.delay );
-               } else {
-                       maybeFetch();
-               }
-               $.suggestions.special( context );
-       },
-
-       special: function ( context ) {
-               // Allow custom rendering - but otherwise don't do any rendering
-               if ( typeof context.config.special.render === 'function' ) {
-                       // Wait for the browser to update the value
-                       setTimeout( function () {
-                               // Render special
-                               var $special = context.data.$container.find( '.suggestions-special' );
-                               context.config.special.render.call( $special, context.data.$textbox.val(), context );
-                       }, 1 );
-               }
-       },
-
-       /**
-        * Sets the value of a property, and updates the widget accordingly
-        * @param property String Name of property
-        * @param value Mixed Value to set property with
-        */
-       configure: function ( context, property, value ) {
-               var newCSS,
-                       $autoEllipseMe, $result, $results, childrenWidth,
-                       i, expWidth, matchedText, maxWidth, text;
-
-               // Validate creation using fallback values
-               switch ( property ) {
-                       case 'fetch':
-                       case 'cancel':
-                       case 'special':
-                       case 'result':
-                       case '$region':
-                       case 'expandFrom':
-                               context.config[property] = value;
-                               break;
-                       case 'suggestions':
-                               context.config[property] = value;
-                               // Update suggestions
-                               if ( context.data !== undefined ) {
-                                       if ( context.data.$textbox.val().length === 0 ) {
-                                               // Hide the div when no suggestion exist
-                                               $.suggestions.hide( context );
-                                       } else {
-                                               // Rebuild the suggestions list
-                                               context.data.$container.show();
-                                               // Update the size and position of the list
-                                               newCSS = {
-                                                       top: context.config.$region.offset().top + context.config.$region.outerHeight(),
-                                                       bottom: 'auto',
-                                                       width: context.config.$region.outerWidth(),
-                                                       height: 'auto'
-                                               };
-
-                                               // Process expandFrom, after this it is set to left or right.
-                                               context.config.expandFrom = ( function ( expandFrom ) {
-                                                       var regionWidth, docWidth, regionCenter, docCenter,
-                                                               docDir = $( document.documentElement ).css( 'direction' ),
-                                                               $region = context.config.$region;
-
-                                                       // Backwards compatible
-                                                       if ( context.config.positionFromLeft ) {
-                                                               expandFrom = 'left';
-
-                                                       // Catch invalid values, default to 'auto'
-                                                       } else if ( $.inArray( expandFrom, ['left', 'right', 'start', 'end', 'auto'] ) === -1 ) {
-                                                               expandFrom = 'auto';
-                                                       }
-
-                                                       if ( expandFrom === 'auto' ) {
-                                                               if ( $region.data( 'searchsuggest-expand-dir' ) ) {
-                                                                       // If the markup explicitly contains a direction, use it.
-                                                                       expandFrom = $region.data( 'searchsuggest-expand-dir' );
-                                                               } else {
-                                                                       regionWidth = $region.outerWidth();
-                                                                       docWidth = $( document ).width();
-                                                                       if ( ( regionWidth / docWidth  ) > 0.85 ) {
-                                                                               // If the input size takes up more than 85% of the document horizontally
-                                                                               // expand the suggestions to the writing direction's native end.
-                                                                               expandFrom = 'start';
-                                                                       } else {
-                                                                               // Calculate the center points of the input and document
-                                                                               regionCenter = $region.offset().left + regionWidth / 2;
-                                                                               docCenter = docWidth / 2;
-                                                                               if ( Math.abs( regionCenter - docCenter ) / docCenter < 0.10 ) {
-                                                                                       // If the input's center is within 10% of the document center
-                                                                                       // use the writing direction's native end.
-                                                                                       expandFrom = 'start';
-                                                                               } else {
-                                                                                       // Otherwise expand the input from the closest side of the page,
-                                                                                       // towards the side of the page with the most free open space
-                                                                                       expandFrom = regionCenter > docCenter ? 'right' : 'left';
-                                                                               }
-                                                                       }
-                                                               }
-                                                       }
-
-                                                       if ( expandFrom === 'start' ) {
-                                                               expandFrom = docDir === 'rtl' ? 'right': 'left';
-
-                                                       } else if ( expandFrom === 'end' ) {
-                                                               expandFrom = docDir === 'rtl' ? 'left': 'right';
-                                                       }
-
-                                                       return expandFrom;
-
-                                               }( context.config.expandFrom ) );
-
-                                               if ( context.config.expandFrom === 'left' ) {
-                                                       // Expand from left
-                                                       newCSS.left = context.config.$region.offset().left;
-                                                       newCSS.right = 'auto';
-                                               } else {
-                                                       // Expand from right
-                                                       newCSS.left = 'auto';
-                                                       newCSS.right = $( document ).width() - ( context.config.$region.offset().left + context.config.$region.outerWidth() );
-                                               }
-
-                                               context.data.$container.css( newCSS );
-                                               $results = context.data.$container.children( '.suggestions-results' );
-                                               $results.empty();
-                                               expWidth = -1;
-                                               $autoEllipseMe = $( [] );
-                                               matchedText = null;
-                                               for ( i = 0; i < context.config.suggestions.length; i++ ) {
-                                                       /*jshint loopfunc:true */
-                                                       text = context.config.suggestions[i];
-                                                       $result = $( '<div>' )
-                                                               .addClass( 'suggestions-result' )
-                                                               .attr( 'rel', i )
-                                                               .data( 'text', context.config.suggestions[i] )
-                                                               .mousemove( function () {
-                                                                       context.data.selectedWithMouse = true;
-                                                                       $.suggestions.highlight(
-                                                                               context,
-                                                                               $(this).closest( '.suggestions-results .suggestions-result' ),
-                                                                               false
-                                                                       );
-                                                               } )
-                                                               .appendTo( $results );
-                                                       // Allow custom rendering
-                                                       if ( typeof context.config.result.render === 'function' ) {
-                                                               context.config.result.render.call( $result, context.config.suggestions[i], context );
-                                                       } else {
-                                                               // Add <span> with text
-                                                               $result.append( $( '<span>' )
-                                                                               .css( 'whiteSpace', 'nowrap' )
-                                                                               .text( text )
-                                                                       );
-                                                       }
-
-                                                       if ( context.config.highlightInput ) {
-                                                               matchedText = context.data.prevText;
-                                                       }
-
-                                                       // Widen results box if needed
-                                                       // New width is only calculated here, applied later
-                                                       childrenWidth = $result.children().outerWidth();
-                                                       if ( childrenWidth > $result.width() && childrenWidth > expWidth ) {
-                                                               // factor in any padding, margin, or border space on the parent
-                                                               expWidth = childrenWidth + ( context.data.$container.width() - $result.width() );
-                                                       }
-                                                       $autoEllipseMe = $autoEllipseMe.add( $result );
-                                               }
-                                               // Apply new width for results box, if any
-                                               if ( expWidth > context.data.$container.width() ) {
-                                                       maxWidth = context.config.maxExpandFactor * context.data.$textbox.width();
-                                                       context.data.$container.width( Math.min( expWidth, maxWidth ) );
-                                               }
-                                               // autoEllipse the results. Has to be done after changing the width
-                                               $autoEllipseMe.autoEllipsis( {
-                                                       hasSpan: true,
-                                                       tooltip: true,
-                                                       matchText: matchedText
-                                               } );
-                                       }
-                               }
-                               break;
-                       case 'maxRows':
-                               context.config[property] = Math.max( 1, Math.min( 100, value ) );
-                               break;
-                       case 'delay':
-                               context.config[property] = Math.max( 0, Math.min( 1200, value ) );
-                               break;
-                       case 'maxExpandFactor':
-                               context.config[property] = Math.max( 1, value );
-                               break;
-                       case 'submitOnClick':
-                       case 'positionFromLeft':
-                       case 'highlightInput':
-                               context.config[property] = value ? true : false;
-                               break;
-               }
-       },
-
-       /**
-        * Highlight a result in the results table
-        * @param result <tr> to highlight: jQuery object, or 'prev' or 'next'
-        * @param updateTextbox If true, put the suggestion in the textbox
-        */
-       highlight: function ( context, result, updateTextbox ) {
-               var selected = context.data.$container.find( '.suggestions-result-current' );
-               if ( !result.get || selected.get( 0 ) !== result.get( 0 ) ) {
-                       if ( result === 'prev' ) {
-                               if( selected.hasClass( 'suggestions-special' ) ) {
-                                       result = context.data.$container.find( '.suggestions-result:last' );
-                               } else {
-                                       result = selected.prev();
-                                       if ( !( result.length && result.hasClass( 'suggestions-result' ) ) ) {
-                                               // there is something in the DOM between selected element and the wrapper, bypass it
-                                               result = selected.parents( '.suggestions-results > *' ).prev().find( '.suggestions-result' ).eq(0);
-                                       }
-
-                                       if ( selected.length === 0 ) {
-                                               // we are at the beginning, so lets jump to the last item
-                                               if ( context.data.$container.find( '.suggestions-special' ).html() !== '' ) {
-                                                       result = context.data.$container.find( '.suggestions-special' );
-                                               } else {
-                                                       result = context.data.$container.find( '.suggestions-results .suggestions-result:last' );
-                                               }
-                                       }
-                               }
-                       } else if ( result === 'next' ) {
-                               if ( selected.length === 0 ) {
-                                       // No item selected, go to the first one
-                                       result = context.data.$container.find( '.suggestions-results .suggestions-result:first' );
-                                       if ( result.length === 0 && context.data.$container.find( '.suggestions-special' ).html() !== '' ) {
-                                               // No suggestion exists, go to the special one directly
-                                               result = context.data.$container.find( '.suggestions-special' );
-                                       }
-                               } else {
-                                       result = selected.next();
-                                       if ( !( result.length && result.hasClass( 'suggestions-result' ) ) ) {
-                                               // there is something in the DOM between selected element and the wrapper, bypass it
-                                               result = selected.parents( '.suggestions-results > *' ).next().find( '.suggestions-result' ).eq(0);
-                                       }
-
-                                       if ( selected.hasClass( 'suggestions-special' ) ) {
-                                               result = $( [] );
-                                       } else if (
-                                               result.length === 0 &&
-                                               context.data.$container.find( '.suggestions-special' ).html() !== ''
-                                       ) {
-                                               // We were at the last item, jump to the specials!
-                                               result = context.data.$container.find( '.suggestions-special' );
-                                       }
-                               }
-                       }
-                       selected.removeClass( 'suggestions-result-current' );
-                       result.addClass( 'suggestions-result-current' );
-               }
-               if ( updateTextbox ) {
-                       if ( result.length === 0 || result.is( '.suggestions-special' ) ) {
-                               $.suggestions.restore( context );
-                       } else {
-                               context.data.$textbox.val( result.data( 'text' ) );
-                               // .val() doesn't call any event handlers, so
-                               // let the world know what happened
-                               context.data.$textbox.change();
-                       }
-                       context.data.$textbox.trigger( 'change' );
-               }
-       },
-
-       /**
-        * Respond to keypress event
-        * @param key Integer Code of key pressed
-        */
-       keypress: function ( e, context, key ) {
-               var selected,
-                       wasVisible = context.data.$container.is( ':visible' ),
-                       preventDefault = false;
-
-               switch ( key ) {
-                       // Arrow down
-                       case 40:
-                               if ( wasVisible ) {
-                                       $.suggestions.highlight( context, 'next', true );
-                                       context.data.selectedWithMouse = false;
-                               } else {
-                                       $.suggestions.update( context, false );
-                               }
-                               preventDefault = true;
-                               break;
-                       // Arrow up
-                       case 38:
-                               if ( wasVisible ) {
-                                       $.suggestions.highlight( context, 'prev', true );
-                                       context.data.selectedWithMouse = false;
-                               }
-                               preventDefault = wasVisible;
-                               break;
-                       // Escape
-                       case 27:
-                               $.suggestions.hide( context );
-                               $.suggestions.restore( context );
-                               $.suggestions.cancel( context );
-                               context.data.$textbox.trigger( 'change' );
-                               preventDefault = wasVisible;
-                               break;
-                       // Enter
-                       case 13:
-                               preventDefault = wasVisible;
-                               selected = context.data.$container.find( '.suggestions-result-current' );
-                               $.suggestions.hide( context );
-                               if ( selected.length === 0 || context.data.selectedWithMouse ) {
-                                       // If nothing is selected or if something was selected with the mouse
-                                       // cancel any current requests and allow the form to be submitted
-                                       // (simply don't prevent default behavior).
-                                       $.suggestions.cancel( context );
-                                       preventDefault = false;
-                               } else if ( selected.is( '.suggestions-special' ) ) {
-                                       if ( typeof context.config.special.select === 'function' ) {
-                                               // Allow the callback to decide whether to prevent default or not
-                                               if ( context.config.special.select.call( selected, context.data.$textbox ) === true ) {
-                                                       preventDefault = false;
-                                               }
-                                       }
-                               } else {
-                                       $.suggestions.highlight( context, selected, true );
-
-                                       if ( typeof context.config.result.select === 'function' ) {
-                                               // Allow the callback to decide whether to prevent default or not
-                                               if ( context.config.result.select.call( selected, context.data.$textbox ) === true ) {
-                                                       preventDefault = false;
-                                               }
-                                       }
-                               }
-                               break;
-                       default:
-                               $.suggestions.update( context, true );
-                               break;
-               }
-               if ( preventDefault ) {
-                       e.preventDefault();
-                       e.stopPropagation();
-               }
-       }
-};
-$.fn.suggestions = function () {
-
-       // Multi-context fields
-       var returnValue,
-               args = arguments;
-
-       $(this).each( function () {
-               var context, key;
-
-               /* Construction / Loading */
-
-               context = $(this).data( 'suggestions-context' );
-               if ( context === undefined || context === null ) {
-                       context = {
-                               config: {
-                                       fetch: function () {},
-                                       cancel: function () {},
-                                       special: {},
-                                       result: {},
-                                       $region: $(this),
-                                       suggestions: [],
-                                       maxRows: 7,
-                                       delay: 120,
-                                       submitOnClick: false,
-                                       maxExpandFactor: 3,
-                                       expandFrom: 'auto',
-                                       highlightInput: false
-                               }
-                       };
-               }
-
-               /* API */
-
-               // Handle various calling styles
-               if ( args.length > 0 ) {
-                       if ( typeof args[0] === 'object' ) {
-                               // Apply set of properties
-                               for ( key in args[0] ) {
-                                       $.suggestions.configure( context, key, args[0][key] );
-                               }
-                       } else if ( typeof args[0] === 'string' ) {
-                               if ( args.length > 1 ) {
-                                       // Set property values
-                                       $.suggestions.configure( context, args[0], args[1] );
-                               } else if ( returnValue === null || returnValue === undefined ) {
-                                       // Get property values, but don't give access to internal data - returns only the first
-                                       returnValue = ( args[0] in context.config ? undefined : context.config[args[0]] );
-                               }
-                       }
-               }
-
-               /* Initialization */
-
-               if ( context.data === undefined ) {
-                       context.data = {
-                               // ID of running timer
-                               timerID: null,
-
-                               // Text in textbox when suggestions were last fetched
-                               prevText: null,
-
-                               // Number of results visible without scrolling
-                               visibleResults: 0,
-
-                               // Suggestion the last mousedown event occured on
-                               mouseDownOn: $( [] ),
-                               $textbox: $(this),
-                               selectedWithMouse: false
-                       };
-
-                       context.data.$container = $( '<div>' )
-                               .css( 'display', 'none' )
-                               .addClass( 'suggestions' )
-                               .append(
-                                       $( '<div>' ).addClass( 'suggestions-results' )
-                                               // Can't use click() because the container div is hidden when the
-                                               // textbox loses focus. Instead, listen for a mousedown followed
-                                               // by a mouseup on the same div.
-                                               .mousedown( function ( e ) {
-                                                       context.data.mouseDownOn = $( e.target ).closest( '.suggestions-results .suggestions-result' );
-                                               } )
-                                               .mouseup( function ( e ) {
-                                                       var $result = $( e.target ).closest( '.suggestions-results .suggestions-result' ),
-                                                               $other = context.data.mouseDownOn;
-
-                                                       context.data.mouseDownOn = $( [] );
-                                                       if ( $result.get( 0 ) !== $other.get( 0 ) ) {
-                                                               return;
-                                                       }
-                                                       // do not interfere with non-left clicks or if modifier keys are pressed (e.g. ctrl-click)
-                                                       if ( !( e.which !== 1 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey ) ) {
-                                                               $.suggestions.highlight( context, $result, true );
-                                                               $.suggestions.hide( context );
-                                                               if ( typeof context.config.result.select === 'function' ) {
-                                                                       context.config.result.select.call( $result, context.data.$textbox );
-                                                               }
-                                                       }
-                                                       // but still restore focus to the textbox, so that the suggestions will be hidden properly
-                                                       context.data.$textbox.focus();
-                                               } )
-                               )
-                               .append(
-                                       $( '<div>' ).addClass( 'suggestions-special' )
-                                               // Can't use click() because the container div is hidden when the
-                                               // textbox loses focus. Instead, listen for a mousedown followed
-                                               // by a mouseup on the same div.
-                                               .mousedown( function ( e ) {
-                                                       context.data.mouseDownOn = $( e.target ).closest( '.suggestions-special' );
-                                               } )
-                                               .mouseup( function ( e ) {
-                                                       var $special = $( e.target ).closest( '.suggestions-special' ),
-                                                               $other = context.data.mouseDownOn;
-
-                                                       context.data.mouseDownOn = $( [] );
-                                                       if ( $special.get( 0 ) !== $other.get( 0 ) ) {
-                                                               return;
-                                                       }
-                                                       // do not interfere with non-left clicks or if modifier keys are pressed (e.g. ctrl-click)
-                                                       if ( !( e.which !== 1 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey ) ) {
-                                                               $.suggestions.hide( context );
-                                                               if ( typeof context.config.special.select === 'function' ) {
-                                                                       context.config.special.select.call( $special, context.data.$textbox );
-                                                               }
-                                                       }
-                                                       // but still restore focus to the textbox, so that the suggestions will be hidden properly
-                                                       context.data.$textbox.focus();
-                                               } )
-                                               .mousemove( function ( e ) {
-                                                       context.data.selectedWithMouse = true;
-                                                       $.suggestions.highlight(
-                                                               context, $( e.target ).closest( '.suggestions-special' ), false
-                                                       );
-                                               } )
-                               )
-                               .appendTo( $( 'body' ) );
-
-                       $(this)
-                               // Stop browser autocomplete from interfering
-                               .attr( 'autocomplete', 'off')
-                               .keydown( function ( e ) {
-                                       // Store key pressed to handle later
-                                       context.data.keypressed = e.which;
-                                       context.data.keypressedCount = 0;
-                               } )
-                               .keypress( function ( e ) {
-                                       context.data.keypressedCount++;
-                                       $.suggestions.keypress( e, context, context.data.keypressed );
-                               } )
-                               .keyup( function ( e ) {
-                                       // Some browsers won't throw keypress() for arrow keys. If we got a keydown and a keyup without a
-                                       // keypress in between, solve it
-                                       if ( context.data.keypressedCount === 0 ) {
-                                               $.suggestions.keypress( e, context, context.data.keypressed );
-                                       }
-                               } )
-                               .blur( function () {
-                                       // When losing focus because of a mousedown
-                                       // on a suggestion, don't hide the suggestions
-                                       if ( context.data.mouseDownOn.length > 0 ) {
-                                               return;
-                                       }
-                                       $.suggestions.hide( context );
-                                       $.suggestions.cancel( context );
-                               } );
-               }
-
-               // Store the context for next time
-               $(this).data( 'suggestions-context', context );
-       } );
-       return returnValue !== undefined ? returnValue : $(this);
-};
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.tabIndex.js b/resources/jquery/jquery.tabIndex.js
deleted file mode 100644 (file)
index cdae0ba..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * jQuery tabIndex
- */
-( function ( $ ) {
-
-       /**
-        * Finds the lowerst tabindex in use within a selection
-        *
-        * @return number Lowest tabindex on the page
-        */
-       $.fn.firstTabIndex = function () {
-               var minTabIndex = null;
-               $(this).find( '[tabindex]' ).each( function () {
-                       var tabIndex = parseInt( $(this).prop( 'tabindex' ), 10 );
-                       // In IE6/IE7 the above jQuery selector returns all elements,
-                       // becuase it has a default value for tabIndex in IE6/IE7 of 0
-                       // (rather than null/undefined). Therefore check "> 0" as well.
-                       // Under IE7 under Windows NT 5.2 is also capable of returning NaN.
-                       if ( tabIndex > 0 && !isNaN( tabIndex ) ) {
-                               // Initial value
-                               if ( minTabIndex === null ) {
-                                       minTabIndex = tabIndex;
-                               } else if ( tabIndex < minTabIndex ) {
-                                       minTabIndex = tabIndex;
-                               }
-                       }
-               } );
-               return minTabIndex;
-       };
-
-       /**
-        * Finds the highest tabindex in use within a selection
-        *
-        * @return number Highest tabindex on the page
-        */
-       $.fn.lastTabIndex = function () {
-               var maxTabIndex = null;
-               $(this).find( '[tabindex]' ).each( function () {
-                       var tabIndex = parseInt( $(this).prop( 'tabindex' ), 10 );
-                       if ( tabIndex > 0 && !isNaN( tabIndex ) ) {
-                               // Initial value
-                               if ( maxTabIndex === null ) {
-                                       maxTabIndex = tabIndex;
-                               } else if ( tabIndex > maxTabIndex ) {
-                                       maxTabIndex = tabIndex;
-                               }
-                       }
-               } );
-               return maxTabIndex;
-       };
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.tablesorter.css b/resources/jquery/jquery.tablesorter.css
deleted file mode 100644 (file)
index a88acc0..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Table Sorting */
-table.jquery-tablesorter th.headerSort {
-       /* @embed */
-       background-image: url(images/sort_both.gif);
-       cursor: pointer;
-       background-repeat: no-repeat;
-       background-position: center right;
-       padding-right: 21px;
-}
-table.jquery-tablesorter th.headerSortUp {
-       /* @embed */
-       background-image: url(images/sort_up.gif);
-}
-table.jquery-tablesorter th.headerSortDown {
-       /* @embed */
-       background-image: url(images/sort_down.gif);
-}
diff --git a/resources/jquery/jquery.tablesorter.js b/resources/jquery/jquery.tablesorter.js
deleted file mode 100644 (file)
index af0d897..0000000
+++ /dev/null
@@ -1,1154 +0,0 @@
-/**
- * TableSorter for MediaWiki
- *
- * Written 2011 Leo Koppelkamm
- * Based on tablesorter.com plugin, written (c) 2007 Christian Bach.
- *
- * Dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- *
- * Depends on mw.config (wgDigitTransformTable, wgDefaultDateFormat, wgContentLanguage)
- * and mw.language.months.
- *
- * Uses 'tableSorterCollation' in mw.config (if available)
- */
-/**
- *
- * @description Create a sortable table with multi-column sorting capabilitys
- *
- * @example $( 'table' ).tablesorter();
- * @desc Create a simple tablesorter interface.
- *
- * @example $( 'table' ).tablesorter( { sortList: [ { 0: 'desc' }, { 1: 'asc' } ] } );
- * @desc Create a tablesorter interface initially sorting on the first and second column.
- *
- * @option String cssHeader ( optional ) A string of the class name to be appended
- *         to sortable tr elements in the thead of the table. Default value:
- *         "header"
- *
- * @option String cssAsc ( optional ) A string of the class name to be appended to
- *         sortable tr elements in the thead on a ascending sort. Default value:
- *         "headerSortUp"
- *
- * @option String cssDesc ( optional ) A string of the class name to be appended
- *         to sortable tr elements in the thead on a descending sort. Default
- *         value: "headerSortDown"
- *
- * @option String sortInitialOrder ( optional ) A string of the inital sorting
- *         order can be asc or desc. Default value: "asc"
- *
- * @option String sortMultisortKey ( optional ) A string of the multi-column sort
- *         key. Default value: "shiftKey"
- *
- * @option Boolean sortLocaleCompare ( optional ) Boolean flag indicating whatever
- *         to use String.localeCampare method or not. Set to false.
- *
- * @option Boolean cancelSelection ( optional ) Boolean flag indicating if
- *         tablesorter should cancel selection of the table headers text.
- *         Default value: true
- *
- * @option Array sortList ( optional ) An array containing objects specifying sorting.
- *         By passing more than one object, multi-sorting will be applied. Object structure:
- *         { <Integer column index>: <String 'asc' or 'desc'> }
- *         Default value: []
- *
- * @option Boolean debug ( optional ) Boolean flag indicating if tablesorter
- *         should display debuging information usefull for development.
- *
- * @event sortEnd.tablesorter: Triggered as soon as any sorting has been applied.
- *
- * @type jQuery
- *
- * @name tablesorter
- *
- * @cat Plugins/Tablesorter
- *
- * @author Christian Bach/christian.bach@polyester.se
- */
-
-( function ( $, mw ) {
-       /* Local scope */
-
-       var ts,
-               parsers = [];
-
-       /* Parser utility functions */
-
-       function getParserById( name ) {
-               var i,
-                       len = parsers.length;
-               for ( i = 0; i < len; i++ ) {
-                       if ( parsers[i].id.toLowerCase() === name.toLowerCase() ) {
-                               return parsers[i];
-                       }
-               }
-               return false;
-       }
-
-       function getElementSortKey( node ) {
-               var $node = $( node ),
-                       // Use data-sort-value attribute.
-                       // Use data() instead of attr() so that live value changes
-                       // are processed as well (bug 38152).
-                       data = $node.data( 'sortValue' );
-
-               if ( data !== null && data !== undefined ) {
-                       // Cast any numbers or other stuff to a string, methods
-                       // like charAt, toLowerCase and split are expected.
-                       return String( data );
-               } else {
-                       if ( !node ) {
-                               return $node.text();
-                       } else if ( node.tagName.toLowerCase() === 'img' ) {
-                               return $node.attr( 'alt' ) || ''; // handle undefined alt
-                       } else {
-                               return $.map( $.makeArray( node.childNodes ), function( elem ) {
-                                       // 1 is for document.ELEMENT_NODE (the constant is undefined on old browsers)
-                                       if ( elem.nodeType === 1 ) {
-                                               return getElementSortKey( elem );
-                                       } else {
-                                               return $.text( elem );
-                                       }
-                               } ).join( '' );
-                       }
-               }
-       }
-
-       function detectParserForColumn( table, rows, cellIndex ) {
-               var l = parsers.length,
-                       nodeValue,
-                       // Start with 1 because 0 is the fallback parser
-                       i = 1,
-                       rowIndex = 0,
-                       concurrent = 0,
-                       needed = ( rows.length > 4 ) ? 5 : rows.length;
-
-               while ( i < l ) {
-                       if ( rows[rowIndex] && rows[rowIndex].cells[cellIndex] ) {
-                               nodeValue = $.trim( getElementSortKey( rows[rowIndex].cells[cellIndex] ) );
-                       } else {
-                               nodeValue = '';
-                       }
-
-                       if ( nodeValue !== '') {
-                               if ( parsers[i].is( nodeValue, table ) ) {
-                                       concurrent++;
-                                       rowIndex++;
-                                       if ( concurrent >= needed ) {
-                                               // Confirmed the parser for multiple cells, let's return it
-                                               return parsers[i];
-                                       }
-                               } else {
-                                       // Check next parser, reset rows
-                                       i++;
-                                       rowIndex = 0;
-                                       concurrent = 0;
-                               }
-                       } else {
-                               // Empty cell
-                               rowIndex++;
-                               if ( rowIndex > rows.length ) {
-                                       rowIndex = 0;
-                                       i++;
-                               }
-                       }
-               }
-
-               // 0 is always the generic parser (text)
-               return parsers[0];
-       }
-
-       function buildParserCache( table, $headers ) {
-               var rows = table.tBodies[0].rows,
-                       sortType,
-                       parsers = [];
-
-               if ( rows[0] ) {
-
-                       var cells = rows[0].cells,
-                               len = cells.length,
-                               i, parser;
-
-                       for ( i = 0; i < len; i++ ) {
-                               parser = false;
-                               sortType = $headers.eq( i ).data( 'sortType' );
-                               if ( sortType !== undefined ) {
-                                       parser = getParserById( sortType );
-                               }
-
-                               if ( parser === false ) {
-                                       parser = detectParserForColumn( table, rows, i );
-                               }
-
-                               parsers.push( parser );
-                       }
-               }
-               return parsers;
-       }
-
-       /* Other utility functions */
-
-       function buildCache( table ) {
-               var totalRows = ( table.tBodies[0] && table.tBodies[0].rows.length ) || 0,
-                       totalCells = ( table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length ) || 0,
-                       parsers = table.config.parsers,
-                       cache = {
-                               row: [],
-                               normalized: []
-                       };
-
-               for ( var i = 0; i < totalRows; ++i ) {
-
-                       // Add the table data to main data array
-                       var $row = $( table.tBodies[0].rows[i] ),
-                               cols = [];
-
-                       // if this is a child row, add it to the last row's children and
-                       // continue to the next row
-                       if ( $row.hasClass( table.config.cssChildRow ) ) {
-                               cache.row[cache.row.length - 1] = cache.row[cache.row.length - 1].add( $row );
-                               // go to the next for loop
-                               continue;
-                       }
-
-                       cache.row.push( $row );
-
-                       for ( var j = 0; j < totalCells; ++j ) {
-                               cols.push( parsers[j].format( getElementSortKey( $row[0].cells[j] ), table, $row[0].cells[j] ) );
-                       }
-
-                       cols.push( cache.normalized.length ); // add position for rowCache
-                       cache.normalized.push( cols );
-                       cols = null;
-               }
-
-               return cache;
-       }
-
-       function appendToTable( table, cache ) {
-               var i, pos, l, j,
-                       row = cache.row,
-                       normalized = cache.normalized,
-                       totalRows = normalized.length,
-                       checkCell = ( normalized[0].length - 1 ),
-                       fragment = document.createDocumentFragment();
-
-               for ( i = 0; i < totalRows; i++ ) {
-                       pos = normalized[i][checkCell];
-
-                       l = row[pos].length;
-
-                       for ( j = 0; j < l; j++ ) {
-                               fragment.appendChild( row[pos][j] );
-                       }
-
-               }
-               table.tBodies[0].appendChild( fragment );
-
-               $( table ).trigger( 'sortEnd.tablesorter' );
-       }
-
-       /**
-        * Find all header rows in a thead-less table and put them in a <thead> tag.
-        * This only treats a row as a header row if it contains only <th>s (no <td>s)
-        * and if it is preceded entirely by header rows. The algorithm stops when
-        * it encounters the first non-header row.
-        *
-        * After this, it will look at all rows at the bottom for footer rows
-        * And place these in a tfoot using similar rules.
-        * @param $table jQuery object for a <table>
-        */
-       function emulateTHeadAndFoot( $table ) {
-               var $thead, $tfoot, i, len,
-                       $rows = $table.find( '> tbody > tr' );
-               if ( !$table.get(0).tHead ) {
-                       $thead = $( '<thead>' );
-                       $rows.each( function () {
-                               if ( $(this).children( 'td' ).length ) {
-                                       // This row contains a <td>, so it's not a header row
-                                       // Stop here
-                                       return false;
-                               }
-                               $thead.append( this );
-                       } );
-                       $table.find(' > tbody:first').before( $thead );
-               }
-               if ( !$table.get(0).tFoot ) {
-                       $tfoot = $( '<tfoot>' );
-                       len = $rows.length;
-                       for ( i = len - 1; i >= 0; i-- ) {
-                               if ( $( $rows[i] ).children( 'td' ).length ){
-                                       break;
-                               }
-                               $tfoot.prepend( $( $rows[i] ));
-                       }
-                       $table.append( $tfoot );
-               }
-       }
-
-       function buildHeaders( table, msg ) {
-               var maxSeen = 0,
-                       colspanOffset = 0,
-                       columns,
-                       i,
-                       $tableHeaders = $( [] ),
-                       $tableRows = $( 'thead:eq(0) > tr', table );
-               if ( $tableRows.length <= 1 ) {
-                       $tableHeaders = $tableRows.children( 'th' );
-               } else {
-                       var rowspan,
-                               colspan,
-                               headerCount,
-                               longestTR,
-                               matrixRowIndex,
-                               matrixColumnIndex,
-                               exploded = [];
-
-                       // Loop through all the dom cells of the thead
-                       $tableRows.each( function ( rowIndex, row ) {
-                               $.each( row.cells, function( columnIndex, cell ) {
-                                       rowspan = Number( cell.rowSpan );
-                                       colspan = Number( cell.colSpan );
-
-                                       // Skip the spots in the exploded matrix that are already filled
-                                       while ( exploded[rowIndex] && exploded[rowIndex][columnIndex] !== undefined ) {
-                                               ++columnIndex;
-                                       }
-
-                                       // Find the actual dimensions of the thead, by placing each cell
-                                       // in the exploded matrix rowspan times colspan times, with the proper offsets
-                                       for ( matrixColumnIndex = columnIndex; matrixColumnIndex < columnIndex + colspan; ++matrixColumnIndex ) {
-                                               for ( matrixRowIndex = rowIndex; matrixRowIndex < rowIndex + rowspan; ++matrixRowIndex ) {
-                                                       if ( !exploded[matrixRowIndex] ) {
-                                                               exploded[matrixRowIndex] = [];
-                                                       }
-                                                       exploded[matrixRowIndex][matrixColumnIndex] = cell;
-                                               }
-                                       }
-                               } );
-                       } );
-                       // We want to find the row that has the most columns (ignoring colspan)
-                       $.each( exploded, function ( index, cellArray ) {
-                               headerCount = $.unique( $(cellArray) ).length;
-                               if ( headerCount >= maxSeen ) {
-                                       maxSeen = headerCount;
-                                       longestTR = index;
-                               }
-                       } );
-                       // We cannot use $.unique() here because it sorts into dom order, which is undesirable
-                       $tableHeaders = $( uniqueElements( exploded[longestTR] ) );
-               }
-
-               // as each header can span over multiple columns (using colspan=N),
-               // we have to bidirectionally map headers to their columns and columns to their headers
-               table.headerToColumns = [];
-               table.columnToHeader = [];
-
-               $tableHeaders.each( function ( headerIndex ) {
-                       columns = [];
-                       for ( i = 0; i < this.colSpan; i++ ) {
-                               table.columnToHeader[ colspanOffset + i ] = headerIndex;
-                               columns.push( colspanOffset + i );
-                       }
-
-                       table.headerToColumns[ headerIndex ] = columns;
-                       colspanOffset += this.colSpan;
-
-                       this.headerIndex = headerIndex;
-                       this.order = 0;
-                       this.count = 0;
-
-                       if ( $( this ).hasClass( table.config.unsortableClass ) ) {
-                               this.sortDisabled = true;
-                       }
-
-                       if ( !this.sortDisabled ) {
-                               $( this )
-                                       .addClass( table.config.cssHeader )
-                                       .prop( 'tabIndex', 0 )
-                                       .attr( {
-                                               role: 'columnheader button',
-                                               title: msg[1]
-                                       } );
-                       }
-
-                       // add cell to headerList
-                       table.config.headerList[headerIndex] = this;
-               } );
-
-               return $tableHeaders;
-
-       }
-
-       /**
-        * Sets the sort count of the columns that are not affected by the sorting to have them sorted
-        * in default (ascending) order when their header cell is clicked the next time.
-        *
-        * @param {jQuery} $headers
-        * @param {Number[][]} sortList
-        * @param {Number[][]} headerToColumns
-        */
-       function setHeadersOrder( $headers, sortList, headerToColumns ) {
-               // Loop through all headers to retrieve the indices of the columns the header spans across:
-               $.each( headerToColumns, function( headerIndex, columns ) {
-
-                       $.each( columns, function( i, columnIndex ) {
-                               var header = $headers[headerIndex];
-
-                               if ( !isValueInArray( columnIndex, sortList ) ) {
-                                       // Column shall not be sorted: Reset header count and order.
-                                       header.order = 0;
-                                       header.count = 0;
-                               } else {
-                                       // Column shall be sorted: Apply designated count and order.
-                                       $.each( sortList, function( j, sortColumn ) {
-                                               if ( sortColumn[0] === i ) {
-                                                       header.order = sortColumn[1];
-                                                       header.count = sortColumn[1] + 1;
-                                                       return false;
-                                               }
-                                       } );
-                               }
-                       } );
-
-               } );
-       }
-
-       function isValueInArray( v, a ) {
-               var l = a.length;
-               for ( var i = 0; i < l; i++ ) {
-                       if ( a[i][0] === v ) {
-                               return true;
-                       }
-               }
-               return false;
-       }
-
-       function uniqueElements( array ) {
-               var uniques = [];
-               $.each( array, function( index, elem ) {
-                       if ( elem !== undefined && $.inArray( elem, uniques ) === -1 ) {
-                               uniques.push( elem );
-                       }
-               } );
-               return uniques;
-       }
-
-       function setHeadersCss( table, $headers, list, css, msg, columnToHeader ) {
-               // Remove all header information and reset titles to default message
-               $headers.removeClass( css[0] ).removeClass( css[1] ).attr( 'title', msg[1] );
-
-               for ( var i = 0; i < list.length; i++ ) {
-                       $headers.eq( columnToHeader[ list[i][0] ] )
-                               .addClass( css[ list[i][1] ] )
-                               .attr( 'title', msg[ list[i][1] ] );
-               }
-       }
-
-       function sortText( a, b ) {
-               return ( (a < b) ? -1 : ((a > b) ? 1 : 0) );
-       }
-
-       function sortTextDesc( a, b ) {
-               return ( (b < a) ? -1 : ((b > a) ? 1 : 0) );
-       }
-
-       function multisort( table, sortList, cache ) {
-               var i,
-                       sortFn = [],
-                       len = sortList.length;
-               for ( i = 0; i < len; i++ ) {
-                       sortFn[i] = ( sortList[i][1] ) ? sortTextDesc : sortText;
-               }
-               cache.normalized.sort( function ( array1, array2 ) {
-                       var i, col, ret;
-                       for ( i = 0; i < len; i++ ) {
-                               col = sortList[i][0];
-                               ret = sortFn[i].call( this, array1[col], array2[col] );
-                               if ( ret !== 0 ) {
-                                       return ret;
-                               }
-                       }
-                       // Fall back to index number column to ensure stable sort
-                       return sortText.call( this, array1[array1.length - 1], array2[array2.length - 1] );
-               } );
-               return cache;
-       }
-
-       function buildTransformTable() {
-               var ascii, localised, i, digitClass,
-                       digits = '0123456789,.'.split( '' ),
-                       separatorTransformTable = mw.config.get( 'wgSeparatorTransformTable' ),
-                       digitTransformTable = mw.config.get( 'wgDigitTransformTable' );
-
-               if ( separatorTransformTable === null || ( separatorTransformTable[0] === '' && digitTransformTable[2] === '' ) ) {
-                       ts.transformTable = false;
-               } else {
-                       ts.transformTable = {};
-
-                       // Unpack the transform table
-                       ascii = separatorTransformTable[0].split( '\t' ).concat( digitTransformTable[0].split( '\t' ) );
-                       localised = separatorTransformTable[1].split( '\t' ).concat( digitTransformTable[1].split( '\t' ) );
-
-                       // Construct regex for number identification
-                       for ( i = 0; i < ascii.length; i++ ) {
-                               ts.transformTable[localised[i]] = ascii[i];
-                               digits.push( $.escapeRE( localised[i] ) );
-                       }
-               }
-               digitClass = '[' + digits.join( '', digits ) + ']';
-
-               // We allow a trailing percent sign, which we just strip. This works fine
-               // if percents and regular numbers aren't being mixed.
-               ts.numberRegex = new RegExp('^(' + '[-+\u2212]?[0-9][0-9,]*(\\.[0-9,]*)?(E[-+\u2212]?[0-9][0-9,]*)?' + // Fortran-style scientific
-               '|' + '[-+\u2212]?' + digitClass + '+[\\s\\xa0]*%?' + // Generic localised
-               ')$', 'i');
-       }
-
-       function buildDateTable() {
-               var i, name,
-                       regex = [];
-
-               ts.monthNames = {};
-
-               for ( i = 0; i < 12; i++ ) {
-                       name = mw.language.months.names[i].toLowerCase();
-                       ts.monthNames[name] = i + 1;
-                       regex.push( $.escapeRE( name ) );
-                       name = mw.language.months.genitive[i].toLowerCase();
-                       ts.monthNames[name] = i + 1;
-                       regex.push( $.escapeRE( name ) );
-                       name = mw.language.months.abbrev[i].toLowerCase().replace( '.', '' );
-                       ts.monthNames[name] = i + 1;
-                       regex.push( $.escapeRE( name ) );
-               }
-
-               // Build piped string
-               regex = regex.join( '|' );
-
-               // Build RegEx
-               // Any date formated with . , ' - or /
-               ts.dateRegex[0] = new RegExp( /^\s*(\d{1,2})[\,\.\-\/'\s]{1,2}(\d{1,2})[\,\.\-\/'\s]{1,2}(\d{2,4})\s*?/i);
-
-               // Written Month name, dmy
-               ts.dateRegex[1] = new RegExp( '^\\s*(\\d{1,2})[\\,\\.\\-\\/\'\\s]+(' + regex + ')' + '[\\,\\.\\-\\/\'\\s]+(\\d{2,4})\\s*$', 'i' );
-
-               // Written Month name, mdy
-               ts.dateRegex[2] = new RegExp( '^\\s*(' + regex + ')' + '[\\,\\.\\-\\/\'\\s]+(\\d{1,2})[\\,\\.\\-\\/\'\\s]+(\\d{2,4})\\s*$', 'i' );
-
-       }
-
-       /**
-        * Replace all rowspanned cells in the body with clones in each row, so sorting
-        * need not worry about them.
-        *
-        * @param $table jQuery object for a <table>
-        */
-       function explodeRowspans( $table ) {
-               var spanningRealCellIndex, rowSpan, colSpan,
-                       cell, i, $tds, $clone, $nextRows,
-                       rowspanCells = $table.find( '> tbody > tr > [rowspan]' ).get();
-
-               // Short circuit
-               if ( !rowspanCells.length ) {
-                       return;
-               }
-
-               // First, we need to make a property like cellIndex but taking into
-               // account colspans. We also cache the rowIndex to avoid having to take
-               // cell.parentNode.rowIndex in the sorting function below.
-               $table.find( '> tbody > tr' ).each( function () {
-                       var i,
-                               col = 0,
-                               l = this.cells.length;
-                       for ( i = 0; i < l; i++ ) {
-                               this.cells[i].realCellIndex = col;
-                               this.cells[i].realRowIndex = this.rowIndex;
-                               col += this.cells[i].colSpan;
-                       }
-               } );
-
-               // Split multi row cells into multiple cells with the same content.
-               // Sort by column then row index to avoid problems with odd table structures.
-               // Re-sort whenever a rowspanned cell's realCellIndex is changed, because it
-               // might change the sort order.
-               function resortCells() {
-                       rowspanCells = rowspanCells.sort( function ( a, b ) {
-                               var ret = a.realCellIndex - b.realCellIndex;
-                               if ( !ret ) {
-                                       ret = a.realRowIndex - b.realRowIndex;
-                               }
-                               return ret;
-                       } );
-                       $.each( rowspanCells, function () {
-                               this.needResort = false;
-                       } );
-               }
-               resortCells();
-
-               function filterfunc() {
-                       return this.realCellIndex >= spanningRealCellIndex;
-               }
-
-               function fixTdCellIndex() {
-                       this.realCellIndex += colSpan;
-                       if ( this.rowSpan > 1 ) {
-                               this.needResort = true;
-                       }
-               }
-
-               while ( rowspanCells.length ) {
-                       if ( rowspanCells[0].needResort ) {
-                               resortCells();
-                       }
-
-                       cell = rowspanCells.shift();
-                       rowSpan = cell.rowSpan;
-                       colSpan = cell.colSpan;
-                       spanningRealCellIndex = cell.realCellIndex;
-                       cell.rowSpan = 1;
-                       $nextRows = $( cell ).parent().nextAll();
-                       for ( i = 0; i < rowSpan - 1; i++ ) {
-                               $tds = $( $nextRows[i].cells ).filter( filterfunc );
-                               $clone = $( cell ).clone();
-                               $clone[0].realCellIndex = spanningRealCellIndex;
-                               if ( $tds.length ) {
-                                       $tds.each( fixTdCellIndex );
-                                       $tds.first().before( $clone );
-                               } else {
-                                       $nextRows.eq( i ).append( $clone );
-                               }
-                       }
-               }
-       }
-
-       function buildCollationTable() {
-               ts.collationTable = mw.config.get( 'tableSorterCollation' );
-               ts.collationRegex = null;
-               if ( ts.collationTable ) {
-                       var key,
-                               keys = [];
-
-                       // Build array of key names
-                       for ( key in ts.collationTable ) {
-                               // Check hasOwn to be safe
-                               if ( ts.collationTable.hasOwnProperty(key) ) {
-                                       keys.push(key);
-                               }
-                       }
-                       if ( keys.length ) {
-                               ts.collationRegex = new RegExp( '[' + keys.join( '' ) + ']', 'ig' );
-                       }
-               }
-       }
-
-       function cacheRegexs() {
-               if ( ts.rgx ) {
-                       return;
-               }
-               ts.rgx = {
-                       IPAddress: [
-                               new RegExp( /^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/)
-                       ],
-                       currency: [
-                               new RegExp( /(^[£$€¥]|[£$€¥]$)/),
-                               new RegExp( /[£$€¥]/g)
-                       ],
-                       url: [
-                               new RegExp( /^(https?|ftp|file):\/\/$/),
-                               new RegExp( /(https?|ftp|file):\/\//)
-                       ],
-                       isoDate: [
-                               new RegExp( /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/)
-                       ],
-                       usLongDate: [
-                               new RegExp( /^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/)
-                       ],
-                       time: [
-                               new RegExp( /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/)
-                       ]
-               };
-       }
-
-       /**
-        * Converts sort objects [ { Integer: String }, ... ] to the internally used nested array
-        * structure [ [ Integer , Integer ], ... ]
-        *
-        * @param sortObjects {Array} List of sort objects.
-        * @return {Array} List of internal sort definitions.
-        */
-
-       function convertSortList( sortObjects ) {
-               var sortList = [];
-               $.each( sortObjects, function( i, sortObject ) {
-                       $.each ( sortObject, function( columnIndex, order ) {
-                               var orderIndex = ( order === 'desc' ) ? 1 : 0;
-                               sortList.push( [parseInt( columnIndex, 10 ), orderIndex] );
-                       } );
-               } );
-               return sortList;
-       }
-
-       /* Public scope */
-
-       $.tablesorter = {
-
-                       defaultOptions: {
-                               cssHeader: 'headerSort',
-                               cssAsc: 'headerSortUp',
-                               cssDesc: 'headerSortDown',
-                               cssChildRow: 'expand-child',
-                               sortInitialOrder: 'asc',
-                               sortMultiSortKey: 'shiftKey',
-                               sortLocaleCompare: false,
-                               unsortableClass: 'unsortable',
-                               parsers: {},
-                               widgets: [],
-                               headers: {},
-                               cancelSelection: true,
-                               sortList: [],
-                               headerList: [],
-                               selectorHeaders: 'thead tr:eq(0) th',
-                               debug: false
-                       },
-
-                       dateRegex: [],
-                       monthNames: {},
-
-                       /**
-                        * @param $tables {jQuery}
-                        * @param settings {Object} (optional)
-                        */
-                       construct: function ( $tables, settings ) {
-                               return $tables.each( function ( i, table ) {
-                                       // Declare and cache.
-                                       var $headers, cache, config, sortCSS, sortMsg,
-                                               $table = $( table ),
-                                               firstTime = true;
-
-                                       // Quit if no tbody
-                                       if ( !table.tBodies ) {
-                                               return;
-                                       }
-                                       if ( !table.tHead ) {
-                                               // No thead found. Look for rows with <th>s and
-                                               // move them into a <thead> tag or a <tfoot> tag
-                                               emulateTHeadAndFoot( $table );
-
-                                               // Still no thead? Then quit
-                                               if ( !table.tHead ) {
-                                                       return;
-                                               }
-                                       }
-                                       $table.addClass( 'jquery-tablesorter' );
-
-                                       // FIXME config should probably not be stored in the plain table node
-                                       // New config object.
-                                       table.config = {};
-
-                                       // Merge and extend.
-                                       config = $.extend( table.config, $.tablesorter.defaultOptions, settings );
-
-                                       // Save the settings where they read
-                                       $.data( table, 'tablesorter', { config: config } );
-
-                                       // Get the CSS class names, could be done else where.
-                                       sortCSS = [ config.cssDesc, config.cssAsc ];
-                                       sortMsg = [ mw.msg( 'sort-descending' ), mw.msg( 'sort-ascending' ) ];
-
-                                       // Build headers
-                                       $headers = buildHeaders( table, sortMsg );
-
-                                       // Grab and process locale settings.
-                                       buildTransformTable();
-                                       buildDateTable();
-
-                                       // Precaching regexps can bring 10 fold
-                                       // performance improvements in some browsers.
-                                       cacheRegexs();
-
-                                       function setupForFirstSort() {
-                                               firstTime = false;
-
-                                               // Defer buildCollationTable to first sort. As user and site scripts
-                                               // may customize tableSorterCollation but load after $.ready(), other
-                                               // scripts may call .tablesorter() before they have done the
-                                               // tableSorterCollation customizations.
-                                               buildCollationTable();
-
-                                               // Legacy fix of .sortbottoms
-                                               // Wrap them inside inside a tfoot (because that's what they actually want to be) &
-                                               // and put the <tfoot> at the end of the <table>
-                                               var $sortbottoms = $table.find( '> tbody > tr.sortbottom' );
-                                               if ( $sortbottoms.length ) {
-                                                       var $tfoot = $table.children( 'tfoot' );
-                                                       if ( $tfoot.length ) {
-                                                               $tfoot.eq(0).prepend( $sortbottoms );
-                                                       } else {
-                                                               $table.append( $( '<tfoot>' ).append( $sortbottoms ) );
-                                                       }
-                                               }
-
-                                               explodeRowspans( $table );
-
-                                               // try to auto detect column type, and store in tables config
-                                               table.config.parsers = buildParserCache( table, $headers );
-                                       }
-
-                                       // Apply event handling to headers
-                                       // this is too big, perhaps break it out?
-                                       $headers.not( '.' + table.config.unsortableClass ).on( 'keypress click', function ( e ) {
-                                               if ( e.type === 'click' && e.target.nodeName.toLowerCase() === 'a' ) {
-                                                       // The user clicked on a link inside a table header.
-                                                       // Do nothing and let the default link click action continue.
-                                                       return true;
-                                               }
-
-                                               if ( e.type === 'keypress' && e.which !== 13 ) {
-                                                       // Only handle keypresses on the "Enter" key.
-                                                       return true;
-                                               }
-
-                                               if ( firstTime ) {
-                                                       setupForFirstSort();
-                                               }
-
-                                               // Build the cache for the tbody cells
-                                               // to share between calculations for this sort action.
-                                               // Re-calculated each time a sort action is performed due to possiblity
-                                               // that sort values change. Shouldn't be too expensive, but if it becomes
-                                               // too slow an event based system should be implemented somehow where
-                                               // cells get event .change() and bubbles up to the <table> here
-                                               cache = buildCache( table );
-
-                                               var totalRows = ( $table[0].tBodies[0] && $table[0].tBodies[0].rows.length ) || 0;
-                                               if ( !table.sortDisabled && totalRows > 0 ) {
-                                                       // Get current column sort order
-                                                       this.order = this.count % 2;
-                                                       this.count++;
-
-                                                       var cell, columns, newSortList, i;
-
-                                                       cell = this;
-                                                       // Get current column index
-                                                       columns = table.headerToColumns[ this.headerIndex ];
-                                                       newSortList = $.map( columns, function ( c ) {
-                                                               // jQuery "helpfully" flattens the arrays...
-                                                               return [[c, cell.order]];
-                                                       });
-                                                       // Index of first column belonging to this header
-                                                       i = columns[0];
-
-                                                       if ( !e[config.sortMultiSortKey] ) {
-                                                               // User only wants to sort on one column set
-                                                               // Flush the sort list and add new columns
-                                                               config.sortList = newSortList;
-                                                       } else {
-                                                               // Multi column sorting
-                                                               // It is not possible for one column to belong to multiple headers,
-                                                               // so this is okay - we don't need to check for every value in the columns array
-                                                               if ( isValueInArray( i, config.sortList ) ) {
-                                                                       // The user has clicked on an already sorted column.
-                                                                       // Reverse the sorting direction for all tables.
-                                                                       for ( var j = 0; j < config.sortList.length; j++ ) {
-                                                                               var s = config.sortList[j],
-                                                                                       o = config.headerList[s[0]];
-                                                                               if ( isValueInArray( s[0], newSortList ) ) {
-                                                                                       o.count = s[1];
-                                                                                       o.count++;
-                                                                                       s[1] = o.count % 2;
-                                                                               }
-                                                                       }
-                                                               } else {
-                                                                       // Add columns to sort list array
-                                                                       config.sortList = config.sortList.concat( newSortList );
-                                                               }
-                                                       }
-
-                                                       // Reset order/counts of cells not affected by sorting
-                                                       setHeadersOrder( $headers, config.sortList, table.headerToColumns );
-
-                                                       // Set CSS for headers
-                                                       setHeadersCss( $table[0], $headers, config.sortList, sortCSS, sortMsg, table.columnToHeader );
-                                                       appendToTable(
-                                                               $table[0], multisort( $table[0], config.sortList, cache )
-                                                       );
-
-                                                       // Stop normal event by returning false
-                                                       return false;
-                                               }
-
-                                       // Cancel selection
-                                       } ).mousedown( function () {
-                                               if ( config.cancelSelection ) {
-                                                       this.onselectstart = function () {
-                                                               return false;
-                                                       };
-                                                       return false;
-                                               }
-                                       } );
-
-                                       /**
-                                        * Sorts the table. If no sorting is specified by passing a list of sort
-                                        * objects, the table is sorted according to the initial sorting order.
-                                        * Passing an empty array will reset sorting (basically just reset the headers
-                                        * making the table appear unsorted).
-                                        *
-                                        * @param sortList {Array} (optional) List of sort objects.
-                                        */
-                                       $table.data( 'tablesorter' ).sort = function ( sortList ) {
-
-                                               if ( firstTime ) {
-                                                       setupForFirstSort();
-                                               }
-
-                                               if ( sortList === undefined ) {
-                                                       sortList = config.sortList;
-                                               } else if ( sortList.length > 0 ) {
-                                                       sortList = convertSortList( sortList );
-                                               }
-
-                                               // Set each column's sort count to be able to determine the correct sort
-                                               // order when clicking on a header cell the next time
-                                               setHeadersOrder( $headers, sortList, table.headerToColumns );
-
-                                               // re-build the cache for the tbody cells
-                                               cache = buildCache( table );
-
-                                               // set css for headers
-                                               setHeadersCss( table, $headers, sortList, sortCSS, sortMsg, table.columnToHeader );
-
-                                               // sort the table and append it to the dom
-                                               appendToTable( table, multisort( table, sortList, cache ) );
-                                       };
-
-                                       // sort initially
-                                       if ( config.sortList.length > 0 ) {
-                                               setupForFirstSort();
-                                               config.sortList = convertSortList( config.sortList );
-                                               $table.data( 'tablesorter' ).sort();
-                                       }
-
-                               } );
-                       },
-
-                       addParser: function ( parser ) {
-                               var l = parsers.length,
-                                       a = true;
-                               for ( var i = 0; i < l; i++ ) {
-                                       if ( parsers[i].id.toLowerCase() === parser.id.toLowerCase() ) {
-                                               a = false;
-                                       }
-                               }
-                               if ( a ) {
-                                       parsers.push( parser );
-                               }
-                       },
-
-                       formatDigit: function ( s ) {
-                               var out, c, p, i;
-                               if ( ts.transformTable !== false ) {
-                                       out = '';
-                                       for ( p = 0; p < s.length; p++ ) {
-                                               c = s.charAt(p);
-                                               if ( c in ts.transformTable ) {
-                                                       out += ts.transformTable[c];
-                                               } else {
-                                                       out += c;
-                                               }
-                                       }
-                                       s = out;
-                               }
-                               i = parseFloat( s.replace( /[, ]/g, '' ).replace( '\u2212', '-' ) );
-                               return isNaN( i ) ? 0 : i;
-                       },
-
-                       formatFloat: function ( s ) {
-                               var i = parseFloat(s);
-                               return isNaN( i ) ? 0 : i;
-                       },
-
-                       formatInt: function ( s ) {
-                               var i = parseInt( s, 10 );
-                               return isNaN( i ) ? 0 : i;
-                       },
-
-                       clearTableBody: function ( table ) {
-                               $( table.tBodies[0] ).empty();
-                       }
-               };
-
-       // Shortcut
-       ts = $.tablesorter;
-
-       // Register as jQuery prototype method
-       $.fn.tablesorter = function ( settings ) {
-               return ts.construct( this, settings );
-       };
-
-       // Add default parsers
-       ts.addParser( {
-               id: 'text',
-               is: function () {
-                       return true;
-               },
-               format: function ( s ) {
-                       s = $.trim( s.toLowerCase() );
-                       if ( ts.collationRegex ) {
-                               var tsc = ts.collationTable;
-                               s = s.replace( ts.collationRegex, function ( match ) {
-                                       var r = tsc[match] ? tsc[match] : tsc[match.toUpperCase()];
-                                       return r.toLowerCase();
-                               } );
-                       }
-                       return s;
-               },
-               type: 'text'
-       } );
-
-       ts.addParser( {
-               id: 'IPAddress',
-               is: function ( s ) {
-                       return ts.rgx.IPAddress[0].test(s);
-               },
-               format: function ( s ) {
-                       var a = s.split( '.' ),
-                               r = '',
-                               l = a.length;
-                       for ( var i = 0; i < l; i++ ) {
-                               var item = a[i];
-                               if ( item.length === 1 ) {
-                                       r += '00' + item;
-                               } else if ( item.length === 2 ) {
-                                       r += '0' + item;
-                               } else {
-                                       r += item;
-                               }
-                       }
-                       return $.tablesorter.formatFloat(r);
-               },
-               type: 'numeric'
-       } );
-
-       ts.addParser( {
-               id: 'currency',
-               is: function ( s ) {
-                       return ts.rgx.currency[0].test(s);
-               },
-               format: function ( s ) {
-                       return $.tablesorter.formatDigit( s.replace( ts.rgx.currency[1], '' ) );
-               },
-               type: 'numeric'
-       } );
-
-       ts.addParser( {
-               id: 'url',
-               is: function ( s ) {
-                       return ts.rgx.url[0].test(s);
-               },
-               format: function ( s ) {
-                       return $.trim( s.replace( ts.rgx.url[1], '' ) );
-               },
-               type: 'text'
-       } );
-
-       ts.addParser( {
-               id: 'isoDate',
-               is: function ( s ) {
-                       return ts.rgx.isoDate[0].test(s);
-               },
-               format: function ( s ) {
-                       return $.tablesorter.formatFloat((s !== '') ? new Date(s.replace(
-                       new RegExp( /-/g), '/')).getTime() : '0' );
-               },
-               type: 'numeric'
-       } );
-
-       ts.addParser( {
-               id: 'usLongDate',
-               is: function ( s ) {
-                       return ts.rgx.usLongDate[0].test(s);
-               },
-               format: function ( s ) {
-                       return $.tablesorter.formatFloat( new Date(s).getTime() );
-               },
-               type: 'numeric'
-       } );
-
-       ts.addParser( {
-               id: 'date',
-               is: function ( s ) {
-                       return ( ts.dateRegex[0].test(s) || ts.dateRegex[1].test(s) || ts.dateRegex[2].test(s ));
-               },
-               format: function ( s ) {
-                       var match;
-                       s = $.trim( s.toLowerCase() );
-
-                       if ( ( match = s.match( ts.dateRegex[0] ) ) !== null ) {
-                               if ( mw.config.get( 'wgDefaultDateFormat' ) === 'mdy' || mw.config.get( 'wgContentLanguage' ) === 'en' ) {
-                                       s = [ match[3], match[1], match[2] ];
-                               } else if ( mw.config.get( 'wgDefaultDateFormat' ) === 'dmy' ) {
-                                       s = [ match[3], match[2], match[1] ];
-                               } else {
-                                       // If we get here, we don't know which order the dd-dd-dddd
-                                       // date is in. So return something not entirely invalid.
-                                       return '99999999';
-                               }
-                       } else if ( ( match = s.match( ts.dateRegex[1] ) ) !== null ) {
-                               s = [ match[3], '' + ts.monthNames[match[2]], match[1] ];
-                       } else if ( ( match = s.match( ts.dateRegex[2] ) ) !== null ) {
-                               s = [ match[3], '' + ts.monthNames[match[1]], match[2] ];
-                       } else {
-                               // Should never get here
-                               return '99999999';
-                       }
-
-                       // Pad Month and Day
-                       if ( s[1].length === 1 ) {
-                               s[1] = '0' + s[1];
-                       }
-                       if ( s[2].length === 1 ) {
-                               s[2] = '0' + s[2];
-                       }
-
-                       var y;
-                       if ( ( y = parseInt( s[0], 10) ) < 100 ) {
-                               // Guestimate years without centuries
-                               if ( y < 30 ) {
-                                       s[0] = 2000 + y;
-                               } else {
-                                       s[0] = 1900 + y;
-                               }
-                       }
-                       while ( s[0].length < 4 ) {
-                               s[0] = '0' + s[0];
-                       }
-                       return parseInt( s.join( '' ), 10 );
-               },
-               type: 'numeric'
-       } );
-
-       ts.addParser( {
-               id: 'time',
-               is: function ( s ) {
-                       return ts.rgx.time[0].test(s);
-               },
-               format: function ( s ) {
-                       return $.tablesorter.formatFloat( new Date( '2000/01/01 ' + s ).getTime() );
-               },
-               type: 'numeric'
-       } );
-
-       ts.addParser( {
-               id: 'number',
-               is: function ( s ) {
-                       return $.tablesorter.numberRegex.test( $.trim( s ));
-               },
-               format: function ( s ) {
-                       return $.tablesorter.formatDigit(s);
-               },
-               type: 'numeric'
-       } );
-
-}( jQuery, mediaWiki ) );
diff --git a/resources/jquery/jquery.textSelection.js b/resources/jquery/jquery.textSelection.js
deleted file mode 100644 (file)
index 7262fe6..0000000
+++ /dev/null
@@ -1,573 +0,0 @@
-/**
- * These plugins provide extra functionality for interaction with textareas.
- */
-( function ( $ ) {
-       if ( document.selection && document.selection.createRange ) {
-               // On IE, patch the focus() method to restore the windows' scroll position
-               // (bug 32241)
-               $.fn.extend({
-                       focus: ( function ( jqFocus ) {
-                               return function () {
-                                       var $w, state, result;
-                                       if ( arguments.length === 0 ) {
-                                               $w = $( window );
-                                               state = { top: $w.scrollTop(), left: $w.scrollLeft() };
-                                               result = jqFocus.apply( this, arguments );
-                                               window.scrollTo( state.top, state.left );
-                                               return result;
-                                       }
-                                       return jqFocus.apply( this, arguments );
-                               };
-                       }( $.fn.focus ) )
-               });
-       }
-
-       $.fn.textSelection = function ( command, options ) {
-               var fn,
-                       context,
-                       hasIframe,
-                       needSave,
-                       retval;
-
-               /**
-                * Helper function to get an IE TextRange object for an element
-                */
-               function rangeForElementIE( e ) {
-                       if ( e.nodeName.toLowerCase() === 'input' ) {
-                               return e.createTextRange();
-                       } else {
-                               var sel = document.body.createTextRange();
-                               sel.moveToElementText( e );
-                               return sel;
-                       }
-               }
-
-               /**
-                * Helper function for IE for activating the textarea. Called only in the
-                * IE-specific code paths below; makes use of IE-specific non-standard
-                * function setActive() if possible to avoid screen flicker.
-                */
-               function activateElementOnIE( element ) {
-                       if ( element.setActive ) {
-                               element.setActive(); // bug 32241: doesn't scroll
-                       } else {
-                               $( element ).focus(); // may scroll (but we patched it above)
-                       }
-               }
-
-               fn = {
-                       /**
-                        * Get the contents of the textarea
-                        */
-                       getContents: function () {
-                               return this.val();
-                       },
-                       /**
-                        * Get the currently selected text in this textarea. Will focus the textarea
-                        * in some browsers (IE/Opera)
-                        */
-                       getSelection: function () {
-                               var retval, range,
-                                       el = this.get( 0 );
-
-                               if ( $(el).is( ':hidden' ) ) {
-                                       retval = '';
-                               } else if ( document.selection && document.selection.createRange ) {
-                                       activateElementOnIE( el );
-                                       range = document.selection.createRange();
-                                       retval = range.text;
-                               } else if ( el.selectionStart || el.selectionStart === 0 ) {
-                                       retval = el.value.substring( el.selectionStart, el.selectionEnd );
-                               }
-
-                               return retval;
-                       },
-                       /**
-                        * Ported from skins/common/edit.js by Trevor Parscal
-                        * (c) 2009 Wikimedia Foundation (GPLv2) - http://www.wikimedia.org
-                        *
-                        * Inserts text at the beginning and end of a text selection, optionally
-                        * inserting text at the caret when selection is empty.
-                        *
-                        * @fixme document the options parameters
-                        */
-                       encapsulateSelection: function ( options ) {
-                               return this.each( function () {
-                                       var selText, scrollTop, insertText,
-                                               isSample, range, range2, range3, startPos, endPos,
-                                               pre = options.pre,
-                                               post = options.post;
-
-                                       /**
-                                        * Check if the selected text is the same as the insert text
-                                        */
-                                       function checkSelectedText() {
-                                               if ( !selText ) {
-                                                       selText = options.peri;
-                                                       isSample = true;
-                                               } else if ( options.replace ) {
-                                                       selText = options.peri;
-                                               } else {
-                                                       while ( selText.charAt( selText.length - 1 ) === ' ' ) {
-                                                               // Exclude ending space char
-                                                               selText = selText.substring( 0, selText.length - 1 );
-                                                               post += ' ';
-                                                       }
-                                                       while ( selText.charAt( 0 ) === ' ' ) {
-                                                               // Exclude prepending space char
-                                                               selText = selText.substring( 1, selText.length );
-                                                               pre = ' ' + pre;
-                                                       }
-                                               }
-                                       }
-
-                                       /**
-                                        * Do the splitlines stuff.
-                                        *
-                                        * Wrap each line of the selected text with pre and post
-                                        */
-                                       function doSplitLines( selText, pre, post ) {
-                                               var i,
-                                                       insertText = '',
-                                                       selTextArr = selText.split( '\n' );
-                                               for ( i = 0; i < selTextArr.length; i++ ) {
-                                                       insertText += pre + selTextArr[i] + post;
-                                                       if ( i !== selTextArr.length - 1 ) {
-                                                               insertText += '\n';
-                                                       }
-                                               }
-                                               return insertText;
-                                       }
-
-                                       isSample = false;
-                                       // Do nothing if display none
-                                       if ( this.style.display !== 'none' ) {
-                                               if ( document.selection && document.selection.createRange ) {
-                                                       // IE
-
-                                                       // Note that IE9 will trigger the next section unless we check this first.
-                                                       // See bug 35201.
-
-                                                       activateElementOnIE( this );
-                                                       if ( context ) {
-                                                               context.fn.restoreCursorAndScrollTop();
-                                                       }
-                                                       if ( options.selectionStart !== undefined ) {
-                                                               $(this).textSelection( 'setSelection', { 'start': options.selectionStart, 'end': options.selectionEnd } );
-                                                       }
-
-                                                       selText = $(this).textSelection( 'getSelection' );
-                                                       scrollTop = this.scrollTop;
-                                                       range = document.selection.createRange();
-
-                                                       checkSelectedText();
-                                                       insertText = pre + selText + post;
-                                                       if ( options.splitlines ) {
-                                                               insertText = doSplitLines( selText, pre, post );
-                                                       }
-                                                       if ( options.ownline && range.moveStart ) {
-                                                               range2 = document.selection.createRange();
-                                                               range2.collapse();
-                                                               range2.moveStart( 'character', -1 );
-                                                               // FIXME: Which check is correct?
-                                                               if ( range2.text !== '\r' && range2.text !== '\n' && range2.text !== '' ) {
-                                                                       insertText = '\n' + insertText;
-                                                                       pre += '\n';
-                                                               }
-                                                               range3 = document.selection.createRange();
-                                                               range3.collapse( false );
-                                                               range3.moveEnd( 'character', 1 );
-                                                               if ( range3.text !== '\r' && range3.text !== '\n' && range3.text !== '' ) {
-                                                                       insertText += '\n';
-                                                                       post += '\n';
-                                                               }
-                                                       }
-
-                                                       range.text = insertText;
-                                                       if ( isSample && options.selectPeri && range.moveStart ) {
-                                                               range.moveStart( 'character', -post.length - selText.length );
-                                                               range.moveEnd( 'character', -post.length );
-                                                       }
-                                                       range.select();
-                                                       // Restore the scroll position
-                                                       this.scrollTop = scrollTop;
-                                               } else if ( this.selectionStart || this.selectionStart === 0 ) {
-                                                       // Mozilla/Opera
-
-                                                       $(this).focus();
-                                                       if ( options.selectionStart !== undefined ) {
-                                                               $(this).textSelection( 'setSelection', { 'start': options.selectionStart, 'end': options.selectionEnd } );
-                                                       }
-
-                                                       selText = $(this).textSelection( 'getSelection' );
-                                                       startPos = this.selectionStart;
-                                                       endPos = this.selectionEnd;
-                                                       scrollTop = this.scrollTop;
-                                                       checkSelectedText();
-                                                       if ( options.selectionStart !== undefined
-                                                                       && endPos - startPos !== options.selectionEnd - options.selectionStart )
-                                                       {
-                                                               // This means there is a difference in the selection range returned by browser and what we passed.
-                                                               // This happens for Chrome in the case of composite characters. Ref bug #30130
-                                                               // Set the startPos to the correct position.
-                                                               startPos = options.selectionStart;
-                                                       }
-
-                                                       insertText = pre + selText + post;
-                                                       if ( options.splitlines ) {
-                                                               insertText = doSplitLines( selText, pre, post );
-                                                       }
-                                                       if ( options.ownline ) {
-                                                               if ( startPos !== 0 && this.value.charAt( startPos - 1 ) !== '\n' && this.value.charAt( startPos - 1 ) !== '\r' ) {
-                                                                       insertText = '\n' + insertText;
-                                                                       pre += '\n';
-                                                               }
-                                                               if ( this.value.charAt( endPos ) !== '\n' && this.value.charAt( endPos ) !== '\r' ) {
-                                                                       insertText += '\n';
-                                                                       post += '\n';
-                                                               }
-                                                       }
-                                                       this.value = this.value.substring( 0, startPos ) + insertText +
-                                                               this.value.substring( endPos, this.value.length );
-                                                       // Setting this.value scrolls the textarea to the top, restore the scroll position
-                                                       this.scrollTop = scrollTop;
-                                                       if ( window.opera ) {
-                                                               pre = pre.replace( /\r?\n/g, '\r\n' );
-                                                               selText = selText.replace( /\r?\n/g, '\r\n' );
-                                                               post = post.replace( /\r?\n/g, '\r\n' );
-                                                       }
-                                                       if ( isSample && options.selectPeri && !options.splitlines ) {
-                                                               this.selectionStart = startPos + pre.length;
-                                                               this.selectionEnd = startPos + pre.length + selText.length;
-                                                       } else {
-                                                               this.selectionStart = startPos + insertText.length;
-                                                               this.selectionEnd = this.selectionStart;
-                                                       }
-                                               }
-                                       }
-                                       $(this).trigger( 'encapsulateSelection', [ options.pre, options.peri, options.post, options.ownline,
-                                               options.replace, options.spitlines ] );
-                               });
-                       },
-                       /**
-                        * Ported from Wikia's LinkSuggest extension
-                        * https://svn.wikia-code.com/wikia/trunk/extensions/wikia/LinkSuggest
-                        * Some code copied from
-                        * http://www.dedestruct.com/2008/03/22/howto-cross-browser-cursor-position-in-textareas/
-                        *
-                        * Get the position (in resolution of bytes not necessarily characters)
-                        * in a textarea
-                        *
-                        * Will focus the textarea in some browsers (IE/Opera)
-                        *
-                        * @fixme document the options parameters
-                        */
-                        getCaretPosition: function ( options ) {
-                               function getCaret( e ) {
-                                       var caretPos = 0,
-                                               endPos = 0,
-                                               preText, rawPreText, periText,
-                                               rawPeriText, postText, rawPostText,
-                                               // IE Support
-                                               preFinished,
-                                               periFinished,
-                                               postFinished,
-                                               // Range containing text in the selection
-                                               periRange,
-                                               // Range containing text before the selection
-                                               preRange,
-                                               // Range containing text after the selection
-                                               postRange;
-
-                                       if ( document.selection && document.selection.createRange ) {
-                                               // IE doesn't properly report non-selected caret position through
-                                               // the selection ranges when textarea isn't focused. This can
-                                               // lead to saving a bogus empty selection, which then screws up
-                                               // whatever we do later (bug 31847).
-                                               activateElementOnIE( e );
-
-                                               preFinished = false;
-                                               periFinished = false;
-                                               postFinished = false;
-                                               periRange = document.selection.createRange().duplicate();
-
-                                               preRange = rangeForElementIE( e );
-                                               // Move the end where we need it
-                                               preRange.setEndPoint( 'EndToStart', periRange );
-
-                                               postRange = rangeForElementIE( e );
-                                               // Move the start where we need it
-                                               postRange.setEndPoint( 'StartToEnd', periRange );
-
-                                               // Load the text values we need to compare
-                                               preText = rawPreText = preRange.text;
-                                               periText = rawPeriText = periRange.text;
-                                               postText = rawPostText = postRange.text;
-
-                                               /*
-                                                * Check each range for trimmed newlines by shrinking the range by 1
-                                                * character and seeing if the text property has changed. If it has
-                                                * not changed then we know that IE has trimmed a \r\n from the end.
-                                                */
-                                               do {
-                                                       if ( !preFinished ) {
-                                                               if ( preRange.compareEndPoints( 'StartToEnd', preRange ) === 0 ) {
-                                                                       preFinished = true;
-                                                               } else {
-                                                                       preRange.moveEnd( 'character', -1 );
-                                                                       if ( preRange.text === preText ) {
-                                                                               rawPreText += '\r\n';
-                                                                       } else {
-                                                                               preFinished = true;
-                                                                       }
-                                                               }
-                                                       }
-                                                       if ( !periFinished ) {
-                                                               if ( periRange.compareEndPoints( 'StartToEnd', periRange ) === 0 ) {
-                                                                       periFinished = true;
-                                                               } else {
-                                                                       periRange.moveEnd( 'character', -1 );
-                                                                       if ( periRange.text === periText ) {
-                                                                               rawPeriText += '\r\n';
-                                                                       } else {
-                                                                               periFinished = true;
-                                                                       }
-                                                               }
-                                                       }
-                                                       if ( !postFinished ) {
-                                                               if ( postRange.compareEndPoints( 'StartToEnd', postRange ) === 0 ) {
-                                                                       postFinished = true;
-                                                               } else {
-                                                                       postRange.moveEnd( 'character', -1 );
-                                                                       if ( postRange.text === postText ) {
-                                                                               rawPostText += '\r\n';
-                                                                       } else {
-                                                                               postFinished = true;
-                                                                       }
-                                                               }
-                                                       }
-                                               } while ( ( !preFinished || !periFinished || !postFinished ) );
-                                               caretPos = rawPreText.replace( /\r\n/g, '\n' ).length;
-                                               endPos = caretPos + rawPeriText.replace( /\r\n/g, '\n' ).length;
-                                       } else if ( e.selectionStart || e.selectionStart === 0 ) {
-                                               // Firefox support
-                                               caretPos = e.selectionStart;
-                                               endPos = e.selectionEnd;
-                                       }
-                                       return options.startAndEnd ? [ caretPos, endPos ] : caretPos;
-                               }
-                               return getCaret( this.get( 0 ) );
-                       },
-                       /**
-                        * @fixme document the options parameters
-                        */
-                       setSelection: function ( options ) {
-                               return this.each( function () {
-                                       var selection, length, newLines;
-                                       // Do nothing if hidden
-                                       if ( !$(this).is( ':hidden' ) ) {
-                                               if ( this.selectionStart || this.selectionStart === 0 ) {
-                                                       // Opera 9.0 doesn't allow setting selectionStart past
-                                                       // selectionEnd; any attempts to do that will be ignored
-                                                       // Make sure to set them in the right order
-                                                       if ( options.start > this.selectionEnd ) {
-                                                               this.selectionEnd = options.end;
-                                                               this.selectionStart = options.start;
-                                                       } else {
-                                                               this.selectionStart = options.start;
-                                                               this.selectionEnd = options.end;
-                                                       }
-                                               } else if ( document.body.createTextRange ) {
-                                                       selection = rangeForElementIE( this );
-                                                       length = this.value.length;
-                                                       // IE doesn't count \n when computing the offset, so we won't either
-                                                       newLines = this.value.match( /\n/g );
-                                                       if ( newLines ) {
-                                                               length = length - newLines.length;
-                                                       }
-                                                       selection.moveStart( 'character', options.start );
-                                                       selection.moveEnd( 'character', -length + options.end );
-
-                                                       // This line can cause an error under certain circumstances (textarea empty, no selection)
-                                                       // Silence that error
-                                                       try {
-                                                               selection.select();
-                                                       } catch ( e ) { }
-                                               }
-                                       }
-                               });
-                       },
-                       /**
-                        * Ported from Wikia's LinkSuggest extension
-                        * https://svn.wikia-code.com/wikia/trunk/extensions/wikia/LinkSuggest
-                        *
-                        * Scroll a textarea to the current cursor position. You can set the cursor
-                        * position with setSelection()
-                        * @param options boolean Whether to force a scroll even if the caret position
-                        *  is already visible. Defaults to false
-                        *
-                        * @fixme document the options parameters (function body suggests options.force is a boolean, not options itself)
-                        */
-                       scrollToCaretPosition: function ( options ) {
-                               function getLineLength( e ) {
-                                       return Math.floor( e.scrollWidth / ( $.client.profile().platform === 'linux' ? 7 : 8 ) );
-                               }
-                               function getCaretScrollPosition( e ) {
-                                       // FIXME: This functions sucks and is off by a few lines most
-                                       // of the time. It should be replaced by something decent.
-                                       var i, j,
-                                               nextSpace,
-                                               text = e.value.replace( /\r/g, '' ),
-                                               caret = $( e ).textSelection( 'getCaretPosition' ),
-                                               lineLength = getLineLength( e ),
-                                               row = 0,
-                                               charInLine = 0,
-                                               lastSpaceInLine = 0;
-
-                                       for ( i = 0; i < caret; i++ ) {
-                                               charInLine++;
-                                               if ( text.charAt( i ) === ' ' ) {
-                                                       lastSpaceInLine = charInLine;
-                                               } else if ( text.charAt( i ) === '\n' ) {
-                                                       lastSpaceInLine = 0;
-                                                       charInLine = 0;
-                                                       row++;
-                                               }
-                                               if ( charInLine > lineLength ) {
-                                                       if ( lastSpaceInLine > 0 ) {
-                                                               charInLine = charInLine - lastSpaceInLine;
-                                                               lastSpaceInLine = 0;
-                                                               row++;
-                                                       }
-                                               }
-                                       }
-                                       nextSpace = 0;
-                                       for ( j = caret; j < caret + lineLength; j++ ) {
-                                               if (
-                                                       text.charAt( j ) === ' ' ||
-                                                       text.charAt( j ) === '\n' ||
-                                                       caret === text.length
-                                               ) {
-                                                       nextSpace = j;
-                                                       break;
-                                               }
-                                       }
-                                       if ( nextSpace > lineLength && caret <= lineLength ) {
-                                               charInLine = caret - lastSpaceInLine;
-                                               row++;
-                                       }
-                                       return ( $.client.profile().platform === 'mac' ? 13 : ( $.client.profile().platform === 'linux' ? 15 : 16 ) ) * row;
-                               }
-                               return this.each(function () {
-                                       var scroll, range, savedRange, pos, oldScrollTop;
-                                       // Do nothing if hidden
-                                       if ( !$(this).is( ':hidden' ) ) {
-                                               if ( this.selectionStart || this.selectionStart === 0 ) {
-                                                       // Mozilla
-                                                       scroll = getCaretScrollPosition( this );
-                                                       if ( options.force || scroll < $(this).scrollTop() ||
-                                                                       scroll > $(this).scrollTop() + $(this).height() ) {
-                                                               $(this).scrollTop( scroll );
-                                                       }
-                                               } else if ( document.selection && document.selection.createRange ) {
-                                                       // IE / Opera
-                                                       /*
-                                                        * IE automatically scrolls the selected text to the
-                                                        * bottom of the textarea at range.select() time, except
-                                                        * if it was already in view and the cursor position
-                                                        * wasn't changed, in which case it does nothing. To
-                                                        * cover that case, we'll force it to act by moving one
-                                                        * character back and forth.
-                                                        */
-                                                       range = document.body.createTextRange();
-                                                       savedRange = document.selection.createRange();
-                                                       pos = $(this).textSelection( 'getCaretPosition' );
-                                                       oldScrollTop = this.scrollTop;
-                                                       range.moveToElementText( this );
-                                                       range.collapse();
-                                                       range.move( 'character', pos + 1);
-                                                       range.select();
-                                                       if ( this.scrollTop !== oldScrollTop ) {
-                                                               this.scrollTop += range.offsetTop;
-                                                       } else if ( options.force ) {
-                                                               range.move( 'character', -1 );
-                                                               range.select();
-                                                       }
-                                                       savedRange.select();
-                                               }
-                                       }
-                                       $(this).trigger( 'scrollToPosition' );
-                               } );
-                       }
-               };
-
-               // Apply defaults
-               switch ( command ) {
-                       //case 'getContents': // no params
-                       //case 'setContents': // no params with defaults
-                       //case 'getSelection': // no params
-                       case 'encapsulateSelection':
-                               options = $.extend( {
-                                       pre: '', // Text to insert before the cursor/selection
-                                       peri: '', // Text to insert between pre and post and select afterwards
-                                       post: '', // Text to insert after the cursor/selection
-                                       ownline: false, // Put the inserted text on a line of its own
-                                       replace: false, // If there is a selection, replace it with peri instead of leaving it alone
-                                       selectPeri: true, // Select the peri text if it was inserted (but not if there was a selection and replace==false, or if splitlines==true)
-                                       splitlines: false, // If multiple lines are selected, encapsulate each line individually
-                                       selectionStart: undefined, // Position to start selection at
-                                       selectionEnd: undefined // Position to end selection at. Defaults to start
-                               }, options );
-                               break;
-                       case 'getCaretPosition':
-                               options = $.extend( {
-                                       // Return [start, end] instead of just start
-                                       startAndEnd: false
-                               }, options );
-                               // FIXME: We may not need character position-based functions if we insert markers in the right places
-                               break;
-                       case 'setSelection':
-                               options = $.extend( {
-                                       // Position to start selection at
-                                       start: undefined,
-                                       // Position to end selection at. Defaults to start
-                                       end: undefined,
-                                       // Element to start selection in (iframe only)
-                                       startContainer: undefined,
-                                       // Element to end selection in (iframe only). Defaults to startContainer
-                                       endContainer: undefined
-                               }, options );
-
-                               if ( options.end === undefined ) {
-                                       options.end = options.start;
-                               }
-                               if ( options.endContainer === undefined ) {
-                                       options.endContainer = options.startContainer;
-                               }
-                               // FIXME: We may not need character position-based functions if we insert markers in the right places
-                               break;
-                       case 'scrollToCaretPosition':
-                               options = $.extend( {
-                                       force: false // Force a scroll even if the caret position is already visible
-                               }, options );
-                               break;
-               }
-
-               context = $(this).data( 'wikiEditor-context' );
-               hasIframe = context !== undefined && context && context.$iframe !== undefined;
-
-               // IE selection restore voodoo
-               needSave = false;
-               if ( hasIframe && context.savedSelection !== null ) {
-                       context.fn.restoreSelection();
-                       needSave = true;
-               }
-               retval = ( hasIframe ? context.fn : fn )[command].call( this, options );
-               if ( hasIframe && needSave ) {
-                       context.fn.saveSelection();
-               }
-
-               return retval;
-       };
-
-}( jQuery ) );
diff --git a/resources/jquery/jquery.validate.js b/resources/jquery/jquery.validate.js
deleted file mode 100644 (file)
index 72296a6..0000000
+++ /dev/null
@@ -1,1166 +0,0 @@
-/**
- * jQuery Validation Plugin 1.8.1
- *
- * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
- * http://docs.jquery.com/Plugins/Validation
- *
- * Copyright (c) 2006 - 2011 Jörn Zaefferer
- *
- * Dual licensed under the MIT and GPL licenses:
- *   http://www.opensource.org/licenses/mit-license.php
- *   http://www.gnu.org/licenses/gpl.html
- */
-
-(function($) {
-
-$.extend($.fn, {
-       // http://docs.jquery.com/Plugins/Validation/validate
-       validate: function( options ) {
-
-               // if nothing is selected, return nothing; can't chain anyway
-               if (!this.length) {
-                       options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
-                       return;
-               }
-
-               // check if a validator for this form was already created
-               var validator = $.data(this[0], 'validator');
-               if ( validator ) {
-                       return validator;
-               }
-
-               validator = new $.validator( options, this[0] );
-               $.data(this[0], 'validator', validator);
-
-               if ( validator.settings.onsubmit ) {
-
-                       // allow suppresing validation by adding a cancel class to the submit button
-                       this.find("input, button").filter(".cancel").click(function() {
-                               validator.cancelSubmit = true;
-                       });
-
-                       // when a submitHandler is used, capture the submitting button
-                       if (validator.settings.submitHandler) {
-                               this.find("input, button").filter(":submit").click(function() {
-                                       validator.submitButton = this;
-                               });
-                       }
-
-                       // validate the form on submit
-                       this.submit( function( event ) {
-                               if ( validator.settings.debug )
-                                       // prevent form submit to be able to see console output
-                                       event.preventDefault();
-
-                               function handle() {
-                                       if ( validator.settings.submitHandler ) {
-                                               if (validator.submitButton) {
-                                                       // insert a hidden input as a replacement for the missing submit button
-                                                       var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
-                                               }
-                                               validator.settings.submitHandler.call( validator, validator.currentForm );
-                                               if (validator.submitButton) {
-                                                       // and clean up afterwards; thanks to no-block-scope, hidden can be referenced
-                                                       hidden.remove();
-                                               }
-                                               return false;
-                                       }
-                                       return true;
-                               }
-
-                               // prevent submit for invalid forms or custom submit handlers
-                               if ( validator.cancelSubmit ) {
-                                       validator.cancelSubmit = false;
-                                       return handle();
-                               }
-                               if ( validator.form() ) {
-                                       if ( validator.pendingRequest ) {
-                                               validator.formSubmitted = true;
-                                               return false;
-                                       }
-                                       return handle();
-                               } else {
-                                       validator.focusInvalid();
-                                       return false;
-                               }
-                       });
-               }
-
-               return validator;
-       },
-       // http://docs.jquery.com/Plugins/Validation/valid
-       valid: function() {
-        if ( $(this[0]).is('form')) {
-            return this.validate().form();
-        } else {
-            var valid = true;
-            var validator = $(this[0].form).validate();
-            this.each(function() {
-                               valid &= validator.element(this);
-            });
-            return valid;
-        }
-    },
-       // attributes: space seperated list of attributes to retrieve and remove
-       removeAttrs: function(attributes) {
-               var result = {},
-                       $element = this;
-               $.each(attributes.split(/\s/), function(index, value) {
-                       result[value] = $element.attr(value);
-                       $element.removeAttr(value);
-               });
-               return result;
-       },
-       // http://docs.jquery.com/Plugins/Validation/rules
-       rules: function(command, argument) {
-               var element = this[0];
-
-               if (command) {
-                       var settings = $.data(element.form, 'validator').settings;
-                       var staticRules = settings.rules;
-                       var existingRules = $.validator.staticRules(element);
-                       switch(command) {
-                       case "add":
-                               $.extend(existingRules, $.validator.normalizeRule(argument));
-                               staticRules[element.name] = existingRules;
-                               if (argument.messages)
-                                       settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
-                               break;
-                       case "remove":
-                               if (!argument) {
-                                       delete staticRules[element.name];
-                                       return existingRules;
-                               }
-                               var filtered = {};
-                               $.each(argument.split(/\s/), function(index, method) {
-                                       filtered[method] = existingRules[method];
-                                       delete existingRules[method];
-                               });
-                               return filtered;
-                       }
-               }
-
-               var data = $.validator.normalizeRules(
-               $.extend(
-                       {},
-                       $.validator.metadataRules(element),
-                       $.validator.classRules(element),
-                       $.validator.attributeRules(element),
-                       $.validator.staticRules(element)
-               ), element);
-
-               // make sure required is at front
-               if (data.required) {
-                       var param = data.required;
-                       delete data.required;
-                       data = $.extend({required: param}, data);
-               }
-
-               return data;
-       }
-});
-
-// Custom selectors
-$.extend($.expr[":"], {
-       // http://docs.jquery.com/Plugins/Validation/blank
-       blank: function(a) {return !$.trim("" + a.value);},
-       // http://docs.jquery.com/Plugins/Validation/filled
-       filled: function(a) {return !!$.trim("" + a.value);},
-       // http://docs.jquery.com/Plugins/Validation/unchecked
-       unchecked: function(a) {return !a.checked;}
-});
-
-// constructor for validator
-$.validator = function( options, form ) {
-       this.settings = $.extend( true, {}, $.validator.defaults, options );
-       this.currentForm = form;
-       this.init();
-};
-
-$.validator.format = function(source, params) {
-       if ( arguments.length == 1 )
-               return function() {
-                       var args = $.makeArray(arguments);
-                       args.unshift(source);
-                       return $.validator.format.apply( this, args );
-               };
-       if ( arguments.length > 2 && params.constructor != Array  ) {
-               params = $.makeArray(arguments).slice(1);
-       }
-       if ( params.constructor != Array ) {
-               params = [ params ];
-       }
-       $.each(params, function(i, n) {
-               source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
-       });
-       return source;
-};
-
-$.extend($.validator, {
-
-       defaults: {
-               messages: {},
-               groups: {},
-               rules: {},
-               errorClass: "error",
-               validClass: "valid",
-               errorElement: "label",
-               focusInvalid: true,
-               errorContainer: $( [] ),
-               errorLabelContainer: $( [] ),
-               onsubmit: true,
-               ignore: [],
-               ignoreTitle: false,
-               onfocusin: function(element) {
-                       this.lastActive = element;
-
-                       // hide error label and remove error class on focus if enabled
-                       if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
-                               this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
-                               this.addWrapper(this.errorsFor(element)).hide();
-                       }
-               },
-               onfocusout: function(element) {
-                       if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
-                               this.element(element);
-                       }
-               },
-               onkeyup: function(element) {
-                       if ( element.name in this.submitted || element == this.lastElement ) {
-                               this.element(element);
-                       }
-               },
-               onclick: function(element) {
-                       // click on selects, radiobuttons and checkboxes
-                       if ( element.name in this.submitted )
-                               this.element(element);
-                       // or option elements, check parent select in that case
-                       else if (element.parentNode.name in this.submitted)
-                               this.element(element.parentNode);
-               },
-               highlight: function(element, errorClass, validClass) {
-                       if (element.type === 'radio') {
-                               this.findByName(element.name).addClass(errorClass).removeClass(validClass);
-                       } else {
-                               $(element).addClass(errorClass).removeClass(validClass);
-                       }
-               },
-               unhighlight: function(element, errorClass, validClass) {
-                       if (element.type === 'radio') {
-                               this.findByName(element.name).removeClass(errorClass).addClass(validClass);
-                       } else {
-                               $(element).removeClass(errorClass).addClass(validClass);
-                       }
-               }
-       },
-
-       // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
-       setDefaults: function(settings) {
-               $.extend( $.validator.defaults, settings );
-       },
-
-       messages: {
-               required: "This field is required.",
-               remote: "Please fix this field.",
-               email: "Please enter a valid email address.",
-               url: "Please enter a valid URL.",
-               date: "Please enter a valid date.",
-               dateISO: "Please enter a valid date (ISO).",
-               number: "Please enter a valid number.",
-               digits: "Please enter only digits.",
-               creditcard: "Please enter a valid credit card number.",
-               equalTo: "Please enter the same value again.",
-               accept: "Please enter a value with a valid extension.",
-               maxlength: $.validator.format("Please enter no more than {0} characters."),
-               minlength: $.validator.format("Please enter at least {0} characters."),
-               rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
-               range: $.validator.format("Please enter a value between {0} and {1}."),
-               max: $.validator.format("Please enter a value less than or equal to {0}."),
-               min: $.validator.format("Please enter a value greater than or equal to {0}.")
-       },
-
-       autoCreateRanges: false,
-
-       prototype: {
-
-               init: function() {
-                       this.labelContainer = $(this.settings.errorLabelContainer);
-                       this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
-                       this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
-                       this.submitted = {};
-                       this.valueCache = {};
-                       this.pendingRequest = 0;
-                       this.pending = {};
-                       this.invalid = {};
-                       this.reset();
-
-                       var groups = (this.groups = {});
-                       $.each(this.settings.groups, function(key, value) {
-                               $.each(value.split(/\s/), function(index, name) {
-                                       groups[name] = key;
-                               });
-                       });
-                       var rules = this.settings.rules;
-                       $.each(rules, function(key, value) {
-                               rules[key] = $.validator.normalizeRule(value);
-                       });
-
-                       function delegate(event) {
-                               var validator = $.data(this[0].form, "validator"),
-                                       eventType = "on" + event.type.replace(/^validate/, "");
-                               validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
-                       }
-                       $(this.currentForm)
-                               .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
-                               .validateDelegate(":radio, :checkbox, select, option", "click", delegate);
-
-                       if (this.settings.invalidHandler)
-                               $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Validator/form
-               form: function() {
-                       this.checkForm();
-                       $.extend(this.submitted, this.errorMap);
-                       this.invalid = $.extend({}, this.errorMap);
-                       if (!this.valid())
-                               $(this.currentForm).triggerHandler("invalid-form", [this]);
-                       this.showErrors();
-                       return this.valid();
-               },
-
-               checkForm: function() {
-                       this.prepareForm();
-                       for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
-                               this.check( elements[i] );
-                       }
-                       return this.valid();
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Validator/element
-               element: function( element ) {
-                       element = this.clean( element );
-                       this.lastElement = element;
-                       this.prepareElement( element );
-                       this.currentElements = $(element);
-                       var result = this.check( element );
-                       if ( result ) {
-                               delete this.invalid[element.name];
-                       } else {
-                               this.invalid[element.name] = true;
-                       }
-                       if ( !this.numberOfInvalids() ) {
-                               // Hide error containers on last error
-                               this.toHide = this.toHide.add( this.containers );
-                       }
-                       this.showErrors();
-                       return result;
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
-               showErrors: function(errors) {
-                       if(errors) {
-                               // add items to error list and map
-                               $.extend( this.errorMap, errors );
-                               this.errorList = [];
-                               for ( var name in errors ) {
-                                       this.errorList.push({
-                                               message: errors[name],
-                                               element: this.findByName(name)[0]
-                                       });
-                               }
-                               // remove items from success list
-                               this.successList = $.grep( this.successList, function(element) {
-                                       return !(element.name in errors);
-                               });
-                       }
-                       this.settings.showErrors
-                               ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
-                               : this.defaultShowErrors();
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
-               resetForm: function() {
-                       if ( $.fn.resetForm )
-                               $( this.currentForm ).resetForm();
-                       this.submitted = {};
-                       this.prepareForm();
-                       this.hideErrors();
-                       this.elements().removeClass( this.settings.errorClass );
-               },
-
-               numberOfInvalids: function() {
-                       return this.objectLength(this.invalid);
-               },
-
-               objectLength: function( obj ) {
-                       var count = 0;
-                       for ( var i in obj )
-                               count++;
-                       return count;
-               },
-
-               hideErrors: function() {
-                       this.addWrapper( this.toHide ).hide();
-               },
-
-               valid: function() {
-                       return this.size() == 0;
-               },
-
-               size: function() {
-                       return this.errorList.length;
-               },
-
-               focusInvalid: function() {
-                       if( this.settings.focusInvalid ) {
-                               try {
-                                       $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
-                                       .filter(":visible")
-                                       .focus()
-                                       // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
-                                       .trigger("focusin");
-                               } catch(e) {
-                                       // ignore IE throwing errors when focusing hidden elements
-                               }
-                       }
-               },
-
-               findLastActive: function() {
-                       var lastActive = this.lastActive;
-                       return lastActive && $.grep(this.errorList, function(n) {
-                               return n.element.name == lastActive.name;
-                       }).length == 1 && lastActive;
-               },
-
-               elements: function() {
-                       var validator = this,
-                               rulesCache = {};
-
-                       // select all valid inputs inside the form (no submit or reset buttons)
-                       return $(this.currentForm)
-                       .find("input, select, textarea")
-                       .not(":submit, :reset, :image, [disabled]")
-                       .not( this.settings.ignore )
-                       .filter(function() {
-                               !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
-
-                               // select only the first element for each name, and only those with rules specified
-                               if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
-                                       return false;
-
-                               rulesCache[this.name] = true;
-                               return true;
-                       });
-               },
-
-               clean: function( selector ) {
-                       return $( selector )[0];
-               },
-
-               errors: function() {
-                       return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
-               },
-
-               reset: function() {
-                       this.successList = [];
-                       this.errorList = [];
-                       this.errorMap = {};
-                       this.toShow = $([]);
-                       this.toHide = $([]);
-                       this.currentElements = $([]);
-               },
-
-               prepareForm: function() {
-                       this.reset();
-                       this.toHide = this.errors().add( this.containers );
-               },
-
-               prepareElement: function( element ) {
-                       this.reset();
-                       this.toHide = this.errorsFor(element);
-               },
-
-               check: function( element ) {
-                       element = this.clean( element );
-
-                       // if radio/checkbox, validate first element in group instead
-                       if (this.checkable(element)) {
-                               element = this.findByName( element.name ).not(this.settings.ignore)[0];
-                       }
-
-                       var rules = $(element).rules();
-                       var dependencyMismatch = false;
-                       for (var method in rules ) {
-                               var rule = { method: method, parameters: rules[method] };
-                               try {
-                                       var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
-
-                                       // if a method indicates that the field is optional and therefore valid,
-                                       // don't mark it as valid when there are no other rules
-                                       if ( result == "dependency-mismatch" ) {
-                                               dependencyMismatch = true;
-                                               continue;
-                                       }
-                                       dependencyMismatch = false;
-
-                                       if ( result == "pending" ) {
-                                               this.toHide = this.toHide.not( this.errorsFor(element) );
-                                               return;
-                                       }
-
-                                       if( !result ) {
-                                               this.formatAndAdd( element, rule );
-                                               return false;
-                                       }
-                               } catch(e) {
-                                       this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
-                                                + ", check the '" + rule.method + "' method", e);
-                                       throw e;
-                               }
-                       }
-                       if (dependencyMismatch)
-                               return;
-                       if ( this.objectLength(rules) )
-                               this.successList.push(element);
-                       return true;
-               },
-
-               // return the custom message for the given element and validation method
-               // specified in the element's "messages" metadata
-               customMetaMessage: function(element, method) {
-                       if (!$.metadata)
-                               return;
-
-                       var meta = this.settings.meta
-                               ? $(element).metadata()[this.settings.meta]
-                               : $(element).metadata();
-
-                       return meta && meta.messages && meta.messages[method];
-               },
-
-               // return the custom message for the given element name and validation method
-               customMessage: function( name, method ) {
-                       var m = this.settings.messages[name];
-                       return m && (m.constructor == String
-                               ? m
-                               : m[method]);
-               },
-
-               // return the first defined argument, allowing empty strings
-               findDefined: function() {
-                       for(var i = 0; i < arguments.length; i++) {
-                               if (arguments[i] !== undefined)
-                                       return arguments[i];
-                       }
-                       return undefined;
-               },
-
-               defaultMessage: function( element, method) {
-                       return this.findDefined(
-                               this.customMessage( element.name, method ),
-                               this.customMetaMessage( element, method ),
-                               // title is never undefined, so handle empty string as undefined
-                               !this.settings.ignoreTitle && element.title || undefined,
-                               $.validator.messages[method],
-                               "<strong>Warning: No message defined for " + element.name + "</strong>"
-                       );
-               },
-
-               formatAndAdd: function( element, rule ) {
-                       var message = this.defaultMessage( element, rule.method ),
-                               theregex = /\$?\{(\d+)\}/g;
-                       if ( typeof message == "function" ) {
-                               message = message.call(this, rule.parameters, element);
-                       } else if (theregex.test(message)) {
-                               message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
-                       }
-                       this.errorList.push({
-                               message: message,
-                               element: element
-                       });
-
-                       this.errorMap[element.name] = message;
-                       this.submitted[element.name] = message;
-               },
-
-               addWrapper: function(toToggle) {
-                       if ( this.settings.wrapper )
-                               toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
-                       return toToggle;
-               },
-
-               defaultShowErrors: function() {
-                       for ( var i = 0; this.errorList[i]; i++ ) {
-                               var error = this.errorList[i];
-                               this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
-                               this.showLabel( error.element, error.message );
-                       }
-                       if( this.errorList.length ) {
-                               this.toShow = this.toShow.add( this.containers );
-                       }
-                       if (this.settings.success) {
-                               for ( var i = 0; this.successList[i]; i++ ) {
-                                       this.showLabel( this.successList[i] );
-                               }
-                       }
-                       if (this.settings.unhighlight) {
-                               for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
-                                       this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
-                               }
-                       }
-                       this.toHide = this.toHide.not( this.toShow );
-                       this.hideErrors();
-                       this.addWrapper( this.toShow ).show();
-               },
-
-               validElements: function() {
-                       return this.currentElements.not(this.invalidElements());
-               },
-
-               invalidElements: function() {
-                       return $(this.errorList).map(function() {
-                               return this.element;
-                       });
-               },
-
-               showLabel: function(element, message) {
-                       var label = this.errorsFor( element );
-                       if ( label.length ) {
-                               // refresh error/success class
-                               label.removeClass().addClass( this.settings.errorClass );
-
-                               // check if we have a generated label, replace the message then
-                               label.attr("generated") && label.html(message);
-                       } else {
-                               // create label
-                               label = $("<" + this.settings.errorElement + "/>")
-                                       .attr({"for":  this.idOrName(element), generated: true})
-                                       .addClass(this.settings.errorClass)
-                                       .html(message || "");
-                               if ( this.settings.wrapper ) {
-                                       // make sure the element is visible, even in IE
-                                       // actually showing the wrapped element is handled elsewhere
-                                       label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
-                               }
-                               if ( !this.labelContainer.append(label).length )
-                                       this.settings.errorPlacement
-                                               ? this.settings.errorPlacement(label, $(element) )
-                                               : label.insertAfter(element);
-                       }
-                       if ( !message && this.settings.success ) {
-                               label.text("");
-                               typeof this.settings.success == "string"
-                                       ? label.addClass( this.settings.success )
-                                       : this.settings.success( label );
-                       }
-                       this.toShow = this.toShow.add(label);
-               },
-
-               errorsFor: function(element) {
-                       var name = this.idOrName(element);
-               return this.errors().filter(function() {
-                               return $(this).attr('for') == name;
-                       });
-               },
-
-               idOrName: function(element) {
-                       return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
-               },
-
-               checkable: function( element ) {
-                       return /radio|checkbox/i.test(element.type);
-               },
-
-               findByName: function( name ) {
-                       // select by name and filter by form for performance over form.find("[name=...]")
-                       var form = this.currentForm;
-                       return $(document.getElementsByName(name)).map(function(index, element) {
-                               return element.form == form && element.name == name && element  || null;
-                       });
-               },
-
-               getLength: function(value, element) {
-                       switch( element.nodeName.toLowerCase() ) {
-                       case 'select':
-                               return $("option:selected", element).length;
-                       case 'input':
-                               if( this.checkable( element) )
-                                       return this.findByName(element.name).filter(':checked').length;
-                       }
-                       return value.length;
-               },
-
-               depend: function(param, element) {
-                       return this.dependTypes[typeof param]
-                               ? this.dependTypes[typeof param](param, element)
-                               : true;
-               },
-
-               dependTypes: {
-                       "boolean": function(param, element) {
-                               return param;
-                       },
-                       "string": function(param, element) {
-                               return !!$(param, element.form).length;
-                       },
-                       "function": function(param, element) {
-                               return param(element);
-                       }
-               },
-
-               optional: function(element) {
-                       return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
-               },
-
-               startRequest: function(element) {
-                       if (!this.pending[element.name]) {
-                               this.pendingRequest++;
-                               this.pending[element.name] = true;
-                       }
-               },
-
-               stopRequest: function(element, valid) {
-                       this.pendingRequest--;
-                       // sometimes synchronization fails, make sure pendingRequest is never < 0
-                       if (this.pendingRequest < 0)
-                               this.pendingRequest = 0;
-                       delete this.pending[element.name];
-                       if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
-                               $(this.currentForm).submit();
-                               this.formSubmitted = false;
-                       } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
-                               $(this.currentForm).triggerHandler("invalid-form", [this]);
-                               this.formSubmitted = false;
-                       }
-               },
-
-               previousValue: function(element) {
-                       return $.data(element, "previousValue") || $.data(element, "previousValue", {
-                               old: null,
-                               valid: true,
-                               message: this.defaultMessage( element, "remote" )
-                       });
-               }
-
-       },
-
-       classRuleSettings: {
-               required: {required: true},
-               email: {email: true},
-               url: {url: true},
-               date: {date: true},
-               dateISO: {dateISO: true},
-               dateDE: {dateDE: true},
-               number: {number: true},
-               numberDE: {numberDE: true},
-               digits: {digits: true},
-               creditcard: {creditcard: true}
-       },
-
-       addClassRules: function(className, rules) {
-               className.constructor == String ?
-                       this.classRuleSettings[className] = rules :
-                       $.extend(this.classRuleSettings, className);
-       },
-
-       classRules: function(element) {
-               var rules = {};
-               var classes = $(element).attr('class');
-               classes && $.each(classes.split(' '), function() {
-                       if (this in $.validator.classRuleSettings) {
-                               $.extend(rules, $.validator.classRuleSettings[this]);
-                       }
-               });
-               return rules;
-       },
-
-       attributeRules: function(element) {
-               var rules = {};
-               var $element = $(element);
-
-               for (var method in $.validator.methods) {
-                       var value = $element.attr(method);
-                       if (value) {
-                               rules[method] = value;
-                       }
-               }
-
-               // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
-               if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
-                       delete rules.maxlength;
-               }
-
-               return rules;
-       },
-
-       metadataRules: function(element) {
-               if (!$.metadata) return {};
-
-               var meta = $.data(element.form, 'validator').settings.meta;
-               return meta ?
-                       $(element).metadata()[meta] :
-                       $(element).metadata();
-       },
-
-       staticRules: function(element) {
-               var rules = {};
-               var validator = $.data(element.form, 'validator');
-               if (validator.settings.rules) {
-                       rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
-               }
-               return rules;
-       },
-
-       normalizeRules: function(rules, element) {
-               // handle dependency check
-               $.each(rules, function(prop, val) {
-                       // ignore rule when param is explicitly false, eg. required:false
-                       if (val === false) {
-                               delete rules[prop];
-                               return;
-                       }
-                       if (val.param || val.depends) {
-                               var keepRule = true;
-                               switch (typeof val.depends) {
-                                       case "string":
-                                               keepRule = !!$(val.depends, element.form).length;
-                                               break;
-                                       case "function":
-                                               keepRule = val.depends.call(element, element);
-                                               break;
-                               }
-                               if (keepRule) {
-                                       rules[prop] = val.param !== undefined ? val.param : true;
-                               } else {
-                                       delete rules[prop];
-                               }
-                       }
-               });
-
-               // evaluate parameters
-               $.each(rules, function(rule, parameter) {
-                       rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
-               });
-
-               // clean number parameters
-               $.each(['minlength', 'maxlength', 'min', 'max'], function() {
-                       if (rules[this]) {
-                               rules[this] = Number(rules[this]);
-                       }
-               });
-               $.each(['rangelength', 'range'], function() {
-                       if (rules[this]) {
-                               rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
-                       }
-               });
-
-               if ($.validator.autoCreateRanges) {
-                       // auto-create ranges
-                       if (rules.min && rules.max) {
-                               rules.range = [rules.min, rules.max];
-                               delete rules.min;
-                               delete rules.max;
-                       }
-                       if (rules.minlength && rules.maxlength) {
-                               rules.rangelength = [rules.minlength, rules.maxlength];
-                               delete rules.minlength;
-                               delete rules.maxlength;
-                       }
-               }
-
-               // To support custom messages in metadata ignore rule methods titled "messages"
-               if (rules.messages) {
-                       delete rules.messages;
-               }
-
-               return rules;
-       },
-
-       // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
-       normalizeRule: function(data) {
-               if( typeof data == "string" ) {
-                       var transformed = {};
-                       $.each(data.split(/\s/), function() {
-                               transformed[this] = true;
-                       });
-                       data = transformed;
-               }
-               return data;
-       },
-
-       // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
-       addMethod: function(name, method, message) {
-               $.validator.methods[name] = method;
-               $.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
-               if (method.length < 3) {
-                       $.validator.addClassRules(name, $.validator.normalizeRule(name));
-               }
-       },
-
-       methods: {
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/required
-               required: function(value, element, param) {
-                       // check if dependency is met
-                       if ( !this.depend(param, element) )
-                               return "dependency-mismatch";
-                       switch( element.nodeName.toLowerCase() ) {
-                       case 'select':
-                               // could be an array for select-multiple or a string, both are fine this way
-                               var val = $(element).val();
-                               return val && val.length > 0;
-                       case 'input':
-                               if ( this.checkable(element) )
-                                       return this.getLength(value, element) > 0;
-                       default:
-                               return $.trim(value).length > 0;
-                       }
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/remote
-               remote: function(value, element, param) {
-                       if ( this.optional(element) )
-                               return "dependency-mismatch";
-
-                       var previous = this.previousValue(element);
-                       if (!this.settings.messages[element.name] )
-                               this.settings.messages[element.name] = {};
-                       previous.originalMessage = this.settings.messages[element.name].remote;
-                       this.settings.messages[element.name].remote = previous.message;
-
-                       param = typeof param == "string" && {url:param} || param;
-
-                       if ( this.pending[element.name] ) {
-                               return "pending";
-                       }
-                       if ( previous.old === value ) {
-                               return previous.valid;
-                       }
-
-                       previous.old = value;
-                       var validator = this;
-                       this.startRequest(element);
-                       var data = {};
-                       data[element.name] = value;
-                       $.ajax($.extend(true, {
-                               url: param,
-                               mode: "abort",
-                               port: "validate" + element.name,
-                               dataType: "json",
-                               data: data,
-                               success: function(response) {
-                                       validator.settings.messages[element.name].remote = previous.originalMessage;
-                                       var valid = response === true;
-                                       if ( valid ) {
-                                               var submitted = validator.formSubmitted;
-                                               validator.prepareElement(element);
-                                               validator.formSubmitted = submitted;
-                                               validator.successList.push(element);
-                                               validator.showErrors();
-                                       } else {
-                                               var errors = {};
-                                               var message = response || validator.defaultMessage( element, "remote" );
-                                               errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
-                                               validator.showErrors(errors);
-                                       }
-                                       previous.valid = valid;
-                                       validator.stopRequest(element, valid);
-                               }
-                       }, param));
-                       return "pending";
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/minlength
-               minlength: function(value, element, param) {
-                       return this.optional(element) || this.getLength($.trim(value), element) >= param;
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
-               maxlength: function(value, element, param) {
-                       return this.optional(element) || this.getLength($.trim(value), element) <= param;
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
-               rangelength: function(value, element, param) {
-                       var length = this.getLength($.trim(value), element);
-                       return this.optional(element) || ( length >= param[0] && length <= param[1] );
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/min
-               min: function( value, element, param ) {
-                       return this.optional(element) || value >= param;
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/max
-               max: function( value, element, param ) {
-                       return this.optional(element) || value <= param;
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/range
-               range: function( value, element, param ) {
-                       return this.optional(element) || ( value >= param[0] && value <= param[1] );
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/email
-               email: function(value, element) {
-                       // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
-                       return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/url
-               url: function(value, element) {
-                       // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
-                       return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/date
-               date: function(value, element) {
-                       return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
-               dateISO: function(value, element) {
-                       return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/number
-               number: function(value, element) {
-                       return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/digits
-               digits: function(value, element) {
-                       return this.optional(element) || /^\d+$/.test(value);
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
-               // based on http://en.wikipedia.org/wiki/Luhn
-               creditcard: function(value, element) {
-                       if ( this.optional(element) )
-                               return "dependency-mismatch";
-                       // accept only digits and dashes
-                       if (/[^0-9-]+/.test(value))
-                               return false;
-                       var nCheck = 0,
-                               nDigit = 0,
-                               bEven = false;
-
-                       value = value.replace(/\D/g, "");
-
-                       for (var n = value.length - 1; n >= 0; n--) {
-                               var cDigit = value.charAt(n);
-                               var nDigit = parseInt(cDigit, 10);
-                               if (bEven) {
-                                       if ((nDigit *= 2) > 9)
-                                               nDigit -= 9;
-                               }
-                               nCheck += nDigit;
-                               bEven = !bEven;
-                       }
-
-                       return (nCheck % 10) == 0;
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/accept
-               accept: function(value, element, param) {
-                       param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
-                       return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
-               },
-
-               // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
-               equalTo: function(value, element, param) {
-                       // bind to the blur event of the target in order to revalidate whenever the target field is updated
-                       // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
-                       var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
-                               $(element).valid();
-                       });
-                       return value == target.val();
-               }
-
-       }
-
-});
-
-// deprecated, use $.validator.format instead
-$.format = $.validator.format;
-
-})(jQuery);
-
-// ajax mode: abort
-// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
-// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
-;(function($) {
-       var pendingRequests = {};
-       // Use a prefilter if available (1.5+)
-       if ( $.ajaxPrefilter ) {
-               $.ajaxPrefilter(function(settings, _, xhr) {
-                       var port = settings.port;
-                       if (settings.mode == "abort") {
-                               if ( pendingRequests[port] ) {
-                                       pendingRequests[port].abort();
-                               }
-                               pendingRequests[port] = xhr;
-                       }
-               });
-       } else {
-               // Proxy ajax
-               var ajax = $.ajax;
-               $.ajax = function(settings) {
-                       var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
-                               port = ( "port" in settings ? settings : $.ajaxSettings ).port;
-                       if (mode == "abort") {
-                               if ( pendingRequests[port] ) {
-                                       pendingRequests[port].abort();
-                               }
-                               return (pendingRequests[port] = ajax.apply(this, arguments));
-                       }
-                       return ajax.apply(this, arguments);
-               };
-       }
-})(jQuery);
-
-// provides cross-browser focusin and focusout events
-// IE has native support, in other browsers, use event caputuring (neither bubbles)
-
-// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
-// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
-;(function($) {
-       // only implement if not provided by jQuery core (since 1.4)
-       // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
-       if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
-               $.each({
-                       focus: 'focusin',
-                       blur: 'focusout'
-               }, function( original, fix ){
-                       $.event.special[fix] = {
-                               setup:function() {
-                                       this.addEventListener( original, handler, true );
-                               },
-                               teardown:function() {
-                                       this.removeEventListener( original, handler, true );
-                               },
-                               handler: function(e) {
-                                       arguments[0] = $.event.fix(e);
-                                       arguments[0].type = fix;
-                                       return $.event.handle.apply(this, arguments);
-                               }
-                       };
-                       function handler(e) {
-                               e = $.event.fix(e);
-                               e.type = fix;
-                               return $.event.handle.call(this, e);
-                       }
-               });
-       };
-       $.extend($.fn, {
-               validateDelegate: function(delegate, type, handler) {
-                       return this.bind(type, function(event) {
-                               var target = $(event.target);
-                               if (target.is(delegate)) {
-                                       return handler.apply(target, arguments);
-                               }
-                       });
-               }
-       });
-})(jQuery);
diff --git a/resources/jquery/jquery.xmldom.js b/resources/jquery/jquery.xmldom.js
deleted file mode 100644 (file)
index 85d0083..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*!
- * jQuery xmlDOM Plugin v1.0
- * http://outwestmedia.com/jquery-plugins/xmldom/
- *
- * Released: 2009-04-06
- * Version: 1.0
- *
- * Copyright (c) 2009 Jonathan Sharp, Out West Media LLC.
- * Dual licensed under the MIT and GPL licenses.
- * http://docs.jquery.com/License
- */
-(function($) {
-       // IE DOMParser wrapper
-       if ( window['DOMParser'] == undefined && window.ActiveXObject ) {
-               DOMParser = function() { };
-               DOMParser.prototype.parseFromString = function( xmlString ) {
-                       var doc = new ActiveXObject('Microsoft.XMLDOM');
-               doc.async = 'false';
-               doc.loadXML( xmlString );
-                       return doc;
-               };
-       }
-       
-       $.xmlDOM = function(xml, onErrorFn) {
-               try {
-                       var xmlDoc      = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
-                       if ( $.isXMLDoc( xmlDoc ) ) {
-                               var err = $('parsererror', xmlDoc);
-                               if ( err.length == 1 ) {
-                                       throw('Error: ' + $(xmlDoc).text() );
-                               }
-                       } else {
-                               throw('Unable to parse XML');
-                       }
-               } catch( e ) {
-                       var msg = ( e.name == undefined ? e : e.name + ': ' + e.message );
-                       if ( $.isFunction( onErrorFn ) ) {
-                               onErrorFn( msg );
-                       } else {
-                               $(document).trigger('xmlParseError', [ msg ]);
-                       }
-                       return $([]);
-               }
-               return $( xmlDoc );
-       };
-})(jQuery);
\ No newline at end of file
diff --git a/resources/lib/jquery.chosen/LICENSE b/resources/lib/jquery.chosen/LICENSE
new file mode 100644 (file)
index 0000000..0675dc5
--- /dev/null
@@ -0,0 +1,24 @@
+# Chosen, a Select Box Enhancer for jQuery and Protoype
+## by Patrick Filler for [Harvest](http://getharvest.com)
+
+Available for use under the [MIT License](http://en.wikipedia.org/wiki/MIT_License)
+
+Copyright (c) 2011-2013 by Harvest
+
+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/resources/lib/jquery.chosen/chosen-sprite.png b/resources/lib/jquery.chosen/chosen-sprite.png
new file mode 100644 (file)
index 0000000..3611ae4
Binary files /dev/null and b/resources/lib/jquery.chosen/chosen-sprite.png differ
diff --git a/resources/lib/jquery.chosen/chosen-sprite@2x.png b/resources/lib/jquery.chosen/chosen-sprite@2x.png
new file mode 100644 (file)
index 0000000..bd61d96
Binary files /dev/null and b/resources/lib/jquery.chosen/chosen-sprite@2x.png differ
diff --git a/resources/lib/jquery.chosen/chosen.css b/resources/lib/jquery.chosen/chosen.css
new file mode 100644 (file)
index 0000000..17793ed
--- /dev/null
@@ -0,0 +1,440 @@
+/* @group Base */
+.chzn-container {
+  font-size: 13px;
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+  zoom: 1;
+  *display: inline;
+}
+.chzn-container .chzn-drop {
+  background: #fff;
+  border: 1px solid #aaa;
+  border-top: 0;
+  position: absolute;
+  top: 100%;
+  left: -9999px;
+  -webkit-box-shadow: 0 4px 5px rgba(0,0,0,.15);
+  -moz-box-shadow   : 0 4px 5px rgba(0,0,0,.15);
+  box-shadow        : 0 4px 5px rgba(0,0,0,.15);
+  z-index: 1010;
+  width: 100%;
+  -moz-box-sizing   : border-box;
+  -ms-box-sizing    : border-box;
+  -webkit-box-sizing: border-box;
+  -khtml-box-sizing : border-box;
+  box-sizing        : border-box;
+}
+
+.chzn-container.chzn-with-drop .chzn-drop {
+  left: 0;
+}
+
+/* @end */
+
+/* @group Single Chosen */
+.chzn-container-single .chzn-single {
+  background-color: #ffffff;
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0 );   
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));
+  background-image: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
+  background-image: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
+  background-image: linear-gradient(#ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); 
+  -webkit-border-radius: 5px;
+  -moz-border-radius   : 5px;
+  border-radius        : 5px;
+  -moz-background-clip   : padding;
+  -webkit-background-clip: padding-box;
+  background-clip        : padding-box;
+  border: 1px solid #aaaaaa;
+  -webkit-box-shadow: 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
+  -moz-box-shadow   : 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
+  box-shadow        : 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
+  display: block;
+  overflow: hidden;
+  white-space: nowrap;
+  position: relative;
+  height: 23px;
+  line-height: 24px;
+  padding: 0 0 0 8px;
+  color: #444444;
+  text-decoration: none;
+}
+.chzn-container-single .chzn-default {
+  color: #999;
+}
+.chzn-container-single .chzn-single span {
+  margin-right: 26px;
+  display: block;
+  overflow: hidden;
+  white-space: nowrap;
+  -o-text-overflow: ellipsis;
+  -ms-text-overflow: ellipsis;
+  text-overflow: ellipsis;
+}
+.chzn-container-single .chzn-single abbr {
+  display: block;
+  position: absolute;
+  right: 26px;
+  top: 6px;
+  width: 12px;
+  height: 12px;
+  font-size: 1px;
+  background: url('chosen-sprite.png') -42px 1px no-repeat;
+}
+.chzn-container-single .chzn-single abbr:hover {
+  background-position: -42px -10px;
+}
+.chzn-container-single.chzn-disabled .chzn-single abbr:hover {
+  background-position: -42px -10px;
+}
+.chzn-container-single .chzn-single div {
+  position: absolute;
+  right: 0;
+  top: 0;
+  display: block;
+  height: 100%;
+  width: 18px;
+}
+.chzn-container-single .chzn-single div b {
+  background: url('chosen-sprite.png') no-repeat 0px 2px;
+  display: block;
+  width: 100%;
+  height: 100%;
+}
+.chzn-container-single .chzn-search {
+  padding: 3px 4px;
+  position: relative;
+  margin: 0;
+  white-space: nowrap;
+  z-index: 1010;
+}
+.chzn-container-single .chzn-search input {
+  background: #fff url('chosen-sprite.png') no-repeat 100% -20px;
+  background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
+  background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+  background: url('chosen-sprite.png') no-repeat 100% -20px, -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+  background: url('chosen-sprite.png') no-repeat 100% -20px, -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+  background: url('chosen-sprite.png') no-repeat 100% -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
+  margin: 1px 0;
+  padding: 4px 20px 4px 5px;
+  outline: 0;
+  border: 1px solid #aaa;
+  font-family: sans-serif;
+  font-size: 1em;
+  width: 100%;
+  -moz-box-sizing   : border-box;
+  -ms-box-sizing    : border-box;
+  -webkit-box-sizing: border-box;
+  -khtml-box-sizing : border-box;
+  box-sizing        : border-box;
+}
+.chzn-container-single .chzn-drop {
+  margin-top: -1px;
+  -webkit-border-radius: 0 0 4px 4px;
+  -moz-border-radius   : 0 0 4px 4px;
+  border-radius        : 0 0 4px 4px;
+  -moz-background-clip   : padding;
+  -webkit-background-clip: padding-box;
+  background-clip        : padding-box;
+}
+.chzn-container-single-nosearch .chzn-search {
+  position: absolute;
+  left: -9999px;
+}
+/* @end */
+
+/* @group Multi Chosen */
+.chzn-container-multi .chzn-choices {
+  background-color: #fff;
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+  background-image: -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+  background-image: -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+  background-image: linear-gradient(#eeeeee 1%, #ffffff 15%);
+  border: 1px solid #aaa;
+  margin: 0;
+  padding: 0;
+  cursor: text;
+  overflow: hidden;
+  height: auto !important;
+  height: 1%;
+  position: relative;
+  width: 100%;
+  -moz-box-sizing   : border-box;
+  -ms-box-sizing    : border-box;
+  -webkit-box-sizing: border-box;
+  -khtml-box-sizing : border-box;
+  box-sizing        : border-box;
+}
+.chzn-container-multi .chzn-choices li {
+  float: left;
+  list-style: none;
+}
+.chzn-container-multi .chzn-choices .search-field {
+  white-space: nowrap;
+  margin: 0;
+  padding: 0;
+}
+.chzn-container-multi .chzn-choices .search-field input {
+  color: #666;
+  background: transparent !important;
+  border: 0 !important;
+  font-family: sans-serif;
+  font-size: 100%;
+  height: 15px;
+  padding: 5px;
+  margin: 1px 0;
+  outline: 0;
+  -webkit-box-shadow: none;
+  -moz-box-shadow   : none;
+  box-shadow        : none;
+}
+.chzn-container-multi .chzn-choices .search-field .default {
+  color: #999;
+}
+.chzn-container-multi .chzn-choices .search-choice {
+  -webkit-border-radius: 3px;
+  -moz-border-radius   : 3px;
+  border-radius        : 3px;
+  -moz-background-clip   : padding;
+  -webkit-background-clip: padding-box;
+  background-clip        : padding-box;
+  background-color: #e4e4e4;
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 ); 
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
+  background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+  background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+  background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+  background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); 
+  -webkit-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
+  -moz-box-shadow   : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
+  box-shadow        : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
+  color: #333;
+  border: 1px solid #aaaaaa;
+  line-height: 13px;
+  padding: 3px 20px 3px 5px;
+  margin: 3px 0 3px 5px;
+  position: relative;
+  cursor: default;
+}
+.chzn-container-multi .chzn-choices .search-choice.search-choice-disabled {
+  background-color: #e4e4e4;
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 );
+  background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
+  background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+  background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+  background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+  background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+  background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+  color: #666;
+  border: 1px solid #cccccc;
+  padding-right: 5px;
+}
+.chzn-container-multi .chzn-choices .search-choice-focus {
+  background: #d4d4d4;
+}
+.chzn-container-multi .chzn-choices .search-choice .search-choice-close {
+  display: block;
+  position: absolute;
+  right: 3px;
+  top: 4px;
+  width: 12px;
+  height: 12px;
+  font-size: 1px;
+  background: url('chosen-sprite.png') -42px 1px no-repeat;
+}
+.chzn-container-multi .chzn-choices .search-choice .search-choice-close:hover {
+  background-position: -42px -10px;
+}
+.chzn-container-multi .chzn-choices .search-choice-focus .search-choice-close {
+  background-position: -42px -10px;
+}
+/* @end */
+
+/* @group Results */
+.chzn-container .chzn-results {
+  margin: 0 4px 4px 0;
+  max-height: 240px;
+  padding: 0 0 0 4px;
+  position: relative;
+  overflow-x: hidden;
+  overflow-y: auto;
+  -webkit-overflow-scrolling: touch;
+}
+.chzn-container-multi .chzn-results {
+  margin: 0;
+  padding: 0;
+}
+.chzn-container .chzn-results li {
+  display: none;
+  line-height: 15px;
+  padding: 5px 6px;
+  margin: 0;
+  list-style: none;
+}
+.chzn-container .chzn-results .active-result {
+  cursor: pointer;
+  display: list-item;
+}
+.chzn-container .chzn-results .highlighted {
+  background-color: #3875d7;
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3875d7', endColorstr='#2a62bc', GradientType=0 );  
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
+  background-image: -webkit-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
+  background-image: -moz-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
+  background-image: -o-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
+  background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
+  color: #fff;
+}
+.chzn-container .chzn-results li em {
+  background: #feffde;
+  font-style: normal;
+}
+.chzn-container .chzn-results .highlighted em {
+  background: transparent;
+}
+.chzn-container .chzn-results .no-results {
+  background: #f4f4f4;
+  display: list-item;
+}
+.chzn-container .chzn-results .group-result {
+  cursor: default;
+  color: #999;
+  font-weight: bold;
+}
+.chzn-container .chzn-results .group-option {
+  padding-left: 15px;
+}
+.chzn-container-multi .chzn-drop .result-selected {
+  display: none;
+}
+.chzn-container .chzn-results-scroll {
+  background: white;
+  margin: 0 4px;
+  position: absolute;
+  text-align: center;
+  width: 321px; /* This should by dynamic with js */
+  z-index: 1;
+}
+.chzn-container .chzn-results-scroll span {
+  display: inline-block;
+  height: 17px;
+  text-indent: -5000px;
+  width: 9px;
+}
+.chzn-container .chzn-results-scroll-down {
+  bottom: 0;
+}
+.chzn-container .chzn-results-scroll-down span {
+  background: url('chosen-sprite.png') no-repeat -4px -3px;
+}
+.chzn-container .chzn-results-scroll-up span {
+  background: url('chosen-sprite.png') no-repeat -22px -3px;
+}
+/* @end */
+
+/* @group Active  */
+.chzn-container-active .chzn-single {
+  -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
+  -moz-box-shadow   : 0 0 5px rgba(0,0,0,.3);
+  box-shadow        : 0 0 5px rgba(0,0,0,.3);
+  border: 1px solid #5897fb;
+}
+.chzn-container-active.chzn-with-drop .chzn-single {
+  border: 1px solid #aaa;
+  -webkit-box-shadow: 0 1px 0 #fff inset;
+  -moz-box-shadow   : 0 1px 0 #fff inset;
+  box-shadow        : 0 1px 0 #fff inset;
+  background-color: #eee;
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0 );
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
+  background-image: -moz-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
+  background-image: -o-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
+  background-image: linear-gradient(#eeeeee 20%, #ffffff 80%);
+  -webkit-border-bottom-left-radius : 0;
+  -webkit-border-bottom-right-radius: 0;
+  -moz-border-radius-bottomleft : 0;
+  -moz-border-radius-bottomright: 0;
+  border-bottom-left-radius : 0;
+  border-bottom-right-radius: 0;
+}
+.chzn-container-active.chzn-with-drop .chzn-single div {
+  background: transparent;
+  border-left: none;
+}
+.chzn-container-active.chzn-with-drop .chzn-single div b {
+  background-position: -18px 2px;
+}
+.chzn-container-active .chzn-choices {
+  -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
+  -moz-box-shadow   : 0 0 5px rgba(0,0,0,.3);
+  box-shadow        : 0 0 5px rgba(0,0,0,.3);
+  border: 1px solid #5897fb;
+}
+.chzn-container-active .chzn-choices .search-field input {
+  color: #111 !important;
+}
+/* @end */
+
+/* @group Disabled Support */
+.chzn-disabled {
+  cursor: default;
+  opacity:0.5 !important;
+}
+.chzn-disabled .chzn-single {
+  cursor: default;
+}
+.chzn-disabled .chzn-choices .search-choice .search-choice-close {
+  cursor: default;
+}
+
+/* @group Right to Left */
+.chzn-rtl { text-align: right; }
+.chzn-rtl .chzn-single { padding: 0 8px 0 0; overflow: visible; }
+.chzn-rtl .chzn-single span { margin-left: 26px; margin-right: 0; direction: rtl; }
+
+.chzn-rtl .chzn-single div { left: 3px; right: auto; }
+.chzn-rtl .chzn-single abbr {
+  left: 26px;
+  right: auto;
+}
+.chzn-rtl .chzn-choices .search-field input { direction: rtl; }
+.chzn-rtl .chzn-choices li { float: right; }
+.chzn-rtl .chzn-choices .search-choice { padding: 3px 5px 3px 19px; margin: 3px 5px 3px 0; }
+.chzn-rtl .chzn-choices .search-choice .search-choice-close { left: 4px; right: auto; }
+.chzn-rtl .chzn-search { left: 9999px; }
+.chzn-rtl.chzn-with-drop .chzn-search { left: 0px; }
+.chzn-rtl .chzn-drop { left: 9999px; }
+.chzn-rtl.chzn-container-single .chzn-results { margin: 0 0 4px 4px; padding: 0 4px 0 0; }
+.chzn-rtl .chzn-results .group-option { padding-left: 0; padding-right: 15px; }
+.chzn-rtl.chzn-container-active.chzn-with-drop .chzn-single div { border-right: none; }
+.chzn-rtl .chzn-search input {
+  background: #fff url('chosen-sprite.png') no-repeat -30px -20px;
+  background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
+  background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);  
+  background: url('chosen-sprite.png') no-repeat -30px -20px, -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+  background: url('chosen-sprite.png') no-repeat -30px -20px, -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+  background: url('chosen-sprite.png') no-repeat -30px -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
+  padding: 4px 5px 4px 20px;
+  direction: rtl;
+}
+.chzn-container-single.chzn-rtl .chzn-single div b {
+  background-position: 6px 2px;
+}
+.chzn-container-single.chzn-rtl.chzn-with-drop .chzn-single div b {
+  background-position: -12px 2px;
+}
+/* @end */
+
+/* @group Retina compatibility */
+@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi)  {
+  .chzn-rtl .chzn-search input, .chzn-container-single .chzn-single abbr, .chzn-container-single .chzn-single div b, .chzn-container-single .chzn-search input, .chzn-container-multi .chzn-choices .search-choice .search-choice-close, .chzn-container .chzn-results-scroll-down span, .chzn-container .chzn-results-scroll-up span {
+      background-image: url('chosen-sprite@2x.png') !important;
+      background-repeat: no-repeat !important;
+      background-size: 52px 37px !important;
+  }
+}
+/* @end */
diff --git a/resources/lib/jquery.chosen/chosen.jquery.js b/resources/lib/jquery.chosen/chosen.jquery.js
new file mode 100644 (file)
index 0000000..745174f
--- /dev/null
@@ -0,0 +1,1103 @@
+// Chosen, a Select Box Enhancer for jQuery and Protoype
+// by Patrick Filler for Harvest, http://getharvest.com
+//
+// Version 0.9.14
+// Full source at https://github.com/harvesthq/chosen
+// Copyright (c) 2011 Harvest http://getharvest.com
+
+// MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
+// This file is generated by `cake build`, do not edit it by hand.
+(function() {
+  var SelectParser;
+
+  SelectParser = (function() {
+
+    function SelectParser() {
+      this.options_index = 0;
+      this.parsed = [];
+    }
+
+    SelectParser.prototype.add_node = function(child) {
+      if (child.nodeName.toUpperCase() === "OPTGROUP") {
+        return this.add_group(child);
+      } else {
+        return this.add_option(child);
+      }
+    };
+
+    SelectParser.prototype.add_group = function(group) {
+      var group_position, option, _i, _len, _ref, _results;
+      group_position = this.parsed.length;
+      this.parsed.push({
+        array_index: group_position,
+        group: true,
+        label: group.label,
+        children: 0,
+        disabled: group.disabled
+      });
+      _ref = group.childNodes;
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        option = _ref[_i];
+        _results.push(this.add_option(option, group_position, group.disabled));
+      }
+      return _results;
+    };
+
+    SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
+      if (option.nodeName.toUpperCase() === "OPTION") {
+        if (option.text !== "") {
+          if (group_position != null) {
+            this.parsed[group_position].children += 1;
+          }
+          this.parsed.push({
+            array_index: this.parsed.length,
+            options_index: this.options_index,
+            value: option.value,
+            text: option.text,
+            html: option.innerHTML,
+            selected: option.selected,
+            disabled: group_disabled === true ? group_disabled : option.disabled,
+            group_array_index: group_position,
+            classes: option.className,
+            style: option.style.cssText
+          });
+        } else {
+          this.parsed.push({
+            array_index: this.parsed.length,
+            options_index: this.options_index,
+            empty: true
+          });
+        }
+        return this.options_index += 1;
+      }
+    };
+
+    return SelectParser;
+
+  })();
+
+  SelectParser.select_to_array = function(select) {
+    var child, parser, _i, _len, _ref;
+    parser = new SelectParser();
+    _ref = select.childNodes;
+    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+      child = _ref[_i];
+      parser.add_node(child);
+    }
+    return parser.parsed;
+  };
+
+  this.SelectParser = SelectParser;
+
+}).call(this);
+
+/*
+Chosen source: generate output using 'cake build'
+Copyright (c) 2011 by Harvest
+*/
+
+
+(function() {
+  var AbstractChosen, root;
+
+  root = this;
+
+  AbstractChosen = (function() {
+
+    function AbstractChosen(form_field, options) {
+      this.form_field = form_field;
+      this.options = options != null ? options : {};
+      if (!AbstractChosen.browser_is_supported()) {
+        return;
+      }
+      this.is_multiple = this.form_field.multiple;
+      this.set_default_text();
+      this.set_default_values();
+      this.setup();
+      this.set_up_html();
+      this.register_observers();
+      this.finish_setup();
+    }
+
+    AbstractChosen.prototype.set_default_values = function() {
+      var _this = this;
+      this.click_test_action = function(evt) {
+        return _this.test_active_click(evt);
+      };
+      this.activate_action = function(evt) {
+        return _this.activate_field(evt);
+      };
+      this.active_field = false;
+      this.mouse_on_container = false;
+      this.results_showing = false;
+      this.result_highlighted = null;
+      this.result_single_selected = null;
+      this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
+      this.disable_search_threshold = this.options.disable_search_threshold || 0;
+      this.disable_search = this.options.disable_search || false;
+      this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
+      this.search_contains = this.options.search_contains || false;
+      this.choices = 0;
+      this.single_backstroke_delete = this.options.single_backstroke_delete || false;
+      this.max_selected_options = this.options.max_selected_options || Infinity;
+      return this.inherit_select_classes = this.options.inherit_select_classes || false;
+    };
+
+    AbstractChosen.prototype.set_default_text = function() {
+      if (this.form_field.getAttribute("data-placeholder")) {
+        this.default_text = this.form_field.getAttribute("data-placeholder");
+      } else if (this.is_multiple) {
+        this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
+      } else {
+        this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
+      }
+      return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
+    };
+
+    AbstractChosen.prototype.mouse_enter = function() {
+      return this.mouse_on_container = true;
+    };
+
+    AbstractChosen.prototype.mouse_leave = function() {
+      return this.mouse_on_container = false;
+    };
+
+    AbstractChosen.prototype.input_focus = function(evt) {
+      var _this = this;
+      if (this.is_multiple) {
+        if (!this.active_field) {
+          return setTimeout((function() {
+            return _this.container_mousedown();
+          }), 50);
+        }
+      } else {
+        if (!this.active_field) {
+          return this.activate_field();
+        }
+      }
+    };
+
+    AbstractChosen.prototype.input_blur = function(evt) {
+      var _this = this;
+      if (!this.mouse_on_container) {
+        this.active_field = false;
+        return setTimeout((function() {
+          return _this.blur_test();
+        }), 100);
+      }
+    };
+
+    AbstractChosen.prototype.result_add_option = function(option) {
+      var classes, style;
+      if (!option.disabled) {
+        option.dom_id = this.container_id + "_o_" + option.array_index;
+        classes = option.selected && this.is_multiple ? [] : ["active-result"];
+        if (option.selected) {
+          classes.push("result-selected");
+        }
+        if (option.group_array_index != null) {
+          classes.push("group-option");
+        }
+        if (option.classes !== "") {
+          classes.push(option.classes);
+        }
+        style = option.style.cssText !== "" ? " style=\"" + option.style + "\"" : "";
+        return '<li id="' + option.dom_id + '" class="' + classes.join(' ') + '"' + style + '>' + option.html + '</li>';
+      } else {
+        return "";
+      }
+    };
+
+    AbstractChosen.prototype.results_update_field = function() {
+      this.set_default_text();
+      if (!this.is_multiple) {
+        this.results_reset_cleanup();
+      }
+      this.result_clear_highlight();
+      this.result_single_selected = null;
+      return this.results_build();
+    };
+
+    AbstractChosen.prototype.results_toggle = function() {
+      if (this.results_showing) {
+        return this.results_hide();
+      } else {
+        return this.results_show();
+      }
+    };
+
+    AbstractChosen.prototype.results_search = function(evt) {
+      if (this.results_showing) {
+        return this.winnow_results();
+      } else {
+        return this.results_show();
+      }
+    };
+
+    AbstractChosen.prototype.choices_click = function(evt) {
+      evt.preventDefault();
+      if (!this.results_showing) {
+        return this.results_show();
+      }
+    };
+
+    AbstractChosen.prototype.keyup_checker = function(evt) {
+      var stroke, _ref;
+      stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
+      this.search_field_scale();
+      switch (stroke) {
+        case 8:
+          if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) {
+            return this.keydown_backstroke();
+          } else if (!this.pending_backstroke) {
+            this.result_clear_highlight();
+            return this.results_search();
+          }
+          break;
+        case 13:
+          evt.preventDefault();
+          if (this.results_showing) {
+            return this.result_select(evt);
+          }
+          break;
+        case 27:
+          if (this.results_showing) {
+            this.results_hide();
+          }
+          return true;
+        case 9:
+        case 38:
+        case 40:
+        case 16:
+        case 91:
+        case 17:
+          break;
+        default:
+          return this.results_search();
+      }
+    };
+
+    AbstractChosen.prototype.generate_field_id = function() {
+      var new_id;
+      new_id = this.generate_random_id();
+      this.form_field.id = new_id;
+      return new_id;
+    };
+
+    AbstractChosen.prototype.generate_random_char = function() {
+      var chars, newchar, rand;
+      chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+      rand = Math.floor(Math.random() * chars.length);
+      return newchar = chars.substring(rand, rand + 1);
+    };
+
+    AbstractChosen.prototype.container_width = function() {
+      var width;
+      if (this.options.width != null) {
+        return this.options.width;
+      }
+      width = window.getComputedStyle != null ? parseFloat(window.getComputedStyle(this.form_field).getPropertyValue('width')) : (typeof jQuery !== "undefined" && jQuery !== null) && (this.form_field_jq != null) ? this.form_field_jq.outerWidth() : this.form_field.getWidth();
+      return width + "px";
+    };
+
+    AbstractChosen.browser_is_supported = function() {
+      var _ref;
+      if (window.navigator.appName === "Microsoft Internet Explorer") {
+        return (null !== (_ref = document.documentMode) && _ref >= 8);
+      }
+      return true;
+    };
+
+    AbstractChosen.default_multiple_text = "Select Some Options";
+
+    AbstractChosen.default_single_text = "Select an Option";
+
+    AbstractChosen.default_no_result_text = "No results match";
+
+    return AbstractChosen;
+
+  })();
+
+  root.AbstractChosen = AbstractChosen;
+
+}).call(this);
+
+/*
+Chosen source: generate output using 'cake build'
+Copyright (c) 2011 by Harvest
+*/
+
+
+(function() {
+  var $, Chosen, root,
+    __hasProp = {}.hasOwnProperty,
+    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+  root = this;
+
+  $ = jQuery;
+
+  $.fn.extend({
+    chosen: function(options) {
+      if (!AbstractChosen.browser_is_supported()) {
+        return this;
+      }
+      return this.each(function(input_field) {
+        var $this;
+        $this = $(this);
+        if (!$this.hasClass("chzn-done")) {
+          return $this.data('chosen', new Chosen(this, options));
+        }
+      });
+    }
+  });
+
+  Chosen = (function(_super) {
+
+    __extends(Chosen, _super);
+
+    function Chosen() {
+      return Chosen.__super__.constructor.apply(this, arguments);
+    }
+
+    Chosen.prototype.setup = function() {
+      this.form_field_jq = $(this.form_field);
+      this.current_selectedIndex = this.form_field.selectedIndex;
+      return this.is_rtl = this.form_field_jq.hasClass("chzn-rtl");
+    };
+
+    Chosen.prototype.finish_setup = function() {
+      return this.form_field_jq.addClass("chzn-done");
+    };
+
+    Chosen.prototype.set_up_html = function() {
+      var container_classes, container_props;
+      this.container_id = this.form_field.id.length ? this.form_field.id.replace(/[^\w]/g, '_') : this.generate_field_id();
+      this.container_id += "_chzn";
+      container_classes = ["chzn-container"];
+      container_classes.push("chzn-container-" + (this.is_multiple ? "multi" : "single"));
+      if (this.inherit_select_classes && this.form_field.className) {
+        container_classes.push(this.form_field.className);
+      }
+      if (this.is_rtl) {
+        container_classes.push("chzn-rtl");
+      }
+      container_props = {
+        'id': this.container_id,
+        'class': container_classes.join(' '),
+        'style': "width: " + (this.container_width()) + ";",
+        'title': this.form_field.title
+      };
+      this.container = $("<div />", container_props);
+      if (this.is_multiple) {
+        this.container.html('<ul class="chzn-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:auto;" /></li></ul><div class="chzn-drop"><ul class="chzn-results"></ul></div>');
+      } else {
+        this.container.html('<a href="javascript:void(0)" class="chzn-single chzn-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chzn-drop"><div class="chzn-search"><input type="text" autocomplete="off" /></div><ul class="chzn-results"></ul></div>');
+      }
+      this.form_field_jq.hide().after(this.container);
+      this.dropdown = this.container.find('div.chzn-drop').first();
+      this.search_field = this.container.find('input').first();
+      this.search_results = this.container.find('ul.chzn-results').first();
+      this.search_field_scale();
+      this.search_no_results = this.container.find('li.no-results').first();
+      if (this.is_multiple) {
+        this.search_choices = this.container.find('ul.chzn-choices').first();
+        this.search_container = this.container.find('li.search-field').first();
+      } else {
+        this.search_container = this.container.find('div.chzn-search').first();
+        this.selected_item = this.container.find('.chzn-single').first();
+      }
+      this.results_build();
+      this.set_tab_index();
+      this.set_label_behavior();
+      return this.form_field_jq.trigger("liszt:ready", {
+        chosen: this
+      });
+    };
+
+    Chosen.prototype.register_observers = function() {
+      var _this = this;
+      this.container.mousedown(function(evt) {
+        _this.container_mousedown(evt);
+      });
+      this.container.mouseup(function(evt) {
+        _this.container_mouseup(evt);
+      });
+      this.container.mouseenter(function(evt) {
+        _this.mouse_enter(evt);
+      });
+      this.container.mouseleave(function(evt) {
+        _this.mouse_leave(evt);
+      });
+      this.search_results.mouseup(function(evt) {
+        _this.search_results_mouseup(evt);
+      });
+      this.search_results.mouseover(function(evt) {
+        _this.search_results_mouseover(evt);
+      });
+      this.search_results.mouseout(function(evt) {
+        _this.search_results_mouseout(evt);
+      });
+      this.search_results.bind('mousewheel DOMMouseScroll', function(evt) {
+        _this.search_results_mousewheel(evt);
+      });
+      this.form_field_jq.bind("liszt:updated", function(evt) {
+        _this.results_update_field(evt);
+      });
+      this.form_field_jq.bind("liszt:activate", function(evt) {
+        _this.activate_field(evt);
+      });
+      this.form_field_jq.bind("liszt:open", function(evt) {
+        _this.container_mousedown(evt);
+      });
+      this.search_field.blur(function(evt) {
+        _this.input_blur(evt);
+      });
+      this.search_field.keyup(function(evt) {
+        _this.keyup_checker(evt);
+      });
+      this.search_field.keydown(function(evt) {
+        _this.keydown_checker(evt);
+      });
+      this.search_field.focus(function(evt) {
+        _this.input_focus(evt);
+      });
+      if (this.is_multiple) {
+        return this.search_choices.click(function(evt) {
+          _this.choices_click(evt);
+        });
+      } else {
+        return this.container.click(function(evt) {
+          evt.preventDefault();
+        });
+      }
+    };
+
+    Chosen.prototype.search_field_disabled = function() {
+      this.is_disabled = this.form_field_jq[0].disabled;
+      if (this.is_disabled) {
+        this.container.addClass('chzn-disabled');
+        this.search_field[0].disabled = true;
+        if (!this.is_multiple) {
+          this.selected_item.unbind("focus", this.activate_action);
+        }
+        return this.close_field();
+      } else {
+        this.container.removeClass('chzn-disabled');
+        this.search_field[0].disabled = false;
+        if (!this.is_multiple) {
+          return this.selected_item.bind("focus", this.activate_action);
+        }
+      }
+    };
+
+    Chosen.prototype.container_mousedown = function(evt) {
+      if (!this.is_disabled) {
+        if (evt && evt.type === "mousedown" && !this.results_showing) {
+          evt.preventDefault();
+        }
+        if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
+          if (!this.active_field) {
+            if (this.is_multiple) {
+              this.search_field.val("");
+            }
+            $(document).click(this.click_test_action);
+            this.results_show();
+          } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chzn-single").length)) {
+            evt.preventDefault();
+            this.results_toggle();
+          }
+          return this.activate_field();
+        }
+      }
+    };
+
+    Chosen.prototype.container_mouseup = function(evt) {
+      if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
+        return this.results_reset(evt);
+      }
+    };
+
+    Chosen.prototype.search_results_mousewheel = function(evt) {
+      var delta, _ref, _ref1;
+      delta = -((_ref = evt.originalEvent) != null ? _ref.wheelDelta : void 0) || ((_ref1 = evt.originialEvent) != null ? _ref1.detail : void 0);
+      if (delta != null) {
+        evt.preventDefault();
+        if (evt.type === 'DOMMouseScroll') {
+          delta = delta * 40;
+        }
+        return this.search_results.scrollTop(delta + this.search_results.scrollTop());
+      }
+    };
+
+    Chosen.prototype.blur_test = function(evt) {
+      if (!this.active_field && this.container.hasClass("chzn-container-active")) {
+        return this.close_field();
+      }
+    };
+
+    Chosen.prototype.close_field = function() {
+      $(document).unbind("click", this.click_test_action);
+      this.active_field = false;
+      this.results_hide();
+      this.container.removeClass("chzn-container-active");
+      this.winnow_results_clear();
+      this.clear_backstroke();
+      this.show_search_field_default();
+      return this.search_field_scale();
+    };
+
+    Chosen.prototype.activate_field = function() {
+      this.container.addClass("chzn-container-active");
+      this.active_field = true;
+      this.search_field.val(this.search_field.val());
+      return this.search_field.focus();
+    };
+
+    Chosen.prototype.test_active_click = function(evt) {
+      if ($(evt.target).parents('#' + this.container_id).length) {
+        return this.active_field = true;
+      } else {
+        return this.close_field();
+      }
+    };
+
+    Chosen.prototype.results_build = function() {
+      var content, data, _i, _len, _ref;
+      this.parsing = true;
+      this.results_data = root.SelectParser.select_to_array(this.form_field);
+      if (this.is_multiple && this.choices > 0) {
+        this.search_choices.find("li.search-choice").remove();
+        this.choices = 0;
+      } else if (!this.is_multiple) {
+        this.selected_item.addClass("chzn-default").find("span").text(this.default_text);
+        if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
+          this.container.addClass("chzn-container-single-nosearch");
+        } else {
+          this.container.removeClass("chzn-container-single-nosearch");
+        }
+      }
+      content = '';
+      _ref = this.results_data;
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        data = _ref[_i];
+        if (data.group) {
+          content += this.result_add_group(data);
+        } else if (!data.empty) {
+          content += this.result_add_option(data);
+          if (data.selected && this.is_multiple) {
+            this.choice_build(data);
+          } else if (data.selected && !this.is_multiple) {
+            this.selected_item.removeClass("chzn-default").find("span").text(data.text);
+            if (this.allow_single_deselect) {
+              this.single_deselect_control_build();
+            }
+          }
+        }
+      }
+      this.search_field_disabled();
+      this.show_search_field_default();
+      this.search_field_scale();
+      this.search_results.html(content);
+      return this.parsing = false;
+    };
+
+    Chosen.prototype.result_add_group = function(group) {
+      if (!group.disabled) {
+        group.dom_id = this.container_id + "_g_" + group.array_index;
+        return '<li id="' + group.dom_id + '" class="group-result">' + $("<div />").text(group.label).html() + '</li>';
+      } else {
+        return "";
+      }
+    };
+
+    Chosen.prototype.result_do_highlight = function(el) {
+      var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
+      if (el.length) {
+        this.result_clear_highlight();
+        this.result_highlight = el;
+        this.result_highlight.addClass("highlighted");
+        maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
+        visible_top = this.search_results.scrollTop();
+        visible_bottom = maxHeight + visible_top;
+        high_top = this.result_highlight.position().top + this.search_results.scrollTop();
+        high_bottom = high_top + this.result_highlight.outerHeight();
+        if (high_bottom >= visible_bottom) {
+          return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
+        } else if (high_top < visible_top) {
+          return this.search_results.scrollTop(high_top);
+        }
+      }
+    };
+
+    Chosen.prototype.result_clear_highlight = function() {
+      if (this.result_highlight) {
+        this.result_highlight.removeClass("highlighted");
+      }
+      return this.result_highlight = null;
+    };
+
+    Chosen.prototype.results_show = function() {
+      if (this.result_single_selected != null) {
+        this.result_do_highlight(this.result_single_selected);
+      } else if (this.is_multiple && this.max_selected_options <= this.choices) {
+        this.form_field_jq.trigger("liszt:maxselected", {
+          chosen: this
+        });
+        return false;
+      }
+      this.container.addClass("chzn-with-drop");
+      this.form_field_jq.trigger("liszt:showing_dropdown", {
+        chosen: this
+      });
+      this.results_showing = true;
+      this.search_field.focus();
+      this.search_field.val(this.search_field.val());
+      return this.winnow_results();
+    };
+
+    Chosen.prototype.results_hide = function() {
+      this.result_clear_highlight();
+      this.container.removeClass("chzn-with-drop");
+      this.form_field_jq.trigger("liszt:hiding_dropdown", {
+        chosen: this
+      });
+      return this.results_showing = false;
+    };
+
+    Chosen.prototype.set_tab_index = function(el) {
+      var ti;
+      if (this.form_field_jq.attr("tabindex")) {
+        ti = this.form_field_jq.attr("tabindex");
+        this.form_field_jq.attr("tabindex", -1);
+        return this.search_field.attr("tabindex", ti);
+      }
+    };
+
+    Chosen.prototype.set_label_behavior = function() {
+      var _this = this;
+      this.form_field_label = this.form_field_jq.parents("label");
+      if (!this.form_field_label.length && this.form_field.id.length) {
+        this.form_field_label = $("label[for=" + this.form_field.id + "]");
+      }
+      if (this.form_field_label.length > 0) {
+        return this.form_field_label.click(function(evt) {
+          if (_this.is_multiple) {
+            return _this.container_mousedown(evt);
+          } else {
+            return _this.activate_field();
+          }
+        });
+      }
+    };
+
+    Chosen.prototype.show_search_field_default = function() {
+      if (this.is_multiple && this.choices < 1 && !this.active_field) {
+        this.search_field.val(this.default_text);
+        return this.search_field.addClass("default");
+      } else {
+        this.search_field.val("");
+        return this.search_field.removeClass("default");
+      }
+    };
+
+    Chosen.prototype.search_results_mouseup = function(evt) {
+      var target;
+      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
+      if (target.length) {
+        this.result_highlight = target;
+        this.result_select(evt);
+        return this.search_field.focus();
+      }
+    };
+
+    Chosen.prototype.search_results_mouseover = function(evt) {
+      var target;
+      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
+      if (target) {
+        return this.result_do_highlight(target);
+      }
+    };
+
+    Chosen.prototype.search_results_mouseout = function(evt) {
+      if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
+        return this.result_clear_highlight();
+      }
+    };
+
+    Chosen.prototype.choice_build = function(item) {
+      var choice_id, html, link,
+        _this = this;
+      if (this.is_multiple && this.max_selected_options <= this.choices) {
+        this.form_field_jq.trigger("liszt:maxselected", {
+          chosen: this
+        });
+        return false;
+      }
+      choice_id = this.container_id + "_c_" + item.array_index;
+      this.choices += 1;
+      if (item.disabled) {
+        html = '<li class="search-choice search-choice-disabled" id="' + choice_id + '"><span>' + item.html + '</span></li>';
+      } else {
+        html = '<li class="search-choice" id="' + choice_id + '"><span>' + item.html + '</span><a href="javascript:void(0)" class="search-choice-close" rel="' + item.array_index + '"></a></li>';
+      }
+      this.search_container.before(html);
+      link = $('#' + choice_id).find("a").first();
+      return link.click(function(evt) {
+        return _this.choice_destroy_link_click(evt);
+      });
+    };
+
+    Chosen.prototype.choice_destroy_link_click = function(evt) {
+      evt.preventDefault();
+      evt.stopPropagation();
+      if (!this.is_disabled) {
+        return this.choice_destroy($(evt.target));
+      }
+    };
+
+    Chosen.prototype.choice_destroy = function(link) {
+      if (this.result_deselect(link.attr("rel"))) {
+        this.choices -= 1;
+        this.show_search_field_default();
+        if (this.is_multiple && this.choices > 0 && this.search_field.val().length < 1) {
+          this.results_hide();
+        }
+        link.parents('li').first().remove();
+        return this.search_field_scale();
+      }
+    };
+
+    Chosen.prototype.results_reset = function() {
+      this.form_field.options[0].selected = true;
+      this.selected_item.find("span").text(this.default_text);
+      if (!this.is_multiple) {
+        this.selected_item.addClass("chzn-default");
+      }
+      this.show_search_field_default();
+      this.results_reset_cleanup();
+      this.form_field_jq.trigger("change");
+      if (this.active_field) {
+        return this.results_hide();
+      }
+    };
+
+    Chosen.prototype.results_reset_cleanup = function() {
+      this.current_selectedIndex = this.form_field.selectedIndex;
+      return this.selected_item.find("abbr").remove();
+    };
+
+    Chosen.prototype.result_select = function(evt) {
+      var high, high_id, item, position;
+      if (this.result_highlight) {
+        high = this.result_highlight;
+        high_id = high.attr("id");
+        this.result_clear_highlight();
+        if (this.is_multiple) {
+          this.result_deactivate(high);
+        } else {
+          this.search_results.find(".result-selected").removeClass("result-selected");
+          this.result_single_selected = high;
+          this.selected_item.removeClass("chzn-default");
+        }
+        high.addClass("result-selected");
+        position = high_id.substr(high_id.lastIndexOf("_") + 1);
+        item = this.results_data[position];
+        item.selected = true;
+        this.form_field.options[item.options_index].selected = true;
+        if (this.is_multiple) {
+          this.choice_build(item);
+        } else {
+          this.selected_item.find("span").first().text(item.text);
+          if (this.allow_single_deselect) {
+            this.single_deselect_control_build();
+          }
+        }
+        if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
+          this.results_hide();
+        }
+        this.search_field.val("");
+        if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
+          this.form_field_jq.trigger("change", {
+            'selected': this.form_field.options[item.options_index].value
+          });
+        }
+        this.current_selectedIndex = this.form_field.selectedIndex;
+        return this.search_field_scale();
+      }
+    };
+
+    Chosen.prototype.result_activate = function(el) {
+      return el.addClass("active-result");
+    };
+
+    Chosen.prototype.result_deactivate = function(el) {
+      return el.removeClass("active-result");
+    };
+
+    Chosen.prototype.result_deselect = function(pos) {
+      var result, result_data;
+      result_data = this.results_data[pos];
+      if (!this.form_field.options[result_data.options_index].disabled) {
+        result_data.selected = false;
+        this.form_field.options[result_data.options_index].selected = false;
+        result = $("#" + this.container_id + "_o_" + pos);
+        result.removeClass("result-selected").addClass("active-result").show();
+        this.result_clear_highlight();
+        this.winnow_results();
+        this.form_field_jq.trigger("change", {
+          deselected: this.form_field.options[result_data.options_index].value
+        });
+        this.search_field_scale();
+        return true;
+      } else {
+        return false;
+      }
+    };
+
+    Chosen.prototype.single_deselect_control_build = function() {
+      if (this.allow_single_deselect && this.selected_item.find("abbr").length < 1) {
+        return this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
+      }
+    };
+
+    Chosen.prototype.winnow_results = function() {
+      var found, option, part, parts, regex, regexAnchor, result, result_id, results, searchText, startpos, text, zregex, _i, _j, _len, _len1, _ref;
+      this.no_results_clear();
+      results = 0;
+      searchText = this.search_field.val() === this.default_text ? "" : $('<div/>').text($.trim(this.search_field.val())).html();
+      regexAnchor = this.search_contains ? "" : "^";
+      regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
+      zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
+      _ref = this.results_data;
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        option = _ref[_i];
+        if (!option.disabled && !option.empty) {
+          if (option.group) {
+            $('#' + option.dom_id).css('display', 'none');
+          } else if (!(this.is_multiple && option.selected)) {
+            found = false;
+            result_id = option.dom_id;
+            result = $("#" + result_id);
+            if (regex.test(option.html)) {
+              found = true;
+              results += 1;
+            } else if (this.enable_split_word_search && (option.html.indexOf(" ") >= 0 || option.html.indexOf("[") === 0)) {
+              parts = option.html.replace(/\[|\]/g, "").split(" ");
+              if (parts.length) {
+                for (_j = 0, _len1 = parts.length; _j < _len1; _j++) {
+                  part = parts[_j];
+                  if (regex.test(part)) {
+                    found = true;
+                    results += 1;
+                  }
+                }
+              }
+            }
+            if (found) {
+              if (searchText.length) {
+                startpos = option.html.search(zregex);
+                text = option.html.substr(0, startpos + searchText.length) + '</em>' + option.html.substr(startpos + searchText.length);
+                text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
+              } else {
+                text = option.html;
+              }
+              result.html(text);
+              this.result_activate(result);
+              if (option.group_array_index != null) {
+                $("#" + this.results_data[option.group_array_index].dom_id).css('display', 'list-item');
+              }
+            } else {
+              if (this.result_highlight && result_id === this.result_highlight.attr('id')) {
+                this.result_clear_highlight();
+              }
+              this.result_deactivate(result);
+            }
+          }
+        }
+      }
+      if (results < 1 && searchText.length) {
+        return this.no_results(searchText);
+      } else {
+        return this.winnow_results_set_highlight();
+      }
+    };
+
+    Chosen.prototype.winnow_results_clear = function() {
+      var li, lis, _i, _len, _results;
+      this.search_field.val("");
+      lis = this.search_results.find("li");
+      _results = [];
+      for (_i = 0, _len = lis.length; _i < _len; _i++) {
+        li = lis[_i];
+        li = $(li);
+        if (li.hasClass("group-result")) {
+          _results.push(li.css('display', 'auto'));
+        } else if (!this.is_multiple || !li.hasClass("result-selected")) {
+          _results.push(this.result_activate(li));
+        } else {
+          _results.push(void 0);
+        }
+      }
+      return _results;
+    };
+
+    Chosen.prototype.winnow_results_set_highlight = function() {
+      var do_high, selected_results;
+      if (!this.result_highlight) {
+        selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
+        do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
+        if (do_high != null) {
+          return this.result_do_highlight(do_high);
+        }
+      }
+    };
+
+    Chosen.prototype.no_results = function(terms) {
+      var no_results_html;
+      no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
+      no_results_html.find("span").first().html(terms);
+      return this.search_results.append(no_results_html);
+    };
+
+    Chosen.prototype.no_results_clear = function() {
+      return this.search_results.find(".no-results").remove();
+    };
+
+    Chosen.prototype.keydown_arrow = function() {
+      var first_active, next_sib;
+      if (!this.result_highlight) {
+        first_active = this.search_results.find("li.active-result").first();
+        if (first_active) {
+          this.result_do_highlight($(first_active));
+        }
+      } else if (this.results_showing) {
+        next_sib = this.result_highlight.nextAll("li.active-result").first();
+        if (next_sib) {
+          this.result_do_highlight(next_sib);
+        }
+      }
+      if (!this.results_showing) {
+        return this.results_show();
+      }
+    };
+
+    Chosen.prototype.keyup_arrow = function() {
+      var prev_sibs;
+      if (!this.results_showing && !this.is_multiple) {
+        return this.results_show();
+      } else if (this.result_highlight) {
+        prev_sibs = this.result_highlight.prevAll("li.active-result");
+        if (prev_sibs.length) {
+          return this.result_do_highlight(prev_sibs.first());
+        } else {
+          if (this.choices > 0) {
+            this.results_hide();
+          }
+          return this.result_clear_highlight();
+        }
+      }
+    };
+
+    Chosen.prototype.keydown_backstroke = function() {
+      var next_available_destroy;
+      if (this.pending_backstroke) {
+        this.choice_destroy(this.pending_backstroke.find("a").first());
+        return this.clear_backstroke();
+      } else {
+        next_available_destroy = this.search_container.siblings("li.search-choice").last();
+        if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
+          this.pending_backstroke = next_available_destroy;
+          if (this.single_backstroke_delete) {
+            return this.keydown_backstroke();
+          } else {
+            return this.pending_backstroke.addClass("search-choice-focus");
+          }
+        }
+      }
+    };
+
+    Chosen.prototype.clear_backstroke = function() {
+      if (this.pending_backstroke) {
+        this.pending_backstroke.removeClass("search-choice-focus");
+      }
+      return this.pending_backstroke = null;
+    };
+
+    Chosen.prototype.keydown_checker = function(evt) {
+      var stroke, _ref;
+      stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
+      this.search_field_scale();
+      if (stroke !== 8 && this.pending_backstroke) {
+        this.clear_backstroke();
+      }
+      switch (stroke) {
+        case 8:
+          this.backstroke_length = this.search_field.val().length;
+          break;
+        case 9:
+          if (this.results_showing && !this.is_multiple) {
+            this.result_select(evt);
+          }
+          this.mouse_on_container = false;
+          break;
+        case 13:
+          evt.preventDefault();
+          break;
+        case 38:
+          evt.preventDefault();
+          this.keyup_arrow();
+          break;
+        case 40:
+          this.keydown_arrow();
+          break;
+      }
+    };
+
+    Chosen.prototype.search_field_scale = function() {
+      var div, h, style, style_block, styles, w, _i, _len;
+      if (this.is_multiple) {
+        h = 0;
+        w = 0;
+        style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
+        styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
+        for (_i = 0, _len = styles.length; _i < _len; _i++) {
+          style = styles[_i];
+          style_block += style + ":" + this.search_field.css(style) + ";";
+        }
+        div = $('<div />', {
+          'style': style_block
+        });
+        div.text(this.search_field.val());
+        $('body').append(div);
+        w = div.width() + 25;
+        div.remove();
+        if (!this.f_width) {
+          this.f_width = this.container.outerWidth();
+        }
+        if (w > this.f_width - 10) {
+          w = this.f_width - 10;
+        }
+        return this.search_field.css({
+          'width': w + 'px'
+        });
+      }
+    };
+
+    Chosen.prototype.generate_random_id = function() {
+      var string;
+      string = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char();
+      while ($("#" + string).length > 0) {
+        string += this.generate_random_char();
+      }
+      return string;
+    };
+
+    return Chosen;
+
+  })(AbstractChosen);
+
+  root.Chosen = Chosen;
+
+}).call(this);
diff --git a/resources/lib/jquery.effects/jquery.effects.blind.js b/resources/lib/jquery.effects/jquery.effects.blind.js
new file mode 100644 (file)
index 0000000..ac25bbd
--- /dev/null
@@ -0,0 +1,49 @@
+/*!
+ * jQuery UI Effects Blind 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Blind
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.blind = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','bottom','left','right'];
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
+               var direction = o.options.direction || 'vertical'; // Default direction
+
+               // Adjust
+               $.effects.save(el, props); el.show(); // Save & Show
+               var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
+               var ref = (direction == 'vertical') ? 'height' : 'width';
+               var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
+               if(mode == 'show') wrapper.css(ref, 0); // Shift
+
+               // Animation
+               var animation = {};
+               animation[ref] = mode == 'show' ? distance : 0;
+
+               // Animate
+               wrapper.animate(animation, o.duration, o.options.easing, function() {
+                       if(mode == 'hide') el.hide(); // Hide
+                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+                       if(o.callback) o.callback.apply(el[0], arguments); // Callback
+                       el.dequeue();
+               });
+
+       });
+
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.bounce.js b/resources/lib/jquery.effects/jquery.effects.bounce.js
new file mode 100644 (file)
index 0000000..1169d77
--- /dev/null
@@ -0,0 +1,78 @@
+/*!
+ * jQuery UI Effects Bounce 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Bounce
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.bounce = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','bottom','left','right'];
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
+               var direction = o.options.direction || 'up'; // Default direction
+               var distance = o.options.distance || 20; // Default distance
+               var times = o.options.times || 5; // Default # of times
+               var speed = o.duration || 250; // Default speed per bounce
+               if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
+
+               // Adjust
+               $.effects.save(el, props); el.show(); // Save & Show
+               $.effects.createWrapper(el); // Create Wrapper
+               var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
+               var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
+               var distance = o.options.distance || (ref == 'top' ? el.outerHeight(true) / 3 : el.outerWidth(true) / 3);
+               if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
+               if (mode == 'hide') distance = distance / (times * 2);
+               if (mode != 'hide') times--;
+
+               // Animate
+               if (mode == 'show') { // Show Bounce
+                       var animation = {opacity: 1};
+                       animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
+                       el.animate(animation, speed / 2, o.options.easing);
+                       distance = distance / 2;
+                       times--;
+               };
+               for (var i = 0; i < times; i++) { // Bounces
+                       var animation1 = {}, animation2 = {};
+                       animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
+                       animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
+                       el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
+                       distance = (mode == 'hide') ? distance * 2 : distance / 2;
+               };
+               if (mode == 'hide') { // Last Bounce
+                       var animation = {opacity: 0};
+                       animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
+                       el.animate(animation, speed / 2, o.options.easing, function(){
+                               el.hide(); // Hide
+                               $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+                               if(o.callback) o.callback.apply(this, arguments); // Callback
+                       });
+               } else {
+                       var animation1 = {}, animation2 = {};
+                       animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
+                       animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
+                       el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
+                               $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+                               if(o.callback) o.callback.apply(this, arguments); // Callback
+                       });
+               };
+               el.queue('fx', function() { el.dequeue(); });
+               el.dequeue();
+       });
+
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.clip.js b/resources/lib/jquery.effects/jquery.effects.clip.js
new file mode 100644 (file)
index 0000000..edd51a6
--- /dev/null
@@ -0,0 +1,54 @@
+/*!
+ * jQuery UI Effects Clip 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Clip
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.clip = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','bottom','left','right','height','width'];
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
+               var direction = o.options.direction || 'vertical'; // Default direction
+
+               // Adjust
+               $.effects.save(el, props); el.show(); // Save & Show
+               var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
+               var animate = el[0].tagName == 'IMG' ? wrapper : el;
+               var ref = {
+                       size: (direction == 'vertical') ? 'height' : 'width',
+                       position: (direction == 'vertical') ? 'top' : 'left'
+               };
+               var distance = (direction == 'vertical') ? animate.height() : animate.width();
+               if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
+
+               // Animation
+               var animation = {};
+               animation[ref.size] = mode == 'show' ? distance : 0;
+               animation[ref.position] = mode == 'show' ? 0 : distance / 2;
+
+               // Animate
+               animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
+                       if(mode == 'hide') el.hide(); // Hide
+                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+                       if(o.callback) o.callback.apply(el[0], arguments); // Callback
+                       el.dequeue();
+               }});
+
+       });
+
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.core.js b/resources/lib/jquery.effects/jquery.effects.core.js
new file mode 100644 (file)
index 0000000..7fd946f
--- /dev/null
@@ -0,0 +1,612 @@
+/*!
+ * jQuery UI Effects 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/
+ */
+;jQuery.effects || (function($, undefined) {
+
+$.effects = {};
+
+
+
+/******************************************************************************/
+/****************************** COLOR ANIMATIONS ******************************/
+/******************************************************************************/
+
+// override the animation for color styles
+$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
+       'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
+function(i, attr) {
+       $.fx.step[attr] = function(fx) {
+               if (!fx.colorInit) {
+                       fx.start = getColor(fx.elem, attr);
+                       fx.end = getRGB(fx.end);
+                       fx.colorInit = true;
+               }
+
+               fx.elem.style[attr] = 'rgb(' +
+                       Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
+                       Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
+                       Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
+       };
+});
+
+// Color Conversion functions from highlightFade
+// By Blair Mitchelmore
+// http://jquery.offput.ca/highlightFade/
+
+// Parse strings looking for color tuples [255,255,255]
+function getRGB(color) {
+               var result;
+
+               // Check if we're already dealing with an array of colors
+               if ( color && color.constructor == Array && color.length == 3 )
+                               return color;
+
+               // Look for rgb(num,num,num)
+               if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
+                               return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
+
+               // Look for rgb(num%,num%,num%)
+               if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
+                               return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
+
+               // Look for #a0b1c2
+               if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
+                               return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
+
+               // Look for #fff
+               if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
+                               return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
+
+               // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
+               if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
+                               return colors['transparent'];
+
+               // Otherwise, we're most likely dealing with a named color
+               return colors[$.trim(color).toLowerCase()];
+}
+
+function getColor(elem, attr) {
+               var color;
+
+               do {
+                               // jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
+                               color = ($.curCSS || $.css)(elem, attr);
+
+                               // Keep going until we find an element that has color, or we hit the body
+                               if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
+                                               break;
+
+                               attr = "backgroundColor";
+               } while ( elem = elem.parentNode );
+
+               return getRGB(color);
+};
+
+// Some named colors to work with
+// From Interface by Stefan Petre
+// http://interface.eyecon.ro/
+
+var colors = {
+       aqua:[0,255,255],
+       azure:[240,255,255],
+       beige:[245,245,220],
+       black:[0,0,0],
+       blue:[0,0,255],
+       brown:[165,42,42],
+       cyan:[0,255,255],
+       darkblue:[0,0,139],
+       darkcyan:[0,139,139],
+       darkgrey:[169,169,169],
+       darkgreen:[0,100,0],
+       darkkhaki:[189,183,107],
+       darkmagenta:[139,0,139],
+       darkolivegreen:[85,107,47],
+       darkorange:[255,140,0],
+       darkorchid:[153,50,204],
+       darkred:[139,0,0],
+       darksalmon:[233,150,122],
+       darkviolet:[148,0,211],
+       fuchsia:[255,0,255],
+       gold:[255,215,0],
+       green:[0,128,0],
+       indigo:[75,0,130],
+       khaki:[240,230,140],
+       lightblue:[173,216,230],
+       lightcyan:[224,255,255],
+       lightgreen:[144,238,144],
+       lightgrey:[211,211,211],
+       lightpink:[255,182,193],
+       lightyellow:[255,255,224],
+       lime:[0,255,0],
+       magenta:[255,0,255],
+       maroon:[128,0,0],
+       navy:[0,0,128],
+       olive:[128,128,0],
+       orange:[255,165,0],
+       pink:[255,192,203],
+       purple:[128,0,128],
+       violet:[128,0,128],
+       red:[255,0,0],
+       silver:[192,192,192],
+       white:[255,255,255],
+       yellow:[255,255,0],
+       transparent: [255,255,255]
+};
+
+
+
+/******************************************************************************/
+/****************************** CLASS ANIMATIONS ******************************/
+/******************************************************************************/
+
+var classAnimationActions = ['add', 'remove', 'toggle'],
+       shorthandStyles = {
+               border: 1,
+               borderBottom: 1,
+               borderColor: 1,
+               borderLeft: 1,
+               borderRight: 1,
+               borderTop: 1,
+               borderWidth: 1,
+               margin: 1,
+               padding: 1
+       };
+
+function getElementStyles() {
+       var style = document.defaultView
+                       ? document.defaultView.getComputedStyle(this, null)
+                       : this.currentStyle,
+               newStyle = {},
+               key,
+               camelCase;
+
+       // webkit enumerates style porperties
+       if (style && style.length && style[0] && style[style[0]]) {
+               var len = style.length;
+               while (len--) {
+                       key = style[len];
+                       if (typeof style[key] == 'string') {
+                               camelCase = key.replace(/\-(\w)/g, function(all, letter){
+                                       return letter.toUpperCase();
+                               });
+                               newStyle[camelCase] = style[key];
+                       }
+               }
+       } else {
+               for (key in style) {
+                       if (typeof style[key] === 'string') {
+                               newStyle[key] = style[key];
+                       }
+               }
+       }
+       
+       return newStyle;
+}
+
+function filterStyles(styles) {
+       var name, value;
+       for (name in styles) {
+               value = styles[name];
+               if (
+                       // ignore null and undefined values
+                       value == null ||
+                       // ignore functions (when does this occur?)
+                       $.isFunction(value) ||
+                       // shorthand styles that need to be expanded
+                       name in shorthandStyles ||
+                       // ignore scrollbars (break in IE)
+                       (/scrollbar/).test(name) ||
+
+                       // only colors or values that can be converted to numbers
+                       (!(/color/i).test(name) && isNaN(parseFloat(value)))
+               ) {
+                       delete styles[name];
+               }
+       }
+       
+       return styles;
+}
+
+function styleDifference(oldStyle, newStyle) {
+       var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
+               name;
+
+       for (name in newStyle) {
+               if (oldStyle[name] != newStyle[name]) {
+                       diff[name] = newStyle[name];
+               }
+       }
+
+       return diff;
+}
+
+$.effects.animateClass = function(value, duration, easing, callback) {
+       if ($.isFunction(easing)) {
+               callback = easing;
+               easing = null;
+       }
+
+       return this.queue(function() {
+               var that = $(this),
+                       originalStyleAttr = that.attr('style') || ' ',
+                       originalStyle = filterStyles(getElementStyles.call(this)),
+                       newStyle,
+                       className = that.attr('class') || "";
+
+               $.each(classAnimationActions, function(i, action) {
+                       if (value[action]) {
+                               that[action + 'Class'](value[action]);
+                       }
+               });
+               newStyle = filterStyles(getElementStyles.call(this));
+               that.attr('class', className);
+
+               that.animate(styleDifference(originalStyle, newStyle), {
+                       queue: false,
+                       duration: duration,
+                       easing: easing,
+                       complete: function() {
+                               $.each(classAnimationActions, function(i, action) {
+                                       if (value[action]) { that[action + 'Class'](value[action]); }
+                               });
+                               // work around bug in IE by clearing the cssText before setting it
+                               if (typeof that.attr('style') == 'object') {
+                                       that.attr('style').cssText = '';
+                                       that.attr('style').cssText = originalStyleAttr;
+                               } else {
+                                       that.attr('style', originalStyleAttr);
+                               }
+                               if (callback) { callback.apply(this, arguments); }
+                               $.dequeue( this );
+                       }
+               });
+       });
+};
+
+$.fn.extend({
+       _addClass: $.fn.addClass,
+       addClass: function(classNames, speed, easing, callback) {
+               return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
+       },
+
+       _removeClass: $.fn.removeClass,
+       removeClass: function(classNames,speed,easing,callback) {
+               return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
+       },
+
+       _toggleClass: $.fn.toggleClass,
+       toggleClass: function(classNames, force, speed, easing, callback) {
+               if ( typeof force == "boolean" || force === undefined ) {
+                       if ( !speed ) {
+                               // without speed parameter;
+                               return this._toggleClass(classNames, force);
+                       } else {
+                               return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
+                       }
+               } else {
+                       // without switch parameter;
+                       return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
+               }
+       },
+
+       switchClass: function(remove,add,speed,easing,callback) {
+               return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
+       }
+});
+
+
+
+/******************************************************************************/
+/*********************************** EFFECTS **********************************/
+/******************************************************************************/
+
+$.extend($.effects, {
+       version: "1.8.24",
+
+       // Saves a set of properties in a data storage
+       save: function(element, set) {
+               for(var i=0; i < set.length; i++) {
+                       if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
+               }
+       },
+
+       // Restores a set of previously saved properties from a data storage
+       restore: function(element, set) {
+               for(var i=0; i < set.length; i++) {
+                       if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
+               }
+       },
+
+       setMode: function(el, mode) {
+               if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
+               return mode;
+       },
+
+       getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
+               // this should be a little more flexible in the future to handle a string & hash
+               var y, x;
+               switch (origin[0]) {
+                       case 'top': y = 0; break;
+                       case 'middle': y = 0.5; break;
+                       case 'bottom': y = 1; break;
+                       default: y = origin[0] / original.height;
+               };
+               switch (origin[1]) {
+                       case 'left': x = 0; break;
+                       case 'center': x = 0.5; break;
+                       case 'right': x = 1; break;
+                       default: x = origin[1] / original.width;
+               };
+               return {x: x, y: y};
+       },
+
+       // Wraps the element around a wrapper that copies position properties
+       createWrapper: function(element) {
+
+               // if the element is already wrapped, return it
+               if (element.parent().is('.ui-effects-wrapper')) {
+                       return element.parent();
+               }
+
+               // wrap the element
+               var props = {
+                               width: element.outerWidth(true),
+                               height: element.outerHeight(true),
+                               'float': element.css('float')
+                       },
+                       wrapper = $('<div></div>')
+                               .addClass('ui-effects-wrapper')
+                               .css({
+                                       fontSize: '100%',
+                                       background: 'transparent',
+                                       border: 'none',
+                                       margin: 0,
+                                       padding: 0
+                               }),
+                       active = document.activeElement;
+
+               // support: Firefox
+               // Firefox incorrectly exposes anonymous content
+               // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
+               try {
+                       active.id;
+               } catch( e ) {
+                       active = document.body;
+               }
+
+               element.wrap( wrapper );
+
+               // Fixes #7595 - Elements lose focus when wrapped.
+               if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
+                       $( active ).focus();
+               }
+               
+               wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
+
+               // transfer positioning properties to the wrapper
+               if (element.css('position') == 'static') {
+                       wrapper.css({ position: 'relative' });
+                       element.css({ position: 'relative' });
+               } else {
+                       $.extend(props, {
+                               position: element.css('position'),
+                               zIndex: element.css('z-index')
+                       });
+                       $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
+                               props[pos] = element.css(pos);
+                               if (isNaN(parseInt(props[pos], 10))) {
+                                       props[pos] = 'auto';
+                               }
+                       });
+                       element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
+               }
+
+               return wrapper.css(props).show();
+       },
+
+       removeWrapper: function(element) {
+               var parent,
+                       active = document.activeElement;
+               
+               if (element.parent().is('.ui-effects-wrapper')) {
+                       parent = element.parent().replaceWith(element);
+                       // Fixes #7595 - Elements lose focus when wrapped.
+                       if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
+                               $( active ).focus();
+                       }
+                       return parent;
+               }
+                       
+               return element;
+       },
+
+       setTransition: function(element, list, factor, value) {
+               value = value || {};
+               $.each(list, function(i, x){
+                       var unit = element.cssUnit(x);
+                       if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
+               });
+               return value;
+       }
+});
+
+
+function _normalizeArguments(effect, options, speed, callback) {
+       // shift params for method overloading
+       if (typeof effect == 'object') {
+               callback = options;
+               speed = null;
+               options = effect;
+               effect = options.effect;
+       }
+       if ($.isFunction(options)) {
+               callback = options;
+               speed = null;
+               options = {};
+       }
+        if (typeof options == 'number' || $.fx.speeds[options]) {
+               callback = speed;
+               speed = options;
+               options = {};
+       }
+       if ($.isFunction(speed)) {
+               callback = speed;
+               speed = null;
+       }
+
+       options = options || {};
+
+       speed = speed || options.duration;
+       speed = $.fx.off ? 0 : typeof speed == 'number'
+               ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
+
+       callback = callback || options.complete;
+
+       return [effect, options, speed, callback];
+}
+
+function standardSpeed( speed ) {
+       // valid standard speeds
+       if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
+               return true;
+       }
+       
+       // invalid strings - treat as "normal" speed
+       if ( typeof speed === "string" && !$.effects[ speed ] ) {
+               return true;
+       }
+       
+       return false;
+}
+
+$.fn.extend({
+       effect: function(effect, options, speed, callback) {
+               var args = _normalizeArguments.apply(this, arguments),
+                       // TODO: make effects take actual parameters instead of a hash
+                       args2 = {
+                               options: args[1],
+                               duration: args[2],
+                               callback: args[3]
+                       },
+                       mode = args2.options.mode,
+                       effectMethod = $.effects[effect];
+               
+               if ( $.fx.off || !effectMethod ) {
+                       // delegate to the original method (e.g., .show()) if possible
+                       if ( mode ) {
+                               return this[ mode ]( args2.duration, args2.callback );
+                       } else {
+                               return this.each(function() {
+                                       if ( args2.callback ) {
+                                               args2.callback.call( this );
+                                       }
+                               });
+                       }
+               }
+               
+               return effectMethod.call(this, args2);
+       },
+
+       _show: $.fn.show,
+       show: function(speed) {
+               if ( standardSpeed( speed ) ) {
+                       return this._show.apply(this, arguments);
+               } else {
+                       var args = _normalizeArguments.apply(this, arguments);
+                       args[1].mode = 'show';
+                       return this.effect.apply(this, args);
+               }
+       },
+
+       _hide: $.fn.hide,
+       hide: function(speed) {
+               if ( standardSpeed( speed ) ) {
+                       return this._hide.apply(this, arguments);
+               } else {
+                       var args = _normalizeArguments.apply(this, arguments);
+                       args[1].mode = 'hide';
+                       return this.effect.apply(this, args);
+               }
+       },
+
+       // jQuery core overloads toggle and creates _toggle
+       __toggle: $.fn.toggle,
+       toggle: function(speed) {
+               if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
+                       return this.__toggle.apply(this, arguments);
+               } else {
+                       var args = _normalizeArguments.apply(this, arguments);
+                       args[1].mode = 'toggle';
+                       return this.effect.apply(this, args);
+               }
+       },
+
+       // helper functions
+       cssUnit: function(key) {
+               var style = this.css(key), val = [];
+               $.each( ['em','px','%','pt'], function(i, unit){
+                       if(style.indexOf(unit) > 0)
+                               val = [parseFloat(style), unit];
+               });
+               return val;
+       }
+});
+
+
+
+/******************************************************************************/
+/*********************************** EASING ***********************************/
+/******************************************************************************/
+
+// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
+
+var baseEasings = {};
+
+$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
+       baseEasings[ name ] = function( p ) {
+               return Math.pow( p, i + 2 );
+       };
+});
+
+$.extend( baseEasings, {
+       Sine: function ( p ) {
+               return 1 - Math.cos( p * Math.PI / 2 );
+       },
+       Circ: function ( p ) {
+               return 1 - Math.sqrt( 1 - p * p );
+       },
+       Elastic: function( p ) {
+               return p === 0 || p === 1 ? p :
+                       -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
+       },
+       Back: function( p ) {
+               return p * p * ( 3 * p - 2 );
+       },
+       Bounce: function ( p ) {
+               var pow2,
+                       bounce = 4;
+
+               while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
+               return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
+       }
+});
+
+$.each( baseEasings, function( name, easeIn ) {
+       $.easing[ "easeIn" + name ] = easeIn;
+       $.easing[ "easeOut" + name ] = function( p ) {
+               return 1 - easeIn( 1 - p );
+       };
+       $.easing[ "easeInOut" + name ] = function( p ) {
+               return p < .5 ?
+                       easeIn( p * 2 ) / 2 :
+                       easeIn( p * -2 + 2 ) / -2 + 1;
+       };
+});
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.drop.js b/resources/lib/jquery.effects/jquery.effects.drop.js
new file mode 100644 (file)
index 0000000..97e5abd
--- /dev/null
@@ -0,0 +1,50 @@
+/*!
+ * jQuery UI Effects Drop 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Drop
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.drop = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','bottom','left','right','opacity'];
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
+               var direction = o.options.direction || 'left'; // Default Direction
+
+               // Adjust
+               $.effects.save(el, props); el.show(); // Save & Show
+               $.effects.createWrapper(el); // Create Wrapper
+               var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
+               var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
+               var distance = o.options.distance || (ref == 'top' ? el.outerHeight( true ) / 2 : el.outerWidth( true ) / 2);
+               if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
+
+               // Animation
+               var animation = {opacity: mode == 'show' ? 1 : 0};
+               animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
+
+               // Animate
+               el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
+                       if(mode == 'hide') el.hide(); // Hide
+                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+                       if(o.callback) o.callback.apply(this, arguments); // Callback
+                       el.dequeue();
+               }});
+
+       });
+
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.explode.js b/resources/lib/jquery.effects/jquery.effects.explode.js
new file mode 100644 (file)
index 0000000..f63e47a
--- /dev/null
@@ -0,0 +1,79 @@
+/*!
+ * jQuery UI Effects Explode 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Explode
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.explode = function(o) {
+
+       return this.queue(function() {
+
+       var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
+       var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
+
+       o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
+       var el = $(this).show().css('visibility', 'hidden');
+       var offset = el.offset();
+
+       //Substract the margins - not fixing the problem yet.
+       offset.top -= parseInt(el.css("marginTop"),10) || 0;
+       offset.left -= parseInt(el.css("marginLeft"),10) || 0;
+
+       var width = el.outerWidth(true);
+       var height = el.outerHeight(true);
+
+       for(var i=0;i<rows;i++) { // =
+               for(var j=0;j<cells;j++) { // ||
+                       el
+                               .clone()
+                               .appendTo('body')
+                               .wrap('<div></div>')
+                               .css({
+                                       position: 'absolute',
+                                       visibility: 'visible',
+                                       left: -j*(width/cells),
+                                       top: -i*(height/rows)
+                               })
+                               .parent()
+                               .addClass('ui-effects-explode')
+                               .css({
+                                       position: 'absolute',
+                                       overflow: 'hidden',
+                                       width: width/cells,
+                                       height: height/rows,
+                                       left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
+                                       top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
+                                       opacity: o.options.mode == 'show' ? 0 : 1
+                               }).animate({
+                                       left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
+                                       top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
+                                       opacity: o.options.mode == 'show' ? 1 : 0
+                               }, o.duration || 500);
+               }
+       }
+
+       // Set a timeout, to call the callback approx. when the other animations have finished
+       setTimeout(function() {
+
+               o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
+                               if(o.callback) o.callback.apply(el[0]); // Callback
+                               el.dequeue();
+
+                               $('div.ui-effects-explode').remove();
+
+       }, o.duration || 500);
+
+
+       });
+
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.fade.js b/resources/lib/jquery.effects/jquery.effects.fade.js
new file mode 100644 (file)
index 0000000..7aa37b1
--- /dev/null
@@ -0,0 +1,32 @@
+/*!
+ * jQuery UI Effects Fade 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Fade
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.fade = function(o) {
+       return this.queue(function() {
+               var elem = $(this),
+                       mode = $.effects.setMode(elem, o.options.mode || 'hide');
+
+               elem.animate({ opacity: mode }, {
+                       queue: false,
+                       duration: o.duration,
+                       easing: o.options.easing,
+                       complete: function() {
+                               (o.callback && o.callback.apply(this, arguments));
+                               elem.dequeue();
+                       }
+               });
+       });
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.fold.js b/resources/lib/jquery.effects/jquery.effects.fold.js
new file mode 100644 (file)
index 0000000..06cc553
--- /dev/null
@@ -0,0 +1,56 @@
+/*!
+ * jQuery UI Effects Fold 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Fold
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.fold = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','bottom','left','right'];
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
+               var size = o.options.size || 15; // Default fold size
+               var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
+               var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
+
+               // Adjust
+               $.effects.save(el, props); el.show(); // Save & Show
+               var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
+               var widthFirst = ((mode == 'show') != horizFirst);
+               var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
+               var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
+               var percent = /([0-9]+)%/.exec(size);
+               if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
+               if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
+
+               // Animation
+               var animation1 = {}, animation2 = {};
+               animation1[ref[0]] = mode == 'show' ? distance[0] : size;
+               animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
+
+               // Animate
+               wrapper.animate(animation1, duration, o.options.easing)
+               .animate(animation2, duration, o.options.easing, function() {
+                       if(mode == 'hide') el.hide(); // Hide
+                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+                       if(o.callback) o.callback.apply(el[0], arguments); // Callback
+                       el.dequeue();
+               });
+
+       });
+
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.highlight.js b/resources/lib/jquery.effects/jquery.effects.highlight.js
new file mode 100644 (file)
index 0000000..ad9e7bd
--- /dev/null
@@ -0,0 +1,50 @@
+/*!
+ * jQuery UI Effects Highlight 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Highlight
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.highlight = function(o) {
+       return this.queue(function() {
+               var elem = $(this),
+                       props = ['backgroundImage', 'backgroundColor', 'opacity'],
+                       mode = $.effects.setMode(elem, o.options.mode || 'show'),
+                       animation = {
+                               backgroundColor: elem.css('backgroundColor')
+                       };
+
+               if (mode == 'hide') {
+                       animation.opacity = 0;
+               }
+
+               $.effects.save(elem, props);
+               elem
+                       .show()
+                       .css({
+                               backgroundImage: 'none',
+                               backgroundColor: o.options.color || '#ffff99'
+                       })
+                       .animate(animation, {
+                               queue: false,
+                               duration: o.duration,
+                               easing: o.options.easing,
+                               complete: function() {
+                                       (mode == 'hide' && elem.hide());
+                                       $.effects.restore(elem, props);
+                                       (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
+                                       (o.callback && o.callback.apply(this, arguments));
+                                       elem.dequeue();
+                               }
+                       });
+       });
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.pulsate.js b/resources/lib/jquery.effects/jquery.effects.pulsate.js
new file mode 100644 (file)
index 0000000..d730bee
--- /dev/null
@@ -0,0 +1,51 @@
+/*!
+ * jQuery UI Effects Pulsate 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Pulsate
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.pulsate = function(o) {
+       return this.queue(function() {
+               var elem = $(this),
+                       mode = $.effects.setMode(elem, o.options.mode || 'show'),
+                       times = ((o.options.times || 5) * 2) - 1,
+                       duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
+                       isVisible = elem.is(':visible'),
+                       animateTo = 0;
+
+               if (!isVisible) {
+                       elem.css('opacity', 0).show();
+                       animateTo = 1;
+               }
+
+               if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
+                       times--;
+               }
+
+               for (var i = 0; i < times; i++) {
+                       elem.animate({ opacity: animateTo }, duration, o.options.easing);
+                       animateTo = (animateTo + 1) % 2;
+               }
+
+               elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
+                       if (animateTo == 0) {
+                               elem.hide();
+                       }
+                       (o.callback && o.callback.apply(this, arguments));
+               });
+
+               elem
+                       .queue('fx', function() { elem.dequeue(); })
+                       .dequeue();
+       });
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.scale.js b/resources/lib/jquery.effects/jquery.effects.scale.js
new file mode 100644 (file)
index 0000000..52d1871
--- /dev/null
@@ -0,0 +1,178 @@
+/*!
+ * jQuery UI Effects Scale 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Scale
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.puff = function(o) {
+       return this.queue(function() {
+               var elem = $(this),
+                       mode = $.effects.setMode(elem, o.options.mode || 'hide'),
+                       percent = parseInt(o.options.percent, 10) || 150,
+                       factor = percent / 100,
+                       original = { height: elem.height(), width: elem.width() };
+
+               $.extend(o.options, {
+                       fade: true,
+                       mode: mode,
+                       percent: mode == 'hide' ? percent : 100,
+                       from: mode == 'hide'
+                               ? original
+                               : {
+                                       height: original.height * factor,
+                                       width: original.width * factor
+                               }
+               });
+
+               elem.effect('scale', o.options, o.duration, o.callback);
+               elem.dequeue();
+       });
+};
+
+$.effects.scale = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this);
+
+               // Set options
+               var options = $.extend(true, {}, o.options);
+               var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
+               var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
+               var direction = o.options.direction || 'both'; // Set default axis
+               var origin = o.options.origin; // The origin of the scaling
+               if (mode != 'effect') { // Set default origin and restore for show/hide
+                       options.origin = origin || ['middle','center'];
+                       options.restore = true;
+               }
+               var original = {height: el.height(), width: el.width()}; // Save original
+               el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
+
+               // Adjust
+               var factor = { // Set scaling factor
+                       y: direction != 'horizontal' ? (percent / 100) : 1,
+                       x: direction != 'vertical' ? (percent / 100) : 1
+               };
+               el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
+
+               if (o.options.fade) { // Fade option to support puff
+                       if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
+                       if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
+               };
+
+               // Animation
+               options.from = el.from; options.to = el.to; options.mode = mode;
+
+               // Animate
+               el.effect('size', options, o.duration, o.callback);
+               el.dequeue();
+       });
+
+};
+
+$.effects.size = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity'];
+               var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore
+               var props2 = ['width','height','overflow']; // Copy for children
+               var cProps = ['fontSize'];
+               var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
+               var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
+               var restore = o.options.restore || false; // Default restore
+               var scale = o.options.scale || 'both'; // Default scale mode
+               var origin = o.options.origin; // The origin of the sizing
+               var original = {height: el.height(), width: el.width()}; // Save original
+               el.from = o.options.from || original; // Default from state
+               el.to = o.options.to || original; // Default to state
+               // Adjust
+               if (origin) { // Calculate baseline shifts
+                       var baseline = $.effects.getBaseline(origin, original);
+                       el.from.top = (original.height - el.from.height) * baseline.y;
+                       el.from.left = (original.width - el.from.width) * baseline.x;
+                       el.to.top = (original.height - el.to.height) * baseline.y;
+                       el.to.left = (original.width - el.to.width) * baseline.x;
+               };
+               var factor = { // Set scaling factor
+                       from: {y: el.from.height / original.height, x: el.from.width / original.width},
+                       to: {y: el.to.height / original.height, x: el.to.width / original.width}
+               };
+               if (scale == 'box' || scale == 'both') { // Scale the css box
+                       if (factor.from.y != factor.to.y) { // Vertical props scaling
+                               props = props.concat(vProps);
+                               el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
+                               el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
+                       };
+                       if (factor.from.x != factor.to.x) { // Horizontal props scaling
+                               props = props.concat(hProps);
+                               el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
+                               el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
+                       };
+               };
+               if (scale == 'content' || scale == 'both') { // Scale the content
+                       if (factor.from.y != factor.to.y) { // Vertical props scaling
+                               props = props.concat(cProps);
+                               el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
+                               el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
+                       };
+               };
+               $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
+               $.effects.createWrapper(el); // Create Wrapper
+               el.css('overflow','hidden').css(el.from); // Shift
+
+               // Animate
+               if (scale == 'content' || scale == 'both') { // Scale the children
+                       vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
+                       hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
+                       props2 = props.concat(vProps).concat(hProps); // Concat
+                       el.find("*[width]").each(function(){
+                               var child = $(this);
+                               if (restore) $.effects.save(child, props2);
+                               var c_original = {height: child.height(), width: child.width()}; // Save original
+                               child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
+                               child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
+                               if (factor.from.y != factor.to.y) { // Vertical props scaling
+                                       child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
+                                       child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
+                               };
+                               if (factor.from.x != factor.to.x) { // Horizontal props scaling
+                                       child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
+                                       child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
+                               };
+                               child.css(child.from); // Shift children
+                               child.animate(child.to, o.duration, o.options.easing, function(){
+                                       if (restore) $.effects.restore(child, props2); // Restore children
+                               }); // Animate children
+                       });
+               };
+
+               // Animate
+               el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
+                       if (el.to.opacity === 0) {
+                               el.css('opacity', el.from.opacity);
+                       }
+                       if(mode == 'hide') el.hide(); // Hide
+                       $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
+                       if(o.callback) o.callback.apply(this, arguments); // Callback
+                       el.dequeue();
+               }});
+
+       });
+
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.shake.js b/resources/lib/jquery.effects/jquery.effects.shake.js
new file mode 100644 (file)
index 0000000..44b8ea4
--- /dev/null
@@ -0,0 +1,57 @@
+/*!
+ * jQuery UI Effects Shake 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Shake
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.shake = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','bottom','left','right'];
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
+               var direction = o.options.direction || 'left'; // Default direction
+               var distance = o.options.distance || 20; // Default distance
+               var times = o.options.times || 3; // Default # of times
+               var speed = o.duration || o.options.duration || 140; // Default speed per shake
+
+               // Adjust
+               $.effects.save(el, props); el.show(); // Save & Show
+               $.effects.createWrapper(el); // Create Wrapper
+               var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
+               var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
+
+               // Animation
+               var animation = {}, animation1 = {}, animation2 = {};
+               animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
+               animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
+               animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
+
+               // Animate
+               el.animate(animation, speed, o.options.easing);
+               for (var i = 1; i < times; i++) { // Shakes
+                       el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
+               };
+               el.animate(animation1, speed, o.options.easing).
+               animate(animation, speed / 2, o.options.easing, function(){ // Last shake
+                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+                       if(o.callback) o.callback.apply(this, arguments); // Callback
+               });
+               el.queue('fx', function() { el.dequeue(); });
+               el.dequeue();
+       });
+
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.slide.js b/resources/lib/jquery.effects/jquery.effects.slide.js
new file mode 100644 (file)
index 0000000..502e6c9
--- /dev/null
@@ -0,0 +1,50 @@
+/*!
+ * jQuery UI Effects Slide 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Slide
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.slide = function(o) {
+
+       return this.queue(function() {
+
+               // Create element
+               var el = $(this), props = ['position','top','bottom','left','right'];
+
+               // Set options
+               var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
+               var direction = o.options.direction || 'left'; // Default Direction
+
+               // Adjust
+               $.effects.save(el, props); el.show(); // Save & Show
+               $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
+               var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
+               var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
+               var distance = o.options.distance || (ref == 'top' ? el.outerHeight( true ) : el.outerWidth( true ));
+               if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift
+
+               // Animation
+               var animation = {};
+               animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
+
+               // Animate
+               el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
+                       if(mode == 'hide') el.hide(); // Hide
+                       $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
+                       if(o.callback) o.callback.apply(this, arguments); // Callback
+                       el.dequeue();
+               }});
+
+       });
+
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.effects/jquery.effects.transfer.js b/resources/lib/jquery.effects/jquery.effects.transfer.js
new file mode 100644 (file)
index 0000000..4ee4ae8
--- /dev/null
@@ -0,0 +1,45 @@
+/*!
+ * jQuery UI Effects Transfer 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Effects/Transfer
+ *
+ * Depends:
+ *     jquery.effects.core.js
+ */
+(function( $, undefined ) {
+
+$.effects.transfer = function(o) {
+       return this.queue(function() {
+               var elem = $(this),
+                       target = $(o.options.to),
+                       endPosition = target.offset(),
+                       animation = {
+                               top: endPosition.top,
+                               left: endPosition.left,
+                               height: target.innerHeight(),
+                               width: target.innerWidth()
+                       },
+                       startPosition = elem.offset(),
+                       transfer = $('<div class="ui-effects-transfer"></div>')
+                               .appendTo(document.body)
+                               .addClass(o.options.className)
+                               .css({
+                                       top: startPosition.top,
+                                       left: startPosition.left,
+                                       height: elem.innerHeight(),
+                                       width: elem.innerWidth(),
+                                       position: 'absolute'
+                               })
+                               .animate(animation, o.duration, o.options.easing, function() {
+                                       transfer.remove();
+                                       (o.callback && o.callback.apply(elem[0], arguments));
+                                       elem.dequeue();
+                               });
+       });
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-af.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-af.js
new file mode 100644 (file)
index 0000000..0922ef7
--- /dev/null
@@ -0,0 +1,23 @@
+/* Afrikaans initialisation for the jQuery UI date picker plugin. */
+/* Written by Renier Pretorius. */
+jQuery(function($){
+       $.datepicker.regional['af'] = {
+               closeText: 'Selekteer',
+               prevText: 'Vorige',
+               nextText: 'Volgende',
+               currentText: 'Vandag',
+               monthNames: ['Januarie','Februarie','Maart','April','Mei','Junie',
+               'Julie','Augustus','September','Oktober','November','Desember'],
+               monthNamesShort: ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun',
+               'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
+               dayNames: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],
+               dayNamesShort: ['Son', 'Maa', 'Din', 'Woe', 'Don', 'Vry', 'Sat'],
+               dayNamesMin: ['So','Ma','Di','Wo','Do','Vr','Sa'],
+               weekHeader: 'Wk',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['af']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar.js
new file mode 100644 (file)
index 0000000..8a9218d
--- /dev/null
@@ -0,0 +1,23 @@
+/* Arabic Translation for jQuery UI date picker plugin. */
+/* Khaled Alhourani -- me@khaledalhourani.com */
+/* NOTE: monthNames are the original months names and they are the Arabic names, not the new months name فبراير - يناير and there isn't any Arabic roots for these months */
+jQuery(function($){
+       $.datepicker.regional['ar'] = {
+               closeText: 'إغلاق',
+               prevText: '&#x3c;السابق',
+               nextText: 'التالي&#x3e;',
+               currentText: 'اليوم',
+               monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'مايو', 'حزيران',
+               'تموز', 'آب', 'أيلول',       'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
+               monthNamesShort: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
+               dayNames: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+               dayNamesShort: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+               dayNamesMin: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+               weekHeader: 'أسبوع',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 6,
+               isRTL: true,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['ar']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-az.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-az.js
new file mode 100644 (file)
index 0000000..57802a4
--- /dev/null
@@ -0,0 +1,23 @@
+/* Azerbaijani (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Jamil Najafov (necefov33@gmail.com). */
+jQuery(function($) {
+       $.datepicker.regional['az'] = {
+               closeText: 'Bağla',
+               prevText: '&#x3c;Geri',
+               nextText: 'İrəli&#x3e;',
+               currentText: 'Bugün',
+               monthNames: ['Yanvar','Fevral','Mart','Aprel','May','İyun',
+               'İyul','Avqust','Sentyabr','Oktyabr','Noyabr','Dekabr'],
+               monthNamesShort: ['Yan','Fev','Mar','Apr','May','İyun',
+               'İyul','Avq','Sen','Okt','Noy','Dek'],
+               dayNames: ['Bazar','Bazar ertəsi','Çərşənbə axşamı','Çərşənbə','Cümə axşamı','Cümə','Şənbə'],
+               dayNamesShort: ['B','Be','Ça','Ç','Ca','C','Ş'],
+               dayNamesMin: ['B','B','Ç','С','Ç','C','Ş'],
+               weekHeader: 'Hf',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['az']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bg.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bg.js
new file mode 100644 (file)
index 0000000..c19d20f
--- /dev/null
@@ -0,0 +1,24 @@
+/* Bulgarian initialisation for the jQuery UI date picker plugin. */
+/* Written by Stoyan Kyosev (http://svest.org). */
+jQuery(function($){
+    $.datepicker.regional['bg'] = {
+        closeText: 'затвори',
+        prevText: '&#x3c;назад',
+        nextText: 'напред&#x3e;',
+               nextBigText: '&#x3e;&#x3e;',
+        currentText: 'днес',
+        monthNames: ['Януари','Февруари','Март','Април','Май','Юни',
+        'Юли','Август','Септември','Октомври','Ноември','Декември'],
+        monthNamesShort: ['Яну','Фев','Мар','Апр','Май','Юни',
+        'Юли','Авг','Сеп','Окт','Нов','Дек'],
+        dayNames: ['Неделя','Понеделник','Вторник','Сряда','Четвъртък','Петък','Събота'],
+        dayNamesShort: ['Нед','Пон','Вто','Сря','Чет','Пет','Съб'],
+        dayNamesMin: ['Не','По','Вт','Ср','Че','Пе','Съ'],
+               weekHeader: 'Wk',
+        dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+        isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+    $.datepicker.setDefaults($.datepicker.regional['bg']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bs.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bs.js
new file mode 100644 (file)
index 0000000..d4dc8b0
--- /dev/null
@@ -0,0 +1,23 @@
+/* Bosnian i18n for the jQuery UI date picker plugin. */
+/* Written by Kenan Konjo. */
+jQuery(function($){
+       $.datepicker.regional['bs'] = {
+               closeText: 'Zatvori', 
+               prevText: '&#x3c;', 
+               nextText: '&#x3e;', 
+               currentText: 'Danas', 
+               monthNames: ['Januar','Februar','Mart','April','Maj','Juni',
+               'Juli','August','Septembar','Oktobar','Novembar','Decembar'],
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+               'Jul','Aug','Sep','Okt','Nov','Dec'],
+               dayNames: ['Nedelja','Ponedeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],
+               dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],
+               dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
+               weekHeader: 'Wk',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['bs']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ca.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ca.js
new file mode 100644 (file)
index 0000000..b128e69
--- /dev/null
@@ -0,0 +1,23 @@
+/* Inicialització en català per a l'extenció 'calendar' per jQuery. */
+/* Writers: (joan.leon@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['ca'] = {
+               closeText: 'Tancar',
+               prevText: '&#x3c;Ant',
+               nextText: 'Seg&#x3e;',
+               currentText: 'Avui',
+               monthNames: ['Gener','Febrer','Mar&ccedil;','Abril','Maig','Juny',
+               'Juliol','Agost','Setembre','Octubre','Novembre','Desembre'],
+               monthNamesShort: ['Gen','Feb','Mar','Abr','Mai','Jun',
+               'Jul','Ago','Set','Oct','Nov','Des'],
+               dayNames: ['Diumenge','Dilluns','Dimarts','Dimecres','Dijous','Divendres','Dissabte'],
+               dayNamesShort: ['Dug','Dln','Dmt','Dmc','Djs','Dvn','Dsb'],
+               dayNamesMin: ['Dg','Dl','Dt','Dc','Dj','Dv','Ds'],
+               weekHeader: 'Sm',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['ca']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cs.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cs.js
new file mode 100644 (file)
index 0000000..9805bcd
--- /dev/null
@@ -0,0 +1,23 @@
+/* Czech initialisation for the jQuery UI date picker plugin. */
+/* Written by Tomas Muller (tomas@tomas-muller.net). */
+jQuery(function($){
+       $.datepicker.regional['cs'] = {
+               closeText: 'Zavřít',
+               prevText: '&#x3c;Dříve',
+               nextText: 'Později&#x3e;',
+               currentText: 'Nyní',
+               monthNames: ['leden','únor','březen','duben','květen','červen',
+        'červenec','srpen','září','říjen','listopad','prosinec'],
+               monthNamesShort: ['led','úno','bře','dub','kvě','čer',
+               'čvc','srp','zář','říj','lis','pro'],
+               dayNames: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'],
+               dayNamesShort: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
+               dayNamesMin: ['ne','po','út','st','čt','pá','so'],
+               weekHeader: 'Týd',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['cs']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-da.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-da.js
new file mode 100644 (file)
index 0000000..176044e
--- /dev/null
@@ -0,0 +1,23 @@
+/* Danish initialisation for the jQuery UI date picker plugin. */
+/* Written by Jan Christensen ( deletestuff@gmail.com). */
+jQuery(function($){
+    $.datepicker.regional['da'] = {
+               closeText: 'Luk',
+        prevText: '&#x3c;Forrige',
+               nextText: 'Næste&#x3e;',
+               currentText: 'Idag',
+        monthNames: ['Januar','Februar','Marts','April','Maj','Juni',
+        'Juli','August','September','Oktober','November','December'],
+        monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+        'Jul','Aug','Sep','Okt','Nov','Dec'],
+               dayNames: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],
+               dayNamesShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'],
+               dayNamesMin: ['Sø','Ma','Ti','On','To','Fr','Lø'],
+               weekHeader: 'Uge',
+        dateFormat: 'dd-mm-yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+    $.datepicker.setDefaults($.datepicker.regional['da']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de.js
new file mode 100644 (file)
index 0000000..f3ef9e8
--- /dev/null
@@ -0,0 +1,23 @@
+/* German initialisation for the jQuery UI date picker plugin. */
+/* Written by Milian Wolff (mail@milianw.de). */
+jQuery(function($){
+       $.datepicker.regional['de'] = {
+               closeText: 'schließen',
+               prevText: '&#x3c;zurück',
+               nextText: 'Vor&#x3e;',
+               currentText: 'heute',
+               monthNames: ['Januar','Februar','März','April','Mai','Juni',
+               'Juli','August','September','Oktober','November','Dezember'],
+               monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun',
+               'Jul','Aug','Sep','Okt','Nov','Dez'],
+               dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
+               dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+               dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+               weekHeader: 'KW',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['de']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-el.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-el.js
new file mode 100644 (file)
index 0000000..6d775f9
--- /dev/null
@@ -0,0 +1,23 @@
+/* Greek (el) initialisation for the jQuery UI date picker plugin. */
+/* Written by Alex Cicovic (http://www.alexcicovic.com) */
+jQuery(function($){
+       $.datepicker.regional['el'] = {
+               closeText: 'Κλείσιμο',
+               prevText: 'Προηγούμενος',
+               nextText: 'Επόμενος',
+               currentText: 'Τρέχων Μήνας',
+               monthNames: ['Ιανουάριος','Φεβρουάριος','Μάρτιος','Απρίλιος','Μάιος','Ιούνιος',
+               'Ιούλιος','Αύγουστος','Σεπτέμβριος','Οκτώβριος','Νοέμβριος','Δεκέμβριος'],
+               monthNamesShort: ['Ιαν','Φεβ','Μαρ','Απρ','Μαι','Ιουν',
+               'Ιουλ','Αυγ','Σεπ','Οκτ','Νοε','Δεκ'],
+               dayNames: ['Κυριακή','Δευτέρα','Τρίτη','Τετάρτη','Πέμπτη','Παρασκευή','Σάββατο'],
+               dayNamesShort: ['Κυρ','Δευ','Τρι','Τετ','Πεμ','Παρ','Σαβ'],
+               dayNamesMin: ['Κυ','Δε','Τρ','Τε','Πε','Πα','Σα'],
+               weekHeader: 'Εβδ',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['el']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js
new file mode 100644 (file)
index 0000000..16a096e
--- /dev/null
@@ -0,0 +1,23 @@
+/* English/UK initialisation for the jQuery UI date picker plugin. */
+/* Written by Stuart. */
+jQuery(function($){
+       $.datepicker.regional['en-GB'] = {
+               closeText: 'Done',
+               prevText: 'Prev',
+               nextText: 'Next',
+               currentText: 'Today',
+               monthNames: ['January','February','March','April','May','June',
+               'July','August','September','October','November','December'],
+               monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+               'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+               dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
+               dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
+               dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'],
+               weekHeader: 'Wk',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['en-GB']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eo.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eo.js
new file mode 100644 (file)
index 0000000..6cabc2c
--- /dev/null
@@ -0,0 +1,23 @@
+/* Esperanto initialisation for the jQuery UI date picker plugin. */
+/* Written by Olivier M. (olivierweb@ifrance.com). */
+jQuery(function($){
+       $.datepicker.regional['eo'] = {
+               closeText: 'Fermi',
+               prevText: '&lt;Anta',
+               nextText: 'Sekv&gt;',
+               currentText: 'Nuna',
+               monthNames: ['Januaro','Februaro','Marto','Aprilo','Majo','Junio',
+               'Julio','Aŭgusto','Septembro','Oktobro','Novembro','Decembro'],
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+               'Jul','Aŭg','Sep','Okt','Nov','Dec'],
+               dayNames: ['Dimanĉo','Lundo','Mardo','Merkredo','Ĵaŭdo','Vendredo','Sabato'],
+               dayNamesShort: ['Dim','Lun','Mar','Mer','Ĵaŭ','Ven','Sab'],
+               dayNamesMin: ['Di','Lu','Ma','Me','Ĵa','Ve','Sa'],
+               weekHeader: 'Sb',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['eo']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-es.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-es.js
new file mode 100644 (file)
index 0000000..a02133d
--- /dev/null
@@ -0,0 +1,23 @@
+/* Inicialización en español para la extensión 'UI date picker' para jQuery. */
+/* Traducido por Vester (xvester@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['es'] = {
+               closeText: 'Cerrar',
+               prevText: '&#x3c;Ant',
+               nextText: 'Sig&#x3e;',
+               currentText: 'Hoy',
+               monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio',
+               'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
+               monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun',
+               'Jul','Ago','Sep','Oct','Nov','Dic'],
+               dayNames: ['Domingo','Lunes','Martes','Mi&eacute;rcoles','Jueves','Viernes','S&aacute;bado'],
+               dayNamesShort: ['Dom','Lun','Mar','Mi&eacute;','Juv','Vie','S&aacute;b'],
+               dayNamesMin: ['Do','Lu','Ma','Mi','Ju','Vi','S&aacute;'],
+               weekHeader: 'Sm',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['es']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-et.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-et.js
new file mode 100644 (file)
index 0000000..32702b2
--- /dev/null
@@ -0,0 +1,23 @@
+/* Estonian initialisation for the jQuery UI date picker plugin. */
+/* Written by Mart Sõmermaa (mrts.pydev at gmail com). */
+jQuery(function($){
+       $.datepicker.regional['et'] = {
+               closeText: 'Sulge',
+               prevText: 'Eelnev',
+               nextText: 'Järgnev',
+               currentText: 'Täna',
+               monthNames: ['Jaanuar','Veebruar','Märts','Aprill','Mai','Juuni',
+               'Juuli','August','September','Oktoober','November','Detsember'],
+               monthNamesShort: ['Jaan', 'Veebr', 'Märts', 'Apr', 'Mai', 'Juuni',
+               'Juuli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dets'],
+               dayNames: ['Pühapäev', 'Esmaspäev', 'Teisipäev', 'Kolmapäev', 'Neljapäev', 'Reede', 'Laupäev'],
+               dayNamesShort: ['Pühap', 'Esmasp', 'Teisip', 'Kolmap', 'Neljap', 'Reede', 'Laup'],
+               dayNamesMin: ['P','E','T','K','N','R','L'],
+               weekHeader: 'näd',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['et']);
+}); 
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eu.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eu.js
new file mode 100644 (file)
index 0000000..ff66e49
--- /dev/null
@@ -0,0 +1,23 @@
+/* Euskarako oinarria 'UI date picker' jquery-ko extentsioarentzat */
+/* Karrikas-ek itzulia (karrikas@karrikas.com) */
+jQuery(function($){
+       $.datepicker.regional['eu'] = {
+               closeText: 'Egina',
+               prevText: '&#x3c;Aur',
+               nextText: 'Hur&#x3e;',
+               currentText: 'Gaur',
+               monthNames: ['urtarrila','otsaila','martxoa','apirila','maiatza','ekaina',
+                       'uztaila','abuztua','iraila','urria','azaroa','abendua'],
+               monthNamesShort: ['urt.','ots.','mar.','api.','mai.','eka.',
+                       'uzt.','abu.','ira.','urr.','aza.','abe.'],
+               dayNames: ['igandea','astelehena','asteartea','asteazkena','osteguna','ostirala','larunbata'],
+               dayNamesShort: ['ig.','al.','ar.','az.','og.','ol.','lr.'],
+               dayNamesMin: ['ig','al','ar','az','og','ol','lr'],
+               weekHeader: 'As',
+               dateFormat: 'yy-mm-dd',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['eu']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fa.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fa.js
new file mode 100644 (file)
index 0000000..be8acd2
--- /dev/null
@@ -0,0 +1,59 @@
+/* Persian (Farsi) Translation for the jQuery UI date picker plugin. */
+/* Javad Mowlanezhad -- jmowla@gmail.com */
+/* Jalali calendar should supported soon! (Its implemented but I have to test it) */
+jQuery(function($) {
+       $.datepicker.regional['fa'] = {
+               closeText: 'بستن',
+               prevText: '&#x3C;قبلی',
+               nextText: 'بعدی&#x3E;',
+               currentText: 'امروز',
+               monthNames: [
+                       'فروردين',
+                       'ارديبهشت',
+                       'خرداد',
+                       'تير',
+                       'مرداد',
+                       'شهريور',
+                       'مهر',
+                       'آبان',
+                       'آذر',
+                       'دی',
+                       'بهمن',
+                       'اسفند'
+               ],
+               monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],
+               dayNames: [
+                       'يکشنبه',
+                       'دوشنبه',
+                       'سه‌شنبه',
+                       'چهارشنبه',
+                       'پنجشنبه',
+                       'جمعه',
+                       'شنبه'
+               ],
+               dayNamesShort: [
+                       'ی',
+                       'د',
+                       'س',
+                       'چ',
+                       'پ',
+                       'ج', 
+                       'ش'
+               ],
+               dayNamesMin: [
+                       'ی',
+                       'د',
+                       'س',
+                       'چ',
+                       'پ',
+                       'ج', 
+                       'ش'
+               ],
+               weekHeader: 'هف',
+               dateFormat: 'yy/mm/dd',
+               firstDay: 6,
+               isRTL: true,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['fa']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fi.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fi.js
new file mode 100644 (file)
index 0000000..4c5adda
--- /dev/null
@@ -0,0 +1,23 @@
+/* Finnish initialisation for the jQuery UI date picker plugin. */
+/* Written by Harri Kilpiö (harrikilpio@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['fi'] = {
+               closeText: 'Sulje',
+               prevText: '&#xAB;Edellinen',
+               nextText: 'Seuraava&#xBB;',
+               currentText: 'T&#xE4;n&#xE4;&#xE4;n',
+               monthNames: ['Tammikuu','Helmikuu','Maaliskuu','Huhtikuu','Toukokuu','Kes&#xE4;kuu',
+               'Hein&#xE4;kuu','Elokuu','Syyskuu','Lokakuu','Marraskuu','Joulukuu'],
+               monthNamesShort: ['Tammi','Helmi','Maalis','Huhti','Touko','Kes&#xE4;',
+               'Hein&#xE4;','Elo','Syys','Loka','Marras','Joulu'],
+               dayNamesShort: ['Su','Ma','Ti','Ke','To','Pe','La'],
+               dayNames: ['Sunnuntai','Maanantai','Tiistai','Keskiviikko','Torstai','Perjantai','Lauantai'],
+               dayNamesMin: ['Su','Ma','Ti','Ke','To','Pe','La'],
+               weekHeader: 'Vk',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['fi']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fo.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fo.js
new file mode 100644 (file)
index 0000000..8a6cb99
--- /dev/null
@@ -0,0 +1,23 @@
+/* Faroese initialisation for the jQuery UI date picker plugin */
+/* Written by Sverri Mohr Olsen, sverrimo@gmail.com */
+jQuery(function($){
+       $.datepicker.regional['fo'] = {
+               closeText: 'Lat aftur',
+               prevText: '&#x3c;Fyrra',
+               nextText: 'Næsta&#x3e;',
+               currentText: 'Í dag',
+               monthNames: ['Januar','Februar','Mars','Apríl','Mei','Juni',
+               'Juli','August','September','Oktober','November','Desember'],
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',
+               'Jul','Aug','Sep','Okt','Nov','Des'],
+               dayNames: ['Sunnudagur','Mánadagur','Týsdagur','Mikudagur','Hósdagur','Fríggjadagur','Leyardagur'],
+               dayNamesShort: ['Sun','Mán','Týs','Mik','Hós','Frí','Ley'],
+               dayNamesMin: ['Su','Má','Tý','Mi','Hó','Fr','Le'],
+               weekHeader: 'Vk',
+               dateFormat: 'dd-mm-yy',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['fo']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr.js
new file mode 100644 (file)
index 0000000..7e79363
--- /dev/null
@@ -0,0 +1,25 @@
+/* French initialisation for the jQuery UI date picker plugin. */
+/* Written by Keith Wood (kbwood{at}iinet.com.au),
+              Stéphane Nahmani (sholby@sholby.net),
+              Stéphane Raimbault <stephane.raimbault@gmail.com> */
+jQuery(function($){
+       $.datepicker.regional['fr'] = {
+               closeText: 'Fermer',
+               prevText: 'Précédent',
+               nextText: 'Suivant',
+               currentText: 'Aujourd\'hui',
+               monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',
+               'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
+               monthNamesShort: ['Janv.','Févr.','Mars','Avril','Mai','Juin',
+               'Juil.','Août','Sept.','Oct.','Nov.','Déc.'],
+               dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
+               dayNamesShort: ['Dim.','Lun.','Mar.','Mer.','Jeu.','Ven.','Sam.'],
+               dayNamesMin: ['D','L','M','M','J','V','S'],
+               weekHeader: 'Sem.',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['fr']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-gl.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-gl.js
new file mode 100644 (file)
index 0000000..278403e
--- /dev/null
@@ -0,0 +1,23 @@
+/* Galician localization for 'UI date picker' jQuery extension. */
+/* Translated by Jorge Barreiro <yortx.barry@gmail.com>. */
+jQuery(function($){
+       $.datepicker.regional['gl'] = {
+               closeText: 'Pechar',
+               prevText: '&#x3c;Ant',
+               nextText: 'Seg&#x3e;',
+               currentText: 'Hoxe',
+               monthNames: ['Xaneiro','Febreiro','Marzo','Abril','Maio','Xuño',
+               'Xullo','Agosto','Setembro','Outubro','Novembro','Decembro'],
+               monthNamesShort: ['Xan','Feb','Mar','Abr','Mai','Xuñ',
+               'Xul','Ago','Set','Out','Nov','Dec'],
+               dayNames: ['Domingo','Luns','Martes','M&eacute;rcores','Xoves','Venres','S&aacute;bado'],
+               dayNamesShort: ['Dom','Lun','Mar','M&eacute;r','Xov','Ven','S&aacute;b'],
+               dayNamesMin: ['Do','Lu','Ma','M&eacute;','Xo','Ve','S&aacute;'],
+               weekHeader: 'Sm',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['gl']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-he.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-he.js
new file mode 100644 (file)
index 0000000..135cdec
--- /dev/null
@@ -0,0 +1,23 @@
+/* Hebrew initialisation for the UI Datepicker extension. */
+/* Written by Amir Hardon (ahardon at gmail dot com). */
+jQuery(function($){
+       $.datepicker.regional['he'] = {
+               closeText: 'סגור',
+               prevText: '&#x3c;הקודם',
+               nextText: 'הבא&#x3e;',
+               currentText: 'היום',
+               monthNames: ['ינואר','פברואר','מרץ','אפריל','מאי','יוני',
+               'יולי','אוגוסט','ספטמבר','אוקטובר','נובמבר','דצמבר'],
+               monthNamesShort: ['ינו','פבר','מרץ','אפר','מאי','יוני',
+               'יולי','אוג','ספט','אוק','נוב','דצמ'],
+               dayNames: ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת'],
+               dayNamesShort: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
+               dayNamesMin: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
+               weekHeader: 'Wk',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 0,
+               isRTL: true,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['he']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hi.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hi.js
new file mode 100644 (file)
index 0000000..6c563b9
--- /dev/null
@@ -0,0 +1,23 @@
+/* Hindi initialisation for the jQuery UI date picker plugin. */
+/* Written by Michael Dawart. */
+jQuery(function($){
+       $.datepicker.regional['hi'] = {
+               closeText: 'बंद',
+               prevText: 'पिछला',
+               nextText: 'अगला',
+               currentText: 'आज',
+               monthNames: ['जनवरी ','फरवरी','मार्च','अप्रेल','मई','जून',
+               'जूलाई','अगस्त ','सितम्बर','अक्टूबर','नवम्बर','दिसम्बर'],
+               monthNamesShort: ['जन', 'फर', 'मार्च', 'अप्रेल', 'मई', 'जून',
+               'जूलाई', 'अग', 'सित', 'अक्ट', 'नव', 'दि'],
+               dayNames: ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरुवार', 'शुक्रवार', 'शनिवार'],
+               dayNamesShort: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
+               dayNamesMin: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
+               weekHeader: 'हफ्ता',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['hi']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hr.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hr.js
new file mode 100644 (file)
index 0000000..1eb3dd9
--- /dev/null
@@ -0,0 +1,23 @@
+/* Croatian i18n for the jQuery UI date picker plugin. */
+/* Written by Vjekoslav Nesek. */
+jQuery(function($){
+       $.datepicker.regional['hr'] = {
+               closeText: 'Zatvori',
+               prevText: '&#x3c;',
+               nextText: '&#x3e;',
+               currentText: 'Danas',
+               monthNames: ['Siječanj','Veljača','Ožujak','Travanj','Svibanj','Lipanj',
+               'Srpanj','Kolovoz','Rujan','Listopad','Studeni','Prosinac'],
+               monthNamesShort: ['Sij','Velj','Ožu','Tra','Svi','Lip',
+               'Srp','Kol','Ruj','Lis','Stu','Pro'],
+               dayNames: ['Nedjelja','Ponedjeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],
+               dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],
+               dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
+               weekHeader: 'Tje',
+               dateFormat: 'dd.mm.yy.',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['hr']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hu.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hu.js
new file mode 100644 (file)
index 0000000..b28c268
--- /dev/null
@@ -0,0 +1,23 @@
+/* Hungarian initialisation for the jQuery UI date picker plugin. */
+/* Written by Istvan Karaszi (jquery@spam.raszi.hu). */
+jQuery(function($){
+       $.datepicker.regional['hu'] = {
+               closeText: 'bezár',
+               prevText: 'vissza',
+               nextText: 'előre',
+               currentText: 'ma',
+               monthNames: ['Január', 'Február', 'Március', 'Április', 'Május', 'Június',
+               'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'],
+               monthNamesShort: ['Jan', 'Feb', 'Már', 'Ápr', 'Máj', 'Jún',
+               'Júl', 'Aug', 'Szep', 'Okt', 'Nov', 'Dec'],
+               dayNames: ['Vasárnap', 'Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'],
+               dayNamesShort: ['Vas', 'Hét', 'Ked', 'Sze', 'Csü', 'Pén', 'Szo'],
+               dayNamesMin: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],
+               weekHeader: 'Hét',
+               dateFormat: 'yy.mm.dd.',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: true,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['hu']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hy.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hy.js
new file mode 100644 (file)
index 0000000..c6cc194
--- /dev/null
@@ -0,0 +1,23 @@
+/* Armenian(UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Levon Zakaryan (levon.zakaryan@gmail.com)*/
+jQuery(function($){
+       $.datepicker.regional['hy'] = {
+               closeText: 'Փակել',
+               prevText: '&#x3c;Նախ.',
+               nextText: 'Հաջ.&#x3e;',
+               currentText: 'Այսօր',
+               monthNames: ['Հունվար','Փետրվար','Մարտ','Ապրիլ','Մայիս','Հունիս',
+               'Հուլիս','Օգոստոս','Սեպտեմբեր','Հոկտեմբեր','Նոյեմբեր','Դեկտեմբեր'],
+               monthNamesShort: ['Հունվ','Փետր','Մարտ','Ապր','Մայիս','Հունիս',
+               'Հուլ','Օգս','Սեպ','Հոկ','Նոյ','Դեկ'],
+               dayNames: ['կիրակի','եկուշաբթի','երեքշաբթի','չորեքշաբթի','հինգշաբթի','ուրբաթ','շաբաթ'],
+               dayNamesShort: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],
+               dayNamesMin: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],
+               weekHeader: 'ՇԲՏ',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['hy']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-id.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-id.js
new file mode 100644 (file)
index 0000000..c626fbb
--- /dev/null
@@ -0,0 +1,23 @@
+/* Indonesian initialisation for the jQuery UI date picker plugin. */
+/* Written by Deden Fathurahman (dedenf@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['id'] = {
+               closeText: 'Tutup',
+               prevText: '&#x3c;mundur',
+               nextText: 'maju&#x3e;',
+               currentText: 'hari ini',
+               monthNames: ['Januari','Februari','Maret','April','Mei','Juni',
+               'Juli','Agustus','September','Oktober','Nopember','Desember'],
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',
+               'Jul','Agus','Sep','Okt','Nop','Des'],
+               dayNames: ['Minggu','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'],
+               dayNamesShort: ['Min','Sen','Sel','Rab','kam','Jum','Sab'],
+               dayNamesMin: ['Mg','Sn','Sl','Rb','Km','jm','Sb'],
+               weekHeader: 'Mg',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['id']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-is.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-is.js
new file mode 100644 (file)
index 0000000..c53235a
--- /dev/null
@@ -0,0 +1,23 @@
+/* Icelandic initialisation for the jQuery UI date picker plugin. */
+/* Written by Haukur H. Thorsson (haukur@eskill.is). */
+jQuery(function($){
+       $.datepicker.regional['is'] = {
+               closeText: 'Loka',
+               prevText: '&#x3c; Fyrri',
+               nextText: 'N&aelig;sti &#x3e;',
+               currentText: '&Iacute; dag',
+               monthNames: ['Jan&uacute;ar','Febr&uacute;ar','Mars','Apr&iacute;l','Ma&iacute','J&uacute;n&iacute;',
+               'J&uacute;l&iacute;','&Aacute;g&uacute;st','September','Okt&oacute;ber','N&oacute;vember','Desember'],
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Ma&iacute;','J&uacute;n',
+               'J&uacute;l','&Aacute;g&uacute;','Sep','Okt','N&oacute;v','Des'],
+               dayNames: ['Sunnudagur','M&aacute;nudagur','&THORN;ri&eth;judagur','Mi&eth;vikudagur','Fimmtudagur','F&ouml;studagur','Laugardagur'],
+               dayNamesShort: ['Sun','M&aacute;n','&THORN;ri','Mi&eth;','Fim','F&ouml;s','Lau'],
+               dayNamesMin: ['Su','M&aacute;','&THORN;r','Mi','Fi','F&ouml;','La'],
+               weekHeader: 'Vika',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['is']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-it.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-it.js
new file mode 100644 (file)
index 0000000..59da2df
--- /dev/null
@@ -0,0 +1,23 @@
+/* Italian initialisation for the jQuery UI date picker plugin. */
+/* Written by Antonello Pasella (antonello.pasella@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['it'] = {
+               closeText: 'Chiudi',
+               prevText: '&#x3c;Prec',
+               nextText: 'Succ&#x3e;',
+               currentText: 'Oggi',
+               monthNames: ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno',
+                       'Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],
+               monthNamesShort: ['Gen','Feb','Mar','Apr','Mag','Giu',
+                       'Lug','Ago','Set','Ott','Nov','Dic'],
+               dayNames: ['Domenica','Luned&#236','Marted&#236','Mercoled&#236','Gioved&#236','Venerd&#236','Sabato'],
+               dayNamesShort: ['Dom','Lun','Mar','Mer','Gio','Ven','Sab'],
+               dayNamesMin: ['Do','Lu','Ma','Me','Gi','Ve','Sa'],
+               weekHeader: 'Sm',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['it']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ja.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ja.js
new file mode 100644 (file)
index 0000000..7eb4268
--- /dev/null
@@ -0,0 +1,23 @@
+/* Japanese initialisation for the jQuery UI date picker plugin. */
+/* Written by Kentaro SATO (kentaro@ranvis.com). */
+jQuery(function($){
+       $.datepicker.regional['ja'] = {
+               closeText: '閉じる',
+               prevText: '&#x3c;前',
+               nextText: '次&#x3e;',
+               currentText: '今日',
+               monthNames: ['1月','2月','3月','4月','5月','6月',
+               '7月','8月','9月','10月','11月','12月'],
+               monthNamesShort: ['1月','2月','3月','4月','5月','6月',
+               '7月','8月','9月','10月','11月','12月'],
+               dayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],
+               dayNamesShort: ['日','月','火','水','木','金','土'],
+               dayNamesMin: ['日','月','火','水','木','金','土'],
+               weekHeader: '週',
+               dateFormat: 'yy/mm/dd',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: true,
+               yearSuffix: '年'};
+       $.datepicker.setDefaults($.datepicker.regional['ja']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ka.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ka.js
new file mode 100644 (file)
index 0000000..c10658d
--- /dev/null
@@ -0,0 +1,21 @@
+/* Georgian (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Lado Lomidze (lado.lomidze@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['ka'] = {
+               closeText: 'დახურვა',
+               prevText: '&#x3c; წინა',
+               nextText: 'შემდეგი &#x3e;',
+               currentText: 'დღეს',
+               monthNames: ['იანვარი','თებერვალი','მარტი','აპრილი','მაისი','ივნისი', 'ივლისი','აგვისტო','სექტემბერი','ოქტომბერი','ნოემბერი','დეკემბერი'],
+               monthNamesShort: ['იან','თებ','მარ','აპრ','მაი','ივნ', 'ივლ','აგვ','სექ','ოქტ','ნოე','დეკ'],
+               dayNames: ['კვირა','ორშაბათი','სამშაბათი','ოთხშაბათი','ხუთშაბათი','პარასკევი','შაბათი'],
+               dayNamesShort: ['კვ','ორშ','სამ','ოთხ','ხუთ','პარ','შაბ'],
+               dayNamesMin: ['კვ','ორშ','სამ','ოთხ','ხუთ','პარ','შაბ'],
+               weekHeader: 'კვირა',
+               dateFormat: 'dd-mm-yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['ka']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-kk.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-kk.js
new file mode 100644 (file)
index 0000000..79e3f24
--- /dev/null
@@ -0,0 +1,23 @@
+/* Kazakh (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Dmitriy Karasyov (dmitriy.karasyov@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['kk'] = {
+               closeText: 'Жабу',
+               prevText: '&#x3c;Алдыңғы',
+               nextText: 'Келесі&#x3e;',
+               currentText: 'Бүгін',
+               monthNames: ['Қаңтар','Ақпан','Наурыз','Сәуір','Мамыр','Маусым',
+               'Шілде','Тамыз','Қыркүйек','Қазан','Қараша','Желтоқсан'],
+               monthNamesShort: ['Қаң','Ақп','Нау','Сәу','Мам','Мау',
+               'Шіл','Там','Қыр','Қаз','Қар','Жел'],
+               dayNames: ['Жексенбі','Дүйсенбі','Сейсенбі','Сәрсенбі','Бейсенбі','Жұма','Сенбі'],
+               dayNamesShort: ['жкс','дсн','ссн','срс','бсн','жма','снб'],
+               dayNamesMin: ['Жк','Дс','Сс','Ср','Бс','Жм','Сн'],
+               weekHeader: 'Не',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['kk']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-km.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-km.js
new file mode 100644 (file)
index 0000000..f9c4e3a
--- /dev/null
@@ -0,0 +1,23 @@
+/* Khmer initialisation for the jQuery calendar extension. */
+/* Written by Chandara Om (chandara.teacher@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['km'] = {
+               closeText: 'ធ្វើ​រួច',
+               prevText: 'មុន',
+               nextText: 'បន្ទាប់',
+               currentText: 'ថ្ងៃ​នេះ',
+               monthNames: ['មករា','កុម្ភៈ','មីនា','មេសា','ឧសភា','មិថុនា',
+               'កក្កដា','សីហា','កញ្ញា','តុលា','វិច្ឆិកា','ធ្នូ'],
+               monthNamesShort: ['មករា','កុម្ភៈ','មីនា','មេសា','ឧសភា','មិថុនា',
+               'កក្កដា','សីហា','កញ្ញា','តុលា','វិច្ឆិកា','ធ្នូ'],
+               dayNames: ['អាទិត្យ', 'ចន្ទ', 'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ', 'សៅរ៍'],
+               dayNamesShort: ['អា', 'ច', 'អ', 'ពុ', 'ព្រហ', 'សុ', 'សៅ'],
+               dayNamesMin: ['អា', 'ច', 'អ', 'ពុ', 'ព្រហ', 'សុ', 'សៅ'],
+               weekHeader: 'សប្ដាហ៍',
+               dateFormat: 'dd-mm-yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['km']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ko.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ko.js
new file mode 100644 (file)
index 0000000..0411242
--- /dev/null
@@ -0,0 +1,23 @@
+/* Korean initialisation for the jQuery calendar extension. */
+/* Written by DaeKwon Kang (ncrash.dk@gmail.com), Edited by Genie. */
+jQuery(function($){
+       $.datepicker.regional['ko'] = {
+               closeText: '닫기',
+               prevText: '이전달',
+               nextText: '다음달',
+               currentText: '오늘',
+               monthNames: ['1월','2월','3월','4월','5월','6월',
+               '7월','8월','9월','10월','11월','12월'],
+               monthNamesShort: ['1월','2월','3월','4월','5월','6월',
+               '7월','8월','9월','10월','11월','12월'],
+               dayNames: ['일요일','월요일','화요일','수요일','목요일','금요일','토요일'],
+               dayNamesShort: ['일','월','화','수','목','금','토'],
+               dayNamesMin: ['일','월','화','수','목','금','토'],
+               weekHeader: 'Wk',
+               dateFormat: 'yy-mm-dd',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: true,
+               yearSuffix: '년'};
+       $.datepicker.setDefaults($.datepicker.regional['ko']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lb.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lb.js
new file mode 100644 (file)
index 0000000..87c79d5
--- /dev/null
@@ -0,0 +1,23 @@
+/* Luxembourgish initialisation for the jQuery UI date picker plugin. */
+/* Written by Michel Weimerskirch <michel@weimerskirch.net> */
+jQuery(function($){
+       $.datepicker.regional['lb'] = {
+               closeText: 'Fäerdeg',
+               prevText: 'Zréck',
+               nextText: 'Weider',
+               currentText: 'Haut',
+               monthNames: ['Januar','Februar','Mäerz','Abrëll','Mee','Juni',
+               'Juli','August','September','Oktober','November','Dezember'],
+               monthNamesShort: ['Jan', 'Feb', 'Mäe', 'Abr', 'Mee', 'Jun',
+               'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
+               dayNames: ['Sonndeg', 'Méindeg', 'Dënschdeg', 'Mëttwoch', 'Donneschdeg', 'Freideg', 'Samschdeg'],
+               dayNamesShort: ['Son', 'Méi', 'Dën', 'Mët', 'Don', 'Fre', 'Sam'],
+               dayNamesMin: ['So','Mé','Dë','Më','Do','Fr','Sa'],
+               weekHeader: 'W',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['lb']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lt.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lt.js
new file mode 100644 (file)
index 0000000..67d5119
--- /dev/null
@@ -0,0 +1,23 @@
+/* Lithuanian (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* @author Arturas Paleicikas <arturas@avalon.lt> */
+jQuery(function($){
+       $.datepicker.regional['lt'] = {
+               closeText: 'Uždaryti',
+               prevText: '&#x3c;Atgal',
+               nextText: 'Pirmyn&#x3e;',
+               currentText: 'Šiandien',
+               monthNames: ['Sausis','Vasaris','Kovas','Balandis','Gegužė','Birželis',
+               'Liepa','Rugpjūtis','Rugsėjis','Spalis','Lapkritis','Gruodis'],
+               monthNamesShort: ['Sau','Vas','Kov','Bal','Geg','Bir',
+               'Lie','Rugp','Rugs','Spa','Lap','Gru'],
+               dayNames: ['sekmadienis','pirmadienis','antradienis','trečiadienis','ketvirtadienis','penktadienis','šeštadienis'],
+               dayNamesShort: ['sek','pir','ant','tre','ket','pen','šeš'],
+               dayNamesMin: ['Se','Pr','An','Tr','Ke','Pe','Še'],
+               weekHeader: 'Wk',
+               dateFormat: 'yy-mm-dd',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['lt']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lv.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lv.js
new file mode 100644 (file)
index 0000000..003934e
--- /dev/null
@@ -0,0 +1,23 @@
+/* Latvian (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* @author Arturas Paleicikas <arturas.paleicikas@metasite.net> */
+jQuery(function($){
+       $.datepicker.regional['lv'] = {
+               closeText: 'Aizvērt',
+               prevText: 'Iepr',
+               nextText: 'Nāka',
+               currentText: 'Šodien',
+               monthNames: ['Janvāris','Februāris','Marts','Aprīlis','Maijs','Jūnijs',
+               'Jūlijs','Augusts','Septembris','Oktobris','Novembris','Decembris'],
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jūn',
+               'Jūl','Aug','Sep','Okt','Nov','Dec'],
+               dayNames: ['svētdiena','pirmdiena','otrdiena','trešdiena','ceturtdiena','piektdiena','sestdiena'],
+               dayNamesShort: ['svt','prm','otr','tre','ctr','pkt','sst'],
+               dayNamesMin: ['Sv','Pr','Ot','Tr','Ct','Pk','Ss'],
+               weekHeader: 'Nav',
+               dateFormat: 'dd-mm-yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['lv']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-mk.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-mk.js
new file mode 100644 (file)
index 0000000..0285325
--- /dev/null
@@ -0,0 +1,23 @@
+/* Macedonian i18n for the jQuery UI date picker plugin. */
+/* Written by Stojce Slavkovski. */
+jQuery(function($){
+       $.datepicker.regional['mk'] = {
+               closeText: 'Затвори',
+               prevText: '&#x3C;',
+               nextText: '&#x3E;',
+               currentText: 'Денес',
+               monthNames: ['Јануари','Февруари','Март','Април','Мај','Јуни',
+               'Јули','Август','Септември','Октомври','Ноември','Декември'],
+               monthNamesShort: ['Јан','Фев','Мар','Апр','Мај','Јун',
+               'Јул','Авг','Сеп','Окт','Ное','Дек'],
+               dayNames: ['Недела','Понеделник','Вторник','Среда','Четврток','Петок','Сабота'],
+               dayNamesShort: ['Нед','Пон','Вто','Сре','Чет','Пет','Саб'],
+               dayNamesMin: ['Не','По','Вт','Ср','Че','Пе','Са'],
+               weekHeader: 'Сед',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['mk']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ml.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ml.js
new file mode 100644 (file)
index 0000000..1e3432c
--- /dev/null
@@ -0,0 +1,23 @@
+/* Malayalam (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Saji Nediyanchath (saji89@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['ml'] = {
+               closeText: 'ശരി',
+               prevText: 'മുന്നത്തെ',  
+               nextText: 'അടുത്തത് ',
+               currentText: 'ഇന്ന്',
+               monthNames: ['ജനുവരി','ഫെബ്രുവരി','മാര്‍ച്ച്','ഏപ്രില്‍','മേയ്','ജൂണ്‍',
+               'ജൂലൈ','ആഗസ്റ്റ്','സെപ്റ്റംബര്‍','ഒക്ടോബര്‍','നവംബര്‍','ഡിസംബര്‍'],
+               monthNamesShort: ['ജനു', 'ഫെബ്', 'മാര്‍', 'ഏപ്രി', 'മേയ്', 'ജൂണ്‍',
+               'ജൂലാ', 'ആഗ', 'സെപ്', 'ഒക്ടോ', 'നവം', 'ഡിസ'],
+               dayNames: ['ഞായര്‍', 'തിങ്കള്‍', 'ചൊവ്വ', 'ബുധന്‍', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],
+               dayNamesShort: ['ഞായ', 'തിങ്ക', 'ചൊവ്വ', 'ബുധ', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],
+               dayNamesMin: ['ഞാ','തി','ചൊ','ബു','വ്യാ','വെ','ശ'],
+               weekHeader: 'ആ',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['ml']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ms.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ms.js
new file mode 100644 (file)
index 0000000..e953ac0
--- /dev/null
@@ -0,0 +1,23 @@
+/* Malaysian initialisation for the jQuery UI date picker plugin. */
+/* Written by Mohd Nawawi Mohamad Jamili (nawawi@ronggeng.net). */
+jQuery(function($){
+       $.datepicker.regional['ms'] = {
+               closeText: 'Tutup',
+               prevText: '&#x3c;Sebelum',
+               nextText: 'Selepas&#x3e;',
+               currentText: 'hari ini',
+               monthNames: ['Januari','Februari','Mac','April','Mei','Jun',
+               'Julai','Ogos','September','Oktober','November','Disember'],
+               monthNamesShort: ['Jan','Feb','Mac','Apr','Mei','Jun',
+               'Jul','Ogo','Sep','Okt','Nov','Dis'],
+               dayNames: ['Ahad','Isnin','Selasa','Rabu','Khamis','Jumaat','Sabtu'],
+               dayNamesShort: ['Aha','Isn','Sel','Rab','kha','Jum','Sab'],
+               dayNamesMin: ['Ah','Is','Se','Ra','Kh','Ju','Sa'],
+               weekHeader: 'Mg',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['ms']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl.js
new file mode 100644 (file)
index 0000000..781fe61
--- /dev/null
@@ -0,0 +1,23 @@
+/* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Mathias Bynens <http://mathiasbynens.be/> */
+jQuery(function($){
+       $.datepicker.regional.nl = {
+               closeText: 'Sluiten',
+               prevText: '←',
+               nextText: '→',
+               currentText: 'Vandaag',
+               monthNames: ['januari', 'februari', 'maart', 'april', 'mei', 'juni',
+               'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
+               monthNamesShort: ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun',
+               'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
+               dayNames: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
+               dayNamesShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'],
+               dayNamesMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
+               weekHeader: 'Wk',
+               dateFormat: 'dd-mm-yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional.nl);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-no.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-no.js
new file mode 100644 (file)
index 0000000..2507043
--- /dev/null
@@ -0,0 +1,23 @@
+/* Norwegian initialisation for the jQuery UI date picker plugin. */
+/* Written by Naimdjon Takhirov (naimdjon@gmail.com). */
+
+jQuery(function($){
+  $.datepicker.regional['no'] = {
+    closeText: 'Lukk',
+    prevText: '&laquo;Forrige',
+    nextText: 'Neste&raquo;',
+    currentText: 'I dag',
+    monthNames: ['januar','februar','mars','april','mai','juni','juli','august','september','oktober','november','desember'],
+    monthNamesShort: ['jan','feb','mar','apr','mai','jun','jul','aug','sep','okt','nov','des'],
+    dayNamesShort: ['søn','man','tir','ons','tor','fre','lør'],
+    dayNames: ['søndag','mandag','tirsdag','onsdag','torsdag','fredag','lørdag'],
+    dayNamesMin: ['sø','ma','ti','on','to','fr','lø'],
+    weekHeader: 'Uke',
+    dateFormat: 'dd.mm.yy',
+    firstDay: 1,
+    isRTL: false,
+    showMonthAfterYear: false,
+    yearSuffix: ''
+  };
+  $.datepicker.setDefaults($.datepicker.regional['no']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pl.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pl.js
new file mode 100644 (file)
index 0000000..61fa29c
--- /dev/null
@@ -0,0 +1,23 @@
+/* Polish initialisation for the jQuery UI date picker plugin. */
+/* Written by Jacek Wysocki (jacek.wysocki@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['pl'] = {
+               closeText: 'Zamknij',
+               prevText: '&#x3c;Poprzedni',
+               nextText: 'Następny&#x3e;',
+               currentText: 'Dziś',
+               monthNames: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec',
+               'Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],
+               monthNamesShort: ['Sty','Lu','Mar','Kw','Maj','Cze',
+               'Lip','Sie','Wrz','Pa','Lis','Gru'],
+               dayNames: ['Niedziela','Poniedziałek','Wtorek','Środa','Czwartek','Piątek','Sobota'],
+               dayNamesShort: ['Nie','Pn','Wt','Śr','Czw','Pt','So'],
+               dayNamesMin: ['N','Pn','Wt','Śr','Cz','Pt','So'],
+               weekHeader: 'Tydz',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['pl']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js
new file mode 100644 (file)
index 0000000..3cc8c79
--- /dev/null
@@ -0,0 +1,23 @@
+/* Brazilian initialisation for the jQuery UI date picker plugin. */
+/* Written by Leonildo Costa Silva (leocsilva@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['pt-BR'] = {
+               closeText: 'Fechar',
+               prevText: '&#x3c;Anterior',
+               nextText: 'Pr&oacute;ximo&#x3e;',
+               currentText: 'Hoje',
+               monthNames: ['Janeiro','Fevereiro','Mar&ccedil;o','Abril','Maio','Junho',
+               'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
+               monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',
+               'Jul','Ago','Set','Out','Nov','Dez'],
+               dayNames: ['Domingo','Segunda-feira','Ter&ccedil;a-feira','Quarta-feira','Quinta-feira','Sexta-feira','S&aacute;bado'],
+               dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
+               dayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
+               weekHeader: 'Sm',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['pt-BR']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt.js
new file mode 100644 (file)
index 0000000..f09f5ae
--- /dev/null
@@ -0,0 +1,22 @@
+/* Portuguese initialisation for the jQuery UI date picker plugin. */
+jQuery(function($){
+       $.datepicker.regional['pt'] = {
+               closeText: 'Fechar',
+               prevText: '&#x3c;Anterior',
+               nextText: 'Seguinte',
+               currentText: 'Hoje',
+               monthNames: ['Janeiro','Fevereiro','Mar&ccedil;o','Abril','Maio','Junho',
+               'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
+               monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',
+               'Jul','Ago','Set','Out','Nov','Dez'],
+               dayNames: ['Domingo','Segunda-feira','Ter&ccedil;a-feira','Quarta-feira','Quinta-feira','Sexta-feira','S&aacute;bado'],
+               dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
+               dayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],
+               weekHeader: 'Sem',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['pt']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-rm.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-rm.js
new file mode 100644 (file)
index 0000000..cf03cd4
--- /dev/null
@@ -0,0 +1,21 @@
+/* Romansh initialisation for the jQuery UI date picker plugin. */
+/* Written by Yvonne Gienal (yvonne.gienal@educa.ch). */
+jQuery(function($){
+       $.datepicker.regional['rm'] = {
+               closeText: 'Serrar',
+               prevText: '&#x3c;Suandant',
+               nextText: 'Precedent&#x3e;',
+               currentText: 'Actual',
+               monthNames: ['Schaner','Favrer','Mars','Avrigl','Matg','Zercladur', 'Fanadur','Avust','Settember','October','November','December'],
+               monthNamesShort: ['Scha','Fev','Mar','Avr','Matg','Zer', 'Fan','Avu','Sett','Oct','Nov','Dec'],
+               dayNames: ['Dumengia','Glindesdi','Mardi','Mesemna','Gievgia','Venderdi','Sonda'],
+               dayNamesShort: ['Dum','Gli','Mar','Mes','Gie','Ven','Som'],
+               dayNamesMin: ['Du','Gl','Ma','Me','Gi','Ve','So'],
+               weekHeader: 'emna',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['rm']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ro.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ro.js
new file mode 100644 (file)
index 0000000..6b140af
--- /dev/null
@@ -0,0 +1,26 @@
+/* Romanian initialisation for the jQuery UI date picker plugin.
+ *
+ * Written by Edmond L. (ll_edmond@walla.com)
+ * and Ionut G. Stan (ionut.g.stan@gmail.com)
+ */
+jQuery(function($){
+       $.datepicker.regional['ro'] = {
+               closeText: 'Închide',
+               prevText: '&laquo; Luna precedentă',
+               nextText: 'Luna următoare &raquo;',
+               currentText: 'Azi',
+               monthNames: ['Ianuarie','Februarie','Martie','Aprilie','Mai','Iunie',
+               'Iulie','August','Septembrie','Octombrie','Noiembrie','Decembrie'],
+               monthNamesShort: ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun',
+               'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+               dayNames: ['Duminică', 'Luni', 'Marţi', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'],
+               dayNamesShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
+               dayNamesMin: ['Du','Lu','Ma','Mi','Jo','Vi','Sâ'],
+               weekHeader: 'Săpt',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['ro']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ru.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ru.js
new file mode 100644 (file)
index 0000000..50a4613
--- /dev/null
@@ -0,0 +1,23 @@
+/* Russian (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Andrew Stromnov (stromnov@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['ru'] = {
+               closeText: 'Закрыть',
+               prevText: '&#x3c;Пред',
+               nextText: 'След&#x3e;',
+               currentText: 'Сегодня',
+               monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь',
+               'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],
+               monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн',
+               'Июл','Авг','Сен','Окт','Ноя','Дек'],
+               dayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'],
+               dayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'],
+               dayNamesMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'],
+               weekHeader: 'Нед',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['ru']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sk.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sk.js
new file mode 100644 (file)
index 0000000..078d1b0
--- /dev/null
@@ -0,0 +1,23 @@
+/* Slovak initialisation for the jQuery UI date picker plugin. */
+/* Written by Vojtech Rinik (vojto@hmm.sk). */
+jQuery(function($){
+       $.datepicker.regional['sk'] = {
+               closeText: 'Zavrieť',
+               prevText: '&#x3c;Predchádzajúci',
+               nextText: 'Nasledujúci&#x3e;',
+               currentText: 'Dnes',
+               monthNames: ['Január','Február','Marec','Apríl','Máj','Jún',
+               'Júl','August','September','Október','November','December'],
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Máj','Jún',
+               'Júl','Aug','Sep','Okt','Nov','Dec'],
+               dayNames: ['Nedeľa','Pondelok','Utorok','Streda','Štvrtok','Piatok','Sobota'],
+               dayNamesShort: ['Ned','Pon','Uto','Str','Štv','Pia','Sob'],
+               dayNamesMin: ['Ne','Po','Ut','St','Št','Pia','So'],
+               weekHeader: 'Ty',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['sk']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sl.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sl.js
new file mode 100644 (file)
index 0000000..5165501
--- /dev/null
@@ -0,0 +1,24 @@
+/* Slovenian initialisation for the jQuery UI date picker plugin. */
+/* Written by Jaka Jancar (jaka@kubje.org). */
+/* c = &#x10D;, s = &#x161; z = &#x17E; C = &#x10C; S = &#x160; Z = &#x17D; */
+jQuery(function($){
+       $.datepicker.regional['sl'] = {
+               closeText: 'Zapri',
+               prevText: '&lt;Prej&#x161;nji',
+               nextText: 'Naslednji&gt;',
+               currentText: 'Trenutni',
+               monthNames: ['Januar','Februar','Marec','April','Maj','Junij',
+               'Julij','Avgust','September','Oktober','November','December'],
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+               'Jul','Avg','Sep','Okt','Nov','Dec'],
+               dayNames: ['Nedelja','Ponedeljek','Torek','Sreda','&#x10C;etrtek','Petek','Sobota'],
+               dayNamesShort: ['Ned','Pon','Tor','Sre','&#x10C;et','Pet','Sob'],
+               dayNamesMin: ['Ne','Po','To','Sr','&#x10C;e','Pe','So'],
+               weekHeader: 'Teden',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['sl']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sq.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sq.js
new file mode 100644 (file)
index 0000000..21974c5
--- /dev/null
@@ -0,0 +1,23 @@
+/* Albanian initialisation for the jQuery UI date picker plugin. */
+/* Written by Flakron Bytyqi (flakron@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['sq'] = {
+               closeText: 'mbylle',
+               prevText: '&#x3c;mbrapa',
+               nextText: 'Përpara&#x3e;',
+               currentText: 'sot',
+               monthNames: ['Janar','Shkurt','Mars','Prill','Maj','Qershor',
+               'Korrik','Gusht','Shtator','Tetor','Nëntor','Dhjetor'],
+               monthNamesShort: ['Jan','Shk','Mar','Pri','Maj','Qer',
+               'Kor','Gus','Sht','Tet','Nën','Dhj'],
+               dayNames: ['E Diel','E Hënë','E Martë','E Mërkurë','E Enjte','E Premte','E Shtune'],
+               dayNamesShort: ['Di','Hë','Ma','Më','En','Pr','Sh'],
+               dayNamesMin: ['Di','Hë','Ma','Më','En','Pr','Sh'],
+               weekHeader: 'Ja',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['sq']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js
new file mode 100644 (file)
index 0000000..e7a8683
--- /dev/null
@@ -0,0 +1,23 @@
+/* Serbian i18n for the jQuery UI date picker plugin. */
+/* Written by Dejan Dimić. */
+jQuery(function($){
+       $.datepicker.regional['sr-SR'] = {
+               closeText: 'Zatvori',
+               prevText: '&#x3c;',
+               nextText: '&#x3e;',
+               currentText: 'Danas',
+               monthNames: ['Januar','Februar','Mart','April','Maj','Jun',
+               'Jul','Avgust','Septembar','Oktobar','Novembar','Decembar'],
+               monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+               'Jul','Avg','Sep','Okt','Nov','Dec'],
+               dayNames: ['Nedelja','Ponedeljak','Utorak','Sreda','Četvrtak','Petak','Subota'],
+               dayNamesShort: ['Ned','Pon','Uto','Sre','Čet','Pet','Sub'],
+               dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
+               weekHeader: 'Sed',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['sr-SR']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr.js
new file mode 100644 (file)
index 0000000..0bd240e
--- /dev/null
@@ -0,0 +1,23 @@
+/* Serbian i18n for the jQuery UI date picker plugin. */
+/* Written by Dejan Dimić. */
+jQuery(function($){
+       $.datepicker.regional['sr'] = {
+               closeText: 'Затвори',
+               prevText: '&#x3c;',
+               nextText: '&#x3e;',
+               currentText: 'Данас',
+               monthNames: ['Јануар','Фебруар','Март','Април','Мај','Јун',
+               'Јул','Август','Септембар','Октобар','Новембар','Децембар'],
+               monthNamesShort: ['Јан','Феб','Мар','Апр','Мај','Јун',
+               'Јул','Авг','Сеп','Окт','Нов','Дец'],
+               dayNames: ['Недеља','Понедељак','Уторак','Среда','Четвртак','Петак','Субота'],
+               dayNamesShort: ['Нед','Пон','Уто','Сре','Чет','Пет','Суб'],
+               dayNamesMin: ['Не','По','Ут','Ср','Че','Пе','Су'],
+               weekHeader: 'Сед',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['sr']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sv.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sv.js
new file mode 100644 (file)
index 0000000..e5f549f
--- /dev/null
@@ -0,0 +1,23 @@
+/* Swedish initialisation for the jQuery UI date picker plugin. */
+/* Written by Anders Ekdahl ( anders@nomadiz.se). */
+jQuery(function($){
+    $.datepicker.regional['sv'] = {
+               closeText: 'Stäng',
+        prevText: '&laquo;Förra',
+               nextText: 'Nästa&raquo;',
+               currentText: 'Idag',
+        monthNames: ['Januari','Februari','Mars','April','Maj','Juni',
+        'Juli','Augusti','September','Oktober','November','December'],
+        monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+        'Jul','Aug','Sep','Okt','Nov','Dec'],
+               dayNamesShort: ['Sön','Mån','Tis','Ons','Tor','Fre','Lör'],
+               dayNames: ['Söndag','Måndag','Tisdag','Onsdag','Torsdag','Fredag','Lördag'],
+               dayNamesMin: ['Sö','Må','Ti','On','To','Fr','Lö'],
+               weekHeader: 'Ve',
+        dateFormat: 'yy-mm-dd',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+    $.datepicker.setDefaults($.datepicker.regional['sv']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ta.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ta.js
new file mode 100644 (file)
index 0000000..40431ed
--- /dev/null
@@ -0,0 +1,23 @@
+/* Tamil (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by S A Sureshkumar (saskumar@live.com). */
+jQuery(function($){
+       $.datepicker.regional['ta'] = {
+               closeText: 'மூடு',
+               prevText: 'முன்னையது',
+               nextText: 'அடுத்தது',
+               currentText: 'இன்று',
+               monthNames: ['தை','மாசி','பங்குனி','சித்திரை','வைகாசி','ஆனி',
+               'ஆடி','ஆவணி','புரட்டாசி','ஐப்பசி','கார்த்திகை','மார்கழி'],
+               monthNamesShort: ['தை','மாசி','பங்','சித்','வைகா','ஆனி',
+               'ஆடி','ஆவ','புர','ஐப்','கார்','மார்'],
+               dayNames: ['ஞாயிற்றுக்கிழமை','திங்கட்கிழமை','செவ்வாய்க்கிழமை','புதன்கிழமை','வியாழக்கிழமை','வெள்ளிக்கிழமை','சனிக்கிழமை'],
+               dayNamesShort: ['ஞாயிறு','திங்கள்','செவ்வாய்','புதன்','வியாழன்','வெள்ளி','சனி'],
+               dayNamesMin: ['ஞா','தி','செ','பு','வி','வெ','ச'],
+               weekHeader: 'Не',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['ta']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-th.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-th.js
new file mode 100644 (file)
index 0000000..2e5300c
--- /dev/null
@@ -0,0 +1,23 @@
+/* Thai initialisation for the jQuery UI date picker plugin. */
+/* Written by pipo (pipo@sixhead.com). */
+jQuery(function($){
+       $.datepicker.regional['th'] = {
+               closeText: 'ปิด',
+               prevText: '&laquo;&nbsp;ย้อน',
+               nextText: 'ถัดไป&nbsp;&raquo;',
+               currentText: 'วันนี้',
+               monthNames: ['มกราคม','กุมภาพันธ์','มีนาคม','เมษายน','พฤษภาคม','มิถุนายน',
+               'กรกฎาคม','สิงหาคม','กันยายน','ตุลาคม','พฤศจิกายน','ธันวาคม'],
+               monthNamesShort: ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.',
+               'ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'],
+               dayNames: ['อาทิตย์','จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์','เสาร์'],
+               dayNamesShort: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],
+               dayNamesMin: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],
+               weekHeader: 'Wk',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['th']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tr.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tr.js
new file mode 100644 (file)
index 0000000..dedfc7f
--- /dev/null
@@ -0,0 +1,23 @@
+/* Turkish initialisation for the jQuery UI date picker plugin. */
+/* Written by Izzet Emre Erkan (kara@karalamalar.net). */
+jQuery(function($){
+       $.datepicker.regional['tr'] = {
+               closeText: 'kapat',
+               prevText: '&#x3c;geri',
+               nextText: 'ileri&#x3e',
+               currentText: 'bugün',
+               monthNames: ['Ocak','Şubat','Mart','Nisan','Mayıs','Haziran',
+               'Temmuz','Ağustos','Eylül','Ekim','Kasım','Aralık'],
+               monthNamesShort: ['Oca','Şub','Mar','Nis','May','Haz',
+               'Tem','Ağu','Eyl','Eki','Kas','Ara'],
+               dayNames: ['Pazar','Pazartesi','Salı','Çarşamba','Perşembe','Cuma','Cumartesi'],
+               dayNamesShort: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],
+               dayNamesMin: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],
+               weekHeader: 'Hf',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['tr']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-uk.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-uk.js
new file mode 100644 (file)
index 0000000..2718f5d
--- /dev/null
@@ -0,0 +1,24 @@
+/* Ukrainian (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Maxim Drogobitskiy (maxdao@gmail.com). */
+/* Corrected by Igor Milla (igor.fsp.milla@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['uk'] = {
+               closeText: 'Закрити',
+               prevText: '&#x3c;',
+               nextText: '&#x3e;',
+               currentText: 'Сьогодні',
+               monthNames: ['Січень','Лютий','Березень','Квітень','Травень','Червень',
+               'Липень','Серпень','Вересень','Жовтень','Листопад','Грудень'],
+               monthNamesShort: ['Січ','Лют','Бер','Кві','Тра','Чер',
+               'Лип','Сер','Вер','Жов','Лис','Гру'],
+               dayNames: ['неділя','понеділок','вівторок','середа','четвер','п’ятниця','субота'],
+               dayNamesShort: ['нед','пнд','вів','срд','чтв','птн','сбт'],
+               dayNamesMin: ['Нд','Пн','Вт','Ср','Чт','Пт','Сб'],
+               weekHeader: 'Тиж',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['uk']);
+});
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-vi.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-vi.js
new file mode 100644 (file)
index 0000000..1d8f7bb
--- /dev/null
@@ -0,0 +1,23 @@
+/* Vietnamese initialisation for the jQuery UI date picker plugin. */
+/* Translated by Le Thanh Huy (lthanhhuy@cit.ctu.edu.vn). */
+jQuery(function($){
+       $.datepicker.regional['vi'] = {
+               closeText: 'Đóng',
+               prevText: '&#x3c;Trước',
+               nextText: 'Tiếp&#x3e;',
+               currentText: 'Hôm nay',
+               monthNames: ['Tháng Một', 'Tháng Hai', 'Tháng Ba', 'Tháng Tư', 'Tháng Năm', 'Tháng Sáu',
+               'Tháng Bảy', 'Tháng Tám', 'Tháng Chín', 'Tháng Mười', 'Tháng Mười Một', 'Tháng Mười Hai'],
+               monthNamesShort: ['Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5', 'Tháng 6',
+               'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11', 'Tháng 12'],
+               dayNames: ['Chủ Nhật', 'Thứ Hai', 'Thứ Ba', 'Thứ Tư', 'Thứ Năm', 'Thứ Sáu', 'Thứ Bảy'],
+               dayNamesShort: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
+               dayNamesMin: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
+               weekHeader: 'Tu',
+               dateFormat: 'dd/mm/yy',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['vi']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js
new file mode 100644 (file)
index 0000000..83f2825
--- /dev/null
@@ -0,0 +1,23 @@
+/* Chinese initialisation for the jQuery UI date picker plugin. */
+/* Written by Cloudream (cloudream@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['zh-CN'] = {
+               closeText: '关闭',
+               prevText: '&#x3c;上月',
+               nextText: '下月&#x3e;',
+               currentText: '今天',
+               monthNames: ['一月','二月','三月','四月','五月','六月',
+               '七月','八月','九月','十月','十一月','十二月'],
+               monthNamesShort: ['一月','二月','三月','四月','五月','六月',
+               '七月','八月','九月','十月','十一月','十二月'],
+               dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
+               dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
+               dayNamesMin: ['日','一','二','三','四','五','六'],
+               weekHeader: '周',
+               dateFormat: 'yy-mm-dd',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: true,
+               yearSuffix: '年'};
+       $.datepicker.setDefaults($.datepicker.regional['zh-CN']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js
new file mode 100644 (file)
index 0000000..11189d3
--- /dev/null
@@ -0,0 +1,23 @@
+/* Chinese initialisation for the jQuery UI date picker plugin. */
+/* Written by SCCY (samuelcychan@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['zh-HK'] = {
+               closeText: '關閉',
+               prevText: '&#x3c;上月',
+               nextText: '下月&#x3e;',
+               currentText: '今天',
+               monthNames: ['一月','二月','三月','四月','五月','六月',
+               '七月','八月','九月','十月','十一月','十二月'],
+               monthNamesShort: ['一月','二月','三月','四月','五月','六月',
+               '七月','八月','九月','十月','十一月','十二月'],
+               dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
+               dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
+               dayNamesMin: ['日','一','二','三','四','五','六'],
+               weekHeader: '周',
+               dateFormat: 'dd-mm-yy',
+               firstDay: 0,
+               isRTL: false,
+               showMonthAfterYear: true,
+               yearSuffix: '年'};
+       $.datepicker.setDefaults($.datepicker.regional['zh-HK']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js
new file mode 100644 (file)
index 0000000..089498b
--- /dev/null
@@ -0,0 +1,23 @@
+/* Chinese initialisation for the jQuery UI date picker plugin. */
+/* Written by Ressol (ressol@gmail.com). */
+jQuery(function($){
+       $.datepicker.regional['zh-TW'] = {
+               closeText: '關閉',
+               prevText: '&#x3c;上月',
+               nextText: '下月&#x3e;',
+               currentText: '今天',
+               monthNames: ['一月','二月','三月','四月','五月','六月',
+               '七月','八月','九月','十月','十一月','十二月'],
+               monthNamesShort: ['一月','二月','三月','四月','五月','六月',
+               '七月','八月','九月','十月','十一月','十二月'],
+               dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
+               dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
+               dayNamesMin: ['日','一','二','三','四','五','六'],
+               weekHeader: '周',
+               dateFormat: 'yy/mm/dd',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: true,
+               yearSuffix: '年'};
+       $.datepicker.setDefaults($.datepicker.regional['zh-TW']);
+});
diff --git a/resources/lib/jquery.ui/jquery.ui.accordion.js b/resources/lib/jquery.ui/jquery.ui.accordion.js
new file mode 100644 (file)
index 0000000..dc1ba60
--- /dev/null
@@ -0,0 +1,611 @@
+/*!
+ * jQuery UI Accordion 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *     jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget( "ui.accordion", {
+       options: {
+               active: 0,
+               animated: "slide",
+               autoHeight: true,
+               clearStyle: false,
+               collapsible: false,
+               event: "click",
+               fillSpace: false,
+               header: "> li > :first-child,> :not(li):even",
+               icons: {
+                       header: "ui-icon-triangle-1-e",
+                       headerSelected: "ui-icon-triangle-1-s"
+               },
+               navigation: false,
+               navigationFilter: function() {
+                       return this.href.toLowerCase() === location.href.toLowerCase();
+               }
+       },
+
+       _create: function() {
+               var self = this,
+                       options = self.options;
+
+               self.running = 0;
+
+               self.element
+                       .addClass( "ui-accordion ui-widget ui-helper-reset" )
+                       // in lack of child-selectors in CSS
+                       // we need to mark top-LIs in a UL-accordion for some IE-fix
+                       .children( "li" )
+                               .addClass( "ui-accordion-li-fix" );
+
+               self.headers = self.element.find( options.header )
+                       .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
+                       .bind( "mouseenter.accordion", function() {
+                               if ( options.disabled ) {
+                                       return;
+                               }
+                               $( this ).addClass( "ui-state-hover" );
+                       })
+                       .bind( "mouseleave.accordion", function() {
+                               if ( options.disabled ) {
+                                       return;
+                               }
+                               $( this ).removeClass( "ui-state-hover" );
+                       })
+                       .bind( "focus.accordion", function() {
+                               if ( options.disabled ) {
+                                       return;
+                               }
+                               $( this ).addClass( "ui-state-focus" );
+                       })
+                       .bind( "blur.accordion", function() {
+                               if ( options.disabled ) {
+                                       return;
+                               }
+                               $( this ).removeClass( "ui-state-focus" );
+                       });
+
+               self.headers.next()
+                       .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
+
+               if ( options.navigation ) {
+                       var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
+                       if ( current.length ) {
+                               var header = current.closest( ".ui-accordion-header" );
+                               if ( header.length ) {
+                                       // anchor within header
+                                       self.active = header;
+                               } else {
+                                       // anchor within content
+                                       self.active = current.closest( ".ui-accordion-content" ).prev();
+                               }
+                       }
+               }
+
+               self.active = self._findActive( self.active || options.active )
+                       .addClass( "ui-state-default ui-state-active" )
+                       .toggleClass( "ui-corner-all" )
+                       .toggleClass( "ui-corner-top" );
+               self.active.next().addClass( "ui-accordion-content-active" );
+
+               self._createIcons();
+               self.resize();
+               
+               // ARIA
+               self.element.attr( "role", "tablist" );
+
+               self.headers
+                       .attr( "role", "tab" )
+                       .bind( "keydown.accordion", function( event ) {
+                               return self._keydown( event );
+                       })
+                       .next()
+                               .attr( "role", "tabpanel" );
+
+               self.headers
+                       .not( self.active || "" )
+                       .attr({
+                               "aria-expanded": "false",
+                               "aria-selected": "false",
+                               tabIndex: -1
+                       })
+                       .next()
+                               .hide();
+
+               // make sure at least one header is in the tab order
+               if ( !self.active.length ) {
+                       self.headers.eq( 0 ).attr( "tabIndex", 0 );
+               } else {
+                       self.active
+                               .attr({
+                                       "aria-expanded": "true",
+                                       "aria-selected": "true",
+                                       tabIndex: 0
+                               });
+               }
+
+               // only need links in tab order for Safari
+               if ( !$.browser.safari ) {
+                       self.headers.find( "a" ).attr( "tabIndex", -1 );
+               }
+
+               if ( options.event ) {
+                       self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
+                               self._clickHandler.call( self, event, this );
+                               event.preventDefault();
+                       });
+               }
+       },
+
+       _createIcons: function() {
+               var options = this.options;
+               if ( options.icons ) {
+                       $( "<span></span>" )
+                               .addClass( "ui-icon " + options.icons.header )
+                               .prependTo( this.headers );
+                       this.active.children( ".ui-icon" )
+                               .toggleClass(options.icons.header)
+                               .toggleClass(options.icons.headerSelected);
+                       this.element.addClass( "ui-accordion-icons" );
+               }
+       },
+
+       _destroyIcons: function() {
+               this.headers.children( ".ui-icon" ).remove();
+               this.element.removeClass( "ui-accordion-icons" );
+       },
+
+       destroy: function() {
+               var options = this.options;
+
+               this.element
+                       .removeClass( "ui-accordion ui-widget ui-helper-reset" )
+                       .removeAttr( "role" );
+
+               this.headers
+                       .unbind( ".accordion" )
+                       .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
+                       .removeAttr( "role" )
+                       .removeAttr( "aria-expanded" )
+                       .removeAttr( "aria-selected" )
+                       .removeAttr( "tabIndex" );
+
+               this.headers.find( "a" ).removeAttr( "tabIndex" );
+               this._destroyIcons();
+               var contents = this.headers.next()
+                       .css( "display", "" )
+                       .removeAttr( "role" )
+                       .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
+               if ( options.autoHeight || options.fillHeight ) {
+                       contents.css( "height", "" );
+               }
+
+               return $.Widget.prototype.destroy.call( this );
+       },
+
+       _setOption: function( key, value ) {
+               $.Widget.prototype._setOption.apply( this, arguments );
+                       
+               if ( key == "active" ) {
+                       this.activate( value );
+               }
+               if ( key == "icons" ) {
+                       this._destroyIcons();
+                       if ( value ) {
+                               this._createIcons();
+                       }
+               }
+               // #5332 - opacity doesn't cascade to positioned elements in IE
+               // so we need to add the disabled class to the headers and panels
+               if ( key == "disabled" ) {
+                       this.headers.add(this.headers.next())
+                               [ value ? "addClass" : "removeClass" ](
+                                       "ui-accordion-disabled ui-state-disabled" );
+               }
+       },
+
+       _keydown: function( event ) {
+               if ( this.options.disabled || event.altKey || event.ctrlKey ) {
+                       return;
+               }
+
+               var keyCode = $.ui.keyCode,
+                       length = this.headers.length,
+                       currentIndex = this.headers.index( event.target ),
+                       toFocus = false;
+
+               switch ( event.keyCode ) {
+                       case keyCode.RIGHT:
+                       case keyCode.DOWN:
+                               toFocus = this.headers[ ( currentIndex + 1 ) % length ];
+                               break;
+                       case keyCode.LEFT:
+                       case keyCode.UP:
+                               toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
+                               break;
+                       case keyCode.SPACE:
+                       case keyCode.ENTER:
+                               this._clickHandler( { target: event.target }, event.target );
+                               event.preventDefault();
+               }
+
+               if ( toFocus ) {
+                       $( event.target ).attr( "tabIndex", -1 );
+                       $( toFocus ).attr( "tabIndex", 0 );
+                       toFocus.focus();
+                       return false;
+               }
+
+               return true;
+       },
+
+       resize: function() {
+               var options = this.options,
+                       maxHeight;
+
+               if ( options.fillSpace ) {
+                       if ( $.browser.msie ) {
+                               var defOverflow = this.element.parent().css( "overflow" );
+                               this.element.parent().css( "overflow", "hidden");
+                       }
+                       maxHeight = this.element.parent().height();
+                       if ($.browser.msie) {
+                               this.element.parent().css( "overflow", defOverflow );
+                       }
+
+                       this.headers.each(function() {
+                               maxHeight -= $( this ).outerHeight( true );
+                       });
+
+                       this.headers.next()
+                               .each(function() {
+                                       $( this ).height( Math.max( 0, maxHeight -
+                                               $( this ).innerHeight() + $( this ).height() ) );
+                               })
+                               .css( "overflow", "auto" );
+               } else if ( options.autoHeight ) {
+                       maxHeight = 0;
+                       this.headers.next()
+                               .each(function() {
+                                       maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
+                               })
+                               .height( maxHeight );
+               }
+
+               return this;
+       },
+
+       activate: function( index ) {
+               // TODO this gets called on init, changing the option without an explicit call for that
+               this.options.active = index;
+               // call clickHandler with custom event
+               var active = this._findActive( index )[ 0 ];
+               this._clickHandler( { target: active }, active );
+
+               return this;
+       },
+
+       _findActive: function( selector ) {
+               return selector
+                       ? typeof selector === "number"
+                               ? this.headers.filter( ":eq(" + selector + ")" )
+                               : this.headers.not( this.headers.not( selector ) )
+                       : selector === false
+                               ? $( [] )
+                               : this.headers.filter( ":eq(0)" );
+       },
+
+       // TODO isn't event.target enough? why the separate target argument?
+       _clickHandler: function( event, target ) {
+               var options = this.options;
+               if ( options.disabled ) {
+                       return;
+               }
+
+               // called only when using activate(false) to close all parts programmatically
+               if ( !event.target ) {
+                       if ( !options.collapsible ) {
+                               return;
+                       }
+                       this.active
+                               .removeClass( "ui-state-active ui-corner-top" )
+                               .addClass( "ui-state-default ui-corner-all" )
+                               .children( ".ui-icon" )
+                                       .removeClass( options.icons.headerSelected )
+                                       .addClass( options.icons.header );
+                       this.active.next().addClass( "ui-accordion-content-active" );
+                       var toHide = this.active.next(),
+                               data = {
+                                       options: options,
+                                       newHeader: $( [] ),
+                                       oldHeader: options.active,
+                                       newContent: $( [] ),
+                                       oldContent: toHide
+                               },
+                               toShow = ( this.active = $( [] ) );
+                       this._toggle( toShow, toHide, data );
+                       return;
+               }
+
+               // get the click target
+               var clicked = $( event.currentTarget || target ),
+                       clickedIsActive = clicked[0] === this.active[0];
+
+               // TODO the option is changed, is that correct?
+               // TODO if it is correct, shouldn't that happen after determining that the click is valid?
+               options.active = options.collapsible && clickedIsActive ?
+                       false :
+                       this.headers.index( clicked );
+
+               // if animations are still active, or the active header is the target, ignore click
+               if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
+                       return;
+               }
+
+               // find elements to show and hide
+               var active = this.active,
+                       toShow = clicked.next(),
+                       toHide = this.active.next(),
+                       data = {
+                               options: options,
+                               newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
+                               oldHeader: this.active,
+                               newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
+                               oldContent: toHide
+                       },
+                       down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
+
+               // when the call to ._toggle() comes after the class changes
+               // it causes a very odd bug in IE 8 (see #6720)
+               this.active = clickedIsActive ? $([]) : clicked;
+               this._toggle( toShow, toHide, data, clickedIsActive, down );
+
+               // switch classes
+               active
+                       .removeClass( "ui-state-active ui-corner-top" )
+                       .addClass( "ui-state-default ui-corner-all" )
+                       .children( ".ui-icon" )
+                               .removeClass( options.icons.headerSelected )
+                               .addClass( options.icons.header );
+               if ( !clickedIsActive ) {
+                       clicked
+                               .removeClass( "ui-state-default ui-corner-all" )
+                               .addClass( "ui-state-active ui-corner-top" )
+                               .children( ".ui-icon" )
+                                       .removeClass( options.icons.header )
+                                       .addClass( options.icons.headerSelected );
+                       clicked
+                               .next()
+                               .addClass( "ui-accordion-content-active" );
+               }
+
+               return;
+       },
+
+       _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
+               var self = this,
+                       options = self.options;
+
+               self.toShow = toShow;
+               self.toHide = toHide;
+               self.data = data;
+
+               var complete = function() {
+                       if ( !self ) {
+                               return;
+                       }
+                       return self._completed.apply( self, arguments );
+               };
+
+               // trigger changestart event
+               self._trigger( "changestart", null, self.data );
+
+               // count elements to animate
+               self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
+
+               if ( options.animated ) {
+                       var animOptions = {};
+
+                       if ( options.collapsible && clickedIsActive ) {
+                               animOptions = {
+                                       toShow: $( [] ),
+                                       toHide: toHide,
+                                       complete: complete,
+                                       down: down,
+                                       autoHeight: options.autoHeight || options.fillSpace
+                               };
+                       } else {
+                               animOptions = {
+                                       toShow: toShow,
+                                       toHide: toHide,
+                                       complete: complete,
+                                       down: down,
+                                       autoHeight: options.autoHeight || options.fillSpace
+                               };
+                       }
+
+                       if ( !options.proxied ) {
+                               options.proxied = options.animated;
+                       }
+
+                       if ( !options.proxiedDuration ) {
+                               options.proxiedDuration = options.duration;
+                       }
+
+                       options.animated = $.isFunction( options.proxied ) ?
+                               options.proxied( animOptions ) :
+                               options.proxied;
+
+                       options.duration = $.isFunction( options.proxiedDuration ) ?
+                               options.proxiedDuration( animOptions ) :
+                               options.proxiedDuration;
+
+                       var animations = $.ui.accordion.animations,
+                               duration = options.duration,
+                               easing = options.animated;
+
+                       if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
+                               easing = "slide";
+                       }
+                       if ( !animations[ easing ] ) {
+                               animations[ easing ] = function( options ) {
+                                       this.slide( options, {
+                                               easing: easing,
+                                               duration: duration || 700
+                                       });
+                               };
+                       }
+
+                       animations[ easing ]( animOptions );
+               } else {
+                       if ( options.collapsible && clickedIsActive ) {
+                               toShow.toggle();
+                       } else {
+                               toHide.hide();
+                               toShow.show();
+                       }
+
+                       complete( true );
+               }
+
+               // TODO assert that the blur and focus triggers are really necessary, remove otherwise
+               toHide.prev()
+                       .attr({
+                               "aria-expanded": "false",
+                               "aria-selected": "false",
+                               tabIndex: -1
+                       })
+                       .blur();
+               toShow.prev()
+                       .attr({
+                               "aria-expanded": "true",
+                               "aria-selected": "true",
+                               tabIndex: 0
+                       })
+                       .focus();
+       },
+
+       _completed: function( cancel ) {
+               this.running = cancel ? 0 : --this.running;
+               if ( this.running ) {
+                       return;
+               }
+
+               if ( this.options.clearStyle ) {
+                       this.toShow.add( this.toHide ).css({
+                               height: "",
+                               overflow: ""
+                       });
+               }
+
+               // other classes are removed before the animation; this one needs to stay until completed
+               this.toHide.removeClass( "ui-accordion-content-active" );
+               // Work around for rendering bug in IE (#5421)
+               if ( this.toHide.length ) {
+                       this.toHide.parent()[0].className = this.toHide.parent()[0].className;
+               }
+
+               this._trigger( "change", null, this.data );
+       }
+});
+
+$.extend( $.ui.accordion, {
+       version: "1.8.24",
+       animations: {
+               slide: function( options, additions ) {
+                       options = $.extend({
+                               easing: "swing",
+                               duration: 300
+                       }, options, additions );
+                       if ( !options.toHide.size() ) {
+                               options.toShow.animate({
+                                       height: "show",
+                                       paddingTop: "show",
+                                       paddingBottom: "show"
+                               }, options );
+                               return;
+                       }
+                       if ( !options.toShow.size() ) {
+                               options.toHide.animate({
+                                       height: "hide",
+                                       paddingTop: "hide",
+                                       paddingBottom: "hide"
+                               }, options );
+                               return;
+                       }
+                       var overflow = options.toShow.css( "overflow" ),
+                               percentDone = 0,
+                               showProps = {},
+                               hideProps = {},
+                               fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
+                               originalWidth;
+                       // fix width before calculating height of hidden element
+                       var s = options.toShow;
+                       originalWidth = s[0].style.width;
+                       s.width( s.parent().width()
+                               - parseFloat( s.css( "paddingLeft" ) )
+                               - parseFloat( s.css( "paddingRight" ) )
+                               - ( parseFloat( s.css( "borderLeftWidth" ) ) || 0 )
+                               - ( parseFloat( s.css( "borderRightWidth" ) ) || 0 ) );
+
+                       $.each( fxAttrs, function( i, prop ) {
+                               hideProps[ prop ] = "hide";
+
+                               var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
+                               showProps[ prop ] = {
+                                       value: parts[ 1 ],
+                                       unit: parts[ 2 ] || "px"
+                               };
+                       });
+                       options.toShow.css({ height: 0, overflow: "hidden" }).show();
+                       options.toHide
+                               .filter( ":hidden" )
+                                       .each( options.complete )
+                               .end()
+                               .filter( ":visible" )
+                               .animate( hideProps, {
+                               step: function( now, settings ) {
+                                       // only calculate the percent when animating height
+                                       // IE gets very inconsistent results when animating elements
+                                       // with small values, which is common for padding
+                                       if ( settings.prop == "height" ) {
+                                               percentDone = ( settings.end - settings.start === 0 ) ? 0 :
+                                                       ( settings.now - settings.start ) / ( settings.end - settings.start );
+                                       }
+
+                                       options.toShow[ 0 ].style[ settings.prop ] =
+                                               ( percentDone * showProps[ settings.prop ].value )
+                                               + showProps[ settings.prop ].unit;
+                               },
+                               duration: options.duration,
+                               easing: options.easing,
+                               complete: function() {
+                                       if ( !options.autoHeight ) {
+                                               options.toShow.css( "height", "" );
+                                       }
+                                       options.toShow.css({
+                                               width: originalWidth,
+                                               overflow: overflow
+                                       });
+                                       options.complete();
+                               }
+                       });
+               },
+               bounceslide: function( options ) {
+                       this.slide( options, {
+                               easing: options.down ? "easeOutBounce" : "swing",
+                               duration: options.down ? 1000 : 200
+                       });
+               }
+       }
+});
+
+})( jQuery );
diff --git a/resources/lib/jquery.ui/jquery.ui.autocomplete.js b/resources/lib/jquery.ui/jquery.ui.autocomplete.js
new file mode 100644 (file)
index 0000000..8d69be2
--- /dev/null
@@ -0,0 +1,631 @@
+/*!
+ * jQuery UI Autocomplete 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *     jquery.ui.widget.js
+ *     jquery.ui.position.js
+ */
+(function( $, undefined ) {
+
+// used to prevent race conditions with remote data sources
+var requestIndex = 0;
+
+$.widget( "ui.autocomplete", {
+       options: {
+               appendTo: "body",
+               autoFocus: false,
+               delay: 300,
+               minLength: 1,
+               position: {
+                       my: "left top",
+                       at: "left bottom",
+                       collision: "none"
+               },
+               source: null
+       },
+
+       pending: 0,
+
+       _create: function() {
+               var self = this,
+                       doc = this.element[ 0 ].ownerDocument,
+                       suppressKeyPress;
+               this.isMultiLine = this.element.is( "textarea" );
+
+               this.element
+                       .addClass( "ui-autocomplete-input" )
+                       .attr( "autocomplete", "off" )
+                       // TODO verify these actually work as intended
+                       .attr({
+                               role: "textbox",
+                               "aria-autocomplete": "list",
+                               "aria-haspopup": "true"
+                       })
+                       .bind( "keydown.autocomplete", function( event ) {
+                               if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) {
+                                       return;
+                               }
+
+                               suppressKeyPress = false;
+                               var keyCode = $.ui.keyCode;
+                               switch( event.keyCode ) {
+                               case keyCode.PAGE_UP:
+                                       self._move( "previousPage", event );
+                                       break;
+                               case keyCode.PAGE_DOWN:
+                                       self._move( "nextPage", event );
+                                       break;
+                               case keyCode.UP:
+                                       self._keyEvent( "previous", event );
+                                       break;
+                               case keyCode.DOWN:
+                                       self._keyEvent( "next", event );
+                                       break;
+                               case keyCode.ENTER:
+                               case keyCode.NUMPAD_ENTER:
+                                       // when menu is open and has focus
+                                       if ( self.menu.active ) {
+                                               // #6055 - Opera still allows the keypress to occur
+                                               // which causes forms to submit
+                                               suppressKeyPress = true;
+                                               event.preventDefault();
+                                       }
+                                       //passthrough - ENTER and TAB both select the current element
+                               case keyCode.TAB:
+                                       if ( !self.menu.active ) {
+                                               return;
+                                       }
+                                       self.menu.select( event );
+                                       break;
+                               case keyCode.ESCAPE:
+                                       self.element.val( self.term );
+                                       self.close( event );
+                                       break;
+                               default:
+                                       // keypress is triggered before the input value is changed
+                                       clearTimeout( self.searching );
+                                       self.searching = setTimeout(function() {
+                                               // only search if the value has changed
+                                               if ( self.term != self.element.val() ) {
+                                                       self.selectedItem = null;
+                                                       self.search( null, event );
+                                               }
+                                       }, self.options.delay );
+                                       break;
+                               }
+                       })
+                       .bind( "keypress.autocomplete", function( event ) {
+                               if ( suppressKeyPress ) {
+                                       suppressKeyPress = false;
+                                       event.preventDefault();
+                               }
+                       })
+                       .bind( "focus.autocomplete", function() {
+                               if ( self.options.disabled ) {
+                                       return;
+                               }
+
+                               self.selectedItem = null;
+                               self.previous = self.element.val();
+                       })
+                       .bind( "blur.autocomplete", function( event ) {
+                               if ( self.options.disabled ) {
+                                       return;
+                               }
+
+                               clearTimeout( self.searching );
+                               // clicks on the menu (or a button to trigger a search) will cause a blur event
+                               self.closing = setTimeout(function() {
+                                       self.close( event );
+                                       self._change( event );
+                               }, 150 );
+                       });
+               this._initSource();
+               this.menu = $( "<ul></ul>" )
+                       .addClass( "ui-autocomplete" )
+                       .appendTo( $( this.options.appendTo || "body", doc )[0] )
+                       // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
+                       .mousedown(function( event ) {
+                               // clicking on the scrollbar causes focus to shift to the body
+                               // but we can't detect a mouseup or a click immediately afterward
+                               // so we have to track the next mousedown and close the menu if
+                               // the user clicks somewhere outside of the autocomplete
+                               var menuElement = self.menu.element[ 0 ];
+                               if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
+                                       setTimeout(function() {
+                                               $( document ).one( 'mousedown', function( event ) {
+                                                       if ( event.target !== self.element[ 0 ] &&
+                                                               event.target !== menuElement &&
+                                                               !$.ui.contains( menuElement, event.target ) ) {
+                                                               self.close();
+                                                       }
+                                               });
+                                       }, 1 );
+                               }
+
+                               // use another timeout to make sure the blur-event-handler on the input was already triggered
+                               setTimeout(function() {
+                                       clearTimeout( self.closing );
+                               }, 13);
+                       })
+                       .menu({
+                               focus: function( event, ui ) {
+                                       var item = ui.item.data( "item.autocomplete" );
+                                       if ( false !== self._trigger( "focus", event, { item: item } ) ) {
+                                               // use value to match what will end up in the input, if it was a key event
+                                               if ( /^key/.test(event.originalEvent.type) ) {
+                                                       self.element.val( item.value );
+                                               }
+                                       }
+                               },
+                               selected: function( event, ui ) {
+                                       var item = ui.item.data( "item.autocomplete" ),
+                                               previous = self.previous;
+
+                                       // only trigger when focus was lost (click on menu)
+                                       if ( self.element[0] !== doc.activeElement ) {
+                                               self.element.focus();
+                                               self.previous = previous;
+                                               // #6109 - IE triggers two focus events and the second
+                                               // is asynchronous, so we need to reset the previous
+                                               // term synchronously and asynchronously :-(
+                                               setTimeout(function() {
+                                                       self.previous = previous;
+                                                       self.selectedItem = item;
+                                               }, 1);
+                                       }
+
+                                       if ( false !== self._trigger( "select", event, { item: item } ) ) {
+                                               self.element.val( item.value );
+                                       }
+                                       // reset the term after the select event
+                                       // this allows custom select handling to work properly
+                                       self.term = self.element.val();
+
+                                       self.close( event );
+                                       self.selectedItem = item;
+                               },
+                               blur: function( event, ui ) {
+                                       // don't set the value of the text field if it's already correct
+                                       // this prevents moving the cursor unnecessarily
+                                       if ( self.menu.element.is(":visible") &&
+                                               ( self.element.val() !== self.term ) ) {
+                                               self.element.val( self.term );
+                                       }
+                               }
+                       })
+                       .zIndex( this.element.zIndex() + 1 )
+                       // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
+                       .css({ top: 0, left: 0 })
+                       .hide()
+                       .data( "menu" );
+               if ( $.fn.bgiframe ) {
+                        this.menu.element.bgiframe();
+               }
+               // turning off autocomplete prevents the browser from remembering the
+               // value when navigating through history, so we re-enable autocomplete
+               // if the page is unloaded before the widget is destroyed. #7790
+               self.beforeunloadHandler = function() {
+                       self.element.removeAttr( "autocomplete" );
+               };
+               $( window ).bind( "beforeunload", self.beforeunloadHandler );
+       },
+
+       destroy: function() {
+               this.element
+                       .removeClass( "ui-autocomplete-input" )
+                       .removeAttr( "autocomplete" )
+                       .removeAttr( "role" )
+                       .removeAttr( "aria-autocomplete" )
+                       .removeAttr( "aria-haspopup" );
+               this.menu.element.remove();
+               $( window ).unbind( "beforeunload", this.beforeunloadHandler );
+               $.Widget.prototype.destroy.call( this );
+       },
+
+       _setOption: function( key, value ) {
+               $.Widget.prototype._setOption.apply( this, arguments );
+               if ( key === "source" ) {
+                       this._initSource();
+               }
+               if ( key === "appendTo" ) {
+                       this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
+               }
+               if ( key === "disabled" && value && this.xhr ) {
+                       this.xhr.abort();
+               }
+       },
+
+       _initSource: function() {
+               var self = this,
+                       array,
+                       url;
+               if ( $.isArray(this.options.source) ) {
+                       array = this.options.source;
+                       this.source = function( request, response ) {
+                               response( $.ui.autocomplete.filter(array, request.term) );
+                       };
+               } else if ( typeof this.options.source === "string" ) {
+                       url = this.options.source;
+                       this.source = function( request, response ) {
+                               if ( self.xhr ) {
+                                       self.xhr.abort();
+                               }
+                               self.xhr = $.ajax({
+                                       url: url,
+                                       data: request,
+                                       dataType: "json",
+                                       success: function( data, status ) {
+                                               response( data );
+                                       },
+                                       error: function() {
+                                               response( [] );
+                                       }
+                               });
+                       };
+               } else {
+                       this.source = this.options.source;
+               }
+       },
+
+       search: function( value, event ) {
+               value = value != null ? value : this.element.val();
+
+               // always save the actual value, not the one passed as an argument
+               this.term = this.element.val();
+
+               if ( value.length < this.options.minLength ) {
+                       return this.close( event );
+               }
+
+               clearTimeout( this.closing );
+               if ( this._trigger( "search", event ) === false ) {
+                       return;
+               }
+
+               return this._search( value );
+       },
+
+       _search: function( value ) {
+               this.pending++;
+               this.element.addClass( "ui-autocomplete-loading" );
+
+               this.source( { term: value }, this._response() );
+       },
+
+       _response: function() {
+               var that = this,
+                       index = ++requestIndex;
+
+               return function( content ) {
+                       if ( index === requestIndex ) {
+                               that.__response( content );
+                       }
+
+                       that.pending--;
+                       if ( !that.pending ) {
+                               that.element.removeClass( "ui-autocomplete-loading" );
+                       }
+               };
+       },
+
+       __response: function( content ) {
+               if ( !this.options.disabled && content && content.length ) {
+                       content = this._normalize( content );
+                       this._suggest( content );
+                       this._trigger( "open" );
+               } else {
+                       this.close();
+               }
+       },
+
+       close: function( event ) {
+               clearTimeout( this.closing );
+               if ( this.menu.element.is(":visible") ) {
+                       this.menu.element.hide();
+                       this.menu.deactivate();
+                       this._trigger( "close", event );
+               }
+       },
+       
+       _change: function( event ) {
+               if ( this.previous !== this.element.val() ) {
+                       this._trigger( "change", event, { item: this.selectedItem } );
+               }
+       },
+
+       _normalize: function( items ) {
+               // assume all items have the right format when the first item is complete
+               if ( items.length && items[0].label && items[0].value ) {
+                       return items;
+               }
+               return $.map( items, function(item) {
+                       if ( typeof item === "string" ) {
+                               return {
+                                       label: item,
+                                       value: item
+                               };
+                       }
+                       return $.extend({
+                               label: item.label || item.value,
+                               value: item.value || item.label
+                       }, item );
+               });
+       },
+
+       _suggest: function( items ) {
+               var ul = this.menu.element
+                       .empty()
+                       .zIndex( this.element.zIndex() + 1 );
+               this._renderMenu( ul, items );
+               // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
+               this.menu.deactivate();
+               this.menu.refresh();
+
+               // size and position menu
+               ul.show();
+               this._resizeMenu();
+               ul.position( $.extend({
+                       of: this.element
+               }, this.options.position ));
+
+               if ( this.options.autoFocus ) {
+                       this.menu.next( new $.Event("mouseover") );
+               }
+       },
+
+       _resizeMenu: function() {
+               var ul = this.menu.element;
+               ul.outerWidth( Math.max(
+                       // Firefox wraps long text (possibly a rounding bug)
+                       // so we add 1px to avoid the wrapping (#7513)
+                       ul.width( "" ).outerWidth() + 1,
+                       this.element.outerWidth()
+               ) );
+       },
+
+       _renderMenu: function( ul, items ) {
+               var self = this;
+               $.each( items, function( index, item ) {
+                       self._renderItem( ul, item );
+               });
+       },
+
+       _renderItem: function( ul, item) {
+               return $( "<li></li>" )
+                       .data( "item.autocomplete", item )
+                       .append( $( "<a></a>" ).text( item.label ) )
+                       .appendTo( ul );
+       },
+
+       _move: function( direction, event ) {
+               if ( !this.menu.element.is(":visible") ) {
+                       this.search( null, event );
+                       return;
+               }
+               if ( this.menu.first() && /^previous/.test(direction) ||
+                               this.menu.last() && /^next/.test(direction) ) {
+                       this.element.val( this.term );
+                       this.menu.deactivate();
+                       return;
+               }
+               this.menu[ direction ]( event );
+       },
+
+       widget: function() {
+               return this.menu.element;
+       },
+       _keyEvent: function( keyEvent, event ) {
+               if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
+                       this._move( keyEvent, event );
+
+                       // prevents moving cursor to beginning/end of the text field in some browsers
+                       event.preventDefault();
+               }
+       }
+});
+
+$.extend( $.ui.autocomplete, {
+       escapeRegex: function( value ) {
+               return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
+       },
+       filter: function(array, term) {
+               var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
+               return $.grep( array, function(value) {
+                       return matcher.test( value.label || value.value || value );
+               });
+       }
+});
+
+}( jQuery ));
+
+/*
+ * jQuery UI Menu (not officially released)
+ * 
+ * This widget isn't yet finished and the API is subject to change. We plan to finish
+ * it for the next release. You're welcome to give it a try anyway and give us feedback,
+ * as long as you're okay with migrating your code later on. We can help with that, too.
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *  jquery.ui.widget.js
+ */
+(function($) {
+
+$.widget("ui.menu", {
+       _create: function() {
+               var self = this;
+               this.element
+                       .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
+                       .attr({
+                               role: "listbox",
+                               "aria-activedescendant": "ui-active-menuitem"
+                       })
+                       .click(function( event ) {
+                               if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
+                                       return;
+                               }
+                               // temporary
+                               event.preventDefault();
+                               self.select( event );
+                       });
+               this.refresh();
+       },
+       
+       refresh: function() {
+               var self = this;
+
+               // don't refresh list items that are already adapted
+               var items = this.element.children("li:not(.ui-menu-item):has(a)")
+                       .addClass("ui-menu-item")
+                       .attr("role", "menuitem");
+               
+               items.children("a")
+                       .addClass("ui-corner-all")
+                       .attr("tabindex", -1)
+                       // mouseenter doesn't work with event delegation
+                       .mouseenter(function( event ) {
+                               self.activate( event, $(this).parent() );
+                       })
+                       .mouseleave(function() {
+                               self.deactivate();
+                       });
+       },
+
+       activate: function( event, item ) {
+               this.deactivate();
+               if (this.hasScroll()) {
+                       var offset = item.offset().top - this.element.offset().top,
+                               scroll = this.element.scrollTop(),
+                               elementHeight = this.element.height();
+                       if (offset < 0) {
+                               this.element.scrollTop( scroll + offset);
+                       } else if (offset >= elementHeight) {
+                               this.element.scrollTop( scroll + offset - elementHeight + item.height());
+                       }
+               }
+               this.active = item.eq(0)
+                       .children("a")
+                               .addClass("ui-state-hover")
+                               .attr("id", "ui-active-menuitem")
+                       .end();
+               this._trigger("focus", event, { item: item });
+       },
+
+       deactivate: function() {
+               if (!this.active) { return; }
+
+               this.active.children("a")
+                       .removeClass("ui-state-hover")
+                       .removeAttr("id");
+               this._trigger("blur");
+               this.active = null;
+       },
+
+       next: function(event) {
+               this.move("next", ".ui-menu-item:first", event);
+       },
+
+       previous: function(event) {
+               this.move("prev", ".ui-menu-item:last", event);
+       },
+
+       first: function() {
+               return this.active && !this.active.prevAll(".ui-menu-item").length;
+       },
+
+       last: function() {
+               return this.active && !this.active.nextAll(".ui-menu-item").length;
+       },
+
+       move: function(direction, edge, event) {
+               if (!this.active) {
+                       this.activate(event, this.element.children(edge));
+                       return;
+               }
+               var next = this.active[direction + "All"](".ui-menu-item").eq(0);
+               if (next.length) {
+                       this.activate(event, next);
+               } else {
+                       this.activate(event, this.element.children(edge));
+               }
+       },
+
+       // TODO merge with previousPage
+       nextPage: function(event) {
+               if (this.hasScroll()) {
+                       // TODO merge with no-scroll-else
+                       if (!this.active || this.last()) {
+                               this.activate(event, this.element.children(".ui-menu-item:first"));
+                               return;
+                       }
+                       var base = this.active.offset().top,
+                               height = this.element.height(),
+                               result = this.element.children(".ui-menu-item").filter(function() {
+                                       var close = $(this).offset().top - base - height + $(this).height();
+                                       // TODO improve approximation
+                                       return close < 10 && close > -10;
+                               });
+
+                       // TODO try to catch this earlier when scrollTop indicates the last page anyway
+                       if (!result.length) {
+                               result = this.element.children(".ui-menu-item:last");
+                       }
+                       this.activate(event, result);
+               } else {
+                       this.activate(event, this.element.children(".ui-menu-item")
+                               .filter(!this.active || this.last() ? ":first" : ":last"));
+               }
+       },
+
+       // TODO merge with nextPage
+       previousPage: function(event) {
+               if (this.hasScroll()) {
+                       // TODO merge with no-scroll-else
+                       if (!this.active || this.first()) {
+                               this.activate(event, this.element.children(".ui-menu-item:last"));
+                               return;
+                       }
+
+                       var base = this.active.offset().top,
+                               height = this.element.height(),
+                               result = this.element.children(".ui-menu-item").filter(function() {
+                                       var close = $(this).offset().top - base + height - $(this).height();
+                                       // TODO improve approximation
+                                       return close < 10 && close > -10;
+                               });
+
+                       // TODO try to catch this earlier when scrollTop indicates the last page anyway
+                       if (!result.length) {
+                               result = this.element.children(".ui-menu-item:first");
+                       }
+                       this.activate(event, result);
+               } else {
+                       this.activate(event, this.element.children(".ui-menu-item")
+                               .filter(!this.active || this.first() ? ":last" : ":first"));
+               }
+       },
+
+       hasScroll: function() {
+               return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
+       },
+
+       select: function( event ) {
+               this._trigger("selected", event, { item: this.active });
+       }
+});
+
+}(jQuery));
diff --git a/resources/lib/jquery.ui/jquery.ui.button.js b/resources/lib/jquery.ui/jquery.ui.button.js
new file mode 100644 (file)
index 0000000..8326262
--- /dev/null
@@ -0,0 +1,414 @@
+/*!
+ * jQuery UI Button 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *     jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+var lastActive, startXPos, startYPos, clickDragged,
+       baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
+       stateClasses = "ui-state-hover ui-state-active ",
+       typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
+       formResetHandler = function() {
+               var buttons = $( this ).find( ":ui-button" );
+               setTimeout(function() {
+                       buttons.button( "refresh" );
+               }, 1 );
+       },
+       radioGroup = function( radio ) {
+               var name = radio.name,
+                       form = radio.form,
+                       radios = $( [] );
+               if ( name ) {
+                       if ( form ) {
+                               radios = $( form ).find( "[name='" + name + "']" );
+                       } else {
+                               radios = $( "[name='" + name + "']", radio.ownerDocument )
+                                       .filter(function() {
+                                               return !this.form;
+                                       });
+                       }
+               }
+               return radios;
+       };
+
+$.widget( "ui.button", {
+       options: {
+               disabled: null,
+               text: true,
+               label: null,
+               icons: {
+                       primary: null,
+                       secondary: null
+               }
+       },
+       _create: function() {
+               this.element.closest( "form" )
+                       .unbind( "reset.button" )
+                       .bind( "reset.button", formResetHandler );
+
+               if ( typeof this.options.disabled !== "boolean" ) {
+                       this.options.disabled = !!this.element.propAttr( "disabled" );
+               } else {
+                       this.element.propAttr( "disabled", this.options.disabled );
+               }
+
+               this._determineButtonType();
+               this.hasTitle = !!this.buttonElement.attr( "title" );
+
+               var self = this,
+                       options = this.options,
+                       toggleButton = this.type === "checkbox" || this.type === "radio",
+                       hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
+                       focusClass = "ui-state-focus";
+
+               if ( options.label === null ) {
+                       options.label = this.buttonElement.html();
+               }
+
+               this.buttonElement
+                       .addClass( baseClasses )
+                       .attr( "role", "button" )
+                       .bind( "mouseenter.button", function() {
+                               if ( options.disabled ) {
+                                       return;
+                               }
+                               $( this ).addClass( "ui-state-hover" );
+                               if ( this === lastActive ) {
+                                       $( this ).addClass( "ui-state-active" );
+                               }
+                       })
+                       .bind( "mouseleave.button", function() {
+                               if ( options.disabled ) {
+                                       return;
+                               }
+                               $( this ).removeClass( hoverClass );
+                       })
+                       .bind( "click.button", function( event ) {
+                               if ( options.disabled ) {
+                                       event.preventDefault();
+                                       event.stopImmediatePropagation();
+                               }
+                       });
+
+               this.element
+                       .bind( "focus.button", function() {
+                               // no need to check disabled, focus won't be triggered anyway
+                               self.buttonElement.addClass( focusClass );
+                       })
+                       .bind( "blur.button", function() {
+                               self.buttonElement.removeClass( focusClass );
+                       });
+
+               if ( toggleButton ) {
+                       this.element.bind( "change.button", function() {
+                               if ( clickDragged ) {
+                                       return;
+                               }
+                               self.refresh();
+                       });
+                       // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
+                       // prevents issue where button state changes but checkbox/radio checked state
+                       // does not in Firefox (see ticket #6970)
+                       this.buttonElement
+                               .bind( "mousedown.button", function( event ) {
+                                       if ( options.disabled ) {
+                                               return;
+                                       }
+                                       clickDragged = false;
+                                       startXPos = event.pageX;
+                                       startYPos = event.pageY;
+                               })
+                               .bind( "mouseup.button", function( event ) {
+                                       if ( options.disabled ) {
+                                               return;
+                                       }
+                                       if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
+                                               clickDragged = true;
+                                       }
+                       });
+               }
+
+               if ( this.type === "checkbox" ) {
+                       this.buttonElement.bind( "click.button", function() {
+                               if ( options.disabled || clickDragged ) {
+                                       return false;
+                               }
+                               $( this ).toggleClass( "ui-state-active" );
+                               self.buttonElement.attr( "aria-pressed", self.element[0].checked );
+                       });
+               } else if ( this.type === "radio" ) {
+                       this.buttonElement.bind( "click.button", function() {
+                               if ( options.disabled || clickDragged ) {
+                                       return false;
+                               }
+                               $( this ).addClass( "ui-state-active" );
+                               self.buttonElement.attr( "aria-pressed", "true" );
+
+                               var radio = self.element[ 0 ];
+                               radioGroup( radio )
+                                       .not( radio )
+                                       .map(function() {
+                                               return $( this ).button( "widget" )[ 0 ];
+                                       })
+                                       .removeClass( "ui-state-active" )
+                                       .attr( "aria-pressed", "false" );
+                       });
+               } else {
+                       this.buttonElement
+                               .bind( "mousedown.button", function() {
+                                       if ( options.disabled ) {
+                                               return false;
+                                       }
+                                       $( this ).addClass( "ui-state-active" );
+                                       lastActive = this;
+                                       $( document ).one( "mouseup", function() {
+                                               lastActive = null;
+                                       });
+                               })
+                               .bind( "mouseup.button", function() {
+                                       if ( options.disabled ) {
+                                               return false;
+                                       }
+                                       $( this ).removeClass( "ui-state-active" );
+                               })
+                               .bind( "keydown.button", function(event) {
+                                       if ( options.disabled ) {
+                                               return false;
+                                       }
+                                       if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
+                                               $( this ).addClass( "ui-state-active" );
+                                       }
+                               })
+                               .bind( "keyup.button", function() {
+                                       $( this ).removeClass( "ui-state-active" );
+                               });
+
+                       if ( this.buttonElement.is("a") ) {
+                               this.buttonElement.keyup(function(event) {
+                                       if ( event.keyCode === $.ui.keyCode.SPACE ) {
+                                               // TODO pass through original event correctly (just as 2nd argument doesn't work)
+                                               $( this ).click();
+                                       }
+                               });
+                       }
+               }
+
+               // TODO: pull out $.Widget's handling for the disabled option into
+               // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
+               // be overridden by individual plugins
+               this._setOption( "disabled", options.disabled );
+               this._resetButton();
+       },
+
+       _determineButtonType: function() {
+
+               if ( this.element.is(":checkbox") ) {
+                       this.type = "checkbox";
+               } else if ( this.element.is(":radio") ) {
+                       this.type = "radio";
+               } else if ( this.element.is("input") ) {
+                       this.type = "input";
+               } else {
+                       this.type = "button";
+               }
+
+               if ( this.type === "checkbox" || this.type === "radio" ) {
+                       // we don't search against the document in case the element
+                       // is disconnected from the DOM
+                       var ancestor = this.element.parents().filter(":last"),
+                               labelSelector = "label[for='" + this.element.attr("id") + "']";
+                       this.buttonElement = ancestor.find( labelSelector );
+                       if ( !this.buttonElement.length ) {
+                               ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
+                               this.buttonElement = ancestor.filter( labelSelector );
+                               if ( !this.buttonElement.length ) {
+                                       this.buttonElement = ancestor.find( labelSelector );
+                               }
+                       }
+                       this.element.addClass( "ui-helper-hidden-accessible" );
+
+                       var checked = this.element.is( ":checked" );
+                       if ( checked ) {
+                               this.buttonElement.addClass( "ui-state-active" );
+                       }
+                       this.buttonElement.attr( "aria-pressed", checked );
+               } else {
+                       this.buttonElement = this.element;
+               }
+       },
+
+       widget: function() {
+               return this.buttonElement;
+       },
+
+       destroy: function() {
+               this.element
+                       .removeClass( "ui-helper-hidden-accessible" );
+               this.buttonElement
+                       .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
+                       .removeAttr( "role" )
+                       .removeAttr( "aria-pressed" )
+                       .html( this.buttonElement.find(".ui-button-text").html() );
+
+               if ( !this.hasTitle ) {
+                       this.buttonElement.removeAttr( "title" );
+               }
+
+               $.Widget.prototype.destroy.call( this );
+       },
+
+       _setOption: function( key, value ) {
+               $.Widget.prototype._setOption.apply( this, arguments );
+               if ( key === "disabled" ) {
+                       if ( value ) {
+                               this.element.propAttr( "disabled", true );
+                       } else {
+                               this.element.propAttr( "disabled", false );
+                       }
+                       return;
+               }
+               this._resetButton();
+       },
+
+       refresh: function() {
+               var isDisabled = this.element.is( ":disabled" );
+               if ( isDisabled !== this.options.disabled ) {
+                       this._setOption( "disabled", isDisabled );
+               }
+               if ( this.type === "radio" ) {
+                       radioGroup( this.element[0] ).each(function() {
+                               if ( $( this ).is( ":checked" ) ) {
+                                       $( this ).button( "widget" )
+                                               .addClass( "ui-state-active" )
+                                               .attr( "aria-pressed", "true" );
+                               } else {
+                                       $( this ).button( "widget" )
+                                               .removeClass( "ui-state-active" )
+                                               .attr( "aria-pressed", "false" );
+                               }
+                       });
+               } else if ( this.type === "checkbox" ) {
+                       if ( this.element.is( ":checked" ) ) {
+                               this.buttonElement
+                                       .addClass( "ui-state-active" )
+                                       .attr( "aria-pressed", "true" );
+                       } else {
+                               this.buttonElement
+                                       .removeClass( "ui-state-active" )
+                                       .attr( "aria-pressed", "false" );
+                       }
+               }
+       },
+
+       _resetButton: function() {
+               if ( this.type === "input" ) {
+                       if ( this.options.label ) {
+                               this.element.val( this.options.label );
+                       }
+                       return;
+               }
+               var buttonElement = this.buttonElement.removeClass( typeClasses ),
+                       buttonText = $( "<span></span>", this.element[0].ownerDocument )
+                               .addClass( "ui-button-text" )
+                               .html( this.options.label )
+                               .appendTo( buttonElement.empty() )
+                               .text(),
+                       icons = this.options.icons,
+                       multipleIcons = icons.primary && icons.secondary,
+                       buttonClasses = [];  
+
+               if ( icons.primary || icons.secondary ) {
+                       if ( this.options.text ) {
+                               buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
+                       }
+
+                       if ( icons.primary ) {
+                               buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
+                       }
+
+                       if ( icons.secondary ) {
+                               buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
+                       }
+
+                       if ( !this.options.text ) {
+                               buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
+
+                               if ( !this.hasTitle ) {
+                                       buttonElement.attr( "title", buttonText );
+                               }
+                       }
+               } else {
+                       buttonClasses.push( "ui-button-text-only" );
+               }
+               buttonElement.addClass( buttonClasses.join( " " ) );
+       }
+});
+
+$.widget( "ui.buttonset", {
+       options: {
+               items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
+       },
+
+       _create: function() {
+               this.element.addClass( "ui-buttonset" );
+       },
+       
+       _init: function() {
+               this.refresh();
+       },
+
+       _setOption: function( key, value ) {
+               if ( key === "disabled" ) {
+                       this.buttons.button( "option", key, value );
+               }
+
+               $.Widget.prototype._setOption.apply( this, arguments );
+       },
+       
+       refresh: function() {
+               var rtl = this.element.css( "direction" ) === "rtl";
+               
+               this.buttons = this.element.find( this.options.items )
+                       .filter( ":ui-button" )
+                               .button( "refresh" )
+                       .end()
+                       .not( ":ui-button" )
+                               .button()
+                       .end()
+                       .map(function() {
+                               return $( this ).button( "widget" )[ 0 ];
+                       })
+                               .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
+                               .filter( ":first" )
+                                       .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
+                               .end()
+                               .filter( ":last" )
+                                       .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
+                               .end()
+                       .end();
+       },
+
+       destroy: function() {
+               this.element.removeClass( "ui-buttonset" );
+               this.buttons
+                       .map(function() {
+                               return $( this ).button( "widget" )[ 0 ];
+                       })
+                               .removeClass( "ui-corner-left ui-corner-right" )
+                       .end()
+                       .button( "destroy" );
+
+               $.Widget.prototype.destroy.call( this );
+       }
+});
+
+}( jQuery ) );
diff --git a/resources/lib/jquery.ui/jquery.ui.core.js b/resources/lib/jquery.ui/jquery.ui.core.js
new file mode 100644 (file)
index 0000000..b36c1ac
--- /dev/null
@@ -0,0 +1,334 @@
+/*!
+ * jQuery UI 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI
+ */
+(function( $, undefined ) {
+
+// prevent duplicate loading
+// this is only a problem because we proxy existing functions
+// and we don't want to double proxy them
+$.ui = $.ui || {};
+if ( $.ui.version ) {
+       return;
+}
+
+$.extend( $.ui, {
+       version: "1.8.24",
+
+       keyCode: {
+               ALT: 18,
+               BACKSPACE: 8,
+               CAPS_LOCK: 20,
+               COMMA: 188,
+               COMMAND: 91,
+               COMMAND_LEFT: 91, // COMMAND
+               COMMAND_RIGHT: 93,
+               CONTROL: 17,
+               DELETE: 46,
+               DOWN: 40,
+               END: 35,
+               ENTER: 13,
+               ESCAPE: 27,
+               HOME: 36,
+               INSERT: 45,
+               LEFT: 37,
+               MENU: 93, // COMMAND_RIGHT
+               NUMPAD_ADD: 107,
+               NUMPAD_DECIMAL: 110,
+               NUMPAD_DIVIDE: 111,
+               NUMPAD_ENTER: 108,
+               NUMPAD_MULTIPLY: 106,
+               NUMPAD_SUBTRACT: 109,
+               PAGE_DOWN: 34,
+               PAGE_UP: 33,
+               PERIOD: 190,
+               RIGHT: 39,
+               SHIFT: 16,
+               SPACE: 32,
+               TAB: 9,
+               UP: 38,
+               WINDOWS: 91 // COMMAND
+       }
+});
+
+// plugins
+$.fn.extend({
+       propAttr: $.fn.prop || $.fn.attr,
+
+       _focus: $.fn.focus,
+       focus: function( delay, fn ) {
+               return typeof delay === "number" ?
+                       this.each(function() {
+                               var elem = this;
+                               setTimeout(function() {
+                                       $( elem ).focus();
+                                       if ( fn ) {
+                                               fn.call( elem );
+                                       }
+                               }, delay );
+                       }) :
+                       this._focus.apply( this, arguments );
+       },
+
+       scrollParent: function() {
+               var scrollParent;
+               if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
+                       scrollParent = this.parents().filter(function() {
+                               return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+                       }).eq(0);
+               } else {
+                       scrollParent = this.parents().filter(function() {
+                               return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+                       }).eq(0);
+               }
+
+               return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
+       },
+
+       zIndex: function( zIndex ) {
+               if ( zIndex !== undefined ) {
+                       return this.css( "zIndex", zIndex );
+               }
+
+               if ( this.length ) {
+                       var elem = $( this[ 0 ] ), position, value;
+                       while ( elem.length && elem[ 0 ] !== document ) {
+                               // Ignore z-index if position is set to a value where z-index is ignored by the browser
+                               // This makes behavior of this function consistent across browsers
+                               // WebKit always returns auto if the element is positioned
+                               position = elem.css( "position" );
+                               if ( position === "absolute" || position === "relative" || position === "fixed" ) {
+                                       // IE returns 0 when zIndex is not specified
+                                       // other browsers return a string
+                                       // we ignore the case of nested elements with an explicit value of 0
+                                       // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
+                                       value = parseInt( elem.css( "zIndex" ), 10 );
+                                       if ( !isNaN( value ) && value !== 0 ) {
+                                               return value;
+                                       }
+                               }
+                               elem = elem.parent();
+                       }
+               }
+
+               return 0;
+       },
+
+       disableSelection: function() {
+               return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
+                       ".ui-disableSelection", function( event ) {
+                               event.preventDefault();
+                       });
+       },
+
+       enableSelection: function() {
+               return this.unbind( ".ui-disableSelection" );
+       }
+});
+
+// support: jQuery <1.8
+if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
+       $.each( [ "Width", "Height" ], function( i, name ) {
+               var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
+                       type = name.toLowerCase(),
+                       orig = {
+                               innerWidth: $.fn.innerWidth,
+                               innerHeight: $.fn.innerHeight,
+                               outerWidth: $.fn.outerWidth,
+                               outerHeight: $.fn.outerHeight
+                       };
+
+               function reduce( elem, size, border, margin ) {
+                       $.each( side, function() {
+                               size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
+                               if ( border ) {
+                                       size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
+                               }
+                               if ( margin ) {
+                                       size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
+                               }
+                       });
+                       return size;
+               }
+
+               $.fn[ "inner" + name ] = function( size ) {
+                       if ( size === undefined ) {
+                               return orig[ "inner" + name ].call( this );
+                       }
+
+                       return this.each(function() {
+                               $( this ).css( type, reduce( this, size ) + "px" );
+                       });
+               };
+
+               $.fn[ "outer" + name] = function( size, margin ) {
+                       if ( typeof size !== "number" ) {
+                               return orig[ "outer" + name ].call( this, size );
+                       }
+
+                       return this.each(function() {
+                               $( this).css( type, reduce( this, size, true, margin ) + "px" );
+                       });
+               };
+       });
+}
+
+// selectors
+function focusable( element, isTabIndexNotNaN ) {
+       var nodeName = element.nodeName.toLowerCase();
+       if ( "area" === nodeName ) {
+               var map = element.parentNode,
+                       mapName = map.name,
+                       img;
+               if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
+                       return false;
+               }
+               img = $( "img[usemap=#" + mapName + "]" )[0];
+               return !!img && visible( img );
+       }
+       return ( /input|select|textarea|button|object/.test( nodeName )
+               ? !element.disabled
+               : "a" == nodeName
+                       ? element.href || isTabIndexNotNaN
+                       : isTabIndexNotNaN)
+               // the element and all of its ancestors must be visible
+               && visible( element );
+}
+
+function visible( element ) {
+       return !$( element ).parents().andSelf().filter(function() {
+               return $.curCSS( this, "visibility" ) === "hidden" ||
+                       $.expr.filters.hidden( this );
+       }).length;
+}
+
+$.extend( $.expr[ ":" ], {
+       data: $.expr.createPseudo ?
+               $.expr.createPseudo(function( dataName ) {
+                       return function( elem ) {
+                               return !!$.data( elem, dataName );
+                       };
+               }) :
+               // support: jQuery <1.8
+               function( elem, i, match ) {
+                       return !!$.data( elem, match[ 3 ] );
+               },
+
+       focusable: function( element ) {
+               return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
+       },
+
+       tabbable: function( element ) {
+               var tabIndex = $.attr( element, "tabindex" ),
+                       isTabIndexNaN = isNaN( tabIndex );
+               return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
+       }
+});
+
+// support
+$(function() {
+       var body = document.body,
+               div = body.appendChild( div = document.createElement( "div" ) );
+
+       // access offsetHeight before setting the style to prevent a layout bug
+       // in IE 9 which causes the elemnt to continue to take up space even
+       // after it is removed from the DOM (#8026)
+       div.offsetHeight;
+
+       $.extend( div.style, {
+               minHeight: "100px",
+               height: "auto",
+               padding: 0,
+               borderWidth: 0
+       });
+
+       $.support.minHeight = div.offsetHeight === 100;
+       $.support.selectstart = "onselectstart" in div;
+
+       // set display to none to avoid a layout bug in IE
+       // http://dev.jquery.com/ticket/4014
+       body.removeChild( div ).style.display = "none";
+});
+
+// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
+if ( !$.curCSS ) {
+       $.curCSS = $.css;
+}
+
+
+
+
+
+// deprecated
+$.extend( $.ui, {
+       // $.ui.plugin is deprecated.  Use the proxy pattern instead.
+       plugin: {
+               add: function( module, option, set ) {
+                       var proto = $.ui[ module ].prototype;
+                       for ( var i in set ) {
+                               proto.plugins[ i ] = proto.plugins[ i ] || [];
+                               proto.plugins[ i ].push( [ option, set[ i ] ] );
+                       }
+               },
+               call: function( instance, name, args ) {
+                       var set = instance.plugins[ name ];
+                       if ( !set || !instance.element[ 0 ].parentNode ) {
+                               return;
+                       }
+       
+                       for ( var i = 0; i < set.length; i++ ) {
+                               if ( instance.options[ set[ i ][ 0 ] ] ) {
+                                       set[ i ][ 1 ].apply( instance.element, args );
+                               }
+                       }
+               }
+       },
+       
+       // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
+       contains: function( a, b ) {
+               return document.compareDocumentPosition ?
+                       a.compareDocumentPosition( b ) & 16 :
+                       a !== b && a.contains( b );
+       },
+       
+       // only used by resizable
+       hasScroll: function( el, a ) {
+       
+               //If overflow is hidden, the element might have extra content, but the user wants to hide it
+               if ( $( el ).css( "overflow" ) === "hidden") {
+                       return false;
+               }
+       
+               var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
+                       has = false;
+       
+               if ( el[ scroll ] > 0 ) {
+                       return true;
+               }
+       
+               // TODO: determine which cases actually cause this to happen
+               // if the element doesn't have the scroll set, see if it's possible to
+               // set the scroll
+               el[ scroll ] = 1;
+               has = ( el[ scroll ] > 0 );
+               el[ scroll ] = 0;
+               return has;
+       },
+       
+       // these are odd functions, fix the API or move into individual plugins
+       isOverAxis: function( x, reference, size ) {
+               //Determines when x coordinate is over "b" element axis
+               return ( x > reference ) && ( x < ( reference + size ) );
+       },
+       isOver: function( y, x, top, left, height, width ) {
+               //Determines when x, y coordinates is over "b" element
+               return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
+       }
+});
+
+})( jQuery );
diff --git a/resources/lib/jquery.ui/jquery.ui.datepicker.js b/resources/lib/jquery.ui/jquery.ui.datepicker.js
new file mode 100644 (file)
index 0000000..1fcea12
--- /dev/null
@@ -0,0 +1,1854 @@
+/*!
+ * jQuery UI Datepicker 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ */
+(function( $, undefined ) {
+
+$.extend($.ui, { datepicker: { version: "1.8.24" } });
+
+var PROP_NAME = 'datepicker';
+var dpuuid = new Date().getTime();
+var instActive;
+
+/* Date picker manager.
+   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
+   Settings for (groups of) date pickers are maintained in an instance object,
+   allowing multiple different settings on the same page. */
+
+function Datepicker() {
+       this.debug = false; // Change this to true to start debugging
+       this._curInst = null; // The current instance in use
+       this._keyEvent = false; // If the last event was a key event
+       this._disabledInputs = []; // List of date picker inputs that have been disabled
+       this._datepickerShowing = false; // True if the popup picker is showing , false if not
+       this._inDialog = false; // True if showing within a "dialog", false if not
+       this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
+       this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
+       this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
+       this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
+       this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
+       this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
+       this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
+       this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
+       this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
+       this.regional = []; // Available regional settings, indexed by language code
+       this.regional[''] = { // Default regional settings
+               closeText: 'Done', // Display text for close link
+               prevText: 'Prev', // Display text for previous month link
+               nextText: 'Next', // Display text for next month link
+               currentText: 'Today', // Display text for current month link
+               monthNames: ['January','February','March','April','May','June',
+                       'July','August','September','October','November','December'], // Names of months for drop-down and formatting
+               monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
+               dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
+               dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
+               dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
+               weekHeader: 'Wk', // Column header for week of the year
+               dateFormat: 'mm/dd/yy', // See format options on parseDate
+               firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
+               isRTL: false, // True if right-to-left language, false if left-to-right
+               showMonthAfterYear: false, // True if the year select precedes month, false for month then year
+               yearSuffix: '' // Additional text to append to the year in the month headers
+       };
+       this._defaults = { // Global defaults for all the date picker instances
+               showOn: 'focus', // 'focus' for popup on focus,
+                       // 'button' for trigger button, or 'both' for either
+               showAnim: 'fadeIn', // Name of jQuery animation for popup
+               showOptions: {}, // Options for enhanced animations
+               defaultDate: null, // Used when field is blank: actual date,
+                       // +/-number for offset from today, null for today
+               appendText: '', // Display text following the input box, e.g. showing the format
+               buttonText: '...', // Text for trigger button
+               buttonImage: '', // URL for trigger button image
+               buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
+               hideIfNoPrevNext: false, // True to hide next/previous month links
+                       // if not applicable, false to just disable them
+               navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
+               gotoCurrent: false, // True if today link goes back to current selection instead
+               changeMonth: false, // True if month can be selected directly, false if only prev/next
+               changeYear: false, // True if year can be selected directly, false if only prev/next
+               yearRange: 'c-10:c+10', // Range of years to display in drop-down,
+                       // either relative to today's year (-nn:+nn), relative to currently displayed year
+                       // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
+               showOtherMonths: false, // True to show dates in other months, false to leave blank
+               selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
+               showWeek: false, // True to show week of the year, false to not show it
+               calculateWeek: this.iso8601Week, // How to calculate the week of the year,
+                       // takes a Date and returns the number of the week for it
+               shortYearCutoff: '+10', // Short year values < this are in the current century,
+                       // > this are in the previous century,
+                       // string value starting with '+' for current year + value
+               minDate: null, // The earliest selectable date, or null for no limit
+               maxDate: null, // The latest selectable date, or null for no limit
+               duration: 'fast', // Duration of display/closure
+               beforeShowDay: null, // Function that takes a date and returns an array with
+                       // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
+                       // [2] = cell title (optional), e.g. $.datepicker.noWeekends
+               beforeShow: null, // Function that takes an input field and
+                       // returns a set of custom settings for the date picker
+               onSelect: null, // Define a callback function when a date is selected
+               onChangeMonthYear: null, // Define a callback function when the month or year is changed
+               onClose: null, // Define a callback function when the datepicker is closed
+               numberOfMonths: 1, // Number of months to show at a time
+               showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
+               stepMonths: 1, // Number of months to step back/forward
+               stepBigMonths: 12, // Number of months to step back/forward for the big links
+               altField: '', // Selector for an alternate field to store selected dates into
+               altFormat: '', // The date format to use for the alternate field
+               constrainInput: true, // The input is constrained by the current date format
+               showButtonPanel: false, // True to show button panel, false to not show it
+               autoSize: false, // True to size the input for the date format, false to leave as is
+               disabled: false // The initial disabled state
+       };
+       $.extend(this._defaults, this.regional['']);
+       this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
+}
+
+$.extend(Datepicker.prototype, {
+       /* Class name added to elements to indicate already configured with a date picker. */
+       markerClassName: 'hasDatepicker',
+       
+       //Keep track of the maximum number of rows displayed (see #7043)
+       maxRows: 4,
+
+       /* Debug logging (if enabled). */
+       log: function () {
+               if (this.debug)
+                       console.log.apply('', arguments);
+       },
+       
+       // TODO rename to "widget" when switching to widget factory
+       _widgetDatepicker: function() {
+               return this.dpDiv;
+       },
+
+       /* Override the default settings for all instances of the date picker.
+          @param  settings  object - the new settings to use as defaults (anonymous object)
+          @return the manager object */
+       setDefaults: function(settings) {
+               extendRemove(this._defaults, settings || {});
+               return this;
+       },
+
+       /* Attach the date picker to a jQuery selection.
+          @param  target    element - the target input field or division or span
+          @param  settings  object - the new settings to use for this date picker instance (anonymous) */
+       _attachDatepicker: function(target, settings) {
+               // check for settings on the control itself - in namespace 'date:'
+               var inlineSettings = null;
+               for (var attrName in this._defaults) {
+                       var attrValue = target.getAttribute('date:' + attrName);
+                       if (attrValue) {
+                               inlineSettings = inlineSettings || {};
+                               try {
+                                       inlineSettings[attrName] = eval(attrValue);
+                               } catch (err) {
+                                       inlineSettings[attrName] = attrValue;
+                               }
+                       }
+               }
+               var nodeName = target.nodeName.toLowerCase();
+               var inline = (nodeName == 'div' || nodeName == 'span');
+               if (!target.id) {
+                       this.uuid += 1;
+                       target.id = 'dp' + this.uuid;
+               }
+               var inst = this._newInst($(target), inline);
+               inst.settings = $.extend({}, settings || {}, inlineSettings || {});
+               if (nodeName == 'input') {
+                       this._connectDatepicker(target, inst);
+               } else if (inline) {
+                       this._inlineDatepicker(target, inst);
+               }
+       },
+
+       /* Create a new instance object. */
+       _newInst: function(target, inline) {
+               var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
+               return {id: id, input: target, // associated target
+                       selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
+                       drawMonth: 0, drawYear: 0, // month being drawn
+                       inline: inline, // is datepicker inline or not
+                       dpDiv: (!inline ? this.dpDiv : // presentation div
+                       bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
+       },
+
+       /* Attach the date picker to an input field. */
+       _connectDatepicker: function(target, inst) {
+               var input = $(target);
+               inst.append = $([]);
+               inst.trigger = $([]);
+               if (input.hasClass(this.markerClassName))
+                       return;
+               this._attachments(input, inst);
+               input.addClass(this.markerClassName).keydown(this._doKeyDown).
+                       keypress(this._doKeyPress).keyup(this._doKeyUp).
+                       bind("setData.datepicker", function(event, key, value) {
+                               inst.settings[key] = value;
+                       }).bind("getData.datepicker", function(event, key) {
+                               return this._get(inst, key);
+                       });
+               this._autoSize(inst);
+               $.data(target, PROP_NAME, inst);
+               //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
+               if( inst.settings.disabled ) {
+                       this._disableDatepicker( target );
+               }
+       },
+
+       /* Make attachments based on settings. */
+       _attachments: function(input, inst) {
+               var appendText = this._get(inst, 'appendText');
+               var isRTL = this._get(inst, 'isRTL');
+               if (inst.append)
+                       inst.append.remove();
+               if (appendText) {
+                       inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
+                       input[isRTL ? 'before' : 'after'](inst.append);
+               }
+               input.unbind('focus', this._showDatepicker);
+               if (inst.trigger)
+                       inst.trigger.remove();
+               var showOn = this._get(inst, 'showOn');
+               if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
+                       input.focus(this._showDatepicker);
+               if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
+                       var buttonText = this._get(inst, 'buttonText');
+                       var buttonImage = this._get(inst, 'buttonImage');
+                       inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
+                               $('<img/>').addClass(this._triggerClass).
+                                       attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
+                               $('<button type="button"></button>').addClass(this._triggerClass).
+                                       html(buttonImage == '' ? buttonText : $('<img/>').attr(
+                                       { src:buttonImage, alt:buttonText, title:buttonText })));
+                       input[isRTL ? 'before' : 'after'](inst.trigger);
+                       inst.trigger.click(function() {
+                               if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
+                                       $.datepicker._hideDatepicker();
+                               else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) {
+                                       $.datepicker._hideDatepicker(); 
+                                       $.datepicker._showDatepicker(input[0]);
+                               } else
+                                       $.datepicker._showDatepicker(input[0]);
+                               return false;
+                       });
+               }
+       },
+
+       /* Apply the maximum length for the date format. */
+       _autoSize: function(inst) {
+               if (this._get(inst, 'autoSize') && !inst.inline) {
+                       var date = new Date(2009, 12 - 1, 20); // Ensure double digits
+                       var dateFormat = this._get(inst, 'dateFormat');
+                       if (dateFormat.match(/[DM]/)) {
+                               var findMax = function(names) {
+                                       var max = 0;
+                                       var maxI = 0;
+                                       for (var i = 0; i < names.length; i++) {
+                                               if (names[i].length > max) {
+                                                       max = names[i].length;
+                                                       maxI = i;
+                                               }
+                                       }
+                                       return maxI;
+                               };
+                               date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
+                                       'monthNames' : 'monthNamesShort'))));
+                               date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
+                                       'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
+                       }
+                       inst.input.attr('size', this._formatDate(inst, date).length);
+               }
+       },
+
+       /* Attach an inline date picker to a div. */
+       _inlineDatepicker: function(target, inst) {
+               var divSpan = $(target);
+               if (divSpan.hasClass(this.markerClassName))
+                       return;
+               divSpan.addClass(this.markerClassName).append(inst.dpDiv).
+                       bind("setData.datepicker", function(event, key, value){
+                               inst.settings[key] = value;
+                       }).bind("getData.datepicker", function(event, key){
+                               return this._get(inst, key);
+                       });
+               $.data(target, PROP_NAME, inst);
+               this._setDate(inst, this._getDefaultDate(inst), true);
+               this._updateDatepicker(inst);
+               this._updateAlternate(inst);
+               //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
+               if( inst.settings.disabled ) {
+                       this._disableDatepicker( target );
+               }
+               // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
+               // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
+               inst.dpDiv.css( "display", "block" );
+       },
+
+       /* Pop-up the date picker in a "dialog" box.
+          @param  input     element - ignored
+          @param  date      string or Date - the initial date to display
+          @param  onSelect  function - the function to call when a date is selected
+          @param  settings  object - update the dialog date picker instance's settings (anonymous object)
+          @param  pos       int[2] - coordinates for the dialog's position within the screen or
+                            event - with x/y coordinates or
+                            leave empty for default (screen centre)
+          @return the manager object */
+       _dialogDatepicker: function(input, date, onSelect, settings, pos) {
+               var inst = this._dialogInst; // internal instance
+               if (!inst) {
+                       this.uuid += 1;
+                       var id = 'dp' + this.uuid;
+                       this._dialogInput = $('<input type="text" id="' + id +
+                               '" style="position: absolute; top: -100px; width: 0px;"/>');
+                       this._dialogInput.keydown(this._doKeyDown);
+                       $('body').append(this._dialogInput);
+                       inst = this._dialogInst = this._newInst(this._dialogInput, false);
+                       inst.settings = {};
+                       $.data(this._dialogInput[0], PROP_NAME, inst);
+               }
+               extendRemove(inst.settings, settings || {});
+               date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
+               this._dialogInput.val(date);
+
+               this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
+               if (!this._pos) {
+                       var browserWidth = document.documentElement.clientWidth;
+                       var browserHeight = document.documentElement.clientHeight;
+                       var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
+                       var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
+                       this._pos = // should use actual width/height below
+                               [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
+               }
+
+               // move input on screen for focus, but hidden behind dialog
+               this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
+               inst.settings.onSelect = onSelect;
+               this._inDialog = true;
+               this.dpDiv.addClass(this._dialogClass);
+               this._showDatepicker(this._dialogInput[0]);
+               if ($.blockUI)
+                       $.blockUI(this.dpDiv);
+               $.data(this._dialogInput[0], PROP_NAME, inst);
+               return this;
+       },
+
+       /* Detach a datepicker from its control.
+          @param  target    element - the target input field or division or span */
+       _destroyDatepicker: function(target) {
+               var $target = $(target);
+               var inst = $.data(target, PROP_NAME);
+               if (!$target.hasClass(this.markerClassName)) {
+                       return;
+               }
+               var nodeName = target.nodeName.toLowerCase();
+               $.removeData(target, PROP_NAME);
+               if (nodeName == 'input') {
+                       inst.append.remove();
+                       inst.trigger.remove();
+                       $target.removeClass(this.markerClassName).
+                               unbind('focus', this._showDatepicker).
+                               unbind('keydown', this._doKeyDown).
+                               unbind('keypress', this._doKeyPress).
+                               unbind('keyup', this._doKeyUp);
+               } else if (nodeName == 'div' || nodeName == 'span')
+                       $target.removeClass(this.markerClassName).empty();
+       },
+
+       /* Enable the date picker to a jQuery selection.
+          @param  target    element - the target input field or division or span */
+       _enableDatepicker: function(target) {
+               var $target = $(target);
+               var inst = $.data(target, PROP_NAME);
+               if (!$target.hasClass(this.markerClassName)) {
+                       return;
+               }
+               var nodeName = target.nodeName.toLowerCase();
+               if (nodeName == 'input') {
+                       target.disabled = false;
+                       inst.trigger.filter('button').
+                               each(function() { this.disabled = false; }).end().
+                               filter('img').css({opacity: '1.0', cursor: ''});
+               }
+               else if (nodeName == 'div' || nodeName == 'span') {
+                       var inline = $target.children('.' + this._inlineClass);
+                       inline.children().removeClass('ui-state-disabled');
+                       inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
+                               removeAttr("disabled");
+               }
+               this._disabledInputs = $.map(this._disabledInputs,
+                       function(value) { return (value == target ? null : value); }); // delete entry
+       },
+
+       /* Disable the date picker to a jQuery selection.
+          @param  target    element - the target input field or division or span */
+       _disableDatepicker: function(target) {
+               var $target = $(target);
+               var inst = $.data(target, PROP_NAME);
+               if (!$target.hasClass(this.markerClassName)) {
+                       return;
+               }
+               var nodeName = target.nodeName.toLowerCase();
+               if (nodeName == 'input') {
+                       target.disabled = true;
+                       inst.trigger.filter('button').
+                               each(function() { this.disabled = true; }).end().
+                               filter('img').css({opacity: '0.5', cursor: 'default'});
+               }
+               else if (nodeName == 'div' || nodeName == 'span') {
+                       var inline = $target.children('.' + this._inlineClass);
+                       inline.children().addClass('ui-state-disabled');
+                       inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
+                               attr("disabled", "disabled");
+               }
+               this._disabledInputs = $.map(this._disabledInputs,
+                       function(value) { return (value == target ? null : value); }); // delete entry
+               this._disabledInputs[this._disabledInputs.length] = target;
+       },
+
+       /* Is the first field in a jQuery collection disabled as a datepicker?
+          @param  target    element - the target input field or division or span
+          @return boolean - true if disabled, false if enabled */
+       _isDisabledDatepicker: function(target) {
+               if (!target) {
+                       return false;
+               }
+               for (var i = 0; i < this._disabledInputs.length; i++) {
+                       if (this._disabledInputs[i] == target)
+                               return true;
+               }
+               return false;
+       },
+
+       /* Retrieve the instance data for the target control.
+          @param  target  element - the target input field or division or span
+          @return  object - the associated instance data
+          @throws  error if a jQuery problem getting data */
+       _getInst: function(target) {
+               try {
+                       return $.data(target, PROP_NAME);
+               }
+               catch (err) {
+                       throw 'Missing instance data for this datepicker';
+               }
+       },
+
+       /* Update or retrieve the settings for a date picker attached to an input field or division.
+          @param  target  element - the target input field or division or span
+          @param  name    object - the new settings to update or
+                          string - the name of the setting to change or retrieve,
+                          when retrieving also 'all' for all instance settings or
+                          'defaults' for all global defaults
+          @param  value   any - the new value for the setting
+                          (omit if above is an object or to retrieve a value) */
+       _optionDatepicker: function(target, name, value) {
+               var inst = this._getInst(target);
+               if (arguments.length == 2 && typeof name == 'string') {
+                       return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
+                               (inst ? (name == 'all' ? $.extend({}, inst.settings) :
+                               this._get(inst, name)) : null));
+               }
+               var settings = name || {};
+               if (typeof name == 'string') {
+                       settings = {};
+                       settings[name] = value;
+               }
+               if (inst) {
+                       if (this._curInst == inst) {
+                               this._hideDatepicker();
+                       }
+                       var date = this._getDateDatepicker(target, true);
+                       var minDate = this._getMinMaxDate(inst, 'min');
+                       var maxDate = this._getMinMaxDate(inst, 'max');
+                       extendRemove(inst.settings, settings);
+                       // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
+                       if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
+                               inst.settings.minDate = this._formatDate(inst, minDate);
+                       if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
+                               inst.settings.maxDate = this._formatDate(inst, maxDate);
+                       this._attachments($(target), inst);
+                       this._autoSize(inst);
+                       this._setDate(inst, date);
+                       this._updateAlternate(inst);
+                       this._updateDatepicker(inst);
+               }
+       },
+
+       // change method deprecated
+       _changeDatepicker: function(target, name, value) {
+               this._optionDatepicker(target, name, value);
+       },
+
+       /* Redraw the date picker attached to an input field or division.
+          @param  target  element - the target input field or division or span */
+       _refreshDatepicker: function(target) {
+               var inst = this._getInst(target);
+               if (inst) {
+                       this._updateDatepicker(inst);
+               }
+       },
+
+       /* Set the dates for a jQuery selection.
+          @param  target   element - the target input field or division or span
+          @param  date     Date - the new date */
+       _setDateDatepicker: function(target, date) {
+               var inst = this._getInst(target);
+               if (inst) {
+                       this._setDate(inst, date);
+                       this._updateDatepicker(inst);
+                       this._updateAlternate(inst);
+               }
+       },
+
+       /* Get the date(s) for the first entry in a jQuery selection.
+          @param  target     element - the target input field or division or span
+          @param  noDefault  boolean - true if no default date is to be used
+          @return Date - the current date */
+       _getDateDatepicker: function(target, noDefault) {
+               var inst = this._getInst(target);
+               if (inst && !inst.inline)
+                       this._setDateFromField(inst, noDefault);
+               return (inst ? this._getDate(inst) : null);
+       },
+
+       /* Handle keystrokes. */
+       _doKeyDown: function(event) {
+               var inst = $.datepicker._getInst(event.target);
+               var handled = true;
+               var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
+               inst._keyEvent = true;
+               if ($.datepicker._datepickerShowing)
+                       switch (event.keyCode) {
+                               case 9: $.datepicker._hideDatepicker();
+                                               handled = false;
+                                               break; // hide on tab out
+                               case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + 
+                                                                       $.datepicker._currentClass + ')', inst.dpDiv);
+                                               if (sel[0])
+                                                       $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
+                                                       var onSelect = $.datepicker._get(inst, 'onSelect');
+                                                       if (onSelect) {
+                                                               var dateStr = $.datepicker._formatDate(inst);
+
+                                                               // trigger custom callback
+                                                               onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
+                                                       }
+                                               else
+                                                       $.datepicker._hideDatepicker();
+                                               return false; // don't submit the form
+                                               break; // select the value on enter
+                               case 27: $.datepicker._hideDatepicker();
+                                               break; // hide on escape
+                               case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+                                                       -$.datepicker._get(inst, 'stepBigMonths') :
+                                                       -$.datepicker._get(inst, 'stepMonths')), 'M');
+                                               break; // previous month/year on page up/+ ctrl
+                               case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+                                                       +$.datepicker._get(inst, 'stepBigMonths') :
+                                                       +$.datepicker._get(inst, 'stepMonths')), 'M');
+                                               break; // next month/year on page down/+ ctrl
+                               case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
+                                               handled = event.ctrlKey || event.metaKey;
+                                               break; // clear on ctrl or command +end
+                               case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
+                                               handled = event.ctrlKey || event.metaKey;
+                                               break; // current on ctrl or command +home
+                               case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
+                                               handled = event.ctrlKey || event.metaKey;
+                                               // -1 day on ctrl or command +left
+                                               if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+                                                                       -$.datepicker._get(inst, 'stepBigMonths') :
+                                                                       -$.datepicker._get(inst, 'stepMonths')), 'M');
+                                               // next month/year on alt +left on Mac
+                                               break;
+                               case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
+                                               handled = event.ctrlKey || event.metaKey;
+                                               break; // -1 week on ctrl or command +up
+                               case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
+                                               handled = event.ctrlKey || event.metaKey;
+                                               // +1 day on ctrl or command +right
+                                               if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+                                                                       +$.datepicker._get(inst, 'stepBigMonths') :
+                                                                       +$.datepicker._get(inst, 'stepMonths')), 'M');
+                                               // next month/year on alt +right
+                                               break;
+                               case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
+                                               handled = event.ctrlKey || event.metaKey;
+                                               break; // +1 week on ctrl or command +down
+                               default: handled = false;
+                       }
+               else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
+                       $.datepicker._showDatepicker(this);
+               else {
+                       handled = false;
+               }
+               if (handled) {
+                       event.preventDefault();
+                       event.stopPropagation();
+               }
+       },
+
+       /* Filter entered characters - based on date format. */
+       _doKeyPress: function(event) {
+               var inst = $.datepicker._getInst(event.target);
+               if ($.datepicker._get(inst, 'constrainInput')) {
+                       var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
+                       var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
+                       return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
+               }
+       },
+
+       /* Synchronise manual entry and field/alternate field. */
+       _doKeyUp: function(event) {
+               var inst = $.datepicker._getInst(event.target);
+               if (inst.input.val() != inst.lastVal) {
+                       try {
+                               var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
+                                       (inst.input ? inst.input.val() : null),
+                                       $.datepicker._getFormatConfig(inst));
+                               if (date) { // only if valid
+                                       $.datepicker._setDateFromField(inst);
+                                       $.datepicker._updateAlternate(inst);
+                                       $.datepicker._updateDatepicker(inst);
+                               }
+                       }
+                       catch (err) {
+                               $.datepicker.log(err);
+                       }
+               }
+               return true;
+       },
+
+       /* Pop-up the date picker for a given input field.
+       If false returned from beforeShow event handler do not show. 
+          @param  input  element - the input field attached to the date picker or
+                         event - if triggered by focus */
+       _showDatepicker: function(input) {
+               input = input.target || input;
+               if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
+                       input = $('input', input.parentNode)[0];
+               if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
+                       return;
+               var inst = $.datepicker._getInst(input);
+               if ($.datepicker._curInst && $.datepicker._curInst != inst) {
+                       $.datepicker._curInst.dpDiv.stop(true, true);
+                       if ( inst && $.datepicker._datepickerShowing ) {
+                               $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
+                       }
+               }
+               var beforeShow = $.datepicker._get(inst, 'beforeShow');
+               var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
+               if(beforeShowSettings === false){
+            //false
+                       return;
+               }
+               extendRemove(inst.settings, beforeShowSettings);
+               inst.lastVal = null;
+               $.datepicker._lastInput = input;
+               $.datepicker._setDateFromField(inst);
+               if ($.datepicker._inDialog) // hide cursor
+                       input.value = '';
+               if (!$.datepicker._pos) { // position below input
+                       $.datepicker._pos = $.datepicker._findPos(input);
+                       $.datepicker._pos[1] += input.offsetHeight; // add the height
+               }
+               var isFixed = false;
+               $(input).parents().each(function() {
+                       isFixed |= $(this).css('position') == 'fixed';
+                       return !isFixed;
+               });
+               if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
+                       $.datepicker._pos[0] -= document.documentElement.scrollLeft;
+                       $.datepicker._pos[1] -= document.documentElement.scrollTop;
+               }
+               var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
+               $.datepicker._pos = null;
+               //to avoid flashes on Firefox
+               inst.dpDiv.empty();
+               // determine sizing offscreen
+               inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
+               $.datepicker._updateDatepicker(inst);
+               // fix width for dynamic number of date pickers
+               // and adjust position before showing
+               offset = $.datepicker._checkOffset(inst, offset, isFixed);
+               inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
+                       'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
+                       left: offset.left + 'px', top: offset.top + 'px'});
+               if (!inst.inline) {
+                       var showAnim = $.datepicker._get(inst, 'showAnim');
+                       var duration = $.datepicker._get(inst, 'duration');
+                       var postProcess = function() {
+                               var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
+                               if( !! cover.length ){
+                                       var borders = $.datepicker._getBorders(inst.dpDiv);
+                                       cover.css({left: -borders[0], top: -borders[1],
+                                               width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
+                               }
+                       };
+                       inst.dpDiv.zIndex($(input).zIndex()+1);
+                       $.datepicker._datepickerShowing = true;
+                       if ($.effects && $.effects[showAnim])
+                               inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
+                       else
+                               inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
+                       if (!showAnim || !duration)
+                               postProcess();
+                       if (inst.input.is(':visible') && !inst.input.is(':disabled'))
+                               inst.input.focus();
+                       $.datepicker._curInst = inst;
+               }
+       },
+
+       /* Generate the date picker content. */
+       _updateDatepicker: function(inst) {
+               var self = this;
+               self.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
+               var borders = $.datepicker._getBorders(inst.dpDiv);
+               instActive = inst; // for delegate hover events
+               inst.dpDiv.empty().append(this._generateHTML(inst));
+               this._attachHandlers(inst);
+               var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
+               if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
+                       cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
+               }
+               inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
+               var numMonths = this._getNumberOfMonths(inst);
+               var cols = numMonths[1];
+               var width = 17;
+               inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
+               if (cols > 1)
+                       inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
+               inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
+                       'Class']('ui-datepicker-multi');
+               inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
+                       'Class']('ui-datepicker-rtl');
+               if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
+                               // #6694 - don't focus the input if it's already focused
+                               // this breaks the change event in IE
+                               inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
+                       inst.input.focus();
+               // deffered render of the years select (to avoid flashes on Firefox) 
+               if( inst.yearshtml ){
+                       var origyearshtml = inst.yearshtml;
+                       setTimeout(function(){
+                               //assure that inst.yearshtml didn't change.
+                               if( origyearshtml === inst.yearshtml && inst.yearshtml ){
+                                       inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
+                               }
+                               origyearshtml = inst.yearshtml = null;
+                       }, 0);
+               }
+       },
+
+       /* Retrieve the size of left and top borders for an element.
+          @param  elem  (jQuery object) the element of interest
+          @return  (number[2]) the left and top borders */
+       _getBorders: function(elem) {
+               var convert = function(value) {
+                       return {thin: 1, medium: 2, thick: 3}[value] || value;
+               };
+               return [parseFloat(convert(elem.css('border-left-width'))),
+                       parseFloat(convert(elem.css('border-top-width')))];
+       },
+
+       /* Check positioning to remain on screen. */
+       _checkOffset: function(inst, offset, isFixed) {
+               var dpWidth = inst.dpDiv.outerWidth();
+               var dpHeight = inst.dpDiv.outerHeight();
+               var inputWidth = inst.input ? inst.input.outerWidth() : 0;
+               var inputHeight = inst.input ? inst.input.outerHeight() : 0;
+               var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft());
+               var viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
+
+               offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
+               offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
+               offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
+
+               // now check if datepicker is showing outside window viewport - move to a better place if so.
+               offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
+                       Math.abs(offset.left + dpWidth - viewWidth) : 0);
+               offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
+                       Math.abs(dpHeight + inputHeight) : 0);
+
+               return offset;
+       },
+
+       /* Find an object's position on the screen. */
+       _findPos: function(obj) {
+               var inst = this._getInst(obj);
+               var isRTL = this._get(inst, 'isRTL');
+        while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
+            obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
+        }
+        var position = $(obj).offset();
+           return [position.left, position.top];
+       },
+
+       /* Hide the date picker from view.
+          @param  input  element - the input field attached to the date picker */
+       _hideDatepicker: function(input) {
+               var inst = this._curInst;
+               if (!inst || (input && inst != $.data(input, PROP_NAME)))
+                       return;
+               if (this._datepickerShowing) {
+                       var showAnim = this._get(inst, 'showAnim');
+                       var duration = this._get(inst, 'duration');
+                       var postProcess = function() {
+                               $.datepicker._tidyDialog(inst);
+                       };
+                       if ($.effects && $.effects[showAnim])
+                               inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
+                       else
+                               inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
+                                       (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
+                       if (!showAnim)
+                               postProcess();
+                       this._datepickerShowing = false;
+                       var onClose = this._get(inst, 'onClose');
+                       if (onClose)
+                               onClose.apply((inst.input ? inst.input[0] : null),
+                                       [(inst.input ? inst.input.val() : ''), inst]);
+                       this._lastInput = null;
+                       if (this._inDialog) {
+                               this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
+                               if ($.blockUI) {
+                                       $.unblockUI();
+                                       $('body').append(this.dpDiv);
+                               }
+                       }
+                       this._inDialog = false;
+               }
+       },
+
+       /* Tidy up after a dialog display. */
+       _tidyDialog: function(inst) {
+               inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
+       },
+
+       /* Close date picker if clicked elsewhere. */
+       _checkExternalClick: function(event) {
+               if (!$.datepicker._curInst)
+                       return;
+
+               var $target = $(event.target),
+                       inst = $.datepicker._getInst($target[0]);
+
+               if ( ( ( $target[0].id != $.datepicker._mainDivId &&
+                               $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
+                               !$target.hasClass($.datepicker.markerClassName) &&
+                               !$target.closest("." + $.datepicker._triggerClass).length &&
+                               $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
+                       ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) )
+                       $.datepicker._hideDatepicker();
+       },
+
+       /* Adjust one of the date sub-fields. */
+       _adjustDate: function(id, offset, period) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               if (this._isDisabledDatepicker(target[0])) {
+                       return;
+               }
+               this._adjustInstDate(inst, offset +
+                       (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
+                       period);
+               this._updateDatepicker(inst);
+       },
+
+       /* Action for current link. */
+       _gotoToday: function(id) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
+                       inst.selectedDay = inst.currentDay;
+                       inst.drawMonth = inst.selectedMonth = inst.currentMonth;
+                       inst.drawYear = inst.selectedYear = inst.currentYear;
+               }
+               else {
+                       var date = new Date();
+                       inst.selectedDay = date.getDate();
+                       inst.drawMonth = inst.selectedMonth = date.getMonth();
+                       inst.drawYear = inst.selectedYear = date.getFullYear();
+               }
+               this._notifyChange(inst);
+               this._adjustDate(target);
+       },
+
+       /* Action for selecting a new month/year. */
+       _selectMonthYear: function(id, select, period) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
+               inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
+                       parseInt(select.options[select.selectedIndex].value,10);
+               this._notifyChange(inst);
+               this._adjustDate(target);
+       },
+
+       /* Action for selecting a day. */
+       _selectDay: function(id, month, year, td) {
+               var target = $(id);
+               if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
+                       return;
+               }
+               var inst = this._getInst(target[0]);
+               inst.selectedDay = inst.currentDay = $('a', td).html();
+               inst.selectedMonth = inst.currentMonth = month;
+               inst.selectedYear = inst.currentYear = year;
+               this._selectDate(id, this._formatDate(inst,
+                       inst.currentDay, inst.currentMonth, inst.currentYear));
+       },
+
+       /* Erase the input field and hide the date picker. */
+       _clearDate: function(id) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               this._selectDate(target, '');
+       },
+
+       /* Update the input field with the selected date. */
+       _selectDate: function(id, dateStr) {
+               var target = $(id);
+               var inst = this._getInst(target[0]);
+               dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
+               if (inst.input)
+                       inst.input.val(dateStr);
+               this._updateAlternate(inst);
+               var onSelect = this._get(inst, 'onSelect');
+               if (onSelect)
+                       onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
+               else if (inst.input)
+                       inst.input.trigger('change'); // fire the change event
+               if (inst.inline)
+                       this._updateDatepicker(inst);
+               else {
+                       this._hideDatepicker();
+                       this._lastInput = inst.input[0];
+                       if (typeof(inst.input[0]) != 'object')
+                               inst.input.focus(); // restore focus
+                       this._lastInput = null;
+               }
+       },
+
+       /* Update any alternate field to synchronise with the main field. */
+       _updateAlternate: function(inst) {
+               var altField = this._get(inst, 'altField');
+               if (altField) { // update alternate field too
+                       var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
+                       var date = this._getDate(inst);
+                       var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
+                       $(altField).each(function() { $(this).val(dateStr); });
+               }
+       },
+
+       /* Set as beforeShowDay function to prevent selection of weekends.
+          @param  date  Date - the date to customise
+          @return [boolean, string] - is this date selectable?, what is its CSS class? */
+       noWeekends: function(date) {
+               var day = date.getDay();
+               return [(day > 0 && day < 6), ''];
+       },
+
+       /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
+          @param  date  Date - the date to get the week for
+          @return  number - the number of the week within the year that contains this date */
+       iso8601Week: function(date) {
+               var checkDate = new Date(date.getTime());
+               // Find Thursday of this week starting on Monday
+               checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
+               var time = checkDate.getTime();
+               checkDate.setMonth(0); // Compare with Jan 1
+               checkDate.setDate(1);
+               return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
+       },
+
+       /* Parse a string value into a date object.
+          See formatDate below for the possible formats.
+
+          @param  format    string - the expected format of the date
+          @param  value     string - the date in the above format
+          @param  settings  Object - attributes include:
+                            shortYearCutoff  number - the cutoff year for determining the century (optional)
+                            dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
+                            dayNames         string[7] - names of the days from Sunday (optional)
+                            monthNamesShort  string[12] - abbreviated names of the months (optional)
+                            monthNames       string[12] - names of the months (optional)
+          @return  Date - the extracted date value or null if value is blank */
+       parseDate: function (format, value, settings) {
+               if (format == null || value == null)
+                       throw 'Invalid arguments';
+               value = (typeof value == 'object' ? value.toString() : value + '');
+               if (value == '')
+                       return null;
+               var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
+               shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
+                               new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
+               var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
+               var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
+               var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
+               var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
+               var year = -1;
+               var month = -1;
+               var day = -1;
+               var doy = -1;
+               var literal = false;
+               // Check whether a format character is doubled
+               var lookAhead = function(match) {
+                       var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+                       if (matches)
+                               iFormat++;
+                       return matches;
+               };
+               // Extract a number from the string value
+               var getNumber = function(match) {
+                       var isDoubled = lookAhead(match);
+                       var size = (match == '@' ? 14 : (match == '!' ? 20 :
+                               (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
+                       var digits = new RegExp('^\\d{1,' + size + '}');
+                       var num = value.substring(iValue).match(digits);
+                       if (!num)
+                               throw 'Missing number at position ' + iValue;
+                       iValue += num[0].length;
+                       return parseInt(num[0], 10);
+               };
+               // Extract a name from the string value and convert to an index
+               var getName = function(match, shortNames, longNames) {
+                       var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
+                               return [ [k, v] ];
+                       }).sort(function (a, b) {
+                               return -(a[1].length - b[1].length);
+                       });
+                       var index = -1;
+                       $.each(names, function (i, pair) {
+                               var name = pair[1];
+                               if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
+                                       index = pair[0];
+                                       iValue += name.length;
+                                       return false;
+                               }
+                       });
+                       if (index != -1)
+                               return index + 1;
+                       else
+                               throw 'Unknown name at position ' + iValue;
+               };
+               // Confirm that a literal character matches the string value
+               var checkLiteral = function() {
+                       if (value.charAt(iValue) != format.charAt(iFormat))
+                               throw 'Unexpected literal at position ' + iValue;
+                       iValue++;
+               };
+               var iValue = 0;
+               for (var iFormat = 0; iFormat < format.length; iFormat++) {
+                       if (literal)
+                               if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+                                       literal = false;
+                               else
+                                       checkLiteral();
+                       else
+                               switch (format.charAt(iFormat)) {
+                                       case 'd':
+                                               day = getNumber('d');
+                                               break;
+                                       case 'D':
+                                               getName('D', dayNamesShort, dayNames);
+                                               break;
+                                       case 'o':
+                                               doy = getNumber('o');
+                                               break;
+                                       case 'm':
+                                               month = getNumber('m');
+                                               break;
+                                       case 'M':
+                                               month = getName('M', monthNamesShort, monthNames);
+                                               break;
+                                       case 'y':
+                                               year = getNumber('y');
+                                               break;
+                                       case '@':
+                                               var date = new Date(getNumber('@'));
+                                               year = date.getFullYear();
+                                               month = date.getMonth() + 1;
+                                               day = date.getDate();
+                                               break;
+                                       case '!':
+                                               var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
+                                               year = date.getFullYear();
+                                               month = date.getMonth() + 1;
+                                               day = date.getDate();
+                                               break;
+                                       case "'":
+                                               if (lookAhead("'"))
+                                                       checkLiteral();
+                                               else
+                                                       literal = true;
+                                               break;
+                                       default:
+                                               checkLiteral();
+                               }
+               }
+               if (iValue < value.length){
+                       throw "Extra/unparsed characters found in date: " + value.substring(iValue);
+               }
+               if (year == -1)
+                       year = new Date().getFullYear();
+               else if (year < 100)
+                       year += new Date().getFullYear() - new Date().getFullYear() % 100 +
+                               (year <= shortYearCutoff ? 0 : -100);
+               if (doy > -1) {
+                       month = 1;
+                       day = doy;
+                       do {
+                               var dim = this._getDaysInMonth(year, month - 1);
+                               if (day <= dim)
+                                       break;
+                               month++;
+                               day -= dim;
+                       } while (true);
+               }
+               var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
+               if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
+                       throw 'Invalid date'; // E.g. 31/02/00
+               return date;
+       },
+
+       /* Standard date formats. */
+       ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
+       COOKIE: 'D, dd M yy',
+       ISO_8601: 'yy-mm-dd',
+       RFC_822: 'D, d M y',
+       RFC_850: 'DD, dd-M-y',
+       RFC_1036: 'D, d M y',
+       RFC_1123: 'D, d M yy',
+       RFC_2822: 'D, d M yy',
+       RSS: 'D, d M y', // RFC 822
+       TICKS: '!',
+       TIMESTAMP: '@',
+       W3C: 'yy-mm-dd', // ISO 8601
+
+       _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
+               Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
+
+       /* Format a date object into a string value.
+          The format can be combinations of the following:
+          d  - day of month (no leading zero)
+          dd - day of month (two digit)
+          o  - day of year (no leading zeros)
+          oo - day of year (three digit)
+          D  - day name short
+          DD - day name long
+          m  - month of year (no leading zero)
+          mm - month of year (two digit)
+          M  - month name short
+          MM - month name long
+          y  - year (two digit)
+          yy - year (four digit)
+          @ - Unix timestamp (ms since 01/01/1970)
+          ! - Windows ticks (100ns since 01/01/0001)
+          '...' - literal text
+          '' - single quote
+
+          @param  format    string - the desired format of the date
+          @param  date      Date - the date value to format
+          @param  settings  Object - attributes include:
+                            dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
+                            dayNames         string[7] - names of the days from Sunday (optional)
+                            monthNamesShort  string[12] - abbreviated names of the months (optional)
+                            monthNames       string[12] - names of the months (optional)
+          @return  string - the date in the above format */
+       formatDate: function (format, date, settings) {
+               if (!date)
+                       return '';
+               var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
+               var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
+               var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
+               var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
+               // Check whether a format character is doubled
+               var lookAhead = function(match) {
+                       var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+                       if (matches)
+                               iFormat++;
+                       return matches;
+               };
+               // Format a number, with leading zero if necessary
+               var formatNumber = function(match, value, len) {
+                       var num = '' + value;
+                       if (lookAhead(match))
+                               while (num.length < len)
+                                       num = '0' + num;
+                       return num;
+               };
+               // Format a name, short or long as requested
+               var formatName = function(match, value, shortNames, longNames) {
+                       return (lookAhead(match) ? longNames[value] : shortNames[value]);
+               };
+               var output = '';
+               var literal = false;
+               if (date)
+                       for (var iFormat = 0; iFormat < format.length; iFormat++) {
+                               if (literal)
+                                       if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+                                               literal = false;
+                                       else
+                                               output += format.charAt(iFormat);
+                               else
+                                       switch (format.charAt(iFormat)) {
+                                               case 'd':
+                                                       output += formatNumber('d', date.getDate(), 2);
+                                                       break;
+                                               case 'D':
+                                                       output += formatName('D', date.getDay(), dayNamesShort, dayNames);
+                                                       break;
+                                               case 'o':
+                                                       output += formatNumber('o',
+                                                               Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
+                                                       break;
+                                               case 'm':
+                                                       output += formatNumber('m', date.getMonth() + 1, 2);
+                                                       break;
+                                               case 'M':
+                                                       output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
+                                                       break;
+                                               case 'y':
+                                                       output += (lookAhead('y') ? date.getFullYear() :
+                                                               (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
+                                                       break;
+                                               case '@':
+                                                       output += date.getTime();
+                                                       break;
+                                               case '!':
+                                                       output += date.getTime() * 10000 + this._ticksTo1970;
+                                                       break;
+                                               case "'":
+                                                       if (lookAhead("'"))
+                                                               output += "'";
+                                                       else
+                                                               literal = true;
+                                                       break;
+                                               default:
+                                                       output += format.charAt(iFormat);
+                                       }
+                       }
+               return output;
+       },
+
+       /* Extract all possible characters from the date format. */
+       _possibleChars: function (format) {
+               var chars = '';
+               var literal = false;
+               // Check whether a format character is doubled
+               var lookAhead = function(match) {
+                       var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+                       if (matches)
+                               iFormat++;
+                       return matches;
+               };
+               for (var iFormat = 0; iFormat < format.length; iFormat++)
+                       if (literal)
+                               if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+                                       literal = false;
+                               else
+                                       chars += format.charAt(iFormat);
+                       else
+                               switch (format.charAt(iFormat)) {
+                                       case 'd': case 'm': case 'y': case '@':
+                                               chars += '0123456789';
+                                               break;
+                                       case 'D': case 'M':
+                                               return null; // Accept anything
+                                       case "'":
+                                               if (lookAhead("'"))
+                                                       chars += "'";
+                                               else
+                                                       literal = true;
+                                               break;
+                                       default:
+                                               chars += format.charAt(iFormat);
+                               }
+               return chars;
+       },
+
+       /* Get a setting value, defaulting if necessary. */
+       _get: function(inst, name) {
+               return inst.settings[name] !== undefined ?
+                       inst.settings[name] : this._defaults[name];
+       },
+
+       /* Parse existing date and initialise date picker. */
+       _setDateFromField: function(inst, noDefault) {
+               if (inst.input.val() == inst.lastVal) {
+                       return;
+               }
+               var dateFormat = this._get(inst, 'dateFormat');
+               var dates = inst.lastVal = inst.input ? inst.input.val() : null;
+               var date, defaultDate;
+               date = defaultDate = this._getDefaultDate(inst);
+               var settings = this._getFormatConfig(inst);
+               try {
+                       date = this.parseDate(dateFormat, dates, settings) || defaultDate;
+               } catch (event) {
+                       this.log(event);
+                       dates = (noDefault ? '' : dates);
+               }
+               inst.selectedDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = date.getFullYear();
+               inst.currentDay = (dates ? date.getDate() : 0);
+               inst.currentMonth = (dates ? date.getMonth() : 0);
+               inst.currentYear = (dates ? date.getFullYear() : 0);
+               this._adjustInstDate(inst);
+       },
+
+       /* Retrieve the default date shown on opening. */
+       _getDefaultDate: function(inst) {
+               return this._restrictMinMax(inst,
+                       this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
+       },
+
+       /* A date may be specified as an exact value or a relative one. */
+       _determineDate: function(inst, date, defaultDate) {
+               var offsetNumeric = function(offset) {
+                       var date = new Date();
+                       date.setDate(date.getDate() + offset);
+                       return date;
+               };
+               var offsetString = function(offset) {
+                       try {
+                               return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
+                                       offset, $.datepicker._getFormatConfig(inst));
+                       }
+                       catch (e) {
+                               // Ignore
+                       }
+                       var date = (offset.toLowerCase().match(/^c/) ?
+                               $.datepicker._getDate(inst) : null) || new Date();
+                       var year = date.getFullYear();
+                       var month = date.getMonth();
+                       var day = date.getDate();
+                       var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
+                       var matches = pattern.exec(offset);
+                       while (matches) {
+                               switch (matches[2] || 'd') {
+                                       case 'd' : case 'D' :
+                                               day += parseInt(matches[1],10); break;
+                                       case 'w' : case 'W' :
+                                               day += parseInt(matches[1],10) * 7; break;
+                                       case 'm' : case 'M' :
+                                               month += parseInt(matches[1],10);
+                                               day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
+                                               break;
+                                       case 'y': case 'Y' :
+                                               year += parseInt(matches[1],10);
+                                               day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
+                                               break;
+                               }
+                               matches = pattern.exec(offset);
+                       }
+                       return new Date(year, month, day);
+               };
+               var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
+                       (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
+               newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
+               if (newDate) {
+                       newDate.setHours(0);
+                       newDate.setMinutes(0);
+                       newDate.setSeconds(0);
+                       newDate.setMilliseconds(0);
+               }
+               return this._daylightSavingAdjust(newDate);
+       },
+
+       /* Handle switch to/from daylight saving.
+          Hours may be non-zero on daylight saving cut-over:
+          > 12 when midnight changeover, but then cannot generate
+          midnight datetime, so jump to 1AM, otherwise reset.
+          @param  date  (Date) the date to check
+          @return  (Date) the corrected date */
+       _daylightSavingAdjust: function(date) {
+               if (!date) return null;
+               date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
+               return date;
+       },
+
+       /* Set the date(s) directly. */
+       _setDate: function(inst, date, noChange) {
+               var clear = !date;
+               var origMonth = inst.selectedMonth;
+               var origYear = inst.selectedYear;
+               var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
+               inst.selectedDay = inst.currentDay = newDate.getDate();
+               inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
+               inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
+               if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
+                       this._notifyChange(inst);
+               this._adjustInstDate(inst);
+               if (inst.input) {
+                       inst.input.val(clear ? '' : this._formatDate(inst));
+               }
+       },
+
+       /* Retrieve the date(s) directly. */
+       _getDate: function(inst) {
+               var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
+                       this._daylightSavingAdjust(new Date(
+                       inst.currentYear, inst.currentMonth, inst.currentDay)));
+                       return startDate;
+       },
+
+       /* Attach the onxxx handlers.  These are declared statically so
+        * they work with static code transformers like Caja.
+        */
+       _attachHandlers: function(inst) {
+               var stepMonths = this._get(inst, 'stepMonths');
+               var id = '#' + inst.id.replace( /\\\\/g, "\\" );
+               inst.dpDiv.find('[data-handler]').map(function () {
+                       var handler = {
+                               prev: function () {
+                                       window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M');
+                               },
+                               next: function () {
+                                       window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M');
+                               },
+                               hide: function () {
+                                       window['DP_jQuery_' + dpuuid].datepicker._hideDatepicker();
+                               },
+                               today: function () {
+                                       window['DP_jQuery_' + dpuuid].datepicker._gotoToday(id);
+                               },
+                               selectDay: function () {
+                                       window['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this);
+                                       return false;
+                               },
+                               selectMonth: function () {
+                                       window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M');
+                                       return false;
+                               },
+                               selectYear: function () {
+                                       window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y');
+                                       return false;
+                               }
+                       };
+                       $(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]);
+               });
+       },
+       
+       /* Generate the HTML for the current state of the date picker. */
+       _generateHTML: function(inst) {
+               var today = new Date();
+               today = this._daylightSavingAdjust(
+                       new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
+               var isRTL = this._get(inst, 'isRTL');
+               var showButtonPanel = this._get(inst, 'showButtonPanel');
+               var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
+               var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
+               var numMonths = this._getNumberOfMonths(inst);
+               var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
+               var stepMonths = this._get(inst, 'stepMonths');
+               var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
+               var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
+                       new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
+               var minDate = this._getMinMaxDate(inst, 'min');
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               var drawMonth = inst.drawMonth - showCurrentAtPos;
+               var drawYear = inst.drawYear;
+               if (drawMonth < 0) {
+                       drawMonth += 12;
+                       drawYear--;
+               }
+               if (maxDate) {
+                       var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
+                               maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
+                       maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
+                       while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
+                               drawMonth--;
+                               if (drawMonth < 0) {
+                                       drawMonth = 11;
+                                       drawYear--;
+                               }
+                       }
+               }
+               inst.drawMonth = drawMonth;
+               inst.drawYear = drawYear;
+               var prevText = this._get(inst, 'prevText');
+               prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
+                       this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
+                       this._getFormatConfig(inst)));
+               var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
+                       '<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click"' +
+                       ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
+                       (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
+               var nextText = this._get(inst, 'nextText');
+               nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
+                       this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
+                       this._getFormatConfig(inst)));
+               var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
+                       '<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click"' +
+                       ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
+                       (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
+               var currentText = this._get(inst, 'currentText');
+               var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
+               currentText = (!navigationAsDateFormat ? currentText :
+                       this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
+               var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">' +
+                       this._get(inst, 'closeText') + '</button>' : '');
+               var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
+                       (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click"' +
+                       '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
+               var firstDay = parseInt(this._get(inst, 'firstDay'),10);
+               firstDay = (isNaN(firstDay) ? 0 : firstDay);
+               var showWeek = this._get(inst, 'showWeek');
+               var dayNames = this._get(inst, 'dayNames');
+               var dayNamesShort = this._get(inst, 'dayNamesShort');
+               var dayNamesMin = this._get(inst, 'dayNamesMin');
+               var monthNames = this._get(inst, 'monthNames');
+               var monthNamesShort = this._get(inst, 'monthNamesShort');
+               var beforeShowDay = this._get(inst, 'beforeShowDay');
+               var showOtherMonths = this._get(inst, 'showOtherMonths');
+               var selectOtherMonths = this._get(inst, 'selectOtherMonths');
+               var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
+               var defaultDate = this._getDefaultDate(inst);
+               var html = '';
+               for (var row = 0; row < numMonths[0]; row++) {
+                       var group = '';
+                       this.maxRows = 4;
+                       for (var col = 0; col < numMonths[1]; col++) {
+                               var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
+                               var cornerClass = ' ui-corner-all';
+                               var calender = '';
+                               if (isMultiMonth) {
+                                       calender += '<div class="ui-datepicker-group';
+                                       if (numMonths[1] > 1)
+                                               switch (col) {
+                                                       case 0: calender += ' ui-datepicker-group-first';
+                                                               cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
+                                                       case numMonths[1]-1: calender += ' ui-datepicker-group-last';
+                                                               cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
+                                                       default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
+                                               }
+                                       calender += '">';
+                               }
+                               calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
+                                       (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
+                                       (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
+                                       this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
+                                       row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
+                                       '</div><table class="ui-datepicker-calendar"><thead>' +
+                                       '<tr>';
+                               var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
+                               for (var dow = 0; dow < 7; dow++) { // days of the week
+                                       var day = (dow + firstDay) % 7;
+                                       thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
+                                               '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
+                               }
+                               calender += thead + '</tr></thead><tbody>';
+                               var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
+                               if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
+                                       inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
+                               var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
+                               var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
+                               var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
+                               this.maxRows = numRows;
+                               var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
+                               for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
+                                       calender += '<tr>';
+                                       var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
+                                               this._get(inst, 'calculateWeek')(printDate) + '</td>');
+                                       for (var dow = 0; dow < 7; dow++) { // create date picker days
+                                               var daySettings = (beforeShowDay ?
+                                                       beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
+                                               var otherMonth = (printDate.getMonth() != drawMonth);
+                                               var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
+                                                       (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
+                                               tbody += '<td class="' +
+                                                       ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
+                                                       (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
+                                                       ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
+                                                       (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
+                                                       // or defaultDate is current printedDate and defaultDate is selectedDate
+                                                       ' ' + this._dayOverClass : '') + // highlight selected day
+                                                       (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
+                                                       (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
+                                                       (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
+                                                       (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
+                                                       ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
+                                                       (unselectable ? '' : ' data-handler="selectDay" data-event="click" data-month="' + printDate.getMonth() + '" data-year="' + printDate.getFullYear() + '"') + '>' + // actions
+                                                       (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
+                                                       (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
+                                                       (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
+                                                       (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
+                                                       (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
+                                                       '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
+                                               printDate.setDate(printDate.getDate() + 1);
+                                               printDate = this._daylightSavingAdjust(printDate);
+                                       }
+                                       calender += tbody + '</tr>';
+                               }
+                               drawMonth++;
+                               if (drawMonth > 11) {
+                                       drawMonth = 0;
+                                       drawYear++;
+                               }
+                               calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
+                                                       ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
+                               group += calender;
+                       }
+                       html += group;
+               }
+               html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
+                       '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
+               inst._keyEvent = false;
+               return html;
+       },
+
+       /* Generate the month and year header. */
+       _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
+                       secondary, monthNames, monthNamesShort) {
+               var changeMonth = this._get(inst, 'changeMonth');
+               var changeYear = this._get(inst, 'changeYear');
+               var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
+               var html = '<div class="ui-datepicker-title">';
+               var monthHtml = '';
+               // month selection
+               if (secondary || !changeMonth)
+                       monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
+               else {
+                       var inMinYear = (minDate && minDate.getFullYear() == drawYear);
+                       var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
+                       monthHtml += '<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';
+                       for (var month = 0; month < 12; month++) {
+                               if ((!inMinYear || month >= minDate.getMonth()) &&
+                                               (!inMaxYear || month <= maxDate.getMonth()))
+                                       monthHtml += '<option value="' + month + '"' +
+                                               (month == drawMonth ? ' selected="selected"' : '') +
+                                               '>' + monthNamesShort[month] + '</option>';
+                       }
+                       monthHtml += '</select>';
+               }
+               if (!showMonthAfterYear)
+                       html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
+               // year selection
+               if ( !inst.yearshtml ) {
+                       inst.yearshtml = '';
+                       if (secondary || !changeYear)
+                               html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
+                       else {
+                               // determine range of years to display
+                               var years = this._get(inst, 'yearRange').split(':');
+                               var thisYear = new Date().getFullYear();
+                               var determineYear = function(value) {
+                                       var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
+                                               (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
+                                               parseInt(value, 10)));
+                                       return (isNaN(year) ? thisYear : year);
+                               };
+                               var year = determineYear(years[0]);
+                               var endYear = Math.max(year, determineYear(years[1] || ''));
+                               year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
+                               endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
+                               inst.yearshtml += '<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';
+                               for (; year <= endYear; year++) {
+                                       inst.yearshtml += '<option value="' + year + '"' +
+                                               (year == drawYear ? ' selected="selected"' : '') +
+                                               '>' + year + '</option>';
+                               }
+                               inst.yearshtml += '</select>';
+                               
+                               html += inst.yearshtml;
+                               inst.yearshtml = null;
+                       }
+               }
+               html += this._get(inst, 'yearSuffix');
+               if (showMonthAfterYear)
+                       html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
+               html += '</div>'; // Close datepicker_header
+               return html;
+       },
+
+       /* Adjust one of the date sub-fields. */
+       _adjustInstDate: function(inst, offset, period) {
+               var year = inst.drawYear + (period == 'Y' ? offset : 0);
+               var month = inst.drawMonth + (period == 'M' ? offset : 0);
+               var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
+                       (period == 'D' ? offset : 0);
+               var date = this._restrictMinMax(inst,
+                       this._daylightSavingAdjust(new Date(year, month, day)));
+               inst.selectedDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = date.getFullYear();
+               if (period == 'M' || period == 'Y')
+                       this._notifyChange(inst);
+       },
+
+       /* Ensure a date is within any min/max bounds. */
+       _restrictMinMax: function(inst, date) {
+               var minDate = this._getMinMaxDate(inst, 'min');
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               var newDate = (minDate && date < minDate ? minDate : date);
+               newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
+               return newDate;
+       },
+
+       /* Notify change of month/year. */
+       _notifyChange: function(inst) {
+               var onChange = this._get(inst, 'onChangeMonthYear');
+               if (onChange)
+                       onChange.apply((inst.input ? inst.input[0] : null),
+                               [inst.selectedYear, inst.selectedMonth + 1, inst]);
+       },
+
+       /* Determine the number of months to show. */
+       _getNumberOfMonths: function(inst) {
+               var numMonths = this._get(inst, 'numberOfMonths');
+               return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
+       },
+
+       /* Determine the current maximum date - ensure no time components are set. */
+       _getMinMaxDate: function(inst, minMax) {
+               return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
+       },
+
+       /* Find the number of days in a given month. */
+       _getDaysInMonth: function(year, month) {
+               return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
+       },
+
+       /* Find the day of the week of the first of a month. */
+       _getFirstDayOfMonth: function(year, month) {
+               return new Date(year, month, 1).getDay();
+       },
+
+       /* Determines if we should allow a "next/prev" month display change. */
+       _canAdjustMonth: function(inst, offset, curYear, curMonth) {
+               var numMonths = this._getNumberOfMonths(inst);
+               var date = this._daylightSavingAdjust(new Date(curYear,
+                       curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
+               if (offset < 0)
+                       date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
+               return this._isInRange(inst, date);
+       },
+
+       /* Is the given date in the accepted range? */
+       _isInRange: function(inst, date) {
+               var minDate = this._getMinMaxDate(inst, 'min');
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               return ((!minDate || date.getTime() >= minDate.getTime()) &&
+                       (!maxDate || date.getTime() <= maxDate.getTime()));
+       },
+
+       /* Provide the configuration settings for formatting/parsing. */
+       _getFormatConfig: function(inst) {
+               var shortYearCutoff = this._get(inst, 'shortYearCutoff');
+               shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
+                       new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
+               return {shortYearCutoff: shortYearCutoff,
+                       dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
+                       monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
+       },
+
+       /* Format the given date for display. */
+       _formatDate: function(inst, day, month, year) {
+               if (!day) {
+                       inst.currentDay = inst.selectedDay;
+                       inst.currentMonth = inst.selectedMonth;
+                       inst.currentYear = inst.selectedYear;
+               }
+               var date = (day ? (typeof day == 'object' ? day :
+                       this._daylightSavingAdjust(new Date(year, month, day))) :
+                       this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
+               return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
+       }
+});
+
+/*
+ * Bind hover events for datepicker elements.
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
+ * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
+ */ 
+function bindHover(dpDiv) {
+       var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
+       return dpDiv.bind('mouseout', function(event) {
+                       var elem = $( event.target ).closest( selector );
+                       if ( !elem.length ) {
+                               return;
+                       }
+                       elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
+               })
+               .bind('mouseover', function(event) {
+                       var elem = $( event.target ).closest( selector );
+                       if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) ||
+                                       !elem.length ) {
+                               return;
+                       }
+                       elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
+                       elem.addClass('ui-state-hover');
+                       if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover');
+                       if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover');
+               });
+}
+
+/* jQuery extend now ignores nulls! */
+function extendRemove(target, props) {
+       $.extend(target, props);
+       for (var name in props)
+               if (props[name] == null || props[name] == undefined)
+                       target[name] = props[name];
+       return target;
+};
+
+/* Determine whether an object is an array. */
+function isArray(a) {
+       return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
+               (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
+};
+
+/* Invoke the datepicker functionality.
+   @param  options  string - a command, optionally followed by additional parameters or
+                    Object - settings for attaching new datepicker functionality
+   @return  jQuery object */
+$.fn.datepicker = function(options){
+       
+       /* Verify an empty collection wasn't passed - Fixes #6976 */
+       if ( !this.length ) {
+               return this;
+       }
+       
+       /* Initialise the date picker. */
+       if (!$.datepicker.initialized) {
+               $(document).mousedown($.datepicker._checkExternalClick).
+                       find('body').append($.datepicker.dpDiv);
+               $.datepicker.initialized = true;
+       }
+
+       var otherArgs = Array.prototype.slice.call(arguments, 1);
+       if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
+               return $.datepicker['_' + options + 'Datepicker'].
+                       apply($.datepicker, [this[0]].concat(otherArgs));
+       if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
+               return $.datepicker['_' + options + 'Datepicker'].
+                       apply($.datepicker, [this[0]].concat(otherArgs));
+       return this.each(function() {
+               typeof options == 'string' ?
+                       $.datepicker['_' + options + 'Datepicker'].
+                               apply($.datepicker, [this].concat(otherArgs)) :
+                       $.datepicker._attachDatepicker(this, options);
+       });
+};
+
+$.datepicker = new Datepicker(); // singleton instance
+$.datepicker.initialized = false;
+$.datepicker.uuid = new Date().getTime();
+$.datepicker.version = "1.8.24";
+
+// Workaround for #4055
+// Add another global to avoid noConflict issues with inline event handlers
+window['DP_jQuery_' + dpuuid] = $;
+
+})(jQuery);
diff --git a/resources/lib/jquery.ui/jquery.ui.dialog.js b/resources/lib/jquery.ui/jquery.ui.dialog.js
new file mode 100644 (file)
index 0000000..06b85f2
--- /dev/null
@@ -0,0 +1,866 @@
+/*!
+ * jQuery UI Dialog 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *     jquery.ui.widget.js
+ *  jquery.ui.button.js
+ *     jquery.ui.draggable.js
+ *     jquery.ui.mouse.js
+ *     jquery.ui.position.js
+ *     jquery.ui.resizable.js
+ */
+(function( $, undefined ) {
+
+var uiDialogClasses =
+               'ui-dialog ' +
+               'ui-widget ' +
+               'ui-widget-content ' +
+               'ui-corner-all ',
+       sizeRelatedOptions = {
+               buttons: true,
+               height: true,
+               maxHeight: true,
+               maxWidth: true,
+               minHeight: true,
+               minWidth: true,
+               width: true
+       },
+       resizableRelatedOptions = {
+               maxHeight: true,
+               maxWidth: true,
+               minHeight: true,
+               minWidth: true
+       };
+
+$.widget("ui.dialog", {
+       options: {
+               autoOpen: true,
+               buttons: {},
+               closeOnEscape: true,
+               closeText: 'close',
+               dialogClass: '',
+               draggable: true,
+               hide: null,
+               height: 'auto',
+               maxHeight: false,
+               maxWidth: false,
+               minHeight: 150,
+               minWidth: 150,
+               modal: false,
+               position: {
+                       my: 'center',
+                       at: 'center',
+                       collision: 'fit',
+                       // ensure that the titlebar is never outside the document
+                       using: function(pos) {
+                               var topOffset = $(this).css(pos).offset().top;
+                               if (topOffset < 0) {
+                                       $(this).css('top', pos.top - topOffset);
+                               }
+                       }
+               },
+               resizable: true,
+               show: null,
+               stack: true,
+               title: '',
+               width: 300,
+               zIndex: 1000
+       },
+
+       _create: function() {
+               this.originalTitle = this.element.attr('title');
+               // #5742 - .attr() might return a DOMElement
+               if ( typeof this.originalTitle !== "string" ) {
+                       this.originalTitle = "";
+               }
+
+               this.options.title = this.options.title || this.originalTitle;
+               var self = this,
+                       options = self.options,
+
+                       title = options.title || '&#160;',
+                       titleId = $.ui.dialog.getTitleId(self.element),
+
+                       uiDialog = (self.uiDialog = $('<div></div>'))
+                               .appendTo(document.body)
+                               .hide()
+                               .addClass(uiDialogClasses + options.dialogClass)
+                               .css({
+                                       zIndex: options.zIndex
+                               })
+                               // setting tabIndex makes the div focusable
+                               // setting outline to 0 prevents a border on focus in Mozilla
+                               .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
+                                       if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
+                                               event.keyCode === $.ui.keyCode.ESCAPE) {
+                                               
+                                               self.close(event);
+                                               event.preventDefault();
+                                       }
+                               })
+                               .attr({
+                                       role: 'dialog',
+                                       'aria-labelledby': titleId
+                               })
+                               .mousedown(function(event) {
+                                       self.moveToTop(false, event);
+                               }),
+
+                       uiDialogContent = self.element
+                               .show()
+                               .removeAttr('title')
+                               .addClass(
+                                       'ui-dialog-content ' +
+                                       'ui-widget-content')
+                               .appendTo(uiDialog),
+
+                       uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
+                               .addClass(
+                                       'ui-dialog-titlebar ' +
+                                       'ui-widget-header ' +
+                                       'ui-corner-all ' +
+                                       'ui-helper-clearfix'
+                               )
+                               .prependTo(uiDialog),
+
+                       uiDialogTitlebarClose = $('<a href="#"></a>')
+                               .addClass(
+                                       'ui-dialog-titlebar-close ' +
+                                       'ui-corner-all'
+                               )
+                               .attr('role', 'button')
+                               .hover(
+                                       function() {
+                                               uiDialogTitlebarClose.addClass('ui-state-hover');
+                                       },
+                                       function() {
+                                               uiDialogTitlebarClose.removeClass('ui-state-hover');
+                                       }
+                               )
+                               .focus(function() {
+                                       uiDialogTitlebarClose.addClass('ui-state-focus');
+                               })
+                               .blur(function() {
+                                       uiDialogTitlebarClose.removeClass('ui-state-focus');
+                               })
+                               .click(function(event) {
+                                       self.close(event);
+                                       return false;
+                               })
+                               .appendTo(uiDialogTitlebar),
+
+                       uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
+                               .addClass(
+                                       'ui-icon ' +
+                                       'ui-icon-closethick'
+                               )
+                               .text(options.closeText)
+                               .appendTo(uiDialogTitlebarClose),
+
+                       uiDialogTitle = $('<span></span>')
+                               .addClass('ui-dialog-title')
+                               .attr('id', titleId)
+                               .html(title)
+                               .prependTo(uiDialogTitlebar);
+
+               //handling of deprecated beforeclose (vs beforeClose) option
+               //Ticket #4669 http://dev.jqueryui.com/ticket/4669
+               //TODO: remove in 1.9pre
+               if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
+                       options.beforeClose = options.beforeclose;
+               }
+
+               uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
+
+               if (options.draggable && $.fn.draggable) {
+                       self._makeDraggable();
+               }
+               if (options.resizable && $.fn.resizable) {
+                       self._makeResizable();
+               }
+
+               self._createButtons(options.buttons);
+               self._isOpen = false;
+
+               if ($.fn.bgiframe) {
+                       uiDialog.bgiframe();
+               }
+       },
+
+       _init: function() {
+               if ( this.options.autoOpen ) {
+                       this.open();
+               }
+       },
+
+       destroy: function() {
+               var self = this;
+               
+               if (self.overlay) {
+                       self.overlay.destroy();
+               }
+               self.uiDialog.hide();
+               self.element
+                       .unbind('.dialog')
+                       .removeData('dialog')
+                       .removeClass('ui-dialog-content ui-widget-content')
+                       .hide().appendTo('body');
+               self.uiDialog.remove();
+
+               if (self.originalTitle) {
+                       self.element.attr('title', self.originalTitle);
+               }
+
+               return self;
+       },
+
+       widget: function() {
+               return this.uiDialog;
+       },
+
+       close: function(event) {
+               var self = this,
+                       maxZ, thisZ;
+               
+               if (false === self._trigger('beforeClose', event)) {
+                       return;
+               }
+
+               if (self.overlay) {
+                       self.overlay.destroy();
+               }
+               self.uiDialog.unbind('keypress.ui-dialog');
+
+               self._isOpen = false;
+
+               if (self.options.hide) {
+                       self.uiDialog.hide(self.options.hide, function() {
+                               self._trigger('close', event);
+                       });
+               } else {
+                       self.uiDialog.hide();
+                       self._trigger('close', event);
+               }
+
+               $.ui.dialog.overlay.resize();
+
+               // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
+               if (self.options.modal) {
+                       maxZ = 0;
+                       $('.ui-dialog').each(function() {
+                               if (this !== self.uiDialog[0]) {
+                                       thisZ = $(this).css('z-index');
+                                       if(!isNaN(thisZ)) {
+                                               maxZ = Math.max(maxZ, thisZ);
+                                       }
+                               }
+                       });
+                       $.ui.dialog.maxZ = maxZ;
+               }
+
+               return self;
+       },
+
+       isOpen: function() {
+               return this._isOpen;
+       },
+
+       // the force parameter allows us to move modal dialogs to their correct
+       // position on open
+       moveToTop: function(force, event) {
+               var self = this,
+                       options = self.options,
+                       saveScroll;
+
+               if ((options.modal && !force) ||
+                       (!options.stack && !options.modal)) {
+                       return self._trigger('focus', event);
+               }
+
+               if (options.zIndex > $.ui.dialog.maxZ) {
+                       $.ui.dialog.maxZ = options.zIndex;
+               }
+               if (self.overlay) {
+                       $.ui.dialog.maxZ += 1;
+                       self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
+               }
+
+               //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
+               //  http://ui.jquery.com/bugs/ticket/3193
+               saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() };
+               $.ui.dialog.maxZ += 1;
+               self.uiDialog.css('z-index', $.ui.dialog.maxZ);
+               self.element.attr(saveScroll);
+               self._trigger('focus', event);
+
+               return self;
+       },
+
+       open: function() {
+               if (this._isOpen) { return; }
+
+               var self = this,
+                       options = self.options,
+                       uiDialog = self.uiDialog;
+
+               self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
+               self._size();
+               self._position(options.position);
+               uiDialog.show(options.show);
+               self.moveToTop(true);
+
+               // prevent tabbing out of modal dialogs
+               if ( options.modal ) {
+                       uiDialog.bind( "keydown.ui-dialog", function( event ) {
+                               if ( event.keyCode !== $.ui.keyCode.TAB ) {
+                                       return;
+                               }
+
+                               var tabbables = $(':tabbable', this),
+                                       first = tabbables.filter(':first'),
+                                       last  = tabbables.filter(':last');
+
+                               if (event.target === last[0] && !event.shiftKey) {
+                                       first.focus(1);
+                                       return false;
+                               } else if (event.target === first[0] && event.shiftKey) {
+                                       last.focus(1);
+                                       return false;
+                               }
+                       });
+               }
+
+               // set focus to the first tabbable element in the content area or the first button
+               // if there are no tabbable elements, set focus on the dialog itself
+               $(self.element.find(':tabbable').get().concat(
+                       uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
+                               uiDialog.get()))).eq(0).focus();
+
+               self._isOpen = true;
+               self._trigger('open');
+
+               return self;
+       },
+
+       _createButtons: function(buttons) {
+               var self = this,
+                       hasButtons = false,
+                       uiDialogButtonPane = $('<div></div>')
+                               .addClass(
+                                       'ui-dialog-buttonpane ' +
+                                       'ui-widget-content ' +
+                                       'ui-helper-clearfix'
+                               ),
+                       uiButtonSet = $( "<div></div>" )
+                               .addClass( "ui-dialog-buttonset" )
+                               .appendTo( uiDialogButtonPane );
+
+               // if we already have a button pane, remove it
+               self.uiDialog.find('.ui-dialog-buttonpane').remove();
+
+               if (typeof buttons === 'object' && buttons !== null) {
+                       $.each(buttons, function() {
+                               return !(hasButtons = true);
+                       });
+               }
+               if (hasButtons) {
+                       $.each(buttons, function(name, props) {
+                               props = $.isFunction( props ) ?
+                                       { click: props, text: name } :
+                                       props;
+                               var button = $('<button type="button"></button>')
+                                       .click(function() {
+                                               props.click.apply(self.element[0], arguments);
+                                       })
+                                       .appendTo(uiButtonSet);
+                               // can't use .attr( props, true ) with jQuery 1.3.2.
+                               $.each( props, function( key, value ) {
+                                       if ( key === "click" ) {
+                                               return;
+                                       }
+                                       if ( key in button ) {
+                                               button[ key ]( value );
+                                       } else {
+                                               button.attr( key, value );
+                                       }
+                               });
+                               if ($.fn.button) {
+                                       button.button();
+                               }
+                       });
+                       uiDialogButtonPane.appendTo(self.uiDialog);
+               }
+       },
+
+       _makeDraggable: function() {
+               var self = this,
+                       options = self.options,
+                       doc = $(document),
+                       heightBeforeDrag;
+
+               function filteredUi(ui) {
+                       return {
+                               position: ui.position,
+                               offset: ui.offset
+                       };
+               }
+
+               self.uiDialog.draggable({
+                       cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
+                       handle: '.ui-dialog-titlebar',
+                       containment: 'document',
+                       start: function(event, ui) {
+                               heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
+                               $(this).height($(this).height()).addClass("ui-dialog-dragging");
+                               self._trigger('dragStart', event, filteredUi(ui));
+                       },
+                       drag: function(event, ui) {
+                               self._trigger('drag', event, filteredUi(ui));
+                       },
+                       stop: function(event, ui) {
+                               options.position = [ui.position.left - doc.scrollLeft(),
+                                       ui.position.top - doc.scrollTop()];
+                               $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
+                               self._trigger('dragStop', event, filteredUi(ui));
+                               $.ui.dialog.overlay.resize();
+                       }
+               });
+       },
+
+       _makeResizable: function(handles) {
+               handles = (handles === undefined ? this.options.resizable : handles);
+               var self = this,
+                       options = self.options,
+                       // .ui-resizable has position: relative defined in the stylesheet
+                       // but dialogs have to use absolute or fixed positioning
+                       position = self.uiDialog.css('position'),
+                       resizeHandles = (typeof handles === 'string' ?
+                               handles :
+                               'n,e,s,w,se,sw,ne,nw'
+                       );
+
+               function filteredUi(ui) {
+                       return {
+                               originalPosition: ui.originalPosition,
+                               originalSize: ui.originalSize,
+                               position: ui.position,
+                               size: ui.size
+                       };
+               }
+
+               self.uiDialog.resizable({
+                       cancel: '.ui-dialog-content',
+                       containment: 'document',
+                       alsoResize: self.element,
+                       maxWidth: options.maxWidth,
+                       maxHeight: options.maxHeight,
+                       minWidth: options.minWidth,
+                       minHeight: self._minHeight(),
+                       handles: resizeHandles,
+                       start: function(event, ui) {
+                               $(this).addClass("ui-dialog-resizing");
+                               self._trigger('resizeStart', event, filteredUi(ui));
+                       },
+                       resize: function(event, ui) {
+                               self._trigger('resize', event, filteredUi(ui));
+                       },
+                       stop: function(event, ui) {
+                               $(this).removeClass("ui-dialog-resizing");
+                               options.height = $(this).height();
+                               options.width = $(this).width();
+                               self._trigger('resizeStop', event, filteredUi(ui));
+                               $.ui.dialog.overlay.resize();
+                       }
+               })
+               .css('position', position)
+               .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
+       },
+
+       _minHeight: function() {
+               var options = this.options;
+
+               if (options.height === 'auto') {
+                       return options.minHeight;
+               } else {
+                       return Math.min(options.minHeight, options.height);
+               }
+       },
+
+       _position: function(position) {
+               var myAt = [],
+                       offset = [0, 0],
+                       isVisible;
+
+               if (position) {
+                       // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
+       //              if (typeof position == 'string' || $.isArray(position)) {
+       //                      myAt = $.isArray(position) ? position : position.split(' ');
+
+                       if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
+                               myAt = position.split ? position.split(' ') : [position[0], position[1]];
+                               if (myAt.length === 1) {
+                                       myAt[1] = myAt[0];
+                               }
+
+                               $.each(['left', 'top'], function(i, offsetPosition) {
+                                       if (+myAt[i] === myAt[i]) {
+                                               offset[i] = myAt[i];
+                                               myAt[i] = offsetPosition;
+                                       }
+                               });
+
+                               position = {
+                                       my: myAt.join(" "),
+                                       at: myAt.join(" "),
+                                       offset: offset.join(" ")
+                               };
+                       } 
+
+                       position = $.extend({}, $.ui.dialog.prototype.options.position, position);
+               } else {
+                       position = $.ui.dialog.prototype.options.position;
+               }
+
+               // need to show the dialog to get the actual offset in the position plugin
+               isVisible = this.uiDialog.is(':visible');
+               if (!isVisible) {
+                       this.uiDialog.show();
+               }
+               this.uiDialog
+                       // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
+                       .css({ top: 0, left: 0 })
+                       .position($.extend({ of: window }, position));
+               if (!isVisible) {
+                       this.uiDialog.hide();
+               }
+       },
+
+       _setOptions: function( options ) {
+               var self = this,
+                       resizableOptions = {},
+                       resize = false;
+
+               $.each( options, function( key, value ) {
+                       self._setOption( key, value );
+                       
+                       if ( key in sizeRelatedOptions ) {
+                               resize = true;
+                       }
+                       if ( key in resizableRelatedOptions ) {
+                               resizableOptions[ key ] = value;
+                       }
+               });
+
+               if ( resize ) {
+                       this._size();
+               }
+               if ( this.uiDialog.is( ":data(resizable)" ) ) {
+                       this.uiDialog.resizable( "option", resizableOptions );
+               }
+       },
+
+       _setOption: function(key, value){
+               var self = this,
+                       uiDialog = self.uiDialog;
+
+               switch (key) {
+                       //handling of deprecated beforeclose (vs beforeClose) option
+                       //Ticket #4669 http://dev.jqueryui.com/ticket/4669
+                       //TODO: remove in 1.9pre
+                       case "beforeclose":
+                               key = "beforeClose";
+                               break;
+                       case "buttons":
+                               self._createButtons(value);
+                               break;
+                       case "closeText":
+                               // ensure that we always pass a string
+                               self.uiDialogTitlebarCloseText.text("" + value);
+                               break;
+                       case "dialogClass":
+                               uiDialog
+                                       .removeClass(self.options.dialogClass)
+                                       .addClass(uiDialogClasses + value);
+                               break;
+                       case "disabled":
+                               if (value) {
+                                       uiDialog.addClass('ui-dialog-disabled');
+                               } else {
+                                       uiDialog.removeClass('ui-dialog-disabled');
+                               }
+                               break;
+                       case "draggable":
+                               var isDraggable = uiDialog.is( ":data(draggable)" );
+                               if ( isDraggable && !value ) {
+                                       uiDialog.draggable( "destroy" );
+                               }
+                               
+                               if ( !isDraggable && value ) {
+                                       self._makeDraggable();
+                               }
+                               break;
+                       case "position":
+                               self._position(value);
+                               break;
+                       case "resizable":
+                               // currently resizable, becoming non-resizable
+                               var isResizable = uiDialog.is( ":data(resizable)" );
+                               if (isResizable && !value) {
+                                       uiDialog.resizable('destroy');
+                               }
+
+                               // currently resizable, changing handles
+                               if (isResizable && typeof value === 'string') {
+                                       uiDialog.resizable('option', 'handles', value);
+                               }
+
+                               // currently non-resizable, becoming resizable
+                               if (!isResizable && value !== false) {
+                                       self._makeResizable(value);
+                               }
+                               break;
+                       case "title":
+                               // convert whatever was passed in o a string, for html() to not throw up
+                               $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
+                               break;
+               }
+
+               $.Widget.prototype._setOption.apply(self, arguments);
+       },
+
+       _size: function() {
+               /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
+                * divs will both have width and height set, so we need to reset them
+                */
+               var options = this.options,
+                       nonContentHeight,
+                       minContentHeight,
+                       isVisible = this.uiDialog.is( ":visible" );
+
+               // reset content sizing
+               this.element.show().css({
+                       width: 'auto',
+                       minHeight: 0,
+                       height: 0
+               });
+
+               if (options.minWidth > options.width) {
+                       options.width = options.minWidth;
+               }
+
+               // reset wrapper sizing
+               // determine the height of all the non-content elements
+               nonContentHeight = this.uiDialog.css({
+                               height: 'auto',
+                               width: options.width
+                       })
+                       .height();
+               minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
+               
+               if ( options.height === "auto" ) {
+                       // only needed for IE6 support
+                       if ( $.support.minHeight ) {
+                               this.element.css({
+                                       minHeight: minContentHeight,
+                                       height: "auto"
+                               });
+                       } else {
+                               this.uiDialog.show();
+                               var autoHeight = this.element.css( "height", "auto" ).height();
+                               if ( !isVisible ) {
+                                       this.uiDialog.hide();
+                               }
+                               this.element.height( Math.max( autoHeight, minContentHeight ) );
+                       }
+               } else {
+                       this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
+               }
+
+               if (this.uiDialog.is(':data(resizable)')) {
+                       this.uiDialog.resizable('option', 'minHeight', this._minHeight());
+               }
+       }
+});
+
+$.extend($.ui.dialog, {
+       version: "1.8.24",
+
+       uuid: 0,
+       maxZ: 0,
+
+       getTitleId: function($el) {
+               var id = $el.attr('id');
+               if (!id) {
+                       this.uuid += 1;
+                       id = this.uuid;
+               }
+               return 'ui-dialog-title-' + id;
+       },
+
+       overlay: function(dialog) {
+               this.$el = $.ui.dialog.overlay.create(dialog);
+       }
+});
+
+$.extend($.ui.dialog.overlay, {
+       instances: [],
+       // reuse old instances due to IE memory leak with alpha transparency (see #5185)
+       oldInstances: [],
+       maxZ: 0,
+       events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
+               function(event) { return event + '.dialog-overlay'; }).join(' '),
+       create: function(dialog) {
+               if (this.instances.length === 0) {
+                       // prevent use of anchors and inputs
+                       // we use a setTimeout in case the overlay is created from an
+                       // event that we're going to be cancelling (see #2804)
+                       setTimeout(function() {
+                               // handle $(el).dialog().dialog('close') (see #4065)
+                               if ($.ui.dialog.overlay.instances.length) {
+                                       $(document).bind($.ui.dialog.overlay.events, function(event) {
+                                               // stop events if the z-index of the target is < the z-index of the overlay
+                                               // we cannot return true when we don't want to cancel the event (#3523)
+                                               if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
+                                                       return false;
+                                               }
+                                       });
+                               }
+                       }, 1);
+
+                       // allow closing by pressing the escape key
+                       $(document).bind('keydown.dialog-overlay', function(event) {
+                               if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
+                                       event.keyCode === $.ui.keyCode.ESCAPE) {
+                                       
+                                       dialog.close(event);
+                                       event.preventDefault();
+                               }
+                       });
+
+                       // handle window resize
+                       $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
+               }
+
+               var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
+                       .appendTo(document.body)
+                       .css({
+                               width: this.width(),
+                               height: this.height()
+                       });
+
+               if ($.fn.bgiframe) {
+                       $el.bgiframe();
+               }
+
+               this.instances.push($el);
+               return $el;
+       },
+
+       destroy: function($el) {
+               var indexOf = $.inArray($el, this.instances);
+               if (indexOf != -1){
+                       this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
+               }
+
+               if (this.instances.length === 0) {
+                       $([document, window]).unbind('.dialog-overlay');
+               }
+
+               $el.remove();
+               
+               // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
+               var maxZ = 0;
+               $.each(this.instances, function() {
+                       maxZ = Math.max(maxZ, this.css('z-index'));
+               });
+               this.maxZ = maxZ;
+       },
+
+       height: function() {
+               var scrollHeight,
+                       offsetHeight;
+               // handle IE 6
+               if ($.browser.msie && $.browser.version < 7) {
+                       scrollHeight = Math.max(
+                               document.documentElement.scrollHeight,
+                               document.body.scrollHeight
+                       );
+                       offsetHeight = Math.max(
+                               document.documentElement.offsetHeight,
+                               document.body.offsetHeight
+                       );
+
+                       if (scrollHeight < offsetHeight) {
+                               return $(window).height() + 'px';
+                       } else {
+                               return scrollHeight + 'px';
+                       }
+               // handle "good" browsers
+               } else {
+                       return $(document).height() + 'px';
+               }
+       },
+
+       width: function() {
+               var scrollWidth,
+                       offsetWidth;
+               // handle IE
+               if ( $.browser.msie ) {
+                       scrollWidth = Math.max(
+                               document.documentElement.scrollWidth,
+                               document.body.scrollWidth
+                       );
+                       offsetWidth = Math.max(
+                               document.documentElement.offsetWidth,
+                               document.body.offsetWidth
+                       );
+
+                       if (scrollWidth < offsetWidth) {
+                               return $(window).width() + 'px';
+                       } else {
+                               return scrollWidth + 'px';
+                       }
+               // handle "good" browsers
+               } else {
+                       return $(document).width() + 'px';
+               }
+       },
+
+       resize: function() {
+               /* If the dialog is draggable and the user drags it past the
+                * right edge of the window, the document becomes wider so we
+                * need to stretch the overlay. If the user then drags the
+                * dialog back to the left, the document will become narrower,
+                * so we need to shrink the overlay to the appropriate size.
+                * This is handled by shrinking the overlay before setting it
+                * to the full document size.
+                */
+               var $overlays = $([]);
+               $.each($.ui.dialog.overlay.instances, function() {
+                       $overlays = $overlays.add(this);
+               });
+
+               $overlays.css({
+                       width: 0,
+                       height: 0
+               }).css({
+                       width: $.ui.dialog.overlay.width(),
+                       height: $.ui.dialog.overlay.height()
+               });
+       }
+});
+
+$.extend($.ui.dialog.overlay.prototype, {
+       destroy: function() {
+               $.ui.dialog.overlay.destroy(this.$el);
+       }
+});
+
+}(jQuery));
diff --git a/resources/lib/jquery.ui/jquery.ui.draggable.js b/resources/lib/jquery.ui/jquery.ui.draggable.js
new file mode 100644 (file)
index 0000000..149035c
--- /dev/null
@@ -0,0 +1,832 @@
+/*!
+ * jQuery UI Draggable 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *     jquery.ui.mouse.js
+ *     jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.draggable", $.ui.mouse, {
+       widgetEventPrefix: "drag",
+       options: {
+               addClasses: true,
+               appendTo: "parent",
+               axis: false,
+               connectToSortable: false,
+               containment: false,
+               cursor: "auto",
+               cursorAt: false,
+               grid: false,
+               handle: false,
+               helper: "original",
+               iframeFix: false,
+               opacity: false,
+               refreshPositions: false,
+               revert: false,
+               revertDuration: 500,
+               scope: "default",
+               scroll: true,
+               scrollSensitivity: 20,
+               scrollSpeed: 20,
+               snap: false,
+               snapMode: "both",
+               snapTolerance: 20,
+               stack: false,
+               zIndex: false
+       },
+       _create: function() {
+
+               if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
+                       this.element[0].style.position = 'relative';
+
+               (this.options.addClasses && this.element.addClass("ui-draggable"));
+               (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
+
+               this._mouseInit();
+
+       },
+
+       destroy: function() {
+               if(!this.element.data('draggable')) return;
+               this.element
+                       .removeData("draggable")
+                       .unbind(".draggable")
+                       .removeClass("ui-draggable"
+                               + " ui-draggable-dragging"
+                               + " ui-draggable-disabled");
+               this._mouseDestroy();
+
+               return this;
+       },
+
+       _mouseCapture: function(event) {
+
+               var o = this.options;
+
+               // among others, prevent a drag on a resizable-handle
+               if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
+                       return false;
+
+               //Quit if we're not on a valid handle
+               this.handle = this._getHandle(event);
+               if (!this.handle)
+                       return false;
+               
+               if ( o.iframeFix ) {
+                       $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
+                               $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
+                               .css({
+                                       width: this.offsetWidth+"px", height: this.offsetHeight+"px",
+                                       position: "absolute", opacity: "0.001", zIndex: 1000
+                               })
+                               .css($(this).offset())
+                               .appendTo("body");
+                       });
+               }
+
+               return true;
+
+       },
+
+       _mouseStart: function(event) {
+
+               var o = this.options;
+
+               //Create and append the visible helper
+               this.helper = this._createHelper(event);
+
+               this.helper.addClass("ui-draggable-dragging");
+
+               //Cache the helper size
+               this._cacheHelperProportions();
+
+               //If ddmanager is used for droppables, set the global draggable
+               if($.ui.ddmanager)
+                       $.ui.ddmanager.current = this;
+
+               /*
+                * - Position generation -
+                * This block generates everything position related - it's the core of draggables.
+                */
+
+               //Cache the margins of the original element
+               this._cacheMargins();
+
+               //Store the helper's css position
+               this.cssPosition = this.helper.css("position");
+               this.scrollParent = this.helper.scrollParent();
+
+               //The element's absolute position on the page minus margins
+               this.offset = this.positionAbs = this.element.offset();
+               this.offset = {
+                       top: this.offset.top - this.margins.top,
+                       left: this.offset.left - this.margins.left
+               };
+
+               $.extend(this.offset, {
+                       click: { //Where the click happened, relative to the element
+                               left: event.pageX - this.offset.left,
+                               top: event.pageY - this.offset.top
+                       },
+                       parent: this._getParentOffset(),
+                       relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
+               });
+
+               //Generate the original position
+               this.originalPosition = this.position = this._generatePosition(event);
+               this.originalPageX = event.pageX;
+               this.originalPageY = event.pageY;
+
+               //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+               (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
+
+               //Set a containment if given in the options
+               if(o.containment)
+                       this._setContainment();
+
+               //Trigger event + callbacks
+               if(this._trigger("start", event) === false) {
+                       this._clear();
+                       return false;
+               }
+
+               //Recache the helper size
+               this._cacheHelperProportions();
+
+               //Prepare the droppable offsets
+               if ($.ui.ddmanager && !o.dropBehaviour)
+                       $.ui.ddmanager.prepareOffsets(this, event);
+
+               
+               this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+               
+               //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
+               if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
+               
+               return true;
+       },
+
+       _mouseDrag: function(event, noPropagation) {
+
+               //Compute the helpers position
+               this.position = this._generatePosition(event);
+               this.positionAbs = this._convertPositionTo("absolute");
+
+               //Call plugins and callbacks and use the resulting position if something is returned
+               if (!noPropagation) {
+                       var ui = this._uiHash();
+                       if(this._trigger('drag', event, ui) === false) {
+                               this._mouseUp({});
+                               return false;
+                       }
+                       this.position = ui.position;
+               }
+
+               if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
+               if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
+               if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
+
+               return false;
+       },
+
+       _mouseStop: function(event) {
+
+               //If we are using droppables, inform the manager about the drop
+               var dropped = false;
+               if ($.ui.ddmanager && !this.options.dropBehaviour)
+                       dropped = $.ui.ddmanager.drop(this, event);
+
+               //if a drop comes from outside (a sortable)
+               if(this.dropped) {
+                       dropped = this.dropped;
+                       this.dropped = false;
+               }
+               
+               //if the original element is no longer in the DOM don't bother to continue (see #8269)
+               var element = this.element[0], elementInDom = false;
+               while ( element && (element = element.parentNode) ) {
+                       if (element == document ) {
+                               elementInDom = true;
+                       }
+               }
+               if ( !elementInDom && this.options.helper === "original" )
+                       return false;
+
+               if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
+                       var self = this;
+                       $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
+                               if(self._trigger("stop", event) !== false) {
+                                       self._clear();
+                               }
+                       });
+               } else {
+                       if(this._trigger("stop", event) !== false) {
+                               this._clear();
+                       }
+               }
+
+               return false;
+       },
+       
+       _mouseUp: function(event) {
+               //Remove frame helpers
+               $("div.ui-draggable-iframeFix").each(function() { 
+                       this.parentNode.removeChild(this); 
+               });
+               
+               //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
+               if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
+               
+               return $.ui.mouse.prototype._mouseUp.call(this, event);
+       },
+       
+       cancel: function() {
+               
+               if(this.helper.is(".ui-draggable-dragging")) {
+                       this._mouseUp({});
+               } else {
+                       this._clear();
+               }
+               
+               return this;
+               
+       },
+
+       _getHandle: function(event) {
+
+               var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
+               $(this.options.handle, this.element)
+                       .find("*")
+                       .andSelf()
+                       .each(function() {
+                               if(this == event.target) handle = true;
+                       });
+
+               return handle;
+
+       },
+
+       _createHelper: function(event) {
+
+               var o = this.options;
+               var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
+
+               if(!helper.parents('body').length)
+                       helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
+
+               if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
+                       helper.css("position", "absolute");
+
+               return helper;
+
+       },
+
+       _adjustOffsetFromHelper: function(obj) {
+               if (typeof obj == 'string') {
+                       obj = obj.split(' ');
+               }
+               if ($.isArray(obj)) {
+                       obj = {left: +obj[0], top: +obj[1] || 0};
+               }
+               if ('left' in obj) {
+                       this.offset.click.left = obj.left + this.margins.left;
+               }
+               if ('right' in obj) {
+                       this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+               }
+               if ('top' in obj) {
+                       this.offset.click.top = obj.top + this.margins.top;
+               }
+               if ('bottom' in obj) {
+                       this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+               }
+       },
+
+       _getParentOffset: function() {
+
+               //Get the offsetParent and cache its position
+               this.offsetParent = this.helper.offsetParent();
+               var po = this.offsetParent.offset();
+
+               // This is a special case where we need to modify a offset calculated on start, since the following happened:
+               // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
+               // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
+               //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
+               if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
+                       po.left += this.scrollParent.scrollLeft();
+                       po.top += this.scrollParent.scrollTop();
+               }
+
+               if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
+               || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
+                       po = { top: 0, left: 0 };
+
+               return {
+                       top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
+                       left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
+               };
+
+       },
+
+       _getRelativeOffset: function() {
+
+               if(this.cssPosition == "relative") {
+                       var p = this.element.position();
+                       return {
+                               top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
+                               left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
+                       };
+               } else {
+                       return { top: 0, left: 0 };
+               }
+
+       },
+
+       _cacheMargins: function() {
+               this.margins = {
+                       left: (parseInt(this.element.css("marginLeft"),10) || 0),
+                       top: (parseInt(this.element.css("marginTop"),10) || 0),
+                       right: (parseInt(this.element.css("marginRight"),10) || 0),
+                       bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
+               };
+       },
+
+       _cacheHelperProportions: function() {
+               this.helperProportions = {
+                       width: this.helper.outerWidth(),
+                       height: this.helper.outerHeight()
+               };
+       },
+
+       _setContainment: function() {
+
+               var o = this.options;
+               if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
+               if(o.containment == 'document' || o.containment == 'window') this.containment = [
+                       o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
+                       o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
+                       (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
+                       (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
+               ];
+
+               if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
+                       var c = $(o.containment);
+                       var ce = c[0]; if(!ce) return;
+                       var co = c.offset();
+                       var over = ($(ce).css("overflow") != 'hidden');
+
+                       this.containment = [
+                               (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
+                               (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
+                               (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
+                               (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top  - this.margins.bottom
+                       ];
+                       this.relative_container = c;
+
+               } else if(o.containment.constructor == Array) {
+                       this.containment = o.containment;
+               }
+
+       },
+
+       _convertPositionTo: function(d, pos) {
+
+               if(!pos) pos = this.position;
+               var mod = d == "absolute" ? 1 : -1;
+               var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+               return {
+                       top: (
+                               pos.top                                                                                                                                 // The absolute mouse position
+                               + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
+                               + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
+                               - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
+                       ),
+                       left: (
+                               pos.left                                                                                                                                // The absolute mouse position
+                               + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
+                               + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
+                               - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
+                       )
+               };
+
+       },
+
+       _generatePosition: function(event) {
+
+               var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+               var pageX = event.pageX;
+               var pageY = event.pageY;
+
+               /*
+                * - Position constraining -
+                * Constrain the position to a mix of grid, containment.
+                */
+
+               if(this.originalPosition) { //If we are not dragging yet, we won't check for options
+                        var containment;
+                        if(this.containment) {
+                                if (this.relative_container){
+                                    var co = this.relative_container.offset();
+                                    containment = [ this.containment[0] + co.left,
+                                                    this.containment[1] + co.top,
+                                                    this.containment[2] + co.left,
+                                                    this.containment[3] + co.top ];
+                                }
+                                else {
+                                    containment = this.containment;
+                                }
+
+                               if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
+                               if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
+                               if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
+                               if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
+                       }
+
+                       if(o.grid) {
+                               //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
+                               var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
+                               pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
+
+                               var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
+                               pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
+                       }
+
+               }
+
+               return {
+                       top: (
+                               pageY                                                                                                                           // The absolute mouse position
+                               - this.offset.click.top                                                                                                 // Click offset (relative to the element)
+                               - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
+                               - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
+                               + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
+                       ),
+                       left: (
+                               pageX                                                                                                                           // The absolute mouse position
+                               - this.offset.click.left                                                                                                // Click offset (relative to the element)
+                               - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
+                               - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
+                               + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
+                       )
+               };
+
+       },
+
+       _clear: function() {
+               this.helper.removeClass("ui-draggable-dragging");
+               if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
+               //if($.ui.ddmanager) $.ui.ddmanager.current = null;
+               this.helper = null;
+               this.cancelHelperRemoval = false;
+       },
+
+       // From now on bulk stuff - mainly helpers
+
+       _trigger: function(type, event, ui) {
+               ui = ui || this._uiHash();
+               $.ui.plugin.call(this, type, [event, ui]);
+               if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
+               return $.Widget.prototype._trigger.call(this, type, event, ui);
+       },
+
+       plugins: {},
+
+       _uiHash: function(event) {
+               return {
+                       helper: this.helper,
+                       position: this.position,
+                       originalPosition: this.originalPosition,
+                       offset: this.positionAbs
+               };
+       }
+
+});
+
+$.extend($.ui.draggable, {
+       version: "1.8.24"
+});
+
+$.ui.plugin.add("draggable", "connectToSortable", {
+       start: function(event, ui) {
+
+               var inst = $(this).data("draggable"), o = inst.options,
+                       uiSortable = $.extend({}, ui, { item: inst.element });
+               inst.sortables = [];
+               $(o.connectToSortable).each(function() {
+                       var sortable = $.data(this, 'sortable');
+                       if (sortable && !sortable.options.disabled) {
+                               inst.sortables.push({
+                                       instance: sortable,
+                                       shouldRevert: sortable.options.revert
+                               });
+                               sortable.refreshPositions();    // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
+                               sortable._trigger("activate", event, uiSortable);
+                       }
+               });
+
+       },
+       stop: function(event, ui) {
+
+               //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
+               var inst = $(this).data("draggable"),
+                       uiSortable = $.extend({}, ui, { item: inst.element });
+
+               $.each(inst.sortables, function() {
+                       if(this.instance.isOver) {
+
+                               this.instance.isOver = 0;
+
+                               inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
+                               this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
+
+                               //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
+                               if(this.shouldRevert) this.instance.options.revert = true;
+
+                               //Trigger the stop of the sortable
+                               this.instance._mouseStop(event);
+
+                               this.instance.options.helper = this.instance.options._helper;
+
+                               //If the helper has been the original item, restore properties in the sortable
+                               if(inst.options.helper == 'original')
+                                       this.instance.currentItem.css({ top: 'auto', left: 'auto' });
+
+                       } else {
+                               this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
+                               this.instance._trigger("deactivate", event, uiSortable);
+                       }
+
+               });
+
+       },
+       drag: function(event, ui) {
+
+               var inst = $(this).data("draggable"), self = this;
+
+               var checkPos = function(o) {
+                       var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
+                       var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
+                       var itemHeight = o.height, itemWidth = o.width;
+                       var itemTop = o.top, itemLeft = o.left;
+
+                       return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
+               };
+
+               $.each(inst.sortables, function(i) {
+                       
+                       //Copy over some variables to allow calling the sortable's native _intersectsWith
+                       this.instance.positionAbs = inst.positionAbs;
+                       this.instance.helperProportions = inst.helperProportions;
+                       this.instance.offset.click = inst.offset.click;
+                       
+                       if(this.instance._intersectsWith(this.instance.containerCache)) {
+
+                               //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
+                               if(!this.instance.isOver) {
+
+                                       this.instance.isOver = 1;
+                                       //Now we fake the start of dragging for the sortable instance,
+                                       //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
+                                       //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
+                                       this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
+                                       this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
+                                       this.instance.options.helper = function() { return ui.helper[0]; };
+
+                                       event.target = this.instance.currentItem[0];
+                                       this.instance._mouseCapture(event, true);
+                                       this.instance._mouseStart(event, true, true);
+
+                                       //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
+                                       this.instance.offset.click.top = inst.offset.click.top;
+                                       this.instance.offset.click.left = inst.offset.click.left;
+                                       this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
+                                       this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
+
+                                       inst._trigger("toSortable", event);
+                                       inst.dropped = this.instance.element; //draggable revert needs that
+                                       //hack so receive/update callbacks work (mostly)
+                                       inst.currentItem = inst.element;
+                                       this.instance.fromOutside = inst;
+
+                               }
+
+                               //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
+                               if(this.instance.currentItem) this.instance._mouseDrag(event);
+
+                       } else {
+
+                               //If it doesn't intersect with the sortable, and it intersected before,
+                               //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
+                               if(this.instance.isOver) {
+
+                                       this.instance.isOver = 0;
+                                       this.instance.cancelHelperRemoval = true;
+                                       
+                                       //Prevent reverting on this forced stop
+                                       this.instance.options.revert = false;
+                                       
+                                       // The out event needs to be triggered independently
+                                       this.instance._trigger('out', event, this.instance._uiHash(this.instance));
+                                       
+                                       this.instance._mouseStop(event, true);
+                                       this.instance.options.helper = this.instance.options._helper;
+
+                                       //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
+                                       this.instance.currentItem.remove();
+                                       if(this.instance.placeholder) this.instance.placeholder.remove();
+
+                                       inst._trigger("fromSortable", event);
+                                       inst.dropped = false; //draggable revert needs that
+                               }
+
+                       };
+
+               });
+
+       }
+});
+
+$.ui.plugin.add("draggable", "cursor", {
+       start: function(event, ui) {
+               var t = $('body'), o = $(this).data('draggable').options;
+               if (t.css("cursor")) o._cursor = t.css("cursor");
+               t.css("cursor", o.cursor);
+       },
+       stop: function(event, ui) {
+               var o = $(this).data('draggable').options;
+               if (o._cursor) $('body').css("cursor", o._cursor);
+       }
+});
+
+$.ui.plugin.add("draggable", "opacity", {
+       start: function(event, ui) {
+               var t = $(ui.helper), o = $(this).data('draggable').options;
+               if(t.css("opacity")) o._opacity = t.css("opacity");
+               t.css('opacity', o.opacity);
+       },
+       stop: function(event, ui) {
+               var o = $(this).data('draggable').options;
+               if(o._opacity) $(ui.helper).css('opacity', o._opacity);
+       }
+});
+
+$.ui.plugin.add("draggable", "scroll", {
+       start: function(event, ui) {
+               var i = $(this).data("draggable");
+               if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
+       },
+       drag: function(event, ui) {
+
+               var i = $(this).data("draggable"), o = i.options, scrolled = false;
+
+               if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
+
+                       if(!o.axis || o.axis != 'x') {
+                               if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
+                                       i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
+                               else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
+                                       i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
+                       }
+
+                       if(!o.axis || o.axis != 'y') {
+                               if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
+                                       i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
+                               else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
+                                       i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
+                       }
+
+               } else {
+
+                       if(!o.axis || o.axis != 'x') {
+                               if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
+                                       scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
+                               else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
+                                       scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
+                       }
+
+                       if(!o.axis || o.axis != 'y') {
+                               if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
+                                       scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
+                               else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
+                                       scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
+                       }
+
+               }
+
+               if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
+                       $.ui.ddmanager.prepareOffsets(i, event);
+
+       }
+});
+
+$.ui.plugin.add("draggable", "snap", {
+       start: function(event, ui) {
+
+               var i = $(this).data("draggable"), o = i.options;
+               i.snapElements = [];
+
+               $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
+                       var $t = $(this); var $o = $t.offset();
+                       if(this != i.element[0]) i.snapElements.push({
+                               item: this,
+                               width: $t.outerWidth(), height: $t.outerHeight(),
+                               top: $o.top, left: $o.left
+                       });
+               });
+
+       },
+       drag: function(event, ui) {
+
+               var inst = $(this).data("draggable"), o = inst.options;
+               var d = o.snapTolerance;
+
+               var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
+                       y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
+
+               for (var i = inst.snapElements.length - 1; i >= 0; i--){
+
+                       var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
+                               t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
+
+                       //Yes, I know, this is insane ;)
+                       if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
+                               if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
+                               inst.snapElements[i].snapping = false;
+                               continue;
+                       }
+
+                       if(o.snapMode != 'inner') {
+                               var ts = Math.abs(t - y2) <= d;
+                               var bs = Math.abs(b - y1) <= d;
+                               var ls = Math.abs(l - x2) <= d;
+                               var rs = Math.abs(r - x1) <= d;
+                               if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
+                               if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
+                               if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
+                               if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
+                       }
+
+                       var first = (ts || bs || ls || rs);
+
+                       if(o.snapMode != 'outer') {
+                               var ts = Math.abs(t - y1) <= d;
+                               var bs = Math.abs(b - y2) <= d;
+                               var ls = Math.abs(l - x1) <= d;
+                               var rs = Math.abs(r - x2) <= d;
+                               if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
+                               if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
+                               if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
+                               if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
+                       }
+
+                       if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
+                               (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
+                       inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
+
+               };
+
+       }
+});
+
+$.ui.plugin.add("draggable", "stack", {
+       start: function(event, ui) {
+
+               var o = $(this).data("draggable").options;
+
+               var group = $.makeArray($(o.stack)).sort(function(a,b) {
+                       return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
+               });
+               if (!group.length) { return; }
+               
+               var min = parseInt(group[0].style.zIndex) || 0;
+               $(group).each(function(i) {
+                       this.style.zIndex = min + i;
+               });
+
+               this[0].style.zIndex = min + group.length;
+
+       }
+});
+
+$.ui.plugin.add("draggable", "zIndex", {
+       start: function(event, ui) {
+               var t = $(ui.helper), o = $(this).data("draggable").options;
+               if(t.css("zIndex")) o._zIndex = t.css("zIndex");
+               t.css('zIndex', o.zIndex);
+       },
+       stop: function(event, ui) {
+               var o = $(this).data("draggable").options;
+               if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
+       }
+});
+
+})(jQuery);
diff --git a/resources/lib/jquery.ui/jquery.ui.droppable.js b/resources/lib/jquery.ui/jquery.ui.droppable.js
new file mode 100644 (file)
index 0000000..f17c222
--- /dev/null
@@ -0,0 +1,301 @@
+/*!
+ * jQuery UI Droppable 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Droppables
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *     jquery.ui.widget.js
+ *     jquery.ui.mouse.js
+ *     jquery.ui.draggable.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.droppable", {
+       widgetEventPrefix: "drop",
+       options: {
+               accept: '*',
+               activeClass: false,
+               addClasses: true,
+               greedy: false,
+               hoverClass: false,
+               scope: 'default',
+               tolerance: 'intersect'
+       },
+       _create: function() {
+
+               var o = this.options, accept = o.accept;
+               this.isover = 0; this.isout = 1;
+
+               this.accept = $.isFunction(accept) ? accept : function(d) {
+                       return d.is(accept);
+               };
+
+               //Store the droppable's proportions
+               this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
+
+               // Add the reference and positions to the manager
+               $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
+               $.ui.ddmanager.droppables[o.scope].push(this);
+
+               (o.addClasses && this.element.addClass("ui-droppable"));
+
+       },
+
+       destroy: function() {
+               var drop = $.ui.ddmanager.droppables[this.options.scope];
+               for ( var i = 0; i < drop.length; i++ )
+                       if ( drop[i] == this )
+                               drop.splice(i, 1);
+
+               this.element
+                       .removeClass("ui-droppable ui-droppable-disabled")
+                       .removeData("droppable")
+                       .unbind(".droppable");
+
+               return this;
+       },
+
+       _setOption: function(key, value) {
+
+               if(key == 'accept') {
+                       this.accept = $.isFunction(value) ? value : function(d) {
+                               return d.is(value);
+                       };
+               }
+               $.Widget.prototype._setOption.apply(this, arguments);
+       },
+
+       _activate: function(event) {
+               var draggable = $.ui.ddmanager.current;
+               if(this.options.activeClass) this.element.addClass(this.options.activeClass);
+               (draggable && this._trigger('activate', event, this.ui(draggable)));
+       },
+
+       _deactivate: function(event) {
+               var draggable = $.ui.ddmanager.current;
+               if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
+               (draggable && this._trigger('deactivate', event, this.ui(draggable)));
+       },
+
+       _over: function(event) {
+
+               var draggable = $.ui.ddmanager.current;
+               if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
+
+               if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+                       if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
+                       this._trigger('over', event, this.ui(draggable));
+               }
+
+       },
+
+       _out: function(event) {
+
+               var draggable = $.ui.ddmanager.current;
+               if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
+
+               if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+                       if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
+                       this._trigger('out', event, this.ui(draggable));
+               }
+
+       },
+
+       _drop: function(event,custom) {
+
+               var draggable = custom || $.ui.ddmanager.current;
+               if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
+
+               var childrenIntersection = false;
+               this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
+                       var inst = $.data(this, 'droppable');
+                       if(
+                               inst.options.greedy
+                               && !inst.options.disabled
+                               && inst.options.scope == draggable.options.scope
+                               && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
+                               && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
+                       ) { childrenIntersection = true; return false; }
+               });
+               if(childrenIntersection) return false;
+
+               if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+                       if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
+                       if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
+                       this._trigger('drop', event, this.ui(draggable));
+                       return this.element;
+               }
+
+               return false;
+
+       },
+
+       ui: function(c) {
+               return {
+                       draggable: (c.currentItem || c.element),
+                       helper: c.helper,
+                       position: c.position,
+                       offset: c.positionAbs
+               };
+       }
+
+});
+
+$.extend($.ui.droppable, {
+       version: "1.8.24"
+});
+
+$.ui.intersect = function(draggable, droppable, toleranceMode) {
+
+       if (!droppable.offset) return false;
+
+       var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
+               y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
+       var l = droppable.offset.left, r = l + droppable.proportions.width,
+               t = droppable.offset.top, b = t + droppable.proportions.height;
+
+       switch (toleranceMode) {
+               case 'fit':
+                       return (l <= x1 && x2 <= r
+                               && t <= y1 && y2 <= b);
+                       break;
+               case 'intersect':
+                       return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
+                               && x2 - (draggable.helperProportions.width / 2) < r // Left Half
+                               && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
+                               && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
+                       break;
+               case 'pointer':
+                       var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
+                               draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
+                               isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
+                       return isOver;
+                       break;
+               case 'touch':
+                       return (
+                                       (y1 >= t && y1 <= b) || // Top edge touching
+                                       (y2 >= t && y2 <= b) || // Bottom edge touching
+                                       (y1 < t && y2 > b)              // Surrounded vertically
+                               ) && (
+                                       (x1 >= l && x1 <= r) || // Left edge touching
+                                       (x2 >= l && x2 <= r) || // Right edge touching
+                                       (x1 < l && x2 > r)              // Surrounded horizontally
+                               );
+                       break;
+               default:
+                       return false;
+                       break;
+               }
+
+};
+
+/*
+       This manager tracks offsets of draggables and droppables
+*/
+$.ui.ddmanager = {
+       current: null,
+       droppables: { 'default': [] },
+       prepareOffsets: function(t, event) {
+
+               var m = $.ui.ddmanager.droppables[t.options.scope] || [];
+               var type = event ? event.type : null; // workaround for #2317
+               var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
+
+               droppablesLoop: for (var i = 0; i < m.length; i++) {
+
+                       if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;   //No disabled and non-accepted
+                       for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
+                       m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;                                                                       //If the element is not visible, continue
+
+                       if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
+
+                       m[i].offset = m[i].element.offset();
+                       m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
+
+               }
+
+       },
+       drop: function(draggable, event) {
+
+               var dropped = false;
+               $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
+
+                       if(!this.options) return;
+                       if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
+                               dropped = this._drop.call(this, event) || dropped;
+
+                       if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+                               this.isout = 1; this.isover = 0;
+                               this._deactivate.call(this, event);
+                       }
+
+               });
+               return dropped;
+
+       },
+       dragStart: function( draggable, event ) {
+               //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
+               draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() {
+                       if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
+               });
+       },
+       drag: function(draggable, event) {
+
+               //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
+               if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
+
+               //Run through all droppables and check their positions based on specific tolerance options
+               $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
+
+                       if(this.options.disabled || this.greedyChild || !this.visible) return;
+                       var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
+
+                       var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
+                       if(!c) return;
+
+                       var parentInstance;
+                       if (this.options.greedy) {
+                               // find droppable parents with same scope
+                               var scope = this.options.scope;
+                               var parent = this.element.parents(':data(droppable)').filter(function () {
+                                       return $.data(this, 'droppable').options.scope === scope;
+                               });
+
+                               if (parent.length) {
+                                       parentInstance = $.data(parent[0], 'droppable');
+                                       parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
+                               }
+                       }
+
+                       // we just moved into a greedy child
+                       if (parentInstance && c == 'isover') {
+                               parentInstance['isover'] = 0;
+                               parentInstance['isout'] = 1;
+                               parentInstance._out.call(parentInstance, event);
+                       }
+
+                       this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
+                       this[c == "isover" ? "_over" : "_out"].call(this, event);
+
+                       // we just moved out of a greedy child
+                       if (parentInstance && c == 'isout') {
+                               parentInstance['isout'] = 0;
+                               parentInstance['isover'] = 1;
+                               parentInstance._over.call(parentInstance, event);
+                       }
+               });
+
+       },
+       dragStop: function( draggable, event ) {
+               draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" );
+               //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
+               if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
+       }
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.ui/jquery.ui.mouse.js b/resources/lib/jquery.ui/jquery.ui.mouse.js
new file mode 100644 (file)
index 0000000..52a1786
--- /dev/null
@@ -0,0 +1,167 @@
+/*!
+ * jQuery UI Mouse 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Mouse
+ *
+ * Depends:
+ *     jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+var mouseHandled = false;
+$( document ).mouseup( function( e ) {
+       mouseHandled = false;
+});
+
+$.widget("ui.mouse", {
+       options: {
+               cancel: ':input,option',
+               distance: 1,
+               delay: 0
+       },
+       _mouseInit: function() {
+               var self = this;
+
+               this.element
+                       .bind('mousedown.'+this.widgetName, function(event) {
+                               return self._mouseDown(event);
+                       })
+                       .bind('click.'+this.widgetName, function(event) {
+                               if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
+                                   $.removeData(event.target, self.widgetName + '.preventClickEvent');
+                                       event.stopImmediatePropagation();
+                                       return false;
+                               }
+                       });
+
+               this.started = false;
+       },
+
+       // TODO: make sure destroying one instance of mouse doesn't mess with
+       // other instances of mouse
+       _mouseDestroy: function() {
+               this.element.unbind('.'+this.widgetName);
+               if ( this._mouseMoveDelegate ) {
+                       $(document)
+                               .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+                               .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+               }
+       },
+
+       _mouseDown: function(event) {
+               // don't let more than one widget handle mouseStart
+               if( mouseHandled ) { return };
+
+               // we may have missed mouseup (out of window)
+               (this._mouseStarted && this._mouseUp(event));
+
+               this._mouseDownEvent = event;
+
+               var self = this,
+                       btnIsLeft = (event.which == 1),
+                       // event.target.nodeName works around a bug in IE 8 with
+                       // disabled inputs (#7620)
+                       elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
+               if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
+                       return true;
+               }
+
+               this.mouseDelayMet = !this.options.delay;
+               if (!this.mouseDelayMet) {
+                       this._mouseDelayTimer = setTimeout(function() {
+                               self.mouseDelayMet = true;
+                       }, this.options.delay);
+               }
+
+               if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+                       this._mouseStarted = (this._mouseStart(event) !== false);
+                       if (!this._mouseStarted) {
+                               event.preventDefault();
+                               return true;
+                       }
+               }
+
+               // Click event may never have fired (Gecko & Opera)
+               if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
+                       $.removeData(event.target, this.widgetName + '.preventClickEvent');
+               }
+
+               // these delegates are required to keep context
+               this._mouseMoveDelegate = function(event) {
+                       return self._mouseMove(event);
+               };
+               this._mouseUpDelegate = function(event) {
+                       return self._mouseUp(event);
+               };
+               $(document)
+                       .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+                       .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+               event.preventDefault();
+               
+               mouseHandled = true;
+               return true;
+       },
+
+       _mouseMove: function(event) {
+               // IE mouseup check - mouseup happened when mouse was out of window
+               if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
+                       return this._mouseUp(event);
+               }
+
+               if (this._mouseStarted) {
+                       this._mouseDrag(event);
+                       return event.preventDefault();
+               }
+
+               if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+                       this._mouseStarted =
+                               (this._mouseStart(this._mouseDownEvent, event) !== false);
+                       (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
+               }
+
+               return !this._mouseStarted;
+       },
+
+       _mouseUp: function(event) {
+               $(document)
+                       .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+                       .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+               if (this._mouseStarted) {
+                       this._mouseStarted = false;
+
+                       if (event.target == this._mouseDownEvent.target) {
+                           $.data(event.target, this.widgetName + '.preventClickEvent', true);
+                       }
+
+                       this._mouseStop(event);
+               }
+
+               return false;
+       },
+
+       _mouseDistanceMet: function(event) {
+               return (Math.max(
+                               Math.abs(this._mouseDownEvent.pageX - event.pageX),
+                               Math.abs(this._mouseDownEvent.pageY - event.pageY)
+                       ) >= this.options.distance
+               );
+       },
+
+       _mouseDelayMet: function(event) {
+               return this.mouseDelayMet;
+       },
+
+       // These are placeholder methods, to be overriden by extending plugin
+       _mouseStart: function(event) {},
+       _mouseDrag: function(event) {},
+       _mouseStop: function(event) {},
+       _mouseCapture: function(event) { return true; }
+});
+
+})(jQuery);
diff --git a/resources/lib/jquery.ui/jquery.ui.position.js b/resources/lib/jquery.ui/jquery.ui.position.js
new file mode 100644 (file)
index 0000000..8b20179
--- /dev/null
@@ -0,0 +1,308 @@
+/*!
+ * jQuery UI Position 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Position
+ */
+(function( $, undefined ) {
+
+$.ui = $.ui || {};
+
+var horizontalPositions = /left|center|right/,
+       verticalPositions = /top|center|bottom/,
+       center = "center",
+       support = {},
+       _position = $.fn.position,
+       _offset = $.fn.offset;
+
+$.fn.position = function( options ) {
+       if ( !options || !options.of ) {
+               return _position.apply( this, arguments );
+       }
+
+       // make a copy, we don't want to modify arguments
+       options = $.extend( {}, options );
+
+       var target = $( options.of ),
+               targetElem = target[0],
+               collision = ( options.collision || "flip" ).split( " " ),
+               offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
+               targetWidth,
+               targetHeight,
+               basePosition;
+
+       if ( targetElem.nodeType === 9 ) {
+               targetWidth = target.width();
+               targetHeight = target.height();
+               basePosition = { top: 0, left: 0 };
+       // TODO: use $.isWindow() in 1.9
+       } else if ( targetElem.setTimeout ) {
+               targetWidth = target.width();
+               targetHeight = target.height();
+               basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
+       } else if ( targetElem.preventDefault ) {
+               // force left top to allow flipping
+               options.at = "left top";
+               targetWidth = targetHeight = 0;
+               basePosition = { top: options.of.pageY, left: options.of.pageX };
+       } else {
+               targetWidth = target.outerWidth();
+               targetHeight = target.outerHeight();
+               basePosition = target.offset();
+       }
+
+       // force my and at to have valid horizontal and veritcal positions
+       // if a value is missing or invalid, it will be converted to center 
+       $.each( [ "my", "at" ], function() {
+               var pos = ( options[this] || "" ).split( " " );
+               if ( pos.length === 1) {
+                       pos = horizontalPositions.test( pos[0] ) ?
+                               pos.concat( [center] ) :
+                               verticalPositions.test( pos[0] ) ?
+                                       [ center ].concat( pos ) :
+                                       [ center, center ];
+               }
+               pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
+               pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
+               options[ this ] = pos;
+       });
+
+       // normalize collision option
+       if ( collision.length === 1 ) {
+               collision[ 1 ] = collision[ 0 ];
+       }
+
+       // normalize offset option
+       offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
+       if ( offset.length === 1 ) {
+               offset[ 1 ] = offset[ 0 ];
+       }
+       offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
+
+       if ( options.at[0] === "right" ) {
+               basePosition.left += targetWidth;
+       } else if ( options.at[0] === center ) {
+               basePosition.left += targetWidth / 2;
+       }
+
+       if ( options.at[1] === "bottom" ) {
+               basePosition.top += targetHeight;
+       } else if ( options.at[1] === center ) {
+               basePosition.top += targetHeight / 2;
+       }
+
+       basePosition.left += offset[ 0 ];
+       basePosition.top += offset[ 1 ];
+
+       return this.each(function() {
+               var elem = $( this ),
+                       elemWidth = elem.outerWidth(),
+                       elemHeight = elem.outerHeight(),
+                       marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
+                       marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
+                       collisionWidth = elemWidth + marginLeft +
+                               ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
+                       collisionHeight = elemHeight + marginTop +
+                               ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
+                       position = $.extend( {}, basePosition ),
+                       collisionPosition;
+
+               if ( options.my[0] === "right" ) {
+                       position.left -= elemWidth;
+               } else if ( options.my[0] === center ) {
+                       position.left -= elemWidth / 2;
+               }
+
+               if ( options.my[1] === "bottom" ) {
+                       position.top -= elemHeight;
+               } else if ( options.my[1] === center ) {
+                       position.top -= elemHeight / 2;
+               }
+
+               // prevent fractions if jQuery version doesn't support them (see #5280)
+               if ( !support.fractions ) {
+                       position.left = Math.round( position.left );
+                       position.top = Math.round( position.top );
+               }
+
+               collisionPosition = {
+                       left: position.left - marginLeft,
+                       top: position.top - marginTop
+               };
+
+               $.each( [ "left", "top" ], function( i, dir ) {
+                       if ( $.ui.position[ collision[i] ] ) {
+                               $.ui.position[ collision[i] ][ dir ]( position, {
+                                       targetWidth: targetWidth,
+                                       targetHeight: targetHeight,
+                                       elemWidth: elemWidth,
+                                       elemHeight: elemHeight,
+                                       collisionPosition: collisionPosition,
+                                       collisionWidth: collisionWidth,
+                                       collisionHeight: collisionHeight,
+                                       offset: offset,
+                                       my: options.my,
+                                       at: options.at
+                               });
+                       }
+               });
+
+               if ( $.fn.bgiframe ) {
+                       elem.bgiframe();
+               }
+               elem.offset( $.extend( position, { using: options.using } ) );
+       });
+};
+
+$.ui.position = {
+       fit: {
+               left: function( position, data ) {
+                       var win = $( window ),
+                               over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
+                       position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
+               },
+               top: function( position, data ) {
+                       var win = $( window ),
+                               over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
+                       position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
+               }
+       },
+
+       flip: {
+               left: function( position, data ) {
+                       if ( data.at[0] === center ) {
+                               return;
+                       }
+                       var win = $( window ),
+                               over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
+                               myOffset = data.my[ 0 ] === "left" ?
+                                       -data.elemWidth :
+                                       data.my[ 0 ] === "right" ?
+                                               data.elemWidth :
+                                               0,
+                               atOffset = data.at[ 0 ] === "left" ?
+                                       data.targetWidth :
+                                       -data.targetWidth,
+                               offset = -2 * data.offset[ 0 ];
+                       position.left += data.collisionPosition.left < 0 ?
+                               myOffset + atOffset + offset :
+                               over > 0 ?
+                                       myOffset + atOffset + offset :
+                                       0;
+               },
+               top: function( position, data ) {
+                       if ( data.at[1] === center ) {
+                               return;
+                       }
+                       var win = $( window ),
+                               over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
+                               myOffset = data.my[ 1 ] === "top" ?
+                                       -data.elemHeight :
+                                       data.my[ 1 ] === "bottom" ?
+                                               data.elemHeight :
+                                               0,
+                               atOffset = data.at[ 1 ] === "top" ?
+                                       data.targetHeight :
+                                       -data.targetHeight,
+                               offset = -2 * data.offset[ 1 ];
+                       position.top += data.collisionPosition.top < 0 ?
+                               myOffset + atOffset + offset :
+                               over > 0 ?
+                                       myOffset + atOffset + offset :
+                                       0;
+               }
+       }
+};
+
+// offset setter from jQuery 1.4
+if ( !$.offset.setOffset ) {
+       $.offset.setOffset = function( elem, options ) {
+               // set position first, in-case top/left are set even on static elem
+               if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
+                       elem.style.position = "relative";
+               }
+               var curElem   = $( elem ),
+                       curOffset = curElem.offset(),
+                       curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
+                       curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
+                       props     = {
+                               top:  (options.top  - curOffset.top)  + curTop,
+                               left: (options.left - curOffset.left) + curLeft
+                       };
+               
+               if ( 'using' in options ) {
+                       options.using.call( elem, props );
+               } else {
+                       curElem.css( props );
+               }
+       };
+
+       $.fn.offset = function( options ) {
+               var elem = this[ 0 ];
+               if ( !elem || !elem.ownerDocument ) { return null; }
+               if ( options ) {
+                       if ( $.isFunction( options ) ) {
+                               return this.each(function( i ) {
+                                       $( this ).offset( options.call( this, i, $( this ).offset() ) );
+                               });
+                       }
+                       return this.each(function() {
+                               $.offset.setOffset( this, options );
+                       });
+               }
+               return _offset.call( this );
+       };
+}
+
+// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
+if ( !$.curCSS ) {
+       $.curCSS = $.css;
+}
+
+// fraction support test (older versions of jQuery don't support fractions)
+(function () {
+       var body = document.getElementsByTagName( "body" )[ 0 ], 
+               div = document.createElement( "div" ),
+               testElement, testElementParent, testElementStyle, offset, offsetTotal;
+
+       //Create a "fake body" for testing based on method used in jQuery.support
+       testElement = document.createElement( body ? "div" : "body" );
+       testElementStyle = {
+               visibility: "hidden",
+               width: 0,
+               height: 0,
+               border: 0,
+               margin: 0,
+               background: "none"
+       };
+       if ( body ) {
+               $.extend( testElementStyle, {
+                       position: "absolute",
+                       left: "-1000px",
+                       top: "-1000px"
+               });
+       }
+       for ( var i in testElementStyle ) {
+               testElement.style[ i ] = testElementStyle[ i ];
+       }
+       testElement.appendChild( div );
+       testElementParent = body || document.documentElement;
+       testElementParent.insertBefore( testElement, testElementParent.firstChild );
+
+       div.style.cssText = "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;";
+
+       offset = $( div ).offset( function( _, offset ) {
+               return offset;
+       }).offset();
+
+       testElement.innerHTML = "";
+       testElementParent.removeChild( testElement );
+
+       offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 );
+       support.fractions = offsetTotal > 21 && offsetTotal < 22;
+})();
+
+}( jQuery ));
diff --git a/resources/lib/jquery.ui/jquery.ui.progressbar.js b/resources/lib/jquery.ui/jquery.ui.progressbar.js
new file mode 100644 (file)
index 0000000..7cea1ba
--- /dev/null
@@ -0,0 +1,109 @@
+/*!
+ * jQuery UI Progressbar 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar
+ *
+ * Depends:
+ *   jquery.ui.core.js
+ *   jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget( "ui.progressbar", {
+       options: {
+               value: 0,
+               max: 100
+       },
+
+       min: 0,
+
+       _create: function() {
+               this.element
+                       .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
+                       .attr({
+                               role: "progressbar",
+                               "aria-valuemin": this.min,
+                               "aria-valuemax": this.options.max,
+                               "aria-valuenow": this._value()
+                       });
+
+               this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
+                       .appendTo( this.element );
+
+               this.oldValue = this._value();
+               this._refreshValue();
+       },
+
+       destroy: function() {
+               this.element
+                       .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
+                       .removeAttr( "role" )
+                       .removeAttr( "aria-valuemin" )
+                       .removeAttr( "aria-valuemax" )
+                       .removeAttr( "aria-valuenow" );
+
+               this.valueDiv.remove();
+
+               $.Widget.prototype.destroy.apply( this, arguments );
+       },
+
+       value: function( newValue ) {
+               if ( newValue === undefined ) {
+                       return this._value();
+               }
+
+               this._setOption( "value", newValue );
+               return this;
+       },
+
+       _setOption: function( key, value ) {
+               if ( key === "value" ) {
+                       this.options.value = value;
+                       this._refreshValue();
+                       if ( this._value() === this.options.max ) {
+                               this._trigger( "complete" );
+                       }
+               }
+
+               $.Widget.prototype._setOption.apply( this, arguments );
+       },
+
+       _value: function() {
+               var val = this.options.value;
+               // normalize invalid value
+               if ( typeof val !== "number" ) {
+                       val = 0;
+               }
+               return Math.min( this.options.max, Math.max( this.min, val ) );
+       },
+
+       _percentage: function() {
+               return 100 * this._value() / this.options.max;
+       },
+
+       _refreshValue: function() {
+               var value = this.value();
+               var percentage = this._percentage();
+
+               if ( this.oldValue !== value ) {
+                       this.oldValue = value;
+                       this._trigger( "change" );
+               }
+
+               this.valueDiv
+                       .toggle( value > this.min )
+                       .toggleClass( "ui-corner-right", value === this.options.max )
+                       .width( percentage.toFixed(0) + "%" );
+               this.element.attr( "aria-valuenow", value );
+       }
+});
+
+$.extend( $.ui.progressbar, {
+       version: "1.8.24"
+});
+
+})( jQuery );
diff --git a/resources/lib/jquery.ui/jquery.ui.resizable.js b/resources/lib/jquery.ui/jquery.ui.resizable.js
new file mode 100644 (file)
index 0000000..6cc6f41
--- /dev/null
@@ -0,0 +1,807 @@
+/*!
+ * jQuery UI Resizable 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *     jquery.ui.mouse.js
+ *     jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.resizable", $.ui.mouse, {
+       widgetEventPrefix: "resize",
+       options: {
+               alsoResize: false,
+               animate: false,
+               animateDuration: "slow",
+               animateEasing: "swing",
+               aspectRatio: false,
+               autoHide: false,
+               containment: false,
+               ghost: false,
+               grid: false,
+               handles: "e,s,se",
+               helper: false,
+               maxHeight: null,
+               maxWidth: null,
+               minHeight: 10,
+               minWidth: 10,
+               zIndex: 1000
+       },
+       _create: function() {
+
+               var self = this, o = this.options;
+               this.element.addClass("ui-resizable");
+
+               $.extend(this, {
+                       _aspectRatio: !!(o.aspectRatio),
+                       aspectRatio: o.aspectRatio,
+                       originalElement: this.element,
+                       _proportionallyResizeElements: [],
+                       _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
+               });
+
+               //Wrap the element if it cannot hold child nodes
+               if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
+
+                       //Create a wrapper element and set the wrapper to the new current internal element
+                       this.element.wrap(
+                               $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
+                                       position: this.element.css('position'),
+                                       width: this.element.outerWidth(),
+                                       height: this.element.outerHeight(),
+                                       top: this.element.css('top'),
+                                       left: this.element.css('left')
+                               })
+                       );
+
+                       //Overwrite the original this.element
+                       this.element = this.element.parent().data(
+                               "resizable", this.element.data('resizable')
+                       );
+
+                       this.elementIsWrapper = true;
+
+                       //Move margins to the wrapper
+                       this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
+                       this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
+
+                       //Prevent Safari textarea resize
+                       this.originalResizeStyle = this.originalElement.css('resize');
+                       this.originalElement.css('resize', 'none');
+
+                       //Push the actual element to our proportionallyResize internal array
+                       this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
+
+                       // avoid IE jump (hard set the margin)
+                       this.originalElement.css({ margin: this.originalElement.css('margin') });
+
+                       // fix handlers offset
+                       this._proportionallyResize();
+
+               }
+
+               this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
+               if(this.handles.constructor == String) {
+
+                       if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
+                       var n = this.handles.split(","); this.handles = {};
+
+                       for(var i = 0; i < n.length; i++) {
+
+                               var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
+                               var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
+
+                               // Apply zIndex to all handles - see #7960
+                               axis.css({ zIndex: o.zIndex });
+
+                               //TODO : What's going on here?
+                               if ('se' == handle) {
+                                       axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
+                               };
+
+                               //Insert into internal handles object and append to element
+                               this.handles[handle] = '.ui-resizable-'+handle;
+                               this.element.append(axis);
+                       }
+
+               }
+
+               this._renderAxis = function(target) {
+
+                       target = target || this.element;
+
+                       for(var i in this.handles) {
+
+                               if(this.handles[i].constructor == String)
+                                       this.handles[i] = $(this.handles[i], this.element).show();
+
+                               //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
+                               if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
+
+                                       var axis = $(this.handles[i], this.element), padWrapper = 0;
+
+                                       //Checking the correct pad and border
+                                       padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
+
+                                       //The padding type i have to apply...
+                                       var padPos = [ 'padding',
+                                               /ne|nw|n/.test(i) ? 'Top' :
+                                               /se|sw|s/.test(i) ? 'Bottom' :
+                                               /^e$/.test(i) ? 'Right' : 'Left' ].join("");
+
+                                       target.css(padPos, padWrapper);
+
+                                       this._proportionallyResize();
+
+                               }
+
+                               //TODO: What's that good for? There's not anything to be executed left
+                               if(!$(this.handles[i]).length)
+                                       continue;
+
+                       }
+               };
+
+               //TODO: make renderAxis a prototype function
+               this._renderAxis(this.element);
+
+               this._handles = $('.ui-resizable-handle', this.element)
+                       .disableSelection();
+
+               //Matching axis name
+               this._handles.mouseover(function() {
+                       if (!self.resizing) {
+                               if (this.className)
+                                       var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
+                               //Axis, default = se
+                               self.axis = axis && axis[1] ? axis[1] : 'se';
+                       }
+               });
+
+               //If we want to auto hide the elements
+               if (o.autoHide) {
+                       this._handles.hide();
+                       $(this.element)
+                               .addClass("ui-resizable-autohide")
+                               .hover(function() {
+                                       if (o.disabled) return;
+                                       $(this).removeClass("ui-resizable-autohide");
+                                       self._handles.show();
+                               },
+                               function(){
+                                       if (o.disabled) return;
+                                       if (!self.resizing) {
+                                               $(this).addClass("ui-resizable-autohide");
+                                               self._handles.hide();
+                                       }
+                               });
+               }
+
+               //Initialize the mouse interaction
+               this._mouseInit();
+
+       },
+
+       destroy: function() {
+
+               this._mouseDestroy();
+
+               var _destroy = function(exp) {
+                       $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
+                               .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
+               };
+
+               //TODO: Unwrap at same DOM position
+               if (this.elementIsWrapper) {
+                       _destroy(this.element);
+                       var wrapper = this.element;
+                       wrapper.after(
+                               this.originalElement.css({
+                                       position: wrapper.css('position'),
+                                       width: wrapper.outerWidth(),
+                                       height: wrapper.outerHeight(),
+                                       top: wrapper.css('top'),
+                                       left: wrapper.css('left')
+                               })
+                       ).remove();
+               }
+
+               this.originalElement.css('resize', this.originalResizeStyle);
+               _destroy(this.originalElement);
+
+               return this;
+       },
+
+       _mouseCapture: function(event) {
+               var handle = false;
+               for (var i in this.handles) {
+                       if ($(this.handles[i])[0] == event.target) {
+                               handle = true;
+                       }
+               }
+
+               return !this.options.disabled && handle;
+       },
+
+       _mouseStart: function(event) {
+
+               var o = this.options, iniPos = this.element.position(), el = this.element;
+
+               this.resizing = true;
+               this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
+
+               // bugfix for http://dev.jquery.com/ticket/1749
+               if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
+                       el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
+               }
+
+               this._renderProxy();
+
+               var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
+
+               if (o.containment) {
+                       curleft += $(o.containment).scrollLeft() || 0;
+                       curtop += $(o.containment).scrollTop() || 0;
+               }
+
+               //Store needed variables
+               this.offset = this.helper.offset();
+               this.position = { left: curleft, top: curtop };
+               this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+               this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+               this.originalPosition = { left: curleft, top: curtop };
+               this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
+               this.originalMousePosition = { left: event.pageX, top: event.pageY };
+
+               //Aspect Ratio
+               this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
+
+           var cursor = $('.ui-resizable-' + this.axis).css('cursor');
+           $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
+
+               el.addClass("ui-resizable-resizing");
+               this._propagate("start", event);
+               return true;
+       },
+
+       _mouseDrag: function(event) {
+
+               //Increase performance, avoid regex
+               var el = this.helper, o = this.options, props = {},
+                       self = this, smp = this.originalMousePosition, a = this.axis;
+
+               var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
+               var trigger = this._change[a];
+               if (!trigger) return false;
+
+               // Calculate the attrs that will be change
+               var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
+
+               // Put this in the mouseDrag handler since the user can start pressing shift while resizing
+               this._updateVirtualBoundaries(event.shiftKey);
+               if (this._aspectRatio || event.shiftKey)
+                       data = this._updateRatio(data, event);
+
+               data = this._respectSize(data, event);
+
+               // plugins callbacks need to be called first
+               this._propagate("resize", event);
+
+               el.css({
+                       top: this.position.top + "px", left: this.position.left + "px",
+                       width: this.size.width + "px", height: this.size.height + "px"
+               });
+
+               if (!this._helper && this._proportionallyResizeElements.length)
+                       this._proportionallyResize();
+
+               this._updateCache(data);
+
+               // calling the user callback at the end
+               this._trigger('resize', event, this.ui());
+
+               return false;
+       },
+
+       _mouseStop: function(event) {
+
+               this.resizing = false;
+               var o = this.options, self = this;
+
+               if(this._helper) {
+                       var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
+                               soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
+                               soffsetw = ista ? 0 : self.sizeDiff.width;
+
+                       var s = { width: (self.helper.width()  - soffsetw), height: (self.helper.height() - soffseth) },
+                               left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
+                               top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
+
+                       if (!o.animate)
+                               this.element.css($.extend(s, { top: top, left: left }));
+
+                       self.helper.height(self.size.height);
+                       self.helper.width(self.size.width);
+
+                       if (this._helper && !o.animate) this._proportionallyResize();
+               }
+
+               $('body').css('cursor', 'auto');
+
+               this.element.removeClass("ui-resizable-resizing");
+
+               this._propagate("stop", event);
+
+               if (this._helper) this.helper.remove();
+               return false;
+
+       },
+
+    _updateVirtualBoundaries: function(forceAspectRatio) {
+        var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
+
+        b = {
+            minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
+            maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
+            minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
+            maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
+        };
+
+        if(this._aspectRatio || forceAspectRatio) {
+            // We want to create an enclosing box whose aspect ration is the requested one
+            // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
+            pMinWidth = b.minHeight * this.aspectRatio;
+            pMinHeight = b.minWidth / this.aspectRatio;
+            pMaxWidth = b.maxHeight * this.aspectRatio;
+            pMaxHeight = b.maxWidth / this.aspectRatio;
+
+            if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
+            if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
+            if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
+            if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
+        }
+        this._vBoundaries = b;
+    },
+
+       _updateCache: function(data) {
+               var o = this.options;
+               this.offset = this.helper.offset();
+               if (isNumber(data.left)) this.position.left = data.left;
+               if (isNumber(data.top)) this.position.top = data.top;
+               if (isNumber(data.height)) this.size.height = data.height;
+               if (isNumber(data.width)) this.size.width = data.width;
+       },
+
+       _updateRatio: function(data, event) {
+
+               var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
+
+               if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
+               else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
+
+               if (a == 'sw') {
+                       data.left = cpos.left + (csize.width - data.width);
+                       data.top = null;
+               }
+               if (a == 'nw') {
+                       data.top = cpos.top + (csize.height - data.height);
+                       data.left = cpos.left + (csize.width - data.width);
+               }
+
+               return data;
+       },
+
+       _respectSize: function(data, event) {
+
+               var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
+                               ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
+                                       isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
+
+               if (isminw) data.width = o.minWidth;
+               if (isminh) data.height = o.minHeight;
+               if (ismaxw) data.width = o.maxWidth;
+               if (ismaxh) data.height = o.maxHeight;
+
+               var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
+               var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
+
+               if (isminw && cw) data.left = dw - o.minWidth;
+               if (ismaxw && cw) data.left = dw - o.maxWidth;
+               if (isminh && ch)       data.top = dh - o.minHeight;
+               if (ismaxh && ch)       data.top = dh - o.maxHeight;
+
+               // fixing jump error on top/left - bug #2330
+               var isNotwh = !data.width && !data.height;
+               if (isNotwh && !data.left && data.top) data.top = null;
+               else if (isNotwh && !data.top && data.left) data.left = null;
+
+               return data;
+       },
+
+       _proportionallyResize: function() {
+
+               var o = this.options;
+               if (!this._proportionallyResizeElements.length) return;
+               var element = this.helper || this.element;
+
+               for (var i=0; i < this._proportionallyResizeElements.length; i++) {
+
+                       var prel = this._proportionallyResizeElements[i];
+
+                       if (!this.borderDif) {
+                               var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
+                                       p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
+
+                               this.borderDif = $.map(b, function(v, i) {
+                                       var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
+                                       return border + padding;
+                               });
+                       }
+
+                       if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
+                               continue;
+
+                       prel.css({
+                               height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
+                               width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
+                       });
+
+               };
+
+       },
+
+       _renderProxy: function() {
+
+               var el = this.element, o = this.options;
+               this.elementOffset = el.offset();
+
+               if(this._helper) {
+
+                       this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
+
+                       // fix ie6 offset TODO: This seems broken
+                       var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
+                       pxyoffset = ( ie6 ? 2 : -1 );
+
+                       this.helper.addClass(this._helper).css({
+                               width: this.element.outerWidth() + pxyoffset,
+                               height: this.element.outerHeight() + pxyoffset,
+                               position: 'absolute',
+                               left: this.elementOffset.left - ie6offset +'px',
+                               top: this.elementOffset.top - ie6offset +'px',
+                               zIndex: ++o.zIndex //TODO: Don't modify option
+                       });
+
+                       this.helper
+                               .appendTo("body")
+                               .disableSelection();
+
+               } else {
+                       this.helper = this.element;
+               }
+
+       },
+
+       _change: {
+               e: function(event, dx, dy) {
+                       return { width: this.originalSize.width + dx };
+               },
+               w: function(event, dx, dy) {
+                       var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+                       return { left: sp.left + dx, width: cs.width - dx };
+               },
+               n: function(event, dx, dy) {
+                       var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+                       return { top: sp.top + dy, height: cs.height - dy };
+               },
+               s: function(event, dx, dy) {
+                       return { height: this.originalSize.height + dy };
+               },
+               se: function(event, dx, dy) {
+                       return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
+               },
+               sw: function(event, dx, dy) {
+                       return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
+               },
+               ne: function(event, dx, dy) {
+                       return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
+               },
+               nw: function(event, dx, dy) {
+                       return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
+               }
+       },
+
+       _propagate: function(n, event) {
+               $.ui.plugin.call(this, n, [event, this.ui()]);
+               (n != "resize" && this._trigger(n, event, this.ui()));
+       },
+
+       plugins: {},
+
+       ui: function() {
+               return {
+                       originalElement: this.originalElement,
+                       element: this.element,
+                       helper: this.helper,
+                       position: this.position,
+                       size: this.size,
+                       originalSize: this.originalSize,
+                       originalPosition: this.originalPosition
+               };
+       }
+
+});
+
+$.extend($.ui.resizable, {
+       version: "1.8.24"
+});
+
+/*
+ * Resizable Extensions
+ */
+
+$.ui.plugin.add("resizable", "alsoResize", {
+
+       start: function (event, ui) {
+               var self = $(this).data("resizable"), o = self.options;
+
+               var _store = function (exp) {
+                       $(exp).each(function() {
+                               var el = $(this);
+                               el.data("resizable-alsoresize", {
+                                       width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
+                                       left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10)
+                               });
+                       });
+               };
+
+               if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
+                       if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
+                       else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
+               }else{
+                       _store(o.alsoResize);
+               }
+       },
+
+       resize: function (event, ui) {
+               var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
+
+               var delta = {
+                       height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
+                       top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
+               },
+
+               _alsoResize = function (exp, c) {
+                       $(exp).each(function() {
+                               var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
+                                       css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
+
+                               $.each(css, function (i, prop) {
+                                       var sum = (start[prop]||0) + (delta[prop]||0);
+                                       if (sum && sum >= 0)
+                                               style[prop] = sum || null;
+                               });
+
+                               el.css(style);
+                       });
+               };
+
+               if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
+                       $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
+               }else{
+                       _alsoResize(o.alsoResize);
+               }
+       },
+
+       stop: function (event, ui) {
+               $(this).removeData("resizable-alsoresize");
+       }
+});
+
+$.ui.plugin.add("resizable", "animate", {
+
+       stop: function(event, ui) {
+               var self = $(this).data("resizable"), o = self.options;
+
+               var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
+                                       soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
+                                               soffsetw = ista ? 0 : self.sizeDiff.width;
+
+               var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
+                                       left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
+                                               top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
+
+               self.element.animate(
+                       $.extend(style, top && left ? { top: top, left: left } : {}), {
+                               duration: o.animateDuration,
+                               easing: o.animateEasing,
+                               step: function() {
+
+                                       var data = {
+                                               width: parseInt(self.element.css('width'), 10),
+                                               height: parseInt(self.element.css('height'), 10),
+                                               top: parseInt(self.element.css('top'), 10),
+                                               left: parseInt(self.element.css('left'), 10)
+                                       };
+
+                                       if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
+
+                                       // propagating resize, and updating values for each animation step
+                                       self._updateCache(data);
+                                       self._propagate("resize", event);
+
+                               }
+                       }
+               );
+       }
+
+});
+
+$.ui.plugin.add("resizable", "containment", {
+
+       start: function(event, ui) {
+               var self = $(this).data("resizable"), o = self.options, el = self.element;
+               var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
+               if (!ce) return;
+
+               self.containerElement = $(ce);
+
+               if (/document/.test(oc) || oc == document) {
+                       self.containerOffset = { left: 0, top: 0 };
+                       self.containerPosition = { left: 0, top: 0 };
+
+                       self.parentData = {
+                               element: $(document), left: 0, top: 0,
+                               width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
+                       };
+               }
+
+               // i'm a node, so compute top, left, right, bottom
+               else {
+                       var element = $(ce), p = [];
+                       $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
+
+                       self.containerOffset = element.offset();
+                       self.containerPosition = element.position();
+                       self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
+
+                       var co = self.containerOffset, ch = self.containerSize.height,  cw = self.containerSize.width,
+                                               width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
+
+                       self.parentData = {
+                               element: ce, left: co.left, top: co.top, width: width, height: height
+                       };
+               }
+       },
+
+       resize: function(event, ui) {
+               var self = $(this).data("resizable"), o = self.options,
+                               ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
+                               pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
+
+               if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
+
+               if (cp.left < (self._helper ? co.left : 0)) {
+                       self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
+                       if (pRatio) self.size.height = self.size.width / self.aspectRatio;
+                       self.position.left = o.helper ? co.left : 0;
+               }
+
+               if (cp.top < (self._helper ? co.top : 0)) {
+                       self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
+                       if (pRatio) self.size.width = self.size.height * self.aspectRatio;
+                       self.position.top = self._helper ? co.top : 0;
+               }
+
+               self.offset.left = self.parentData.left+self.position.left;
+               self.offset.top = self.parentData.top+self.position.top;
+
+               var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
+                                       hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
+
+               var isParent = self.containerElement.get(0) == self.element.parent().get(0),
+                   isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
+
+               if(isParent && isOffsetRelative) woset -= self.parentData.left;
+
+               if (woset + self.size.width >= self.parentData.width) {
+                       self.size.width = self.parentData.width - woset;
+                       if (pRatio) self.size.height = self.size.width / self.aspectRatio;
+               }
+
+               if (hoset + self.size.height >= self.parentData.height) {
+                       self.size.height = self.parentData.height - hoset;
+                       if (pRatio) self.size.width = self.size.height * self.aspectRatio;
+               }
+       },
+
+       stop: function(event, ui){
+               var self = $(this).data("resizable"), o = self.options, cp = self.position,
+                               co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
+
+               var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
+
+               if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
+                       $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
+
+               if (self._helper && !o.animate && (/static/).test(ce.css('position')))
+                       $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
+
+       }
+});
+
+$.ui.plugin.add("resizable", "ghost", {
+
+       start: function(event, ui) {
+
+               var self = $(this).data("resizable"), o = self.options, cs = self.size;
+
+               self.ghost = self.originalElement.clone();
+               self.ghost
+                       .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
+                       .addClass('ui-resizable-ghost')
+                       .addClass(typeof o.ghost == 'string' ? o.ghost : '');
+
+               self.ghost.appendTo(self.helper);
+
+       },
+
+       resize: function(event, ui){
+               var self = $(this).data("resizable"), o = self.options;
+               if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
+       },
+
+       stop: function(event, ui){
+               var self = $(this).data("resizable"), o = self.options;
+               if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
+       }
+
+});
+
+$.ui.plugin.add("resizable", "grid", {
+
+       resize: function(event, ui) {
+               var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
+               o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
+               var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
+
+               if (/^(se|s|e)$/.test(a)) {
+                       self.size.width = os.width + ox;
+                       self.size.height = os.height + oy;
+               }
+               else if (/^(ne)$/.test(a)) {
+                       self.size.width = os.width + ox;
+                       self.size.height = os.height + oy;
+                       self.position.top = op.top - oy;
+               }
+               else if (/^(sw)$/.test(a)) {
+                       self.size.width = os.width + ox;
+                       self.size.height = os.height + oy;
+                       self.position.left = op.left - ox;
+               }
+               else {
+                       self.size.width = os.width + ox;
+                       self.size.height = os.height + oy;
+                       self.position.top = op.top - oy;
+                       self.position.left = op.left - ox;
+               }
+       }
+
+});
+
+var num = function(v) {
+       return parseInt(v, 10) || 0;
+};
+
+var isNumber = function(value) {
+       return !isNaN(parseInt(value, 10));
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery.ui/jquery.ui.selectable.js b/resources/lib/jquery.ui/jquery.ui.selectable.js
new file mode 100644 (file)
index 0000000..44c6e8c
--- /dev/null
@@ -0,0 +1,267 @@
+/*!
+ * jQuery UI Selectable 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectables
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *     jquery.ui.mouse.js
+ *     jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.selectable", $.ui.mouse, {
+       options: {
+               appendTo: 'body',
+               autoRefresh: true,
+               distance: 0,
+               filter: '*',
+               tolerance: 'touch'
+       },
+       _create: function() {
+               var self = this;
+
+               this.element.addClass("ui-selectable");
+
+               this.dragged = false;
+
+               // cache selectee children based on filter
+               var selectees;
+               this.refresh = function() {
+                       selectees = $(self.options.filter, self.element[0]);
+                       selectees.addClass("ui-selectee");
+                       selectees.each(function() {
+                               var $this = $(this);
+                               var pos = $this.offset();
+                               $.data(this, "selectable-item", {
+                                       element: this,
+                                       $element: $this,
+                                       left: pos.left,
+                                       top: pos.top,
+                                       right: pos.left + $this.outerWidth(),
+                                       bottom: pos.top + $this.outerHeight(),
+                                       startselected: false,
+                                       selected: $this.hasClass('ui-selected'),
+                                       selecting: $this.hasClass('ui-selecting'),
+                                       unselecting: $this.hasClass('ui-unselecting')
+                               });
+                       });
+               };
+               this.refresh();
+
+               this.selectees = selectees.addClass("ui-selectee");
+
+               this._mouseInit();
+
+               this.helper = $("<div class='ui-selectable-helper'></div>");
+       },
+
+       destroy: function() {
+               this.selectees
+                       .removeClass("ui-selectee")
+                       .removeData("selectable-item");
+               this.element
+                       .removeClass("ui-selectable ui-selectable-disabled")
+                       .removeData("selectable")
+                       .unbind(".selectable");
+               this._mouseDestroy();
+
+               return this;
+       },
+
+       _mouseStart: function(event) {
+               var self = this;
+
+               this.opos = [event.pageX, event.pageY];
+
+               if (this.options.disabled)
+                       return;
+
+               var options = this.options;
+
+               this.selectees = $(options.filter, this.element[0]);
+
+               this._trigger("start", event);
+
+               $(options.appendTo).append(this.helper);
+               // position helper (lasso)
+               this.helper.css({
+                       "left": event.clientX,
+                       "top": event.clientY,
+                       "width": 0,
+                       "height": 0
+               });
+
+               if (options.autoRefresh) {
+                       this.refresh();
+               }
+
+               this.selectees.filter('.ui-selected').each(function() {
+                       var selectee = $.data(this, "selectable-item");
+                       selectee.startselected = true;
+                       if (!event.metaKey && !event.ctrlKey) {
+                               selectee.$element.removeClass('ui-selected');
+                               selectee.selected = false;
+                               selectee.$element.addClass('ui-unselecting');
+                               selectee.unselecting = true;
+                               // selectable UNSELECTING callback
+                               self._trigger("unselecting", event, {
+                                       unselecting: selectee.element
+                               });
+                       }
+               });
+
+               $(event.target).parents().andSelf().each(function() {
+                       var selectee = $.data(this, "selectable-item");
+                       if (selectee) {
+                               var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected');
+                               selectee.$element
+                                       .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
+                                       .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
+                               selectee.unselecting = !doSelect;
+                               selectee.selecting = doSelect;
+                               selectee.selected = doSelect;
+                               // selectable (UN)SELECTING callback
+                               if (doSelect) {
+                                       self._trigger("selecting", event, {
+                                               selecting: selectee.element
+                                       });
+                               } else {
+                                       self._trigger("unselecting", event, {
+                                               unselecting: selectee.element
+                                       });
+                               }
+                               return false;
+                       }
+               });
+
+       },
+
+       _mouseDrag: function(event) {
+               var self = this;
+               this.dragged = true;
+
+               if (this.options.disabled)
+                       return;
+
+               var options = this.options;
+
+               var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
+               if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
+               if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
+               this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
+
+               this.selectees.each(function() {
+                       var selectee = $.data(this, "selectable-item");
+                       //prevent helper from being selected if appendTo: selectable
+                       if (!selectee || selectee.element == self.element[0])
+                               return;
+                       var hit = false;
+                       if (options.tolerance == 'touch') {
+                               hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
+                       } else if (options.tolerance == 'fit') {
+                               hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
+                       }
+
+                       if (hit) {
+                               // SELECT
+                               if (selectee.selected) {
+                                       selectee.$element.removeClass('ui-selected');
+                                       selectee.selected = false;
+                               }
+                               if (selectee.unselecting) {
+                                       selectee.$element.removeClass('ui-unselecting');
+                                       selectee.unselecting = false;
+                               }
+                               if (!selectee.selecting) {
+                                       selectee.$element.addClass('ui-selecting');
+                                       selectee.selecting = true;
+                                       // selectable SELECTING callback
+                                       self._trigger("selecting", event, {
+                                               selecting: selectee.element
+                                       });
+                               }
+                       } else {
+                               // UNSELECT
+                               if (selectee.selecting) {
+                                       if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
+                                               selectee.$element.removeClass('ui-selecting');
+                                               selectee.selecting = false;
+                                               selectee.$element.addClass('ui-selected');
+                                               selectee.selected = true;
+                                       } else {
+                                               selectee.$element.removeClass('ui-selecting');
+                                               selectee.selecting = false;
+                                               if (selectee.startselected) {
+                                                       selectee.$element.addClass('ui-unselecting');
+                                                       selectee.unselecting = true;
+                                               }
+                                               // selectable UNSELECTING callback
+                                               self._trigger("unselecting", event, {
+                                                       unselecting: selectee.element
+                                               });
+                                       }
+                               }
+                               if (selectee.selected) {
+                                       if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
+                                               selectee.$element.removeClass('ui-selected');
+                                               selectee.selected = false;
+
+                                               selectee.$element.addClass('ui-unselecting');
+                                               selectee.unselecting = true;
+                                               // selectable UNSELECTING callback
+                                               self._trigger("unselecting", event, {
+                                                       unselecting: selectee.element
+                                               });
+                                       }
+                               }
+                       }
+               });
+
+               return false;
+       },
+
+       _mouseStop: function(event) {
+               var self = this;
+
+               this.dragged = false;
+
+               var options = this.options;
+
+               $('.ui-unselecting', this.element[0]).each(function() {
+                       var selectee = $.data(this, "selectable-item");
+                       selectee.$element.removeClass('ui-unselecting');
+                       selectee.unselecting = false;
+                       selectee.startselected = false;
+                       self._trigger("unselected", event, {
+                               unselected: selectee.element
+                       });
+               });
+               $('.ui-selecting', this.element[0]).each(function() {
+                       var selectee = $.data(this, "selectable-item");
+                       selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
+                       selectee.selecting = false;
+                       selectee.selected = true;
+                       selectee.startselected = true;
+                       self._trigger("selected", event, {
+                               selected: selectee.element
+                       });
+               });
+               this._trigger("stop", event);
+
+               this.helper.remove();
+
+               return false;
+       }
+
+});
+
+$.extend($.ui.selectable, {
+       version: "1.8.24"
+});
+
+})(jQuery);
diff --git a/resources/lib/jquery.ui/jquery.ui.slider.js b/resources/lib/jquery.ui/jquery.ui.slider.js
new file mode 100644 (file)
index 0000000..c554e78
--- /dev/null
@@ -0,0 +1,662 @@
+/*!
+ * jQuery UI Slider 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *     jquery.ui.mouse.js
+ *     jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+// number of pages in a slider
+// (how many times can you page up/down to go through the whole range)
+var numPages = 5;
+
+$.widget( "ui.slider", $.ui.mouse, {
+
+       widgetEventPrefix: "slide",
+
+       options: {
+               animate: false,
+               distance: 0,
+               max: 100,
+               min: 0,
+               orientation: "horizontal",
+               range: false,
+               step: 1,
+               value: 0,
+               values: null
+       },
+
+       _create: function() {
+               var self = this,
+                       o = this.options,
+                       existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
+                       handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
+                       handleCount = ( o.values && o.values.length ) || 1,
+                       handles = [];
+
+               this._keySliding = false;
+               this._mouseSliding = false;
+               this._animateOff = true;
+               this._handleIndex = null;
+               this._detectOrientation();
+               this._mouseInit();
+
+               this.element
+                       .addClass( "ui-slider" +
+                               " ui-slider-" + this.orientation +
+                               " ui-widget" +
+                               " ui-widget-content" +
+                               " ui-corner-all" +
+                               ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
+
+               this.range = $([]);
+
+               if ( o.range ) {
+                       if ( o.range === true ) {
+                               if ( !o.values ) {
+                                       o.values = [ this._valueMin(), this._valueMin() ];
+                               }
+                               if ( o.values.length && o.values.length !== 2 ) {
+                                       o.values = [ o.values[0], o.values[0] ];
+                               }
+                       }
+
+                       this.range = $( "<div></div>" )
+                               .appendTo( this.element )
+                               .addClass( "ui-slider-range" +
+                               // note: this isn't the most fittingly semantic framework class for this element,
+                               // but worked best visually with a variety of themes
+                               " ui-widget-header" + 
+                               ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
+               }
+
+               for ( var i = existingHandles.length; i < handleCount; i += 1 ) {
+                       handles.push( handle );
+               }
+
+               this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) );
+
+               this.handle = this.handles.eq( 0 );
+
+               this.handles.add( this.range ).filter( "a" )
+                       .click(function( event ) {
+                               event.preventDefault();
+                       })
+                       .hover(function() {
+                               if ( !o.disabled ) {
+                                       $( this ).addClass( "ui-state-hover" );
+                               }
+                       }, function() {
+                               $( this ).removeClass( "ui-state-hover" );
+                       })
+                       .focus(function() {
+                               if ( !o.disabled ) {
+                                       $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
+                                       $( this ).addClass( "ui-state-focus" );
+                               } else {
+                                       $( this ).blur();
+                               }
+                       })
+                       .blur(function() {
+                               $( this ).removeClass( "ui-state-focus" );
+                       });
+
+               this.handles.each(function( i ) {
+                       $( this ).data( "index.ui-slider-handle", i );
+               });
+
+               this.handles
+                       .keydown(function( event ) {
+                               var index = $( this ).data( "index.ui-slider-handle" ),
+                                       allowed,
+                                       curVal,
+                                       newVal,
+                                       step;
+       
+                               if ( self.options.disabled ) {
+                                       return;
+                               }
+       
+                               switch ( event.keyCode ) {
+                                       case $.ui.keyCode.HOME:
+                                       case $.ui.keyCode.END:
+                                       case $.ui.keyCode.PAGE_UP:
+                                       case $.ui.keyCode.PAGE_DOWN:
+                                       case $.ui.keyCode.UP:
+                                       case $.ui.keyCode.RIGHT:
+                                       case $.ui.keyCode.DOWN:
+                                       case $.ui.keyCode.LEFT:
+                                               event.preventDefault();
+                                               if ( !self._keySliding ) {
+                                                       self._keySliding = true;
+                                                       $( this ).addClass( "ui-state-active" );
+                                                       allowed = self._start( event, index );
+                                                       if ( allowed === false ) {
+                                                               return;
+                                                       }
+                                               }
+                                               break;
+                               }
+       
+                               step = self.options.step;
+                               if ( self.options.values && self.options.values.length ) {
+                                       curVal = newVal = self.values( index );
+                               } else {
+                                       curVal = newVal = self.value();
+                               }
+       
+                               switch ( event.keyCode ) {
+                                       case $.ui.keyCode.HOME:
+                                               newVal = self._valueMin();
+                                               break;
+                                       case $.ui.keyCode.END:
+                                               newVal = self._valueMax();
+                                               break;
+                                       case $.ui.keyCode.PAGE_UP:
+                                               newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
+                                               break;
+                                       case $.ui.keyCode.PAGE_DOWN:
+                                               newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
+                                               break;
+                                       case $.ui.keyCode.UP:
+                                       case $.ui.keyCode.RIGHT:
+                                               if ( curVal === self._valueMax() ) {
+                                                       return;
+                                               }
+                                               newVal = self._trimAlignValue( curVal + step );
+                                               break;
+                                       case $.ui.keyCode.DOWN:
+                                       case $.ui.keyCode.LEFT:
+                                               if ( curVal === self._valueMin() ) {
+                                                       return;
+                                               }
+                                               newVal = self._trimAlignValue( curVal - step );
+                                               break;
+                               }
+       
+                               self._slide( event, index, newVal );
+                       })
+                       .keyup(function( event ) {
+                               var index = $( this ).data( "index.ui-slider-handle" );
+       
+                               if ( self._keySliding ) {
+                                       self._keySliding = false;
+                                       self._stop( event, index );
+                                       self._change( event, index );
+                                       $( this ).removeClass( "ui-state-active" );
+                               }
+       
+                       });
+
+               this._refreshValue();
+
+               this._animateOff = false;
+       },
+
+       destroy: function() {
+               this.handles.remove();
+               this.range.remove();
+
+               this.element
+                       .removeClass( "ui-slider" +
+                               " ui-slider-horizontal" +
+                               " ui-slider-vertical" +
+                               " ui-slider-disabled" +
+                               " ui-widget" +
+                               " ui-widget-content" +
+                               " ui-corner-all" )
+                       .removeData( "slider" )
+                       .unbind( ".slider" );
+
+               this._mouseDestroy();
+
+               return this;
+       },
+
+       _mouseCapture: function( event ) {
+               var o = this.options,
+                       position,
+                       normValue,
+                       distance,
+                       closestHandle,
+                       self,
+                       index,
+                       allowed,
+                       offset,
+                       mouseOverHandle;
+
+               if ( o.disabled ) {
+                       return false;
+               }
+
+               this.elementSize = {
+                       width: this.element.outerWidth(),
+                       height: this.element.outerHeight()
+               };
+               this.elementOffset = this.element.offset();
+
+               position = { x: event.pageX, y: event.pageY };
+               normValue = this._normValueFromMouse( position );
+               distance = this._valueMax() - this._valueMin() + 1;
+               self = this;
+               this.handles.each(function( i ) {
+                       var thisDistance = Math.abs( normValue - self.values(i) );
+                       if ( distance > thisDistance ) {
+                               distance = thisDistance;
+                               closestHandle = $( this );
+                               index = i;
+                       }
+               });
+
+               // workaround for bug #3736 (if both handles of a range are at 0,
+               // the first is always used as the one with least distance,
+               // and moving it is obviously prevented by preventing negative ranges)
+               if( o.range === true && this.values(1) === o.min ) {
+                       index += 1;
+                       closestHandle = $( this.handles[index] );
+               }
+
+               allowed = this._start( event, index );
+               if ( allowed === false ) {
+                       return false;
+               }
+               this._mouseSliding = true;
+
+               self._handleIndex = index;
+
+               closestHandle
+                       .addClass( "ui-state-active" )
+                       .focus();
+               
+               offset = closestHandle.offset();
+               mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
+               this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
+                       left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
+                       top: event.pageY - offset.top -
+                               ( closestHandle.height() / 2 ) -
+                               ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
+                               ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
+                               ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
+               };
+
+               if ( !this.handles.hasClass( "ui-state-hover" ) ) {
+                       this._slide( event, index, normValue );
+               }
+               this._animateOff = true;
+               return true;
+       },
+
+       _mouseStart: function( event ) {
+               return true;
+       },
+
+       _mouseDrag: function( event ) {
+               var position = { x: event.pageX, y: event.pageY },
+                       normValue = this._normValueFromMouse( position );
+               
+               this._slide( event, this._handleIndex, normValue );
+
+               return false;
+       },
+
+       _mouseStop: function( event ) {
+               this.handles.removeClass( "ui-state-active" );
+               this._mouseSliding = false;
+
+               this._stop( event, this._handleIndex );
+               this._change( event, this._handleIndex );
+
+               this._handleIndex = null;
+               this._clickOffset = null;
+               this._animateOff = false;
+
+               return false;
+       },
+       
+       _detectOrientation: function() {
+               this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
+       },
+
+       _normValueFromMouse: function( position ) {
+               var pixelTotal,
+                       pixelMouse,
+                       percentMouse,
+                       valueTotal,
+                       valueMouse;
+
+               if ( this.orientation === "horizontal" ) {
+                       pixelTotal = this.elementSize.width;
+                       pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
+               } else {
+                       pixelTotal = this.elementSize.height;
+                       pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
+               }
+
+               percentMouse = ( pixelMouse / pixelTotal );
+               if ( percentMouse > 1 ) {
+                       percentMouse = 1;
+               }
+               if ( percentMouse < 0 ) {
+                       percentMouse = 0;
+               }
+               if ( this.orientation === "vertical" ) {
+                       percentMouse = 1 - percentMouse;
+               }
+
+               valueTotal = this._valueMax() - this._valueMin();
+               valueMouse = this._valueMin() + percentMouse * valueTotal;
+
+               return this._trimAlignValue( valueMouse );
+       },
+
+       _start: function( event, index ) {
+               var uiHash = {
+                       handle: this.handles[ index ],
+                       value: this.value()
+               };
+               if ( this.options.values && this.options.values.length ) {
+                       uiHash.value = this.values( index );
+                       uiHash.values = this.values();
+               }
+               return this._trigger( "start", event, uiHash );
+       },
+
+       _slide: function( event, index, newVal ) {
+               var otherVal,
+                       newValues,
+                       allowed;
+
+               if ( this.options.values && this.options.values.length ) {
+                       otherVal = this.values( index ? 0 : 1 );
+
+                       if ( ( this.options.values.length === 2 && this.options.range === true ) && 
+                                       ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
+                               ) {
+                               newVal = otherVal;
+                       }
+
+                       if ( newVal !== this.values( index ) ) {
+                               newValues = this.values();
+                               newValues[ index ] = newVal;
+                               // A slide can be canceled by returning false from the slide callback
+                               allowed = this._trigger( "slide", event, {
+                                       handle: this.handles[ index ],
+                                       value: newVal,
+                                       values: newValues
+                               } );
+                               otherVal = this.values( index ? 0 : 1 );
+                               if ( allowed !== false ) {
+                                       this.values( index, newVal, true );
+                               }
+                       }
+               } else {
+                       if ( newVal !== this.value() ) {
+                               // A slide can be canceled by returning false from the slide callback
+                               allowed = this._trigger( "slide", event, {
+                                       handle: this.handles[ index ],
+                                       value: newVal
+                               } );
+                               if ( allowed !== false ) {
+                                       this.value( newVal );
+                               }
+                       }
+               }
+       },
+
+       _stop: function( event, index ) {
+               var uiHash = {
+                       handle: this.handles[ index ],
+                       value: this.value()
+               };
+               if ( this.options.values && this.options.values.length ) {
+                       uiHash.value = this.values( index );
+                       uiHash.values = this.values();
+               }
+
+               this._trigger( "stop", event, uiHash );
+       },
+
+       _change: function( event, index ) {
+               if ( !this._keySliding && !this._mouseSliding ) {
+                       var uiHash = {
+                               handle: this.handles[ index ],
+                               value: this.value()
+                       };
+                       if ( this.options.values && this.options.values.length ) {
+                               uiHash.value = this.values( index );
+                               uiHash.values = this.values();
+                       }
+
+                       this._trigger( "change", event, uiHash );
+               }
+       },
+
+       value: function( newValue ) {
+               if ( arguments.length ) {
+                       this.options.value = this._trimAlignValue( newValue );
+                       this._refreshValue();
+                       this._change( null, 0 );
+                       return;
+               }
+
+               return this._value();
+       },
+
+       values: function( index, newValue ) {
+               var vals,
+                       newValues,
+                       i;
+
+               if ( arguments.length > 1 ) {
+                       this.options.values[ index ] = this._trimAlignValue( newValue );
+                       this._refreshValue();
+                       this._change( null, index );
+                       return;
+               }
+
+               if ( arguments.length ) {
+                       if ( $.isArray( arguments[ 0 ] ) ) {
+                               vals = this.options.values;
+                               newValues = arguments[ 0 ];
+                               for ( i = 0; i < vals.length; i += 1 ) {
+                                       vals[ i ] = this._trimAlignValue( newValues[ i ] );
+                                       this._change( null, i );
+                               }
+                               this._refreshValue();
+                       } else {
+                               if ( this.options.values && this.options.values.length ) {
+                                       return this._values( index );
+                               } else {
+                                       return this.value();
+                               }
+                       }
+               } else {
+                       return this._values();
+               }
+       },
+
+       _setOption: function( key, value ) {
+               var i,
+                       valsLength = 0;
+
+               if ( $.isArray( this.options.values ) ) {
+                       valsLength = this.options.values.length;
+               }
+
+               $.Widget.prototype._setOption.apply( this, arguments );
+
+               switch ( key ) {
+                       case "disabled":
+                               if ( value ) {
+                                       this.handles.filter( ".ui-state-focus" ).blur();
+                                       this.handles.removeClass( "ui-state-hover" );
+                                       this.handles.propAttr( "disabled", true );
+                                       this.element.addClass( "ui-disabled" );
+                               } else {
+                                       this.handles.propAttr( "disabled", false );
+                                       this.element.removeClass( "ui-disabled" );
+                               }
+                               break;
+                       case "orientation":
+                               this._detectOrientation();
+                               this.element
+                                       .removeClass( "ui-slider-horizontal ui-slider-vertical" )
+                                       .addClass( "ui-slider-" + this.orientation );
+                               this._refreshValue();
+                               break;
+                       case "value":
+                               this._animateOff = true;
+                               this._refreshValue();
+                               this._change( null, 0 );
+                               this._animateOff = false;
+                               break;
+                       case "values":
+                               this._animateOff = true;
+                               this._refreshValue();
+                               for ( i = 0; i < valsLength; i += 1 ) {
+                                       this._change( null, i );
+                               }
+                               this._animateOff = false;
+                               break;
+               }
+       },
+
+       //internal value getter
+       // _value() returns value trimmed by min and max, aligned by step
+       _value: function() {
+               var val = this.options.value;
+               val = this._trimAlignValue( val );
+
+               return val;
+       },
+
+       //internal values getter
+       // _values() returns array of values trimmed by min and max, aligned by step
+       // _values( index ) returns single value trimmed by min and max, aligned by step
+       _values: function( index ) {
+               var val,
+                       vals,
+                       i;
+
+               if ( arguments.length ) {
+                       val = this.options.values[ index ];
+                       val = this._trimAlignValue( val );
+
+                       return val;
+               } else {
+                       // .slice() creates a copy of the array
+                       // this copy gets trimmed by min and max and then returned
+                       vals = this.options.values.slice();
+                       for ( i = 0; i < vals.length; i+= 1) {
+                               vals[ i ] = this._trimAlignValue( vals[ i ] );
+                       }
+
+                       return vals;
+               }
+       },
+       
+       // returns the step-aligned value that val is closest to, between (inclusive) min and max
+       _trimAlignValue: function( val ) {
+               if ( val <= this._valueMin() ) {
+                       return this._valueMin();
+               }
+               if ( val >= this._valueMax() ) {
+                       return this._valueMax();
+               }
+               var step = ( this.options.step > 0 ) ? this.options.step : 1,
+                       valModStep = (val - this._valueMin()) % step,
+                       alignValue = val - valModStep;
+
+               if ( Math.abs(valModStep) * 2 >= step ) {
+                       alignValue += ( valModStep > 0 ) ? step : ( -step );
+               }
+
+               // Since JavaScript has problems with large floats, round
+               // the final value to 5 digits after the decimal point (see #4124)
+               return parseFloat( alignValue.toFixed(5) );
+       },
+
+       _valueMin: function() {
+               return this.options.min;
+       },
+
+       _valueMax: function() {
+               return this.options.max;
+       },
+       
+       _refreshValue: function() {
+               var oRange = this.options.range,
+                       o = this.options,
+                       self = this,
+                       animate = ( !this._animateOff ) ? o.animate : false,
+                       valPercent,
+                       _set = {},
+                       lastValPercent,
+                       value,
+                       valueMin,
+                       valueMax;
+
+               if ( this.options.values && this.options.values.length ) {
+                       this.handles.each(function( i, j ) {
+                               valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
+                               _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+                               $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+                               if ( self.options.range === true ) {
+                                       if ( self.orientation === "horizontal" ) {
+                                               if ( i === 0 ) {
+                                                       self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
+                                               }
+                                               if ( i === 1 ) {
+                                                       self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+                                               }
+                                       } else {
+                                               if ( i === 0 ) {
+                                                       self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
+                                               }
+                                               if ( i === 1 ) {
+                                                       self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+                                               }
+                                       }
+                               }
+                               lastValPercent = valPercent;
+                       });
+               } else {
+                       value = this.value();
+                       valueMin = this._valueMin();
+                       valueMax = this._valueMax();
+                       valPercent = ( valueMax !== valueMin ) ?
+                                       ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
+                                       0;
+                       _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+                       this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+
+                       if ( oRange === "min" && this.orientation === "horizontal" ) {
+                               this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
+                       }
+                       if ( oRange === "max" && this.orientation === "horizontal" ) {
+                               this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+                       }
+                       if ( oRange === "min" && this.orientation === "vertical" ) {
+                               this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
+                       }
+                       if ( oRange === "max" && this.orientation === "vertical" ) {
+                               this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+                       }
+               }
+       }
+
+});
+
+$.extend( $.ui.slider, {
+       version: "1.8.24"
+});
+
+}(jQuery));
diff --git a/resources/lib/jquery.ui/jquery.ui.sortable.js b/resources/lib/jquery.ui/jquery.ui.sortable.js
new file mode 100644 (file)
index 0000000..9e0cac6
--- /dev/null
@@ -0,0 +1,1094 @@
+/*!
+ * jQuery UI Sortable 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Sortables
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *     jquery.ui.mouse.js
+ *     jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.sortable", $.ui.mouse, {
+       widgetEventPrefix: "sort",
+       ready: false,
+       options: {
+               appendTo: "parent",
+               axis: false,
+               connectWith: false,
+               containment: false,
+               cursor: 'auto',
+               cursorAt: false,
+               dropOnEmpty: true,
+               forcePlaceholderSize: false,
+               forceHelperSize: false,
+               grid: false,
+               handle: false,
+               helper: "original",
+               items: '> *',
+               opacity: false,
+               placeholder: false,
+               revert: false,
+               scroll: true,
+               scrollSensitivity: 20,
+               scrollSpeed: 20,
+               scope: "default",
+               tolerance: "intersect",
+               zIndex: 1000
+       },
+       _create: function() {
+
+               var o = this.options;
+               this.containerCache = {};
+               this.element.addClass("ui-sortable");
+
+               //Get the items
+               this.refresh();
+
+               //Let's determine if the items are being displayed horizontally
+               this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
+
+               //Let's determine the parent's offset
+               this.offset = this.element.offset();
+
+               //Initialize mouse events for interaction
+               this._mouseInit();
+               
+               //We're ready to go
+               this.ready = true
+
+       },
+
+       destroy: function() {
+               $.Widget.prototype.destroy.call( this );
+               this.element
+                       .removeClass("ui-sortable ui-sortable-disabled");
+               this._mouseDestroy();
+
+               for ( var i = this.items.length - 1; i >= 0; i-- )
+                       this.items[i].item.removeData(this.widgetName + "-item");
+
+               return this;
+       },
+
+       _setOption: function(key, value){
+               if ( key === "disabled" ) {
+                       this.options[ key ] = value;
+       
+                       this.widget()
+                               [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
+               } else {
+                       // Don't call widget base _setOption for disable as it adds ui-state-disabled class
+                       $.Widget.prototype._setOption.apply(this, arguments);
+               }
+       },
+
+       _mouseCapture: function(event, overrideHandle) {
+               var that = this;
+
+               if (this.reverting) {
+                       return false;
+               }
+
+               if(this.options.disabled || this.options.type == 'static') return false;
+
+               //We have to refresh the items data once first
+               this._refreshItems(event);
+
+               //Find out if the clicked node (or one of its parents) is a actual item in this.items
+               var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
+                       if($.data(this, that.widgetName + '-item') == self) {
+                               currentItem = $(this);
+                               return false;
+                       }
+               });
+               if($.data(event.target, that.widgetName + '-item') == self) currentItem = $(event.target);
+
+               if(!currentItem) return false;
+               if(this.options.handle && !overrideHandle) {
+                       var validHandle = false;
+
+                       $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
+                       if(!validHandle) return false;
+               }
+
+               this.currentItem = currentItem;
+               this._removeCurrentsFromItems();
+               return true;
+
+       },
+
+       _mouseStart: function(event, overrideHandle, noActivation) {
+
+               var o = this.options, self = this;
+               this.currentContainer = this;
+
+               //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
+               this.refreshPositions();
+
+               //Create and append the visible helper
+               this.helper = this._createHelper(event);
+
+               //Cache the helper size
+               this._cacheHelperProportions();
+
+               /*
+                * - Position generation -
+                * This block generates everything position related - it's the core of draggables.
+                */
+
+               //Cache the margins of the original element
+               this._cacheMargins();
+
+               //Get the next scrolling parent
+               this.scrollParent = this.helper.scrollParent();
+
+               //The element's absolute position on the page minus margins
+               this.offset = this.currentItem.offset();
+               this.offset = {
+                       top: this.offset.top - this.margins.top,
+                       left: this.offset.left - this.margins.left
+               };
+
+               $.extend(this.offset, {
+                       click: { //Where the click happened, relative to the element
+                               left: event.pageX - this.offset.left,
+                               top: event.pageY - this.offset.top
+                       },
+                       parent: this._getParentOffset(),
+                       relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
+               });
+
+               // Only after we got the offset, we can change the helper's position to absolute
+               // TODO: Still need to figure out a way to make relative sorting possible
+               this.helper.css("position", "absolute");
+               this.cssPosition = this.helper.css("position");
+               
+               //Generate the original position
+               this.originalPosition = this._generatePosition(event);
+               this.originalPageX = event.pageX;
+               this.originalPageY = event.pageY;
+
+               //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+               (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
+
+               //Cache the former DOM position
+               this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
+
+               //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
+               if(this.helper[0] != this.currentItem[0]) {
+                       this.currentItem.hide();
+               }
+
+               //Create the placeholder
+               this._createPlaceholder();
+
+               //Set a containment if given in the options
+               if(o.containment)
+                       this._setContainment();
+
+               if(o.cursor) { // cursor option
+                       if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
+                       $('body').css("cursor", o.cursor);
+               }
+
+               if(o.opacity) { // opacity option
+                       if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
+                       this.helper.css("opacity", o.opacity);
+               }
+
+               if(o.zIndex) { // zIndex option
+                       if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
+                       this.helper.css("zIndex", o.zIndex);
+               }
+
+               //Prepare scrolling
+               if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
+                       this.overflowOffset = this.scrollParent.offset();
+
+               //Call callbacks
+               this._trigger("start", event, this._uiHash());
+
+               //Recache the helper size
+               if(!this._preserveHelperProportions)
+                       this._cacheHelperProportions();
+
+
+               //Post 'activate' events to possible containers
+               if(!noActivation) {
+                        for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
+               }
+
+               //Prepare possible droppables
+               if($.ui.ddmanager)
+                       $.ui.ddmanager.current = this;
+
+               if ($.ui.ddmanager && !o.dropBehaviour)
+                       $.ui.ddmanager.prepareOffsets(this, event);
+
+               this.dragging = true;
+
+               this.helper.addClass("ui-sortable-helper");
+               this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+               return true;
+
+       },
+
+       _mouseDrag: function(event) {
+
+               //Compute the helpers position
+               this.position = this._generatePosition(event);
+               this.positionAbs = this._convertPositionTo("absolute");
+
+               if (!this.lastPositionAbs) {
+                       this.lastPositionAbs = this.positionAbs;
+               }
+
+               //Do scrolling
+               if(this.options.scroll) {
+                       var o = this.options, scrolled = false;
+                       if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
+
+                               if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
+                                       this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
+                               else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
+                                       this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
+
+                               if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
+                                       this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
+                               else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
+                                       this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
+
+                       } else {
+
+                               if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
+                                       scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
+                               else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
+                                       scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
+
+                               if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
+                                       scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
+                               else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
+                                       scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
+
+                       }
+
+                       if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
+                               $.ui.ddmanager.prepareOffsets(this, event);
+               }
+
+               //Regenerate the absolute position used for position checks
+               this.positionAbs = this._convertPositionTo("absolute");
+
+               //Set the helper position
+               if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
+               if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
+
+               //Rearrange
+               for (var i = this.items.length - 1; i >= 0; i--) {
+
+                       //Cache variables and intersection, continue if no intersection
+                       var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
+                       if (!intersection) continue;
+
+                       // Only put the placeholder inside the current Container, skip all
+                       // items form other containers. This works because when moving
+                       // an item from one container to another the
+                       // currentContainer is switched before the placeholder is moved.
+                       //
+                       // Without this moving items in "sub-sortables" can cause the placeholder to jitter
+                       // beetween the outer and inner container.
+                       if (item.instance !== this.currentContainer) continue;
+
+                       if (itemElement != this.currentItem[0] //cannot intersect with itself
+                               &&      this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
+                               &&      !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
+                               && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
+                               //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
+                       ) {
+
+                               this.direction = intersection == 1 ? "down" : "up";
+
+                               if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
+                                       this._rearrange(event, item);
+                               } else {
+                                       break;
+                               }
+
+                               this._trigger("change", event, this._uiHash());
+                               break;
+                       }
+               }
+
+               //Post events to containers
+               this._contactContainers(event);
+
+               //Interconnect with droppables
+               if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
+
+               //Call callbacks
+               this._trigger('sort', event, this._uiHash());
+
+               this.lastPositionAbs = this.positionAbs;
+               return false;
+
+       },
+
+       _mouseStop: function(event, noPropagation) {
+
+               if(!event) return;
+
+               //If we are using droppables, inform the manager about the drop
+               if ($.ui.ddmanager && !this.options.dropBehaviour)
+                       $.ui.ddmanager.drop(this, event);
+
+               if(this.options.revert) {
+                       var self = this;
+                       var cur = self.placeholder.offset();
+
+                       self.reverting = true;
+
+                       $(this.helper).animate({
+                               left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
+                               top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
+                       }, parseInt(this.options.revert, 10) || 500, function() {
+                               self._clear(event);
+                       });
+               } else {
+                       this._clear(event, noPropagation);
+               }
+
+               return false;
+
+       },
+
+       cancel: function() {
+
+               var self = this;
+
+               if(this.dragging) {
+
+                       this._mouseUp({ target: null });
+
+                       if(this.options.helper == "original")
+                               this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
+                       else
+                               this.currentItem.show();
+
+                       //Post deactivating events to containers
+                       for (var i = this.containers.length - 1; i >= 0; i--){
+                               this.containers[i]._trigger("deactivate", null, self._uiHash(this));
+                               if(this.containers[i].containerCache.over) {
+                                       this.containers[i]._trigger("out", null, self._uiHash(this));
+                                       this.containers[i].containerCache.over = 0;
+                               }
+                       }
+
+               }
+
+               if (this.placeholder) {
+                       //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
+                       if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
+                       if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
+
+                       $.extend(this, {
+                               helper: null,
+                               dragging: false,
+                               reverting: false,
+                               _noFinalSort: null
+                       });
+
+                       if(this.domPosition.prev) {
+                               $(this.domPosition.prev).after(this.currentItem);
+                       } else {
+                               $(this.domPosition.parent).prepend(this.currentItem);
+                       }
+               }
+
+               return this;
+
+       },
+
+       serialize: function(o) {
+
+               var items = this._getItemsAsjQuery(o && o.connected);
+               var str = []; o = o || {};
+
+               $(items).each(function() {
+                       var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
+                       if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
+               });
+
+               if(!str.length && o.key) {
+                       str.push(o.key + '=');
+               }
+
+               return str.join('&');
+
+       },
+
+       toArray: function(o) {
+
+               var items = this._getItemsAsjQuery(o && o.connected);
+               var ret = []; o = o || {};
+
+               items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
+               return ret;
+
+       },
+
+       /* Be careful with the following core functions */
+       _intersectsWith: function(item) {
+
+               var x1 = this.positionAbs.left,
+                       x2 = x1 + this.helperProportions.width,
+                       y1 = this.positionAbs.top,
+                       y2 = y1 + this.helperProportions.height;
+
+               var l = item.left,
+                       r = l + item.width,
+                       t = item.top,
+                       b = t + item.height;
+
+               var dyClick = this.offset.click.top,
+                       dxClick = this.offset.click.left;
+
+               var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
+
+               if(        this.options.tolerance == "pointer"
+                       || this.options.forcePointerForContainers
+                       || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
+               ) {
+                       return isOverElement;
+               } else {
+
+                       return (l < x1 + (this.helperProportions.width / 2) // Right Half
+                               && x2 - (this.helperProportions.width / 2) < r // Left Half
+                               && t < y1 + (this.helperProportions.height / 2) // Bottom Half
+                               && y2 - (this.helperProportions.height / 2) < b ); // Top Half
+
+               }
+       },
+
+       _intersectsWithPointer: function(item) {
+
+               var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
+                       isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
+                       isOverElement = isOverElementHeight && isOverElementWidth,
+                       verticalDirection = this._getDragVerticalDirection(),
+                       horizontalDirection = this._getDragHorizontalDirection();
+
+               if (!isOverElement)
+                       return false;
+
+               return this.floating ?
+                       ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
+                       : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
+
+       },
+
+       _intersectsWithSides: function(item) {
+
+               var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
+                       isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
+                       verticalDirection = this._getDragVerticalDirection(),
+                       horizontalDirection = this._getDragHorizontalDirection();
+
+               if (this.floating && horizontalDirection) {
+                       return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
+               } else {
+                       return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
+               }
+
+       },
+
+       _getDragVerticalDirection: function() {
+               var delta = this.positionAbs.top - this.lastPositionAbs.top;
+               return delta != 0 && (delta > 0 ? "down" : "up");
+       },
+
+       _getDragHorizontalDirection: function() {
+               var delta = this.positionAbs.left - this.lastPositionAbs.left;
+               return delta != 0 && (delta > 0 ? "right" : "left");
+       },
+
+       refresh: function(event) {
+               this._refreshItems(event);
+               this.refreshPositions();
+               return this;
+       },
+
+       _connectWith: function() {
+               var options = this.options;
+               return options.connectWith.constructor == String
+                       ? [options.connectWith]
+                       : options.connectWith;
+       },
+       
+       _getItemsAsjQuery: function(connected) {
+
+               var self = this;
+               var items = [];
+               var queries = [];
+               var connectWith = this._connectWith();
+
+               if(connectWith && connected) {
+                       for (var i = connectWith.length - 1; i >= 0; i--){
+                               var cur = $(connectWith[i]);
+                               for (var j = cur.length - 1; j >= 0; j--){
+                                       var inst = $.data(cur[j], this.widgetName);
+                                       if(inst && inst != this && !inst.options.disabled) {
+                                               queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
+                                       }
+                               };
+                       };
+               }
+
+               queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
+
+               for (var i = queries.length - 1; i >= 0; i--){
+                       queries[i][0].each(function() {
+                               items.push(this);
+                       });
+               };
+
+               return $(items);
+
+       },
+
+       _removeCurrentsFromItems: function() {
+
+               var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
+
+               for (var i=0; i < this.items.length; i++) {
+
+                       for (var j=0; j < list.length; j++) {
+                               if(list[j] == this.items[i].item[0])
+                                       this.items.splice(i,1);
+                       };
+
+               };
+
+       },
+
+       _refreshItems: function(event) {
+
+               this.items = [];
+               this.containers = [this];
+               var items = this.items;
+               var self = this;
+               var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
+               var connectWith = this._connectWith();
+
+               if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
+                       for (var i = connectWith.length - 1; i >= 0; i--){
+                               var cur = $(connectWith[i]);
+                               for (var j = cur.length - 1; j >= 0; j--){
+                                       var inst = $.data(cur[j], this.widgetName);
+                                       if(inst && inst != this && !inst.options.disabled) {
+                                               queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
+                                               this.containers.push(inst);
+                                       }
+                               };
+                       };
+               }
+
+               for (var i = queries.length - 1; i >= 0; i--) {
+                       var targetData = queries[i][1];
+                       var _queries = queries[i][0];
+
+                       for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
+                               var item = $(_queries[j]);
+
+                               item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)
+
+                               items.push({
+                                       item: item,
+                                       instance: targetData,
+                                       width: 0, height: 0,
+                                       left: 0, top: 0
+                               });
+                       };
+               };
+
+       },
+
+       refreshPositions: function(fast) {
+
+               //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
+               if(this.offsetParent && this.helper) {
+                       this.offset.parent = this._getParentOffset();
+               }
+
+               for (var i = this.items.length - 1; i >= 0; i--){
+                       var item = this.items[i];
+
+                       //We ignore calculating positions of all connected containers when we're not over them
+                       if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
+                               continue;
+
+                       var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
+
+                       if (!fast) {
+                               item.width = t.outerWidth();
+                               item.height = t.outerHeight();
+                       }
+
+                       var p = t.offset();
+                       item.left = p.left;
+                       item.top = p.top;
+               };
+
+               if(this.options.custom && this.options.custom.refreshContainers) {
+                       this.options.custom.refreshContainers.call(this);
+               } else {
+                       for (var i = this.containers.length - 1; i >= 0; i--){
+                               var p = this.containers[i].element.offset();
+                               this.containers[i].containerCache.left = p.left;
+                               this.containers[i].containerCache.top = p.top;
+                               this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
+                               this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
+                       };
+               }
+
+               return this;
+       },
+
+       _createPlaceholder: function(that) {
+
+               var self = that || this, o = self.options;
+
+               if(!o.placeholder || o.placeholder.constructor == String) {
+                       var className = o.placeholder;
+                       o.placeholder = {
+                               element: function() {
+
+                                       var el = $(document.createElement(self.currentItem[0].nodeName))
+                                               .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
+                                               .removeClass("ui-sortable-helper")[0];
+
+                                       if(!className)
+                                               el.style.visibility = "hidden";
+
+                                       return el;
+                               },
+                               update: function(container, p) {
+
+                                       // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
+                                       // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
+                                       if(className && !o.forcePlaceholderSize) return;
+
+                                       //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
+                                       if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
+                                       if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
+                               }
+                       };
+               }
+
+               //Create the placeholder
+               self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
+
+               //Append it after the actual current item
+               self.currentItem.after(self.placeholder);
+
+               //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
+               o.placeholder.update(self, self.placeholder);
+
+       },
+
+       _contactContainers: function(event) {
+               
+               // get innermost container that intersects with item 
+               var innermostContainer = null, innermostIndex = null;           
+               
+               
+               for (var i = this.containers.length - 1; i >= 0; i--){
+
+                       // never consider a container that's located within the item itself 
+                       if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
+                               continue;
+
+                       if(this._intersectsWith(this.containers[i].containerCache)) {
+
+                               // if we've already found a container and it's more "inner" than this, then continue 
+                               if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
+                                       continue;
+
+                               innermostContainer = this.containers[i]; 
+                               innermostIndex = i;
+                                       
+                       } else {
+                               // container doesn't intersect. trigger "out" event if necessary 
+                               if(this.containers[i].containerCache.over) {
+                                       this.containers[i]._trigger("out", event, this._uiHash(this));
+                                       this.containers[i].containerCache.over = 0;
+                               }
+                       }
+
+               }
+               
+               // if no intersecting containers found, return 
+               if(!innermostContainer) return; 
+
+               // move the item into the container if it's not there already
+               if(this.containers.length === 1) {
+                       this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
+                       this.containers[innermostIndex].containerCache.over = 1;
+               } else if(this.currentContainer != this.containers[innermostIndex]) {
+
+                       //When entering a new container, we will find the item with the least distance and append our item near it
+                       var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
+                       for (var j = this.items.length - 1; j >= 0; j--) {
+                               if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
+                               var cur = this.containers[innermostIndex].floating ? this.items[j].item.offset().left : this.items[j].item.offset().top;
+                               if(Math.abs(cur - base) < dist) {
+                                       dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
+                                       this.direction = (cur - base > 0) ? 'down' : 'up';
+                               }
+                       }
+
+                       if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
+                               return;
+
+                       this.currentContainer = this.containers[innermostIndex];
+                       itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
+                       this._trigger("change", event, this._uiHash());
+                       this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
+
+                       //Update the placeholder
+                       this.options.placeholder.update(this.currentContainer, this.placeholder);
+
+                       this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
+                       this.containers[innermostIndex].containerCache.over = 1;
+               } 
+       
+               
+       },
+
+       _createHelper: function(event) {
+
+               var o = this.options;
+               var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
+
+               if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
+                       $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
+
+               if(helper[0] == this.currentItem[0])
+                       this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
+
+               if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
+               if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
+
+               return helper;
+
+       },
+
+       _adjustOffsetFromHelper: function(obj) {
+               if (typeof obj == 'string') {
+                       obj = obj.split(' ');
+               }
+               if ($.isArray(obj)) {
+                       obj = {left: +obj[0], top: +obj[1] || 0};
+               }
+               if ('left' in obj) {
+                       this.offset.click.left = obj.left + this.margins.left;
+               }
+               if ('right' in obj) {
+                       this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+               }
+               if ('top' in obj) {
+                       this.offset.click.top = obj.top + this.margins.top;
+               }
+               if ('bottom' in obj) {
+                       this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+               }
+       },
+
+       _getParentOffset: function() {
+
+
+               //Get the offsetParent and cache its position
+               this.offsetParent = this.helper.offsetParent();
+               var po = this.offsetParent.offset();
+
+               // This is a special case where we need to modify a offset calculated on start, since the following happened:
+               // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
+               // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
+               //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
+               if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
+                       po.left += this.scrollParent.scrollLeft();
+                       po.top += this.scrollParent.scrollTop();
+               }
+
+               if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
+               || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
+                       po = { top: 0, left: 0 };
+
+               return {
+                       top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
+                       left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
+               };
+
+       },
+
+       _getRelativeOffset: function() {
+
+               if(this.cssPosition == "relative") {
+                       var p = this.currentItem.position();
+                       return {
+                               top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
+                               left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
+                       };
+               } else {
+                       return { top: 0, left: 0 };
+               }
+
+       },
+
+       _cacheMargins: function() {
+               this.margins = {
+                       left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
+                       top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
+               };
+       },
+
+       _cacheHelperProportions: function() {
+               this.helperProportions = {
+                       width: this.helper.outerWidth(),
+                       height: this.helper.outerHeight()
+               };
+       },
+
+       _setContainment: function() {
+
+               var o = this.options;
+               if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
+               if(o.containment == 'document' || o.containment == 'window') this.containment = [
+                       0 - this.offset.relative.left - this.offset.parent.left,
+                       0 - this.offset.relative.top - this.offset.parent.top,
+                       $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
+                       ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
+               ];
+
+               if(!(/^(document|window|parent)$/).test(o.containment)) {
+                       var ce = $(o.containment)[0];
+                       var co = $(o.containment).offset();
+                       var over = ($(ce).css("overflow") != 'hidden');
+
+                       this.containment = [
+                               co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
+                               co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
+                               co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
+                               co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
+                       ];
+               }
+
+       },
+
+       _convertPositionTo: function(d, pos) {
+
+               if(!pos) pos = this.position;
+               var mod = d == "absolute" ? 1 : -1;
+               var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+               return {
+                       top: (
+                               pos.top                                                                                                                                 // The absolute mouse position
+                               + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
+                               + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
+                               - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
+                       ),
+                       left: (
+                               pos.left                                                                                                                                // The absolute mouse position
+                               + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
+                               + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
+                               - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
+                       )
+               };
+
+       },
+
+       _generatePosition: function(event) {
+
+               var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+               // This is another very weird special case that only happens for relative elements:
+               // 1. If the css position is relative
+               // 2. and the scroll parent is the document or similar to the offset parent
+               // we have to refresh the relative offset during the scroll so there are no jumps
+               if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
+                       this.offset.relative = this._getRelativeOffset();
+               }
+
+               var pageX = event.pageX;
+               var pageY = event.pageY;
+
+               /*
+                * - Position constraining -
+                * Constrain the position to a mix of grid, containment.
+                */
+
+               if(this.originalPosition) { //If we are not dragging yet, we won't check for options
+
+                       if(this.containment) {
+                               if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
+                               if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
+                               if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
+                               if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
+                       }
+
+                       if(o.grid) {
+                               var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
+                               pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
+
+                               var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
+                               pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
+                       }
+
+               }
+
+               return {
+                       top: (
+                               pageY                                                                                                                           // The absolute mouse position
+                               - this.offset.click.top                                                                                                 // Click offset (relative to the element)
+                               - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
+                               - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
+                               + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
+                       ),
+                       left: (
+                               pageX                                                                                                                           // The absolute mouse position
+                               - this.offset.click.left                                                                                                // Click offset (relative to the element)
+                               - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
+                               - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
+                               + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
+                       )
+               };
+
+       },
+
+       _rearrange: function(event, i, a, hardRefresh) {
+
+               a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
+
+               //Various things done here to improve the performance:
+               // 1. we create a setTimeout, that calls refreshPositions
+               // 2. on the instance, we have a counter variable, that get's higher after every append
+               // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
+               // 4. this lets only the last addition to the timeout stack through
+               this.counter = this.counter ? ++this.counter : 1;
+               var self = this, counter = this.counter;
+
+               window.setTimeout(function() {
+                       if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
+               },0);
+
+       },
+
+       _clear: function(event, noPropagation) {
+
+               this.reverting = false;
+               // We delay all events that have to be triggered to after the point where the placeholder has been removed and
+               // everything else normalized again
+               var delayedTriggers = [], self = this;
+
+               // We first have to update the dom position of the actual currentItem
+               // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
+               if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
+               this._noFinalSort = null;
+
+               if(this.helper[0] == this.currentItem[0]) {
+                       for(var i in this._storedCSS) {
+                               if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
+                       }
+                       this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
+               } else {
+                       this.currentItem.show();
+               }
+
+               if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
+               if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
+
+               // Check if the items Container has Changed and trigger appropriate
+               // events.
+               if (this !== this.currentContainer) {
+                       if(!noPropagation) {
+                               delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
+                               delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
+                               delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
+                       }
+               }
+
+               //Post events to containers
+               for (var i = this.containers.length - 1; i >= 0; i--){
+                       if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
+                       if(this.containers[i].containerCache.over) {
+                               delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
+                               this.containers[i].containerCache.over = 0;
+                       }
+               }
+
+               //Do what was originally in plugins
+               if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
+               if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
+               if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
+
+               this.dragging = false;
+               if(this.cancelHelperRemoval) {
+                       if(!noPropagation) {
+                               this._trigger("beforeStop", event, this._uiHash());
+                               for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
+                               this._trigger("stop", event, this._uiHash());
+                       }
+
+                       this.fromOutside = false;
+                       return false;
+               }
+
+               if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
+
+               //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
+               this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
+
+               if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
+
+               if(!noPropagation) {
+                       for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
+                       this._trigger("stop", event, this._uiHash());
+               }
+
+               this.fromOutside = false;
+               return true;
+
+       },
+
+       _trigger: function() {
+               if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
+                       this.cancel();
+               }
+       },
+
+       _uiHash: function(inst) {
+               var self = inst || this;
+               return {
+                       helper: self.helper,
+                       placeholder: self.placeholder || $([]),
+                       position: self.position,
+                       originalPosition: self.originalPosition,
+                       offset: self.positionAbs,
+                       item: self.currentItem,
+                       sender: inst ? inst.element : null
+               };
+       }
+
+});
+
+$.extend($.ui.sortable, {
+       version: "1.8.24"
+});
+
+})(jQuery);
diff --git a/resources/lib/jquery.ui/jquery.ui.tabs.js b/resources/lib/jquery.ui/jquery.ui.tabs.js
new file mode 100644 (file)
index 0000000..0c47f0e
--- /dev/null
@@ -0,0 +1,757 @@
+/*!
+ * jQuery UI Tabs 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs
+ *
+ * Depends:
+ *     jquery.ui.core.js
+ *     jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+var tabId = 0,
+       listId = 0;
+
+function getNextTabId() {
+       return ++tabId;
+}
+
+function getNextListId() {
+       return ++listId;
+}
+
+$.widget( "ui.tabs", {
+       options: {
+               add: null,
+               ajaxOptions: null,
+               cache: false,
+               cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
+               collapsible: false,
+               disable: null,
+               disabled: [],
+               enable: null,
+               event: "click",
+               fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
+               idPrefix: "ui-tabs-",
+               load: null,
+               panelTemplate: "<div></div>",
+               remove: null,
+               select: null,
+               show: null,
+               spinner: "<em>Loading&#8230;</em>",
+               tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
+       },
+
+       _create: function() {
+               this._tabify( true );
+       },
+
+       _setOption: function( key, value ) {
+               if ( key == "selected" ) {
+                       if (this.options.collapsible && value == this.options.selected ) {
+                               return;
+                       }
+                       this.select( value );
+               } else {
+                       this.options[ key ] = value;
+                       this._tabify();
+               }
+       },
+
+       _tabId: function( a ) {
+               return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
+                       this.options.idPrefix + getNextTabId();
+       },
+
+       _sanitizeSelector: function( hash ) {
+               // we need this because an id may contain a ":"
+               return hash.replace( /:/g, "\\:" );
+       },
+
+       _cookie: function() {
+               var cookie = this.cookie ||
+                       ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
+               return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
+       },
+
+       _ui: function( tab, panel ) {
+               return {
+                       tab: tab,
+                       panel: panel,
+                       index: this.anchors.index( tab )
+               };
+       },
+
+       _cleanup: function() {
+               // restore all former loading tabs labels
+               this.lis.filter( ".ui-state-processing" )
+                       .removeClass( "ui-state-processing" )
+                       .find( "span:data(label.tabs)" )
+                               .each(function() {
+                                       var el = $( this );
+                                       el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
+                               });
+       },
+
+       _tabify: function( init ) {
+               var self = this,
+                       o = this.options,
+                       fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
+
+               this.list = this.element.find( "ol,ul" ).eq( 0 );
+               this.lis = $( " > li:has(a[href])", this.list );
+               this.anchors = this.lis.map(function() {
+                       return $( "a", this )[ 0 ];
+               });
+               this.panels = $( [] );
+
+               this.anchors.each(function( i, a ) {
+                       var href = $( a ).attr( "href" );
+                       // For dynamically created HTML that contains a hash as href IE < 8 expands
+                       // such href to the full page url with hash and then misinterprets tab as ajax.
+                       // Same consideration applies for an added tab with a fragment identifier
+                       // since a[href=#fragment-identifier] does unexpectedly not match.
+                       // Thus normalize href attribute...
+                       var hrefBase = href.split( "#" )[ 0 ],
+                               baseEl;
+                       if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
+                                       ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
+                               href = a.hash;
+                               a.href = href;
+                       }
+
+                       // inline tab
+                       if ( fragmentId.test( href ) ) {
+                               self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
+                       // remote tab
+                       // prevent loading the page itself if href is just "#"
+                       } else if ( href && href !== "#" ) {
+                               // required for restore on destroy
+                               $.data( a, "href.tabs", href );
+
+                               // TODO until #3808 is fixed strip fragment identifier from url
+                               // (IE fails to load from such url)
+                               $.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
+
+                               var id = self._tabId( a );
+                               a.href = "#" + id;
+                               var $panel = self.element.find( "#" + id );
+                               if ( !$panel.length ) {
+                                       $panel = $( o.panelTemplate )
+                                               .attr( "id", id )
+                                               .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
+                                               .insertAfter( self.panels[ i - 1 ] || self.list );
+                                       $panel.data( "destroy.tabs", true );
+                               }
+                               self.panels = self.panels.add( $panel );
+                       // invalid tab href
+                       } else {
+                               o.disabled.push( i );
+                       }
+               });
+
+               // initialization from scratch
+               if ( init ) {
+                       // attach necessary classes for styling
+                       this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
+                       this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
+                       this.lis.addClass( "ui-state-default ui-corner-top" );
+                       this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
+
+                       // Selected tab
+                       // use "selected" option or try to retrieve:
+                       // 1. from fragment identifier in url
+                       // 2. from cookie
+                       // 3. from selected class attribute on <li>
+                       if ( o.selected === undefined ) {
+                               if ( location.hash ) {
+                                       this.anchors.each(function( i, a ) {
+                                               if ( a.hash == location.hash ) {
+                                                       o.selected = i;
+                                                       return false;
+                                               }
+                                       });
+                               }
+                               if ( typeof o.selected !== "number" && o.cookie ) {
+                                       o.selected = parseInt( self._cookie(), 10 );
+                               }
+                               if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
+                                       o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
+                               }
+                               o.selected = o.selected || ( this.lis.length ? 0 : -1 );
+                       } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
+                               o.selected = -1;
+                       }
+
+                       // sanity check - default to first tab...
+                       o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
+                               ? o.selected
+                               : 0;
+
+                       // Take disabling tabs via class attribute from HTML
+                       // into account and update option properly.
+                       // A selected tab cannot become disabled.
+                       o.disabled = $.unique( o.disabled.concat(
+                               $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
+                                       return self.lis.index( n );
+                               })
+                       ) ).sort();
+
+                       if ( $.inArray( o.selected, o.disabled ) != -1 ) {
+                               o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
+                       }
+
+                       // highlight selected tab
+                       this.panels.addClass( "ui-tabs-hide" );
+                       this.lis.removeClass( "ui-tabs-selected ui-state-active" );
+                       // check for length avoids error when initializing empty list
+                       if ( o.selected >= 0 && this.anchors.length ) {
+                               self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
+                               this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
+
+                               // seems to be expected behavior that the show callback is fired
+                               self.element.queue( "tabs", function() {
+                                       self._trigger( "show", null,
+                                               self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) );
+                               });
+
+                               this.load( o.selected );
+                       }
+
+                       // clean up to avoid memory leaks in certain versions of IE 6
+                       // TODO: namespace this event
+                       $( window ).bind( "unload", function() {
+                               self.lis.add( self.anchors ).unbind( ".tabs" );
+                               self.lis = self.anchors = self.panels = null;
+                       });
+               // update selected after add/remove
+               } else {
+                       o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
+               }
+
+               // update collapsible
+               // TODO: use .toggleClass()
+               this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
+
+               // set or update cookie after init and add/remove respectively
+               if ( o.cookie ) {
+                       this._cookie( o.selected, o.cookie );
+               }
+
+               // disable tabs
+               for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
+                       $( li )[ $.inArray( i, o.disabled ) != -1 &&
+                               // TODO: use .toggleClass()
+                               !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
+               }
+
+               // reset cache if switching from cached to not cached
+               if ( o.cache === false ) {
+                       this.anchors.removeData( "cache.tabs" );
+               }
+
+               // remove all handlers before, tabify may run on existing tabs after add or option change
+               this.lis.add( this.anchors ).unbind( ".tabs" );
+
+               if ( o.event !== "mouseover" ) {
+                       var addState = function( state, el ) {
+                               if ( el.is( ":not(.ui-state-disabled)" ) ) {
+                                       el.addClass( "ui-state-" + state );
+                               }
+                       };
+                       var removeState = function( state, el ) {
+                               el.removeClass( "ui-state-" + state );
+                       };
+                       this.lis.bind( "mouseover.tabs" , function() {
+                               addState( "hover", $( this ) );
+                       });
+                       this.lis.bind( "mouseout.tabs", function() {
+                               removeState( "hover", $( this ) );
+                       });
+                       this.anchors.bind( "focus.tabs", function() {
+                               addState( "focus", $( this ).closest( "li" ) );
+                       });
+                       this.anchors.bind( "blur.tabs", function() {
+                               removeState( "focus", $( this ).closest( "li" ) );
+                       });
+               }
+
+               // set up animations
+               var hideFx, showFx;
+               if ( o.fx ) {
+                       if ( $.isArray( o.fx ) ) {
+                               hideFx = o.fx[ 0 ];
+                               showFx = o.fx[ 1 ];
+                       } else {
+                               hideFx = showFx = o.fx;
+                       }
+               }
+
+               // Reset certain styles left over from animation
+               // and prevent IE's ClearType bug...
+               function resetStyle( $el, fx ) {
+                       $el.css( "display", "" );
+                       if ( !$.support.opacity && fx.opacity ) {
+                               $el[ 0 ].style.removeAttribute( "filter" );
+                       }
+               }
+
+               // Show a tab...
+               var showTab = showFx
+                       ? function( clicked, $show ) {
+                               $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
+                               $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
+                                       .animate( showFx, showFx.duration || "normal", function() {
+                                               resetStyle( $show, showFx );
+                                               self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
+                                       });
+                       }
+                       : function( clicked, $show ) {
+                               $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
+                               $show.removeClass( "ui-tabs-hide" );
+                               self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
+                       };
+
+               // Hide a tab, $show is optional...
+               var hideTab = hideFx
+                       ? function( clicked, $hide ) {
+                               $hide.animate( hideFx, hideFx.duration || "normal", function() {
+                                       self.lis.removeClass( "ui-tabs-selected ui-state-active" );
+                                       $hide.addClass( "ui-tabs-hide" );
+                                       resetStyle( $hide, hideFx );
+                                       self.element.dequeue( "tabs" );
+                               });
+                       }
+                       : function( clicked, $hide, $show ) {
+                               self.lis.removeClass( "ui-tabs-selected ui-state-active" );
+                               $hide.addClass( "ui-tabs-hide" );
+                               self.element.dequeue( "tabs" );
+                       };
+
+               // attach tab event handler, unbind to avoid duplicates from former tabifying...
+               this.anchors.bind( o.event + ".tabs", function() {
+                       var el = this,
+                               $li = $(el).closest( "li" ),
+                               $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
+                               $show = self.element.find( self._sanitizeSelector( el.hash ) );
+
+                       // If tab is already selected and not collapsible or tab disabled or
+                       // or is already loading or click callback returns false stop here.
+                       // Check if click handler returns false last so that it is not executed
+                       // for a disabled or loading tab!
+                       if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
+                               $li.hasClass( "ui-state-disabled" ) ||
+                               $li.hasClass( "ui-state-processing" ) ||
+                               self.panels.filter( ":animated" ).length ||
+                               self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
+                               this.blur();
+                               return false;
+                       }
+
+                       o.selected = self.anchors.index( this );
+
+                       self.abort();
+
+                       // if tab may be closed
+                       if ( o.collapsible ) {
+                               if ( $li.hasClass( "ui-tabs-selected" ) ) {
+                                       o.selected = -1;
+
+                                       if ( o.cookie ) {
+                                               self._cookie( o.selected, o.cookie );
+                                       }
+
+                                       self.element.queue( "tabs", function() {
+                                               hideTab( el, $hide );
+                                       }).dequeue( "tabs" );
+
+                                       this.blur();
+                                       return false;
+                               } else if ( !$hide.length ) {
+                                       if ( o.cookie ) {
+                                               self._cookie( o.selected, o.cookie );
+                                       }
+
+                                       self.element.queue( "tabs", function() {
+                                               showTab( el, $show );
+                                       });
+
+                                       // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
+                                       self.load( self.anchors.index( this ) );
+
+                                       this.blur();
+                                       return false;
+                               }
+                       }
+
+                       if ( o.cookie ) {
+                               self._cookie( o.selected, o.cookie );
+                       }
+
+                       // show new tab
+                       if ( $show.length ) {
+                               if ( $hide.length ) {
+                                       self.element.queue( "tabs", function() {
+                                               hideTab( el, $hide );
+                                       });
+                               }
+                               self.element.queue( "tabs", function() {
+                                       showTab( el, $show );
+                               });
+
+                               self.load( self.anchors.index( this ) );
+                       } else {
+                               throw "jQuery UI Tabs: Mismatching fragment identifier.";
+                       }
+
+                       // Prevent IE from keeping other link focussed when using the back button
+                       // and remove dotted border from clicked link. This is controlled via CSS
+                       // in modern browsers; blur() removes focus from address bar in Firefox
+                       // which can become a usability and annoying problem with tabs('rotate').
+                       if ( $.browser.msie ) {
+                               this.blur();
+                       }
+               });
+
+               // disable click in any case
+               this.anchors.bind( "click.tabs", function(){
+                       return false;
+               });
+       },
+
+    _getIndex: function( index ) {
+               // meta-function to give users option to provide a href string instead of a numerical index.
+               // also sanitizes numerical indexes to valid values.
+               if ( typeof index == "string" ) {
+                       index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
+               }
+
+               return index;
+       },
+
+       destroy: function() {
+               var o = this.options;
+
+               this.abort();
+
+               this.element
+                       .unbind( ".tabs" )
+                       .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
+                       .removeData( "tabs" );
+
+               this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
+
+               this.anchors.each(function() {
+                       var href = $.data( this, "href.tabs" );
+                       if ( href ) {
+                               this.href = href;
+                       }
+                       var $this = $( this ).unbind( ".tabs" );
+                       $.each( [ "href", "load", "cache" ], function( i, prefix ) {
+                               $this.removeData( prefix + ".tabs" );
+                       });
+               });
+
+               this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
+                       if ( $.data( this, "destroy.tabs" ) ) {
+                               $( this ).remove();
+                       } else {
+                               $( this ).removeClass([
+                                       "ui-state-default",
+                                       "ui-corner-top",
+                                       "ui-tabs-selected",
+                                       "ui-state-active",
+                                       "ui-state-hover",
+                                       "ui-state-focus",
+                                       "ui-state-disabled",
+                                       "ui-tabs-panel",
+                                       "ui-widget-content",
+                                       "ui-corner-bottom",
+                                       "ui-tabs-hide"
+                               ].join( " " ) );
+                       }
+               });
+
+               if ( o.cookie ) {
+                       this._cookie( null, o.cookie );
+               }
+
+               return this;
+       },
+
+       add: function( url, label, index ) {
+               if ( index === undefined ) {
+                       index = this.anchors.length;
+               }
+
+               var self = this,
+                       o = this.options,
+                       $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
+                       id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
+
+               $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
+
+               // try to find an existing element before creating a new one
+               var $panel = self.element.find( "#" + id );
+               if ( !$panel.length ) {
+                       $panel = $( o.panelTemplate )
+                               .attr( "id", id )
+                               .data( "destroy.tabs", true );
+               }
+               $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
+
+               if ( index >= this.lis.length ) {
+                       $li.appendTo( this.list );
+                       $panel.appendTo( this.list[ 0 ].parentNode );
+               } else {
+                       $li.insertBefore( this.lis[ index ] );
+                       $panel.insertBefore( this.panels[ index ] );
+               }
+
+               o.disabled = $.map( o.disabled, function( n, i ) {
+                       return n >= index ? ++n : n;
+               });
+
+               this._tabify();
+
+               if ( this.anchors.length == 1 ) {
+                       o.selected = 0;
+                       $li.addClass( "ui-tabs-selected ui-state-active" );
+                       $panel.removeClass( "ui-tabs-hide" );
+                       this.element.queue( "tabs", function() {
+                               self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
+                       });
+
+                       this.load( 0 );
+               }
+
+               this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
+               return this;
+       },
+
+       remove: function( index ) {
+               index = this._getIndex( index );
+               var o = this.options,
+                       $li = this.lis.eq( index ).remove(),
+                       $panel = this.panels.eq( index ).remove();
+
+               // If selected tab was removed focus tab to the right or
+               // in case the last tab was removed the tab to the left.
+               if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
+                       this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
+               }
+
+               o.disabled = $.map(
+                       $.grep( o.disabled, function(n, i) {
+                               return n != index;
+                       }),
+                       function( n, i ) {
+                               return n >= index ? --n : n;
+                       });
+
+               this._tabify();
+
+               this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
+               return this;
+       },
+
+       enable: function( index ) {
+               index = this._getIndex( index );
+               var o = this.options;
+               if ( $.inArray( index, o.disabled ) == -1 ) {
+                       return;
+               }
+
+               this.lis.eq( index ).removeClass( "ui-state-disabled" );
+               o.disabled = $.grep( o.disabled, function( n, i ) {
+                       return n != index;
+               });
+
+               this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
+               return this;
+       },
+
+       disable: function( index ) {
+               index = this._getIndex( index );
+               var self = this, o = this.options;
+               // cannot disable already selected tab
+               if ( index != o.selected ) {
+                       this.lis.eq( index ).addClass( "ui-state-disabled" );
+
+                       o.disabled.push( index );
+                       o.disabled.sort();
+
+                       this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
+               }
+
+               return this;
+       },
+
+       select: function( index ) {
+               index = this._getIndex( index );
+               if ( index == -1 ) {
+                       if ( this.options.collapsible && this.options.selected != -1 ) {
+                               index = this.options.selected;
+                       } else {
+                               return this;
+                       }
+               }
+               this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
+               return this;
+       },
+
+       load: function( index ) {
+               index = this._getIndex( index );
+               var self = this,
+                       o = this.options,
+                       a = this.anchors.eq( index )[ 0 ],
+                       url = $.data( a, "load.tabs" );
+
+               this.abort();
+
+               // not remote or from cache
+               if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
+                       this.element.dequeue( "tabs" );
+                       return;
+               }
+
+               // load remote from here on
+               this.lis.eq( index ).addClass( "ui-state-processing" );
+
+               if ( o.spinner ) {
+                       var span = $( "span", a );
+                       span.data( "label.tabs", span.html() ).html( o.spinner );
+               }
+
+               this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
+                       url: url,
+                       success: function( r, s ) {
+                               self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
+
+                               // take care of tab labels
+                               self._cleanup();
+
+                               if ( o.cache ) {
+                                       $.data( a, "cache.tabs", true );
+                               }
+
+                               self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
+                               try {
+                                       o.ajaxOptions.success( r, s );
+                               }
+                               catch ( e ) {}
+                       },
+                       error: function( xhr, s, e ) {
+                               // take care of tab labels
+                               self._cleanup();
+
+                               self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
+                               try {
+                                       // Passing index avoid a race condition when this method is
+                                       // called after the user has selected another tab.
+                                       // Pass the anchor that initiated this request allows
+                                       // loadError to manipulate the tab content panel via $(a.hash)
+                                       o.ajaxOptions.error( xhr, s, index, a );
+                               }
+                               catch ( e ) {}
+                       }
+               } ) );
+
+               // last, so that load event is fired before show...
+               self.element.dequeue( "tabs" );
+
+               return this;
+       },
+
+       abort: function() {
+               // stop possibly running animations
+               this.element.queue( [] );
+               this.panels.stop( false, true );
+
+               // "tabs" queue must not contain more than two elements,
+               // which are the callbacks for the latest clicked tab...
+               this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
+
+               // terminate pending requests from other tabs
+               if ( this.xhr ) {
+                       this.xhr.abort();
+                       delete this.xhr;
+               }
+
+               // take care of tab labels
+               this._cleanup();
+               return this;
+       },
+
+       url: function( index, url ) {
+               this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
+               return this;
+       },
+
+       length: function() {
+               return this.anchors.length;
+       }
+});
+
+$.extend( $.ui.tabs, {
+       version: "1.8.24"
+});
+
+/*
+ * Tabs Extensions
+ */
+
+/*
+ * Rotate
+ */
+$.extend( $.ui.tabs.prototype, {
+       rotation: null,
+       rotate: function( ms, continuing ) {
+               var self = this,
+                       o = this.options;
+
+               var rotate = self._rotate || ( self._rotate = function( e ) {
+                       clearTimeout( self.rotation );
+                       self.rotation = setTimeout(function() {
+                               var t = o.selected;
+                               self.select( ++t < self.anchors.length ? t : 0 );
+                       }, ms );
+                       
+                       if ( e ) {
+                               e.stopPropagation();
+                       }
+               });
+
+               var stop = self._unrotate || ( self._unrotate = !continuing
+                       ? function(e) {
+                               if (e.clientX) { // in case of a true click
+                                       self.rotate(null);
+                               }
+                       }
+                       : function( e ) {
+                               rotate();
+                       });
+
+               // start rotation
+               if ( ms ) {
+                       this.element.bind( "tabsshow", rotate );
+                       this.anchors.bind( o.event + ".tabs", stop );
+                       rotate();
+               // stop rotation
+               } else {
+                       clearTimeout( self.rotation );
+                       this.element.unbind( "tabsshow", rotate );
+                       this.anchors.unbind( o.event + ".tabs", stop );
+                       delete this._rotate;
+                       delete this._unrotate;
+               }
+
+               return this;
+       }
+});
+
+})( jQuery );
diff --git a/resources/lib/jquery.ui/jquery.ui.widget.js b/resources/lib/jquery.ui/jquery.ui.widget.js
new file mode 100644 (file)
index 0000000..66ef013
--- /dev/null
@@ -0,0 +1,272 @@
+/*!
+ * jQuery UI Widget 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Widget
+ */
+(function( $, undefined ) {
+
+// jQuery 1.4+
+if ( $.cleanData ) {
+       var _cleanData = $.cleanData;
+       $.cleanData = function( elems ) {
+               for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+                       try {
+                               $( elem ).triggerHandler( "remove" );
+                       // http://bugs.jquery.com/ticket/8235
+                       } catch( e ) {}
+               }
+               _cleanData( elems );
+       };
+} else {
+       var _remove = $.fn.remove;
+       $.fn.remove = function( selector, keepData ) {
+               return this.each(function() {
+                       if ( !keepData ) {
+                               if ( !selector || $.filter( selector, [ this ] ).length ) {
+                                       $( "*", this ).add( [ this ] ).each(function() {
+                                               try {
+                                                       $( this ).triggerHandler( "remove" );
+                                               // http://bugs.jquery.com/ticket/8235
+                                               } catch( e ) {}
+                                       });
+                               }
+                       }
+                       return _remove.call( $(this), selector, keepData );
+               });
+       };
+}
+
+$.widget = function( name, base, prototype ) {
+       var namespace = name.split( "." )[ 0 ],
+               fullName;
+       name = name.split( "." )[ 1 ];
+       fullName = namespace + "-" + name;
+
+       if ( !prototype ) {
+               prototype = base;
+               base = $.Widget;
+       }
+
+       // create selector for plugin
+       $.expr[ ":" ][ fullName ] = function( elem ) {
+               return !!$.data( elem, name );
+       };
+
+       $[ namespace ] = $[ namespace ] || {};
+       $[ namespace ][ name ] = function( options, element ) {
+               // allow instantiation without initializing for simple inheritance
+               if ( arguments.length ) {
+                       this._createWidget( options, element );
+               }
+       };
+
+       var basePrototype = new base();
+       // we need to make the options hash a property directly on the new instance
+       // otherwise we'll modify the options hash on the prototype that we're
+       // inheriting from
+//     $.each( basePrototype, function( key, val ) {
+//             if ( $.isPlainObject(val) ) {
+//                     basePrototype[ key ] = $.extend( {}, val );
+//             }
+//     });
+       basePrototype.options = $.extend( true, {}, basePrototype.options );
+       $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
+               namespace: namespace,
+               widgetName: name,
+               widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
+               widgetBaseClass: fullName
+       }, prototype );
+
+       $.widget.bridge( name, $[ namespace ][ name ] );
+};
+
+$.widget.bridge = function( name, object ) {
+       $.fn[ name ] = function( options ) {
+               var isMethodCall = typeof options === "string",
+                       args = Array.prototype.slice.call( arguments, 1 ),
+                       returnValue = this;
+
+               // allow multiple hashes to be passed on init
+               options = !isMethodCall && args.length ?
+                       $.extend.apply( null, [ true, options ].concat(args) ) :
+                       options;
+
+               // prevent calls to internal methods
+               if ( isMethodCall && options.charAt( 0 ) === "_" ) {
+                       return returnValue;
+               }
+
+               if ( isMethodCall ) {
+                       this.each(function() {
+                               var instance = $.data( this, name ),
+                                       methodValue = instance && $.isFunction( instance[options] ) ?
+                                               instance[ options ].apply( instance, args ) :
+                                               instance;
+                               // TODO: add this back in 1.9 and use $.error() (see #5972)
+//                             if ( !instance ) {
+//                                     throw "cannot call methods on " + name + " prior to initialization; " +
+//                                             "attempted to call method '" + options + "'";
+//                             }
+//                             if ( !$.isFunction( instance[options] ) ) {
+//                                     throw "no such method '" + options + "' for " + name + " widget instance";
+//                             }
+//                             var methodValue = instance[ options ].apply( instance, args );
+                               if ( methodValue !== instance && methodValue !== undefined ) {
+                                       returnValue = methodValue;
+                                       return false;
+                               }
+                       });
+               } else {
+                       this.each(function() {
+                               var instance = $.data( this, name );
+                               if ( instance ) {
+                                       instance.option( options || {} )._init();
+                               } else {
+                                       $.data( this, name, new object( options, this ) );
+                               }
+                       });
+               }
+
+               return returnValue;
+       };
+};
+
+$.Widget = function( options, element ) {
+       // allow instantiation without initializing for simple inheritance
+       if ( arguments.length ) {
+               this._createWidget( options, element );
+       }
+};
+
+$.Widget.prototype = {
+       widgetName: "widget",
+       widgetEventPrefix: "",
+       options: {
+               disabled: false
+       },
+       _createWidget: function( options, element ) {
+               // $.widget.bridge stores the plugin instance, but we do it anyway
+               // so that it's stored even before the _create function runs
+               $.data( element, this.widgetName, this );
+               this.element = $( element );
+               this.options = $.extend( true, {},
+                       this.options,
+                       this._getCreateOptions(),
+                       options );
+
+               var self = this;
+               this.element.bind( "remove." + this.widgetName, function() {
+                       self.destroy();
+               });
+
+               this._create();
+               this._trigger( "create" );
+               this._init();
+       },
+       _getCreateOptions: function() {
+               return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
+       },
+       _create: function() {},
+       _init: function() {},
+
+       destroy: function() {
+               this.element
+                       .unbind( "." + this.widgetName )
+                       .removeData( this.widgetName );
+               this.widget()
+                       .unbind( "." + this.widgetName )
+                       .removeAttr( "aria-disabled" )
+                       .removeClass(
+                               this.widgetBaseClass + "-disabled " +
+                               "ui-state-disabled" );
+       },
+
+       widget: function() {
+               return this.element;
+       },
+
+       option: function( key, value ) {
+               var options = key;
+
+               if ( arguments.length === 0 ) {
+                       // don't return a reference to the internal hash
+                       return $.extend( {}, this.options );
+               }
+
+               if  (typeof key === "string" ) {
+                       if ( value === undefined ) {
+                               return this.options[ key ];
+                       }
+                       options = {};
+                       options[ key ] = value;
+               }
+
+               this._setOptions( options );
+
+               return this;
+       },
+       _setOptions: function( options ) {
+               var self = this;
+               $.each( options, function( key, value ) {
+                       self._setOption( key, value );
+               });
+
+               return this;
+       },
+       _setOption: function( key, value ) {
+               this.options[ key ] = value;
+
+               if ( key === "disabled" ) {
+                       this.widget()
+                               [ value ? "addClass" : "removeClass"](
+                                       this.widgetBaseClass + "-disabled" + " " +
+                                       "ui-state-disabled" )
+                               .attr( "aria-disabled", value );
+               }
+
+               return this;
+       },
+
+       enable: function() {
+               return this._setOption( "disabled", false );
+       },
+       disable: function() {
+               return this._setOption( "disabled", true );
+       },
+
+       _trigger: function( type, event, data ) {
+               var prop, orig,
+                       callback = this.options[ type ];
+
+               data = data || {};
+               event = $.Event( event );
+               event.type = ( type === this.widgetEventPrefix ?
+                       type :
+                       this.widgetEventPrefix + type ).toLowerCase();
+               // the original event may come from any element
+               // so we need to reset the target on the new event
+               event.target = this.element[ 0 ];
+
+               // copy original event properties over to the new event
+               orig = event.originalEvent;
+               if ( orig ) {
+                       for ( prop in orig ) {
+                               if ( !( prop in event ) ) {
+                                       event[ prop ] = orig[ prop ];
+                               }
+                       }
+               }
+
+               this.element.trigger( event, data );
+
+               return !( $.isFunction(callback) &&
+                       callback.call( this.element[0], event, data ) === false ||
+                       event.isDefaultPrevented() );
+       }
+};
+
+})( jQuery );
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png b/resources/lib/jquery.ui/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644 (file)
index 0000000..e425e6e
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-bg_flat_75_ffffff_40x100.png b/resources/lib/jquery.ui/themes/default/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644 (file)
index 0000000..72d4757
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-bg_flat_75_ffffff_40x100.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_55_fbf9ee_1x400.png b/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644 (file)
index 0000000..3b2914a
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_65_ffffff_1x400.png b/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644 (file)
index 0000000..8569c1b
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_75_dadada_1x400.png b/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644 (file)
index 0000000..d6cc3c5
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_75_e6e6e6_1x400.png b/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644 (file)
index 0000000..86c2baa
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_95_fef1ec_1x400.png b/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644 (file)
index 0000000..4443fdc
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/resources/lib/jquery.ui/themes/default/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644 (file)
index 0000000..3cd467e
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-icons_222222_256x240.png b/resources/lib/jquery.ui/themes/default/images/ui-icons_222222_256x240.png
new file mode 100644 (file)
index 0000000..9a9606f
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-icons_222222_256x240.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-icons_2e83ff_256x240.png b/resources/lib/jquery.ui/themes/default/images/ui-icons_2e83ff_256x240.png
new file mode 100644 (file)
index 0000000..08d2617
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-icons_2e83ff_256x240.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-icons_454545_256x240.png b/resources/lib/jquery.ui/themes/default/images/ui-icons_454545_256x240.png
new file mode 100644 (file)
index 0000000..80cb644
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-icons_454545_256x240.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-icons_888888_256x240.png b/resources/lib/jquery.ui/themes/default/images/ui-icons_888888_256x240.png
new file mode 100644 (file)
index 0000000..8373712
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-icons_888888_256x240.png differ
diff --git a/resources/lib/jquery.ui/themes/default/images/ui-icons_cd0a0a_256x240.png b/resources/lib/jquery.ui/themes/default/images/ui-icons_cd0a0a_256x240.png
new file mode 100644 (file)
index 0000000..34fc893
Binary files /dev/null and b/resources/lib/jquery.ui/themes/default/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.accordion.css b/resources/lib/jquery.ui/themes/default/jquery.ui.accordion.css
new file mode 100644 (file)
index 0000000..cd8f971
--- /dev/null
@@ -0,0 +1,19 @@
+/*!
+ * jQuery UI Accordion 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion#theming
+ */
+/* IE/Win - Fix animation bug - #4615 */
+.ui-accordion { width: 100%; }
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
+.ui-accordion .ui-accordion-content-active { display: block; }
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.autocomplete.css b/resources/lib/jquery.ui/themes/default/jquery.ui.autocomplete.css
new file mode 100644 (file)
index 0000000..c7eaff2
--- /dev/null
@@ -0,0 +1,53 @@
+/*!
+ * jQuery UI Autocomplete 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete#theming
+ */
+.ui-autocomplete { position: absolute; cursor: default; }      
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/*
+ * jQuery UI Menu 1.8.24
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu#theming
+ */
+.ui-menu {
+       list-style:none;
+       padding: 2px;
+       margin: 0;
+       display:block;
+       float: left;
+}
+.ui-menu .ui-menu {
+       margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+       margin:0;
+       padding: 0;
+       zoom: 1;
+       float: left;
+       clear: left;
+       width: 100%;
+}
+.ui-menu .ui-menu-item a {
+       text-decoration:none;
+       display:block;
+       padding:.2em .4em;
+       line-height:1.5;
+       zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+       font-weight: normal;
+       margin: -1px;
+}
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.button.css b/resources/lib/jquery.ui/themes/default/jquery.ui.button.css
new file mode 100644 (file)
index 0000000..cd2dbb6
--- /dev/null
@@ -0,0 +1,110 @@
+/*!
+ * jQuery UI Button 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button#theming
+ */
+
+.ui-button {
+       display: inline-block;
+       position: relative;
+       padding: 0;
+       margin-right: .1em;
+       text-decoration: none !important;
+       cursor: pointer;
+       text-align: center;
+       zoom: 1;
+       overflow: visible; /* the overflow property removes extra width in IE */
+}
+/* to make room for the icon, a width needs to be set here */
+.ui-button-icon-only {
+       width: 2.2em;
+}
+
+/* button elements seem to need a little more width */
+button.ui-button-icon-only {
+       width: 2.4em;
+}
+.ui-button-icons-only {
+       width: 3.4em;
+}
+button.ui-button-icons-only {
+       width: 3.7em;
+}
+
+/*button text element */
+.ui-button .ui-button-text {
+       display: block;
+       line-height: 1.4;
+}
+.ui-button-text-only .ui-button-text {
+       padding: .4em 1em;
+}
+.ui-button-icon-only .ui-button-text,
+.ui-button-icons-only .ui-button-text {
+       padding: .4em;
+       text-indent: -9999999px;
+}
+.ui-button-text-icon-primary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+       padding: .4em 1em .4em 2.1em;
+}
+.ui-button-text-icon-secondary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+       padding: .4em 2.1em .4em 1em;
+}
+.ui-button-text-icons .ui-button-text {
+       padding-left: 2.1em;
+       padding-right: 2.1em;
+}
+/* no icon support for input elements, provide padding by default */
+       input.ui-button {
+       padding: .4em 1em;
+}
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon,
+.ui-button-text-icon-primary .ui-icon,
+.ui-button-text-icon-secondary .ui-icon,
+.ui-button-text-icons .ui-icon,
+.ui-button-icons-only .ui-icon {
+       position: absolute;
+       top: 50%;
+       margin-top: -8px;
+}
+.ui-button-icon-only .ui-icon {
+       left: 50%;
+       margin-left: -8px;
+}
+.ui-button-text-icon-primary .ui-button-icon-primary,
+.ui-button-text-icons .ui-button-icon-primary,
+.ui-button-icons-only .ui-button-icon-primary {
+       left: .5em;
+}
+.ui-button-text-icon-secondary .ui-button-icon-secondary,
+.ui-button-text-icons .ui-button-icon-secondary,
+.ui-button-icons-only .ui-button-icon-secondary {
+       right: .5em;
+}
+.ui-button-text-icons .ui-button-icon-secondary,
+.ui-button-icons-only .ui-button-icon-secondary {
+       right: .5em;
+}
+
+/*button sets*/
+.ui-buttonset {
+       margin-right: 7px;
+}
+.ui-buttonset .ui-button {
+       margin-left: 0;
+       margin-right: -.3em;
+}
+
+/* workarounds */
+button.ui-button::-moz-focus-inner {
+       border: 0;
+       padding: 0; /* reset extra padding in Firefox */
+}
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.core.css b/resources/lib/jquery.ui/themes/default/jquery.ui.core.css
new file mode 100644 (file)
index 0000000..8b953a2
--- /dev/null
@@ -0,0 +1,38 @@
+/*!
+ * jQuery UI CSS Framework 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
+.ui-helper-clearfix:after { clear: both; }
+.ui-helper-clearfix { zoom: 1; }
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.datepicker.css b/resources/lib/jquery.ui/themes/default/jquery.ui.datepicker.css
new file mode 100644 (file)
index 0000000..37d3a98
--- /dev/null
@@ -0,0 +1,66 @@
+/*!
+ * jQuery UI Datepicker 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker#theming
+ */
+.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month, 
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+    position: absolute; /*must have*/
+    z-index: -1; /*must have*/
+    filter: mask(); /*must have*/
+    top: -4px; /*must have*/
+    left: -4px; /*must have*/
+    width: 200px; /*must have*/
+    height: 200px; /*must have*/
+}
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.dialog.css b/resources/lib/jquery.ui/themes/default/jquery.ui.dialog.css
new file mode 100644 (file)
index 0000000..04515f4
--- /dev/null
@@ -0,0 +1,21 @@
+/*!
+ * jQuery UI Dialog 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog#theming
+ */
+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
+.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative;  }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } 
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
+.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.progressbar.css b/resources/lib/jquery.ui/themes/default/jquery.ui.progressbar.css
new file mode 100644 (file)
index 0000000..90bf308
--- /dev/null
@@ -0,0 +1,11 @@
+/*!
+ * jQuery UI Progressbar 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar#theming
+ */
+.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.resizable.css b/resources/lib/jquery.ui/themes/default/jquery.ui.resizable.css
new file mode 100644 (file)
index 0000000..d17873e
--- /dev/null
@@ -0,0 +1,20 @@
+/*!
+ * jQuery UI Resizable 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizable#theming
+ */
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.selectable.css b/resources/lib/jquery.ui/themes/default/jquery.ui.selectable.css
new file mode 100644 (file)
index 0000000..9850ee7
--- /dev/null
@@ -0,0 +1,10 @@
+/*!
+ * jQuery UI Selectable 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectable#theming
+ */
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.slider.css b/resources/lib/jquery.ui/themes/default/jquery.ui.slider.css
new file mode 100644 (file)
index 0000000..fbfe665
--- /dev/null
@@ -0,0 +1,24 @@
+/*!
+ * jQuery UI Slider 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider#theming
+ */
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }
\ No newline at end of file
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.tabs.css b/resources/lib/jquery.ui/themes/default/jquery.ui.tabs.css
new file mode 100644 (file)
index 0000000..f0bee7a
--- /dev/null
@@ -0,0 +1,18 @@
+/*!
+ * jQuery UI Tabs 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs#theming
+ */
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/resources/lib/jquery.ui/themes/default/jquery.ui.theme.css b/resources/lib/jquery.ui/themes/default/jquery.ui.theme.css
new file mode 100644 (file)
index 0000000..b7d2f61
--- /dev/null
@@ -0,0 +1,247 @@
+/*!
+ * jQuery UI CSS Framework 1.8.24
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
+.ui-widget-content a { color: #222222/*{fcContent}*/; }
+.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
+.ui-widget-header a { color: #222222/*{fcHeader}*/; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -khtml-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -khtml-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
+.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; }
\ No newline at end of file
diff --git a/resources/lib/jquery/jquery.appear.js b/resources/lib/jquery/jquery.appear.js
new file mode 100644 (file)
index 0000000..4f77886
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * jQuery.appear
+ * http://code.google.com/p/jquery-appear/
+ *
+ * Copyright (c) 2009 Michael Hixson
+ * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
+*/
+(function($) {
+        
+       $.fn.appear = function(fn, options) {
+                
+               var settings = $.extend({
+                       //arbitrary data to pass to fn
+                       data: undefined,
+                       //call fn only on the first appear?
+                       one: true
+                        
+               }, options);
+                
+               return this.each(function() {
+                
+                       var t = $(this);
+                        
+                       //whether the element is currently visible
+                       t.appeared = false;
+                        
+                       if (!fn) {
+                               //trigger the custom event
+                               t.trigger('appear', settings.data);
+                               return;
+                       }
+                        
+                       var w = $(window);
+                        
+                       //fires the appear event when appropriate
+                       var check = function() {
+                               //is the element hidden?
+                               if (!t.is(':visible')) {
+                                        
+                                       //it became hidden
+                                       t.appeared = false;
+                                       return;
+                               }
+                               //is the element inside the visible window?
+                               var a = w.scrollLeft();
+                               var b = w.scrollTop();
+                               var o = t.offset();
+                               var x = o.left;
+                               var y = o.top;
+                                
+                               if (y + t.height() >= b && 
+                                               y <= b + w.height() &&
+                                               x + t.width() >= a && 
+                                               x <= a + w.width()) {
+                                       //trigger the custom event
+                                       if (!t.appeared) t.trigger('appear', settings.data);
+                                        
+                               } else {
+                                       //it scrolled out of view
+                                       t.appeared = false;
+                               }
+                       };
+                       //create a modified fn with some additional logic
+                       var modifiedFn = function() {
+                                
+                               //mark the element as visible
+                               t.appeared = true;
+                               //is this supposed to happen only once?
+                               if (settings.one) {
+                                       //remove the check
+                                       w.unbind('scroll', check);
+                                       var i = $.inArray(check, $.fn.appear.checks);
+                                       if (i >= 0) $.fn.appear.checks.splice(i, 1);
+                               }
+                               //trigger the original fn
+                               fn.apply(this, arguments);
+                       };
+                        
+                       //bind the modified fn to the element
+                       if (settings.one) t.one('appear', settings.data, modifiedFn);
+                       else t.bind('appear', settings.data, modifiedFn);
+                        
+                       //check whenever the window scrolls
+                       w.scroll(check);
+                        
+                       //check whenever the dom changes
+                       $.fn.appear.checks.push(check);
+                        
+                       //check now
+                       (check)();
+               });
+       };
+        
+       //keep a queue of appearance checks
+       $.extend($.fn.appear, {
+                
+               checks: [],
+               timeout: null,
+               //process the queue
+               checkAll: function() {
+                       var length = $.fn.appear.checks.length;
+                       if (length > 0) while (length--) ($.fn.appear.checks[length])();
+               },
+               //check the queue asynchronously
+               run: function() {
+                       if ($.fn.appear.timeout) clearTimeout($.fn.appear.timeout);
+                       $.fn.appear.timeout = setTimeout($.fn.appear.checkAll, 20);
+               }
+       });
+        
+       //run checks when these methods are called
+       $.each(['append', 'prepend', 'after', 'before', 'attr', 
+                                       'removeAttr', 'addClass', 'removeClass', 'toggleClass', 
+                                       'remove', 'css', 'show', 'hide'], function(i, n) {
+               var old = $.fn[n];
+               if (old) {
+                       $.fn[n] = function() {
+                               var r = old.apply(this, arguments);
+                               $.fn.appear.run();
+                               return r;
+                       }
+               }
+       });
+        
+})(jQuery);
\ No newline at end of file
diff --git a/resources/lib/jquery/jquery.async.js b/resources/lib/jquery/jquery.async.js
new file mode 100644 (file)
index 0000000..2161f6b
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * jQuery Asynchronous Plugin 1.0
+ *
+ * Copyright (c) 2008 Vincent Robert (genezys.net)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ */
+(function($){
+
+// opts.delay : (default 10) delay between async call in ms
+// opts.bulk : (default 500) delay during which the loop can continue synchronously without yielding the CPU
+// opts.test : (default true) function to test in the while test part
+// opts.loop : (default empty) function to call in the while loop part
+// opts.end : (default empty) function to call at the end of the while loop
+$.whileAsync = function(opts) {
+       var delay = Math.abs(opts.delay) || 10,
+               bulk = isNaN(opts.bulk) ? 500 : Math.abs(opts.bulk),
+               test = opts.test || function(){ return true; },
+               loop = opts.loop || function(){},
+               end = opts.end || function(){};
+       
+       (function(){
+
+               var t = false,
+                       begin = new Date();
+                       
+               while( t = test() ) {
+                       loop();
+                       if( bulk === 0 || (new Date() - begin) > bulk ) {
+                               break;
+                       }
+               }
+               if( t ) {
+                       setTimeout(arguments.callee, delay);
+               }
+               else {
+                       end();
+               }
+               
+       })();
+};
+
+// opts.delay : (default 10) delay between async call in ms
+// opts.bulk : (default 500) delay during which the loop can continue synchronously without yielding the CPU
+// opts.loop : (default empty) function to call in the each loop part, signature: function(index, value) this = value
+// opts.end : (default empty) function to call at the end of the each loop
+$.eachAsync = function(array, opts) {
+       var     i = 0,
+               l = array.length,
+               loop = opts.loop || function(){};
+       
+       $.whileAsync(
+               $.extend(opts, {
+                       test: function() { return i < l; },
+                       loop: function() {
+                               var val = array[i];
+                               return loop.call(val, i++, val);
+                       }
+               })
+       );
+};
+
+$.fn.eachAsync = function(opts) {
+       $.eachAsync(this, opts);
+       return this;
+}
+
+})(jQuery);
\ No newline at end of file
diff --git a/resources/lib/jquery/jquery.ba-throttle-debounce.js b/resources/lib/jquery/jquery.ba-throttle-debounce.js
new file mode 100644 (file)
index 0000000..fa30bdf
--- /dev/null
@@ -0,0 +1,252 @@
+/*!
+ * jQuery throttle / debounce - v1.1 - 3/7/2010
+ * http://benalman.com/projects/jquery-throttle-debounce-plugin/
+ * 
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+
+// Script: jQuery throttle / debounce: Sometimes, less is more!
+//
+// *Version: 1.1, Last updated: 3/7/2010*
+// 
+// Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
+// GitHub       - http://github.com/cowboy/jquery-throttle-debounce/
+// Source       - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
+// (Minified)   - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
+// 
+// About: License
+// 
+// Copyright (c) 2010 "Cowboy" Ben Alman,
+// Dual licensed under the MIT and GPL licenses.
+// http://benalman.com/about/license/
+// 
+// About: Examples
+// 
+// These working examples, complete with fully commented code, illustrate a few
+// ways in which this plugin can be used.
+// 
+// Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
+// Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
+// 
+// About: Support and Testing
+// 
+// Information about what version or versions of jQuery this plugin has been
+// tested with, what browsers it has been tested in, and where the unit tests
+// reside (so you can test it yourself).
+// 
+// jQuery Versions - none, 1.3.2, 1.4.2
+// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
+// Unit Tests      - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
+// 
+// About: Release History
+// 
+// 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
+//       executed later than they should. Reworked a fair amount of internal
+//       logic as well.
+// 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
+//       from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
+//       no_trailing throttle parameter and debounce functionality.
+// 
+// Topic: Note for non-jQuery users
+// 
+// jQuery isn't actually required for this plugin, because nothing internal
+// uses any jQuery methods or properties. jQuery is just used as a namespace
+// under which these methods can exist.
+// 
+// Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
+// when this plugin is loaded, the method described below will be created in
+// the `Cowboy` namespace. Usage will be exactly the same, but instead of
+// $.method() or jQuery.method(), you'll need to use Cowboy.method().
+
+(function(window,undefined){
+  '$:nomunge'; // Used by YUI compressor.
+  
+  // Since jQuery really isn't required for this plugin, use `jQuery` as the
+  // namespace only if it already exists, otherwise use the `Cowboy` namespace,
+  // creating it if necessary.
+  var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
+    
+    // Internal method reference.
+    jq_throttle;
+  
+  // Method: jQuery.throttle
+  // 
+  // Throttle execution of a function. Especially useful for rate limiting
+  // execution of handlers on events like resize and scroll. If you want to
+  // rate-limit execution of a function to a single time, see the
+  // <jQuery.debounce> method.
+  // 
+  // In this visualization, | is a throttled-function call and X is the actual
+  // callback execution:
+  // 
+  // > Throttled with `no_trailing` specified as false or unspecified:
+  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
+  // > X    X    X    X    X    X        X    X    X    X    X    X
+  // > 
+  // > Throttled with `no_trailing` specified as true:
+  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
+  // > X    X    X    X    X             X    X    X    X    X
+  // 
+  // Usage:
+  // 
+  // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
+  // > 
+  // > jQuery('selector').bind( 'someevent', throttled );
+  // > jQuery('selector').unbind( 'someevent', throttled );
+  // 
+  // This also works in jQuery 1.4+:
+  // 
+  // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
+  // > jQuery('selector').unbind( 'someevent', callback );
+  // 
+  // Arguments:
+  // 
+  //  delay - (Number) A zero-or-greater delay in milliseconds. For event
+  //    callbacks, values around 100 or 250 (or even higher) are most useful.
+  //  no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
+  //    true, callback will only execute every `delay` milliseconds while the
+  //    throttled-function is being called. If no_trailing is false or
+  //    unspecified, callback will be executed one final time after the last
+  //    throttled-function call. (After the throttled-function has not been
+  //    called for `delay` milliseconds, the internal counter is reset)
+  //  callback - (Function) A function to be executed after delay milliseconds.
+  //    The `this` context and all arguments are passed through, as-is, to
+  //    `callback` when the throttled-function is executed.
+  // 
+  // Returns:
+  // 
+  //  (Function) A new, throttled, function.
+  
+  $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
+    // After wrapper has stopped being called, this timeout ensures that
+    // `callback` is executed at the proper times in `throttle` and `end`
+    // debounce modes.
+    var timeout_id,
+      
+      // Keep track of the last time `callback` was executed.
+      last_exec = 0;
+    
+    // `no_trailing` defaults to falsy.
+    if ( typeof no_trailing !== 'boolean' ) {
+      debounce_mode = callback;
+      callback = no_trailing;
+      no_trailing = undefined;
+    }
+    
+    // The `wrapper` function encapsulates all of the throttling / debouncing
+    // functionality and when executed will limit the rate at which `callback`
+    // is executed.
+    function wrapper() {
+      var that = this,
+        elapsed = +new Date() - last_exec,
+        args = arguments;
+      
+      // Execute `callback` and update the `last_exec` timestamp.
+      function exec() {
+        last_exec = +new Date();
+        callback.apply( that, args );
+      };
+      
+      // If `debounce_mode` is true (at_begin) this is used to clear the flag
+      // to allow future `callback` executions.
+      function clear() {
+        timeout_id = undefined;
+      };
+      
+      if ( debounce_mode && !timeout_id ) {
+        // Since `wrapper` is being called for the first time and
+        // `debounce_mode` is true (at_begin), execute `callback`.
+        exec();
+      }
+      
+      // Clear any existing timeout.
+      timeout_id && clearTimeout( timeout_id );
+      
+      if ( debounce_mode === undefined && elapsed > delay ) {
+        // In throttle mode, if `delay` time has been exceeded, execute
+        // `callback`.
+        exec();
+        
+      } else if ( no_trailing !== true ) {
+        // In trailing throttle mode, since `delay` time has not been
+        // exceeded, schedule `callback` to execute `delay` ms after most
+        // recent execution.
+        // 
+        // If `debounce_mode` is true (at_begin), schedule `clear` to execute
+        // after `delay` ms.
+        // 
+        // If `debounce_mode` is false (at end), schedule `callback` to
+        // execute after `delay` ms.
+        timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
+      }
+    };
+    
+    // Set the guid of `wrapper` function to the same of original callback, so
+    // it can be removed in jQuery 1.4+ .unbind or .die by using the original
+    // callback as a reference.
+    if ( $.guid ) {
+      wrapper.guid = callback.guid = callback.guid || $.guid++;
+    }
+    
+    // Return the wrapper function.
+    return wrapper;
+  };
+  
+  // Method: jQuery.debounce
+  // 
+  // Debounce execution of a function. Debouncing, unlike throttling,
+  // guarantees that a function is only executed a single time, either at the
+  // very beginning of a series of calls, or at the very end. If you want to
+  // simply rate-limit execution of a function, see the <jQuery.throttle>
+  // method.
+  // 
+  // In this visualization, | is a debounced-function call and X is the actual
+  // callback execution:
+  // 
+  // > Debounced with `at_begin` specified as false or unspecified:
+  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
+  // >                          X                                 X
+  // > 
+  // > Debounced with `at_begin` specified as true:
+  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
+  // > X                                 X
+  // 
+  // Usage:
+  // 
+  // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
+  // > 
+  // > jQuery('selector').bind( 'someevent', debounced );
+  // > jQuery('selector').unbind( 'someevent', debounced );
+  // 
+  // This also works in jQuery 1.4+:
+  // 
+  // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
+  // > jQuery('selector').unbind( 'someevent', callback );
+  // 
+  // Arguments:
+  // 
+  //  delay - (Number) A zero-or-greater delay in milliseconds. For event
+  //    callbacks, values around 100 or 250 (or even higher) are most useful.
+  //  at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
+  //    unspecified, callback will only be executed `delay` milliseconds after
+  //    the last debounced-function call. If at_begin is true, callback will be
+  //    executed only at the first debounced-function call. (After the
+  //    throttled-function has not been called for `delay` milliseconds, the
+  //    internal counter is reset)
+  //  callback - (Function) A function to be executed after delay milliseconds.
+  //    The `this` context and all arguments are passed through, as-is, to
+  //    `callback` when the debounced-function is executed.
+  // 
+  // Returns:
+  // 
+  //  (Function) A new, debounced, function.
+  
+  $.debounce = function( delay, at_begin, callback ) {
+    return callback === undefined
+      ? jq_throttle( delay, at_begin, false )
+      : jq_throttle( delay, callback, at_begin !== false );
+  };
+  
+})(this);
diff --git a/resources/lib/jquery/jquery.cookie.js b/resources/lib/jquery/jquery.cookie.js
new file mode 100644 (file)
index 0000000..6d5974a
--- /dev/null
@@ -0,0 +1,47 @@
+/*!
+ * jQuery Cookie Plugin
+ * https://github.com/carhartl/jquery-cookie
+ *
+ * Copyright 2011, Klaus Hartl
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.opensource.org/licenses/GPL-2.0
+ */
+(function($) {
+    $.cookie = function(key, value, options) {
+
+        // key and at least value given, set cookie...
+        if (arguments.length > 1 && (!/Object/.test(Object.prototype.toString.call(value)) || value === null || value === undefined)) {
+            options = $.extend({}, options);
+
+            if (value === null || value === undefined) {
+                options.expires = -1;
+            }
+
+            if (typeof options.expires === 'number') {
+                var days = options.expires, t = options.expires = new Date();
+                t.setDate(t.getDate() + days);
+            }
+
+            value = String(value);
+
+            return (document.cookie = [
+                encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value),
+                options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+                options.path    ? '; path=' + options.path : '',
+                options.domain  ? '; domain=' + options.domain : '',
+                options.secure  ? '; secure' : ''
+            ].join(''));
+        }
+
+        // key and possibly options given, get cookie...
+        options = value || {};
+        var decode = options.raw ? function(s) { return s; } : decodeURIComponent;
+
+        var pairs = document.cookie.split('; ');
+        for (var i = 0, pair; pair = pairs[i] && pairs[i].split('='); i++) {
+            if (decode(pair[0]) === key) return decode(pair[1] || ''); // IE saves cookies with empty string as "c; ", e.g. without "=" as opposed to EOMB, thus pair[1] may be undefined
+        }
+        return null;
+    };
+})(jQuery);
diff --git a/resources/lib/jquery/jquery.cycle.all.js b/resources/lib/jquery/jquery.cycle.all.js
new file mode 100644 (file)
index 0000000..d57fb72
--- /dev/null
@@ -0,0 +1,1529 @@
+/*!
+ * jQuery Cycle Plugin (with Transition Definitions)
+ * Examples and documentation at: http://jquery.malsup.com/cycle/
+ * Copyright (c) 2007-2010 M. Alsup
+ * Version: 2.9999 (13-NOV-2011)
+ * Dual licensed under the MIT and GPL licenses.
+ * http://jquery.malsup.com/license.html
+ * Requires: jQuery v1.3.2 or later
+ */
+;(function($, undefined) {
+
+var ver = '2.9999';
+
+// if $.support is not defined (pre jQuery 1.3) add what I need
+if ($.support == undefined) {
+       $.support = {
+               opacity: !($.browser.msie)
+       };
+}
+
+function debug(s) {
+       $.fn.cycle.debug && log(s);
+}              
+function log() {
+       window.console && console.log && console.log('[cycle] ' + Array.prototype.join.call(arguments,' '));
+}
+$.expr[':'].paused = function(el) {
+       return el.cyclePause;
+}
+
+
+// the options arg can be...
+//   a number  - indicates an immediate transition should occur to the given slide index
+//   a string  - 'pause', 'resume', 'toggle', 'next', 'prev', 'stop', 'destroy' or the name of a transition effect (ie, 'fade', 'zoom', etc)
+//   an object - properties to control the slideshow
+//
+// the arg2 arg can be...
+//   the name of an fx (only used in conjunction with a numeric value for 'options')
+//   the value true (only used in first arg == 'resume') and indicates
+//      that the resume should occur immediately (not wait for next timeout)
+
+$.fn.cycle = function(options, arg2) {
+       var o = { s: this.selector, c: this.context };
+
+       // in 1.3+ we can fix mistakes with the ready state
+       if (this.length === 0 && options != 'stop') {
+               if (!$.isReady && o.s) {
+                       log('DOM not ready, queuing slideshow');
+                       $(function() {
+                               $(o.s,o.c).cycle(options,arg2);
+                       });
+                       return this;
+               }
+               // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
+               log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
+               return this;
+       }
+
+       // iterate the matched nodeset
+       return this.each(function() {
+               var opts = handleArguments(this, options, arg2);
+               if (opts === false)
+                       return;
+
+               opts.updateActivePagerLink = opts.updateActivePagerLink || $.fn.cycle.updateActivePagerLink;
+               
+               // stop existing slideshow for this container (if there is one)
+               if (this.cycleTimeout)
+                       clearTimeout(this.cycleTimeout);
+               this.cycleTimeout = this.cyclePause = 0;
+
+               var $cont = $(this);
+               var $slides = opts.slideExpr ? $(opts.slideExpr, this) : $cont.children();
+               var els = $slides.get();
+
+               var opts2 = buildOptions($cont, $slides, els, opts, o);
+               if (opts2 === false)
+                       return;
+
+               if (els.length < 2) {
+                       log('terminating; too few slides: ' + els.length);
+                       return;
+               }
+
+               var startTime = opts2.continuous ? 10 : getTimeout(els[opts2.currSlide], els[opts2.nextSlide], opts2, !opts2.backwards);
+
+               // if it's an auto slideshow, kick it off
+               if (startTime) {
+                       startTime += (opts2.delay || 0);
+                       if (startTime < 10)
+                               startTime = 10;
+                       debug('first timeout: ' + startTime);
+                       this.cycleTimeout = setTimeout(function(){go(els,opts2,0,!opts.backwards)}, startTime);
+               }
+       });
+};
+
+function triggerPause(cont, byHover, onPager) {
+       var opts = $(cont).data('cycle.opts');
+       var paused = !!cont.cyclePause;
+       if (paused && opts.paused)
+               opts.paused(cont, opts, byHover, onPager);
+       else if (!paused && opts.resumed)
+               opts.resumed(cont, opts, byHover, onPager);
+}
+
+// process the args that were passed to the plugin fn
+function handleArguments(cont, options, arg2) {
+       if (cont.cycleStop == undefined)
+               cont.cycleStop = 0;
+       if (options === undefined || options === null)
+               options = {};
+       if (options.constructor == String) {
+               switch(options) {
+               case 'destroy':
+               case 'stop':
+                       var opts = $(cont).data('cycle.opts');
+                       if (!opts)
+                               return false;
+                       cont.cycleStop++; // callbacks look for change
+                       if (cont.cycleTimeout)
+                               clearTimeout(cont.cycleTimeout);
+                       cont.cycleTimeout = 0;
+                       opts.elements && $(opts.elements).stop();
+                       $(cont).removeData('cycle.opts');
+                       if (options == 'destroy')
+                               destroy(opts);
+                       return false;
+               case 'toggle':
+                       cont.cyclePause = (cont.cyclePause === 1) ? 0 : 1;
+                       checkInstantResume(cont.cyclePause, arg2, cont);
+                       triggerPause(cont);
+                       return false;
+               case 'pause':
+                       cont.cyclePause = 1;
+                       triggerPause(cont);
+                       return false;
+               case 'resume':
+                       cont.cyclePause = 0;
+                       checkInstantResume(false, arg2, cont);
+                       triggerPause(cont);
+                       return false;
+               case 'prev':
+               case 'next':
+                       var opts = $(cont).data('cycle.opts');
+                       if (!opts) {
+                               log('options not found, "prev/next" ignored');
+                               return false;
+                       }
+                       $.fn.cycle[options](opts);
+                       return false;
+               default:
+                       options = { fx: options };
+               };
+               return options;
+       }
+       else if (options.constructor == Number) {
+               // go to the requested slide
+               var num = options;
+               options = $(cont).data('cycle.opts');
+               if (!options) {
+                       log('options not found, can not advance slide');
+                       return false;
+               }
+               if (num < 0 || num >= options.elements.length) {
+                       log('invalid slide index: ' + num);
+                       return false;
+               }
+               options.nextSlide = num;
+               if (cont.cycleTimeout) {
+                       clearTimeout(cont.cycleTimeout);
+                       cont.cycleTimeout = 0;
+               }
+               if (typeof arg2 == 'string')
+                       options.oneTimeFx = arg2;
+               go(options.elements, options, 1, num >= options.currSlide);
+               return false;
+       }
+       return options;
+       
+       function checkInstantResume(isPaused, arg2, cont) {
+               if (!isPaused && arg2 === true) { // resume now!
+                       var options = $(cont).data('cycle.opts');
+                       if (!options) {
+                               log('options not found, can not resume');
+                               return false;
+                       }
+                       if (cont.cycleTimeout) {
+                               clearTimeout(cont.cycleTimeout);
+                               cont.cycleTimeout = 0;
+                       }
+                       go(options.elements, options, 1, !options.backwards);
+               }
+       }
+};
+
+function removeFilter(el, opts) {
+       if (!$.support.opacity && opts.cleartype && el.style.filter) {
+               try { el.style.removeAttribute('filter'); }
+               catch(smother) {} // handle old opera versions
+       }
+};
+
+// unbind event handlers
+function destroy(opts) {
+       if (opts.next)
+               $(opts.next).unbind(opts.prevNextEvent);
+       if (opts.prev)
+               $(opts.prev).unbind(opts.prevNextEvent);
+       
+       if (opts.pager || opts.pagerAnchorBuilder)
+               $.each(opts.pagerAnchors || [], function() {
+                       this.unbind().remove();
+               });
+       opts.pagerAnchors = null;
+       if (opts.destroy) // callback
+               opts.destroy(opts);
+};
+
+// one-time initialization
+function buildOptions($cont, $slides, els, options, o) {
+       var startingSlideSpecified;
+       // support metadata plugin (v1.0 and v2.0)
+       var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});
+       var meta = $.isFunction($cont.data) ? $cont.data(opts.metaAttr) : null;
+       if (meta)
+               opts = $.extend(opts, meta);
+       if (opts.autostop)
+               opts.countdown = opts.autostopCount || els.length;
+
+       var cont = $cont[0];
+       $cont.data('cycle.opts', opts);
+       opts.$cont = $cont;
+       opts.stopCount = cont.cycleStop;
+       opts.elements = els;
+       opts.before = opts.before ? [opts.before] : [];
+       opts.after = opts.after ? [opts.after] : [];
+
+       // push some after callbacks
+       if (!$.support.opacity && opts.cleartype)
+               opts.after.push(function() { removeFilter(this, opts); });
+       if (opts.continuous)
+               opts.after.push(function() { go(els,opts,0,!opts.backwards); });
+
+       saveOriginalOpts(opts);
+
+       // clearType corrections
+       if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
+               clearTypeFix($slides);
+
+       // container requires non-static position so that slides can be position within
+       if ($cont.css('position') == 'static')
+               $cont.css('position', 'relative');
+       if (opts.width)
+               $cont.width(opts.width);
+       if (opts.height && opts.height != 'auto')
+               $cont.height(opts.height);
+
+       if (opts.startingSlide != undefined) {
+               opts.startingSlide = parseInt(opts.startingSlide,10);
+               if (opts.startingSlide >= els.length || opts.startSlide < 0)
+                       opts.startingSlide = 0; // catch bogus input
+               else 
+                       startingSlideSpecified = true;
+       }
+       else if (opts.backwards)
+               opts.startingSlide = els.length - 1;
+       else
+               opts.startingSlide = 0;
+
+       // if random, mix up the slide array
+       if (opts.random) {
+               opts.randomMap = [];
+               for (var i = 0; i < els.length; i++)
+                       opts.randomMap.push(i);
+               opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+               if (startingSlideSpecified) {
+                       // try to find the specified starting slide and if found set start slide index in the map accordingly
+                       for ( var cnt = 0; cnt < els.length; cnt++ ) {
+                               if ( opts.startingSlide == opts.randomMap[cnt] ) {
+                                       opts.randomIndex = cnt;
+                               }
+                       }
+               }
+               else {
+                       opts.randomIndex = 1;
+                       opts.startingSlide = opts.randomMap[1];
+               }
+       }
+       else if (opts.startingSlide >= els.length)
+               opts.startingSlide = 0; // catch bogus input
+       opts.currSlide = opts.startingSlide || 0;
+       var first = opts.startingSlide;
+
+       // set position and zIndex on all the slides
+       $slides.css({position: 'absolute', top:0, left:0}).hide().each(function(i) {
+               var z;
+               if (opts.backwards)
+                       z = first ? i <= first ? els.length + (i-first) : first-i : els.length-i;
+               else
+                       z = first ? i >= first ? els.length - (i-first) : first-i : els.length-i;
+               $(this).css('z-index', z)
+       });
+
+       // make sure first slide is visible
+       $(els[first]).css('opacity',1).show(); // opacity bit needed to handle restart use case
+       removeFilter(els[first], opts);
+
+       // stretch slides
+       if (opts.fit) {
+               if (!opts.aspect) {
+               if (opts.width)
+                   $slides.width(opts.width);
+               if (opts.height && opts.height != 'auto')
+                   $slides.height(opts.height);
+               } else {
+                       $slides.each(function(){
+                               var $slide = $(this);
+                               var ratio = (opts.aspect === true) ? $slide.width()/$slide.height() : opts.aspect;
+                               if( opts.width && $slide.width() != opts.width ) {
+                                       $slide.width( opts.width );
+                                       $slide.height( opts.width / ratio );
+                               }
+
+                               if( opts.height && $slide.height() < opts.height ) {
+                                       $slide.height( opts.height );
+                                       $slide.width( opts.height * ratio );
+                               }
+                       });
+               }
+       }
+
+       if (opts.center && ((!opts.fit) || opts.aspect)) {
+               $slides.each(function(){
+                       var $slide = $(this);
+                       $slide.css({
+                               "margin-left": opts.width ?
+                                       ((opts.width - $slide.width()) / 2) + "px" :
+                                       0,
+                               "margin-top": opts.height ?
+                                       ((opts.height - $slide.height()) / 2) + "px" :
+                                       0
+                       });
+               });
+       }
+
+       if (opts.center && !opts.fit && !opts.slideResize) {
+               $slides.each(function(){
+               var $slide = $(this);
+               $slide.css({
+                       "margin-left": opts.width ? ((opts.width - $slide.width()) / 2) + "px" : 0,
+                       "margin-top": opts.height ? ((opts.height - $slide.height()) / 2) + "px" : 0
+               });
+               });
+       }
+               
+       // stretch container
+       var reshape = opts.containerResize && !$cont.innerHeight();
+       if (reshape) { // do this only if container has no size http://tinyurl.com/da2oa9
+               var maxw = 0, maxh = 0;
+               for(var j=0; j < els.length; j++) {
+                       var $e = $(els[j]), e = $e[0], w = $e.outerWidth(), h = $e.outerHeight();
+                       if (!w) w = e.offsetWidth || e.width || $e.attr('width');
+                       if (!h) h = e.offsetHeight || e.height || $e.attr('height');
+                       maxw = w > maxw ? w : maxw;
+                       maxh = h > maxh ? h : maxh;
+               }
+               if (maxw > 0 && maxh > 0)
+                       $cont.css({width:maxw+'px',height:maxh+'px'});
+       }
+
+       var pauseFlag = false;  // https://github.com/malsup/cycle/issues/44
+       if (opts.pause)
+               $cont.hover(
+                       function(){
+                               pauseFlag = true;
+                               this.cyclePause++;
+                               triggerPause(cont, true);
+                       },
+                       function(){
+                               pauseFlag && this.cyclePause--;
+                               triggerPause(cont, true);
+                       }
+               );
+
+       if (supportMultiTransitions(opts) === false)
+               return false;
+
+       // apparently a lot of people use image slideshows without height/width attributes on the images.
+       // Cycle 2.50+ requires the sizing info for every slide; this block tries to deal with that.
+       var requeue = false;
+       options.requeueAttempts = options.requeueAttempts || 0;
+       $slides.each(function() {
+               // try to get height/width of each slide
+               var $el = $(this);
+               this.cycleH = (opts.fit && opts.height) ? opts.height : ($el.height() || this.offsetHeight || this.height || $el.attr('height') || 0);
+               this.cycleW = (opts.fit && opts.width) ? opts.width : ($el.width() || this.offsetWidth || this.width || $el.attr('width') || 0);
+
+               if ( $el.is('img') ) {
+                       // sigh..  sniffing, hacking, shrugging...  this crappy hack tries to account for what browsers do when
+                       // an image is being downloaded and the markup did not include sizing info (height/width attributes);
+                       // there seems to be some "default" sizes used in this situation
+                       var loadingIE   = ($.browser.msie  && this.cycleW == 28 && this.cycleH == 30 && !this.complete);
+                       var loadingFF   = ($.browser.mozilla && this.cycleW == 34 && this.cycleH == 19 && !this.complete);
+                       var loadingOp   = ($.browser.opera && ((this.cycleW == 42 && this.cycleH == 19) || (this.cycleW == 37 && this.cycleH == 17)) && !this.complete);
+                       var loadingOther = (this.cycleH == 0 && this.cycleW == 0 && !this.complete);
+                       // don't requeue for images that are still loading but have a valid size
+                       if (loadingIE || loadingFF || loadingOp || loadingOther) {
+                               if (o.s && opts.requeueOnImageNotLoaded && ++options.requeueAttempts < 100) { // track retry count so we don't loop forever
+                                       log(options.requeueAttempts,' - img slide not loaded, requeuing slideshow: ', this.src, this.cycleW, this.cycleH);
+                                       setTimeout(function() {$(o.s,o.c).cycle(options)}, opts.requeueTimeout);
+                                       requeue = true;
+                                       return false; // break each loop
+                               }
+                               else {
+                                       log('could not determine size of image: '+this.src, this.cycleW, this.cycleH);
+                               }
+                       }
+               }
+               return true;
+       });
+
+       if (requeue)
+               return false;
+
+       opts.cssBefore = opts.cssBefore || {};
+       opts.cssAfter = opts.cssAfter || {};
+       opts.cssFirst = opts.cssFirst || {};
+       opts.animIn = opts.animIn || {};
+       opts.animOut = opts.animOut || {};
+
+       $slides.not(':eq('+first+')').css(opts.cssBefore);
+       $($slides[first]).css(opts.cssFirst);
+
+       if (opts.timeout) {
+               opts.timeout = parseInt(opts.timeout,10);
+               // ensure that timeout and speed settings are sane
+               if (opts.speed.constructor == String)
+                       opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed,10);
+               if (!opts.sync)
+                       opts.speed = opts.speed / 2;
+               
+               var buffer = opts.fx == 'none' ? 0 : opts.fx == 'shuffle' ? 500 : 250;
+               while((opts.timeout - opts.speed) < buffer) // sanitize timeout
+                       opts.timeout += opts.speed;
+       }
+       if (opts.easing)
+               opts.easeIn = opts.easeOut = opts.easing;
+       if (!opts.speedIn)
+               opts.speedIn = opts.speed;
+       if (!opts.speedOut)
+               opts.speedOut = opts.speed;
+
+       opts.slideCount = els.length;
+       opts.currSlide = opts.lastSlide = first;
+       if (opts.random) {
+               if (++opts.randomIndex == els.length)
+                       opts.randomIndex = 0;
+               opts.nextSlide = opts.randomMap[opts.randomIndex];
+       }
+       else if (opts.backwards)
+               opts.nextSlide = opts.startingSlide == 0 ? (els.length-1) : opts.startingSlide-1;
+       else
+               opts.nextSlide = opts.startingSlide >= (els.length-1) ? 0 : opts.startingSlide+1;
+
+       // run transition init fn
+       if (!opts.multiFx) {
+               var init = $.fn.cycle.transitions[opts.fx];
+               if ($.isFunction(init))
+                       init($cont, $slides, opts);
+               else if (opts.fx != 'custom' && !opts.multiFx) {
+                       log('unknown transition: ' + opts.fx,'; slideshow terminating');
+                       return false;
+               }
+       }
+
+       // fire artificial events
+       var e0 = $slides[first];
+       if (!opts.skipInitializationCallbacks) {
+               if (opts.before.length)
+                       opts.before[0].apply(e0, [e0, e0, opts, true]);
+               if (opts.after.length)
+                       opts.after[0].apply(e0, [e0, e0, opts, true]);
+       }
+       if (opts.next)
+               $(opts.next).bind(opts.prevNextEvent,function(){return advance(opts,1)});
+       if (opts.prev)
+               $(opts.prev).bind(opts.prevNextEvent,function(){return advance(opts,0)});
+       if (opts.pager || opts.pagerAnchorBuilder)
+               buildPager(els,opts);
+
+       exposeAddSlide(opts, els);
+
+       return opts;
+};
+
+// save off original opts so we can restore after clearing state
+function saveOriginalOpts(opts) {
+       opts.original = { before: [], after: [] };
+       opts.original.cssBefore = $.extend({}, opts.cssBefore);
+       opts.original.cssAfter  = $.extend({}, opts.cssAfter);
+       opts.original.animIn    = $.extend({}, opts.animIn);
+       opts.original.animOut   = $.extend({}, opts.animOut);
+       $.each(opts.before, function() { opts.original.before.push(this); });
+       $.each(opts.after,  function() { opts.original.after.push(this); });
+};
+
+function supportMultiTransitions(opts) {
+       var i, tx, txs = $.fn.cycle.transitions;
+       // look for multiple effects
+       if (opts.fx.indexOf(',') > 0) {
+               opts.multiFx = true;
+               opts.fxs = opts.fx.replace(/\s*/g,'').split(',');
+               // discard any bogus effect names
+               for (i=0; i < opts.fxs.length; i++) {
+                       var fx = opts.fxs[i];
+                       tx = txs[fx];
+                       if (!tx || !txs.hasOwnProperty(fx) || !$.isFunction(tx)) {
+                               log('discarding unknown transition: ',fx);
+                               opts.fxs.splice(i,1);
+                               i--;
+                       }
+               }
+               // if we have an empty list then we threw everything away!
+               if (!opts.fxs.length) {
+                       log('No valid transitions named; slideshow terminating.');
+                       return false;
+               }
+       }
+       else if (opts.fx == 'all') {  // auto-gen the list of transitions
+               opts.multiFx = true;
+               opts.fxs = [];
+               for (p in txs) {
+                       tx = txs[p];
+                       if (txs.hasOwnProperty(p) && $.isFunction(tx))
+                               opts.fxs.push(p);
+               }
+       }
+       if (opts.multiFx && opts.randomizeEffects) {
+               // munge the fxs array to make effect selection random
+               var r1 = Math.floor(Math.random() * 20) + 30;
+               for (i = 0; i < r1; i++) {
+                       var r2 = Math.floor(Math.random() * opts.fxs.length);
+                       opts.fxs.push(opts.fxs.splice(r2,1)[0]);
+               }
+               debug('randomized fx sequence: ',opts.fxs);
+       }
+       return true;
+};
+
+// provide a mechanism for adding slides after the slideshow has started
+function exposeAddSlide(opts, els) {
+       opts.addSlide = function(newSlide, prepend) {
+               var $s = $(newSlide), s = $s[0];
+               if (!opts.autostopCount)
+                       opts.countdown++;
+               els[prepend?'unshift':'push'](s);
+               if (opts.els)
+                       opts.els[prepend?'unshift':'push'](s); // shuffle needs this
+               opts.slideCount = els.length;
+
+               // add the slide to the random map and resort
+               if (opts.random) {
+                       opts.randomMap.push(opts.slideCount-1);
+                       opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+               }
+
+               $s.css('position','absolute');
+               $s[prepend?'prependTo':'appendTo'](opts.$cont);
+
+               if (prepend) {
+                       opts.currSlide++;
+                       opts.nextSlide++;
+               }
+
+               if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
+                       clearTypeFix($s);
+
+               if (opts.fit && opts.width)
+                       $s.width(opts.width);
+               if (opts.fit && opts.height && opts.height != 'auto')
+                       $s.height(opts.height);
+               s.cycleH = (opts.fit && opts.height) ? opts.height : $s.height();
+               s.cycleW = (opts.fit && opts.width) ? opts.width : $s.width();
+
+               $s.css(opts.cssBefore);
+
+               if (opts.pager || opts.pagerAnchorBuilder)
+                       $.fn.cycle.createPagerAnchor(els.length-1, s, $(opts.pager), els, opts);
+
+               if ($.isFunction(opts.onAddSlide))
+                       opts.onAddSlide($s);
+               else
+                       $s.hide(); // default behavior
+       };
+}
+
+// reset internal state; we do this on every pass in order to support multiple effects
+$.fn.cycle.resetState = function(opts, fx) {
+       fx = fx || opts.fx;
+       opts.before = []; opts.after = [];
+       opts.cssBefore = $.extend({}, opts.original.cssBefore);
+       opts.cssAfter  = $.extend({}, opts.original.cssAfter);
+       opts.animIn     = $.extend({}, opts.original.animIn);
+       opts.animOut   = $.extend({}, opts.original.animOut);
+       opts.fxFn = null;
+       $.each(opts.original.before, function() { opts.before.push(this); });
+       $.each(opts.original.after,  function() { opts.after.push(this); });
+
+       // re-init
+       var init = $.fn.cycle.transitions[fx];
+       if ($.isFunction(init))
+               init(opts.$cont, $(opts.elements), opts);
+};
+
+// this is the main engine fn, it handles the timeouts, callbacks and slide index mgmt
+function go(els, opts, manual, fwd) {
+       // opts.busy is true if we're in the middle of an animation
+       if (manual && opts.busy && opts.manualTrump) {
+               // let manual transitions requests trump active ones
+               debug('manualTrump in go(), stopping active transition');
+               $(els).stop(true,true);
+               opts.busy = 0;
+       }
+       // don't begin another timeout-based transition if there is one active
+       if (opts.busy) {
+               debug('transition active, ignoring new tx request');
+               return;
+       }
+
+       var p = opts.$cont[0], curr = els[opts.currSlide], next = els[opts.nextSlide];
+
+       // stop cycling if we have an outstanding stop request
+       if (p.cycleStop != opts.stopCount || p.cycleTimeout === 0 && !manual)
+               return;
+
+       // check to see if we should stop cycling based on autostop options
+       if (!manual && !p.cyclePause && !opts.bounce &&
+               ((opts.autostop && (--opts.countdown <= 0)) ||
+               (opts.nowrap && !opts.random && opts.nextSlide < opts.currSlide))) {
+               if (opts.end)
+                       opts.end(opts);
+               return;
+       }
+
+       // if slideshow is paused, only transition on a manual trigger
+       var changed = false;
+       if ((manual || !p.cyclePause) && (opts.nextSlide != opts.currSlide)) {
+               changed = true;
+               var fx = opts.fx;
+               // keep trying to get the slide size if we don't have it yet
+               curr.cycleH = curr.cycleH || $(curr).height();
+               curr.cycleW = curr.cycleW || $(curr).width();
+               next.cycleH = next.cycleH || $(next).height();
+               next.cycleW = next.cycleW || $(next).width();
+
+               // support multiple transition types
+               if (opts.multiFx) {
+                       if (fwd && (opts.lastFx == undefined || ++opts.lastFx >= opts.fxs.length))
+                               opts.lastFx = 0;
+                       else if (!fwd && (opts.lastFx == undefined || --opts.lastFx < 0))
+                               opts.lastFx = opts.fxs.length - 1;
+                       fx = opts.fxs[opts.lastFx];
+               }
+
+               // one-time fx overrides apply to:  $('div').cycle(3,'zoom');
+               if (opts.oneTimeFx) {
+                       fx = opts.oneTimeFx;
+                       opts.oneTimeFx = null;
+               }
+
+               $.fn.cycle.resetState(opts, fx);
+
+               // run the before callbacks
+               if (opts.before.length)
+                       $.each(opts.before, function(i,o) {
+                               if (p.cycleStop != opts.stopCount) return;
+                               o.apply(next, [curr, next, opts, fwd]);
+                       });
+
+               // stage the after callacks
+               var after = function() {
+                       opts.busy = 0;
+                       $.each(opts.after, function(i,o) {
+                               if (p.cycleStop != opts.stopCount) return;
+                               o.apply(next, [curr, next, opts, fwd]);
+                       });
+                       if (!p.cycleStop) {
+                               // queue next transition
+                               queueNext();
+                       }
+               };
+
+               debug('tx firing('+fx+'); currSlide: ' + opts.currSlide + '; nextSlide: ' + opts.nextSlide);
+               
+               // get ready to perform the transition
+               opts.busy = 1;
+               if (opts.fxFn) // fx function provided?
+                       opts.fxFn(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+               else if ($.isFunction($.fn.cycle[opts.fx])) // fx plugin ?
+                       $.fn.cycle[opts.fx](curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+               else
+                       $.fn.cycle.custom(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+       }
+       else {
+               queueNext();
+       }
+
+       if (changed || opts.nextSlide == opts.currSlide) {
+               // calculate the next slide
+               opts.lastSlide = opts.currSlide;
+               if (opts.random) {
+                       opts.currSlide = opts.nextSlide;
+                       if (++opts.randomIndex == els.length) {
+                               opts.randomIndex = 0;
+                               opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+                       }
+                       opts.nextSlide = opts.randomMap[opts.randomIndex];
+                       if (opts.nextSlide == opts.currSlide)
+                               opts.nextSlide = (opts.currSlide == opts.slideCount - 1) ? 0 : opts.currSlide + 1;
+               }
+               else if (opts.backwards) {
+                       var roll = (opts.nextSlide - 1) < 0;
+                       if (roll && opts.bounce) {
+                               opts.backwards = !opts.backwards;
+                               opts.nextSlide = 1;
+                               opts.currSlide = 0;
+                       }
+                       else {
+                               opts.nextSlide = roll ? (els.length-1) : opts.nextSlide-1;
+                               opts.currSlide = roll ? 0 : opts.nextSlide+1;
+                       }
+               }
+               else { // sequence
+                       var roll = (opts.nextSlide + 1) == els.length;
+                       if (roll && opts.bounce) {
+                               opts.backwards = !opts.backwards;
+                               opts.nextSlide = els.length-2;
+                               opts.currSlide = els.length-1;
+                       }
+                       else {
+                               opts.nextSlide = roll ? 0 : opts.nextSlide+1;
+                               opts.currSlide = roll ? els.length-1 : opts.nextSlide-1;
+                       }
+               }
+       }
+       if (changed && opts.pager)
+               opts.updateActivePagerLink(opts.pager, opts.currSlide, opts.activePagerClass);
+       
+       function queueNext() {
+               // stage the next transition
+               var ms = 0, timeout = opts.timeout;
+               if (opts.timeout && !opts.continuous) {
+                       ms = getTimeout(els[opts.currSlide], els[opts.nextSlide], opts, fwd);
+         if (opts.fx == 'shuffle')
+            ms -= opts.speedOut;
+      }
+               else if (opts.continuous && p.cyclePause) // continuous shows work off an after callback, not this timer logic
+                       ms = 10;
+               if (ms > 0)
+                       p.cycleTimeout = setTimeout(function(){ go(els, opts, 0, !opts.backwards) }, ms);
+       }
+};
+
+// invoked after transition
+$.fn.cycle.updateActivePagerLink = function(pager, currSlide, clsName) {
+   $(pager).each(function() {
+       $(this).children().removeClass(clsName).eq(currSlide).addClass(clsName);
+   });
+};
+
+// calculate timeout value for current transition
+function getTimeout(curr, next, opts, fwd) {
+       if (opts.timeoutFn) {
+               // call user provided calc fn
+               var t = opts.timeoutFn.call(curr,curr,next,opts,fwd);
+               while (opts.fx != 'none' && (t - opts.speed) < 250) // sanitize timeout
+                       t += opts.speed;
+               debug('calculated timeout: ' + t + '; speed: ' + opts.speed);
+               if (t !== false)
+                       return t;
+       }
+       return opts.timeout;
+};
+
+// expose next/prev function, caller must pass in state
+$.fn.cycle.next = function(opts) { advance(opts,1); };
+$.fn.cycle.prev = function(opts) { advance(opts,0);};
+
+// advance slide forward or back
+function advance(opts, moveForward) {
+       var val = moveForward ? 1 : -1;
+       var els = opts.elements;
+       var p = opts.$cont[0], timeout = p.cycleTimeout;
+       if (timeout) {
+               clearTimeout(timeout);
+               p.cycleTimeout = 0;
+       }
+       if (opts.random && val < 0) {
+               // move back to the previously display slide
+               opts.randomIndex--;
+               if (--opts.randomIndex == -2)
+                       opts.randomIndex = els.length-2;
+               else if (opts.randomIndex == -1)
+                       opts.randomIndex = els.length-1;
+               opts.nextSlide = opts.randomMap[opts.randomIndex];
+       }
+       else if (opts.random) {
+               opts.nextSlide = opts.randomMap[opts.randomIndex];
+       }
+       else {
+               opts.nextSlide = opts.currSlide + val;
+               if (opts.nextSlide < 0) {
+                       if (opts.nowrap) return false;
+                       opts.nextSlide = els.length - 1;
+               }
+               else if (opts.nextSlide >= els.length) {
+                       if (opts.nowrap) return false;
+                       opts.nextSlide = 0;
+               }
+       }
+
+       var cb = opts.onPrevNextEvent || opts.prevNextClick; // prevNextClick is deprecated
+       if ($.isFunction(cb))
+               cb(val > 0, opts.nextSlide, els[opts.nextSlide]);
+       go(els, opts, 1, moveForward);
+       return false;
+};
+
+function buildPager(els, opts) {
+       var $p = $(opts.pager);
+       $.each(els, function(i,o) {
+               $.fn.cycle.createPagerAnchor(i,o,$p,els,opts);
+       });
+       opts.updateActivePagerLink(opts.pager, opts.startingSlide, opts.activePagerClass);
+};
+
+$.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
+       var a;
+       if ($.isFunction(opts.pagerAnchorBuilder)) {
+               a = opts.pagerAnchorBuilder(i,el);
+               debug('pagerAnchorBuilder('+i+', el) returned: ' + a);
+       }
+       else
+               a = '<a href="#">'+(i+1)+'</a>';
+               
+       if (!a)
+               return;
+       var $a = $(a);
+       // don't reparent if anchor is in the dom
+       if ($a.parents('body').length === 0) {
+               var arr = [];
+               if ($p.length > 1) {
+                       $p.each(function() {
+                               var $clone = $a.clone(true);
+                               $(this).append($clone);
+                               arr.push($clone[0]);
+                       });
+                       $a = $(arr);
+               }
+               else {
+                       $a.appendTo($p);
+               }
+       }
+
+       opts.pagerAnchors =  opts.pagerAnchors || [];
+       opts.pagerAnchors.push($a);
+       
+       var pagerFn = function(e) {
+               e.preventDefault();
+               opts.nextSlide = i;
+               var p = opts.$cont[0], timeout = p.cycleTimeout;
+               if (timeout) {
+                       clearTimeout(timeout);
+                       p.cycleTimeout = 0;
+               }
+               var cb = opts.onPagerEvent || opts.pagerClick; // pagerClick is deprecated
+               if ($.isFunction(cb))
+                       cb(opts.nextSlide, els[opts.nextSlide]);
+               go(els,opts,1,opts.currSlide < i); // trigger the trans
+//             return false; // <== allow bubble
+       }
+       
+       if ( /mouseenter|mouseover/i.test(opts.pagerEvent) ) {
+               $a.hover(pagerFn, function(){/* no-op */} );
+       }
+       else {
+               $a.bind(opts.pagerEvent, pagerFn);
+       }
+       
+       if ( ! /^click/.test(opts.pagerEvent) && !opts.allowPagerClickBubble)
+               $a.bind('click.cycle', function(){return false;}); // suppress click
+       
+       var cont = opts.$cont[0];
+       var pauseFlag = false; // https://github.com/malsup/cycle/issues/44
+       if (opts.pauseOnPagerHover) {
+               $a.hover(
+                       function() { 
+                               pauseFlag = true;
+                               cont.cyclePause++; 
+                               triggerPause(cont,true,true);
+                       }, function() { 
+                               pauseFlag && cont.cyclePause--; 
+                               triggerPause(cont,true,true);
+                       } 
+               );
+       }
+};
+
+// helper fn to calculate the number of slides between the current and the next
+$.fn.cycle.hopsFromLast = function(opts, fwd) {
+       var hops, l = opts.lastSlide, c = opts.currSlide;
+       if (fwd)
+               hops = c > l ? c - l : opts.slideCount - l;
+       else
+               hops = c < l ? l - c : l + opts.slideCount - c;
+       return hops;
+};
+
+// fix clearType problems in ie6 by setting an explicit bg color
+// (otherwise text slides look horrible during a fade transition)
+function clearTypeFix($slides) {
+       debug('applying clearType background-color hack');
+       function hex(s) {
+               s = parseInt(s,10).toString(16);
+               return s.length < 2 ? '0'+s : s;
+       };
+       function getBg(e) {
+               for ( ; e && e.nodeName.toLowerCase() != 'html'; e = e.parentNode) {
+                       var v = $.css(e,'background-color');
+                       if (v && v.indexOf('rgb') >= 0 ) {
+                               var rgb = v.match(/\d+/g);
+                               return '#'+ hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
+                       }
+                       if (v && v != 'transparent')
+                               return v;
+               }
+               return '#ffffff';
+       };
+       $slides.each(function() { $(this).css('background-color', getBg(this)); });
+};
+
+// reset common props before the next transition
+$.fn.cycle.commonReset = function(curr,next,opts,w,h,rev) {
+       $(opts.elements).not(curr).hide();
+       if (typeof opts.cssBefore.opacity == 'undefined')
+               opts.cssBefore.opacity = 1;
+       opts.cssBefore.display = 'block';
+       if (opts.slideResize && w !== false && next.cycleW > 0)
+               opts.cssBefore.width = next.cycleW;
+       if (opts.slideResize && h !== false && next.cycleH > 0)
+               opts.cssBefore.height = next.cycleH;
+       opts.cssAfter = opts.cssAfter || {};
+       opts.cssAfter.display = 'none';
+       $(curr).css('zIndex',opts.slideCount + (rev === true ? 1 : 0));
+       $(next).css('zIndex',opts.slideCount + (rev === true ? 0 : 1));
+};
+
+// the actual fn for effecting a transition
+$.fn.cycle.custom = function(curr, next, opts, cb, fwd, speedOverride) {
+       var $l = $(curr), $n = $(next);
+       var speedIn = opts.speedIn, speedOut = opts.speedOut, easeIn = opts.easeIn, easeOut = opts.easeOut;
+       $n.css(opts.cssBefore);
+       if (speedOverride) {
+               if (typeof speedOverride == 'number')
+                       speedIn = speedOut = speedOverride;
+               else
+                       speedIn = speedOut = 1;
+               easeIn = easeOut = null;
+       }
+       var fn = function() {
+               $n.animate(opts.animIn, speedIn, easeIn, function() {
+                       cb();
+               });
+       };
+       $l.animate(opts.animOut, speedOut, easeOut, function() {
+               $l.css(opts.cssAfter);
+               if (!opts.sync) 
+                       fn();
+       });
+       if (opts.sync) fn();
+};
+
+// transition definitions - only fade is defined here, transition pack defines the rest
+$.fn.cycle.transitions = {
+       fade: function($cont, $slides, opts) {
+               $slides.not(':eq('+opts.currSlide+')').css('opacity',0);
+               opts.before.push(function(curr,next,opts) {
+                       $.fn.cycle.commonReset(curr,next,opts);
+                       opts.cssBefore.opacity = 0;
+               });
+               opts.animIn        = { opacity: 1 };
+               opts.animOut   = { opacity: 0 };
+               opts.cssBefore = { top: 0, left: 0 };
+       }
+};
+
+$.fn.cycle.ver = function() { return ver; };
+
+// override these globally if you like (they are all optional)
+$.fn.cycle.defaults = {
+       activePagerClass: 'activeSlide', // class name used for the active pager link
+       after:             null,  // transition callback (scope set to element that was shown):  function(currSlideElement, nextSlideElement, options, forwardFlag)
+       allowPagerClickBubble: false, // allows or prevents click event on pager anchors from bubbling
+       animIn:            null,  // properties that define how the slide animates in
+       animOut:           null,  // properties that define how the slide animates out
+       aspect:            false,  // preserve aspect ratio during fit resizing, cropping if necessary (must be used with fit option)
+       autostop:          0,     // true to end slideshow after X transitions (where X == slide count)
+       autostopCount: 0,         // number of transitions (optionally used with autostop to define X)
+       backwards:     false, // true to start slideshow at last slide and move backwards through the stack
+       before:            null,  // transition callback (scope set to element to be shown):     function(currSlideElement, nextSlideElement, options, forwardFlag)
+       center:            null,  // set to true to have cycle add top/left margin to each slide (use with width and height options)
+       cleartype:         !$.support.opacity,  // true if clearType corrections should be applied (for IE)
+       cleartypeNoBg: false, // set to true to disable extra cleartype fixing (leave false to force background color setting on slides)
+       containerResize: 1,       // resize container to fit largest slide
+       continuous:        0,     // true to start next transition immediately after current one completes
+       cssAfter:          null,  // properties that defined the state of the slide after transitioning out
+       cssBefore:         null,  // properties that define the initial state of the slide before transitioning in
+       delay:             0,     // additional delay (in ms) for first transition (hint: can be negative)
+       easeIn:            null,  // easing for "in" transition
+       easeOut:           null,  // easing for "out" transition
+       easing:            null,  // easing method for both in and out transitions
+       end:               null,  // callback invoked when the slideshow terminates (use with autostop or nowrap options): function(options)
+       fastOnEvent:   0,         // force fast transitions when triggered manually (via pager or prev/next); value == time in ms
+       fit:               0,     // force slides to fit container
+       fx:                       'fade', // name of transition effect (or comma separated names, ex: 'fade,scrollUp,shuffle')
+       fxFn:              null,  // function used to control the transition: function(currSlideElement, nextSlideElement, options, afterCalback, forwardFlag)
+       height:           'auto', // container height (if the 'fit' option is true, the slides will be set to this height as well)
+       manualTrump:   true,  // causes manual transition to stop an active transition instead of being ignored
+       metaAttr:     'cycle',// data- attribute that holds the option data for the slideshow
+       next:              null,  // element, jQuery object, or jQuery selector string for the element to use as event trigger for next slide
+       nowrap:            0,     // true to prevent slideshow from wrapping
+       onPagerEvent:  null,  // callback fn for pager events: function(zeroBasedSlideIndex, slideElement)
+       onPrevNextEvent: null,// callback fn for prev/next events: function(isNext, zeroBasedSlideIndex, slideElement)
+       pager:             null,  // element, jQuery object, or jQuery selector string for the element to use as pager container
+       pagerAnchorBuilder: null, // callback fn for building anchor links:  function(index, DOMelement)
+       pagerEvent:       'click.cycle', // name of event which drives the pager navigation
+       pause:             0,     // true to enable "pause on hover"
+       pauseOnPagerHover: 0, // true to pause when hovering over pager link
+       prev:              null,  // element, jQuery object, or jQuery selector string for the element to use as event trigger for previous slide
+       prevNextEvent:'click.cycle',// event which drives the manual transition to the previous or next slide
+       random:            0,     // true for random, false for sequence (not applicable to shuffle fx)
+       randomizeEffects: 1,  // valid when multiple effects are used; true to make the effect sequence random
+       requeueOnImageNotLoaded: true, // requeue the slideshow if any image slides are not yet loaded
+       requeueTimeout: 250,  // ms delay for requeue
+       rev:               0,     // causes animations to transition in reverse (for effects that support it such as scrollHorz/scrollVert/shuffle)
+       shuffle:           null,  // coords for shuffle animation, ex: { top:15, left: 200 }
+       skipInitializationCallbacks: false, // set to true to disable the first before/after callback that occurs prior to any transition
+       slideExpr:         null,  // expression for selecting slides (if something other than all children is required)
+       slideResize:   1,     // force slide width/height to fixed size before every transition
+       speed:             1000,  // speed of the transition (any valid fx speed value)
+       speedIn:           null,  // speed of the 'in' transition
+       speedOut:          null,  // speed of the 'out' transition
+       startingSlide: undefined,         // zero-based index of the first slide to be displayed
+       sync:              1,     // true if in/out transitions should occur simultaneously
+       timeout:           4000,  // milliseconds between slide transitions (0 to disable auto advance)
+       timeoutFn:     null,  // callback for determining per-slide timeout value:  function(currSlideElement, nextSlideElement, options, forwardFlag)
+       updateActivePagerLink: null, // callback fn invoked to update the active pager link (adds/removes activePagerClass style)
+       width:         null   // container width (if the 'fit' option is true, the slides will be set to this width as well)
+};
+
+})(jQuery);
+
+
+/*!
+ * jQuery Cycle Plugin Transition Definitions
+ * This script is a plugin for the jQuery Cycle Plugin
+ * Examples and documentation at: http://malsup.com/jquery/cycle/
+ * Copyright (c) 2007-2010 M. Alsup
+ * Version:     2.73
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ */
+(function($) {
+
+//
+// These functions define slide initialization and properties for the named
+// transitions. To save file size feel free to remove any of these that you
+// don't need.
+//
+$.fn.cycle.transitions.none = function($cont, $slides, opts) {
+       opts.fxFn = function(curr,next,opts,after){
+               $(next).show();
+               $(curr).hide();
+               after();
+       };
+};
+
+// not a cross-fade, fadeout only fades out the top slide
+$.fn.cycle.transitions.fadeout = function($cont, $slides, opts) {
+       $slides.not(':eq('+opts.currSlide+')').css({ display: 'block', 'opacity': 1 });
+       opts.before.push(function(curr,next,opts,w,h,rev) {
+               $(curr).css('zIndex',opts.slideCount + (!rev === true ? 1 : 0));
+               $(next).css('zIndex',opts.slideCount + (!rev === true ? 0 : 1));
+       });
+       opts.animIn.opacity = 1;
+       opts.animOut.opacity = 0;
+       opts.cssBefore.opacity = 1;
+       opts.cssBefore.display = 'block';
+       opts.cssAfter.zIndex = 0;
+};
+
+// scrollUp/Down/Left/Right
+$.fn.cycle.transitions.scrollUp = function($cont, $slides, opts) {
+       $cont.css('overflow','hidden');
+       opts.before.push($.fn.cycle.commonReset);
+       var h = $cont.height();
+       opts.cssBefore.top = h;
+       opts.cssBefore.left = 0;
+       opts.cssFirst.top = 0;
+       opts.animIn.top = 0;
+       opts.animOut.top = -h;
+};
+$.fn.cycle.transitions.scrollDown = function($cont, $slides, opts) {
+       $cont.css('overflow','hidden');
+       opts.before.push($.fn.cycle.commonReset);
+       var h = $cont.height();
+       opts.cssFirst.top = 0;
+       opts.cssBefore.top = -h;
+       opts.cssBefore.left = 0;
+       opts.animIn.top = 0;
+       opts.animOut.top = h;
+};
+$.fn.cycle.transitions.scrollLeft = function($cont, $slides, opts) {
+       $cont.css('overflow','hidden');
+       opts.before.push($.fn.cycle.commonReset);
+       var w = $cont.width();
+       opts.cssFirst.left = 0;
+       opts.cssBefore.left = w;
+       opts.cssBefore.top = 0;
+       opts.animIn.left = 0;
+       opts.animOut.left = 0-w;
+};
+$.fn.cycle.transitions.scrollRight = function($cont, $slides, opts) {
+       $cont.css('overflow','hidden');
+       opts.before.push($.fn.cycle.commonReset);
+       var w = $cont.width();
+       opts.cssFirst.left = 0;
+       opts.cssBefore.left = -w;
+       opts.cssBefore.top = 0;
+       opts.animIn.left = 0;
+       opts.animOut.left = w;
+};
+$.fn.cycle.transitions.scrollHorz = function($cont, $slides, opts) {
+       $cont.css('overflow','hidden').width();
+       opts.before.push(function(curr, next, opts, fwd) {
+               if (opts.rev)
+                       fwd = !fwd;
+               $.fn.cycle.commonReset(curr,next,opts);
+               opts.cssBefore.left = fwd ? (next.cycleW-1) : (1-next.cycleW);
+               opts.animOut.left = fwd ? -curr.cycleW : curr.cycleW;
+       });
+       opts.cssFirst.left = 0;
+       opts.cssBefore.top = 0;
+       opts.animIn.left = 0;
+       opts.animOut.top = 0;
+};
+$.fn.cycle.transitions.scrollVert = function($cont, $slides, opts) {
+       $cont.css('overflow','hidden');
+       opts.before.push(function(curr, next, opts, fwd) {
+               if (opts.rev)
+                       fwd = !fwd;
+               $.fn.cycle.commonReset(curr,next,opts);
+               opts.cssBefore.top = fwd ? (1-next.cycleH) : (next.cycleH-1);
+               opts.animOut.top = fwd ? curr.cycleH : -curr.cycleH;
+       });
+       opts.cssFirst.top = 0;
+       opts.cssBefore.left = 0;
+       opts.animIn.top = 0;
+       opts.animOut.left = 0;
+};
+
+// slideX/slideY
+$.fn.cycle.transitions.slideX = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $(opts.elements).not(curr).hide();
+               $.fn.cycle.commonReset(curr,next,opts,false,true);
+               opts.animIn.width = next.cycleW;
+       });
+       opts.cssBefore.left = 0;
+       opts.cssBefore.top = 0;
+       opts.cssBefore.width = 0;
+       opts.animIn.width = 'show';
+       opts.animOut.width = 0;
+};
+$.fn.cycle.transitions.slideY = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $(opts.elements).not(curr).hide();
+               $.fn.cycle.commonReset(curr,next,opts,true,false);
+               opts.animIn.height = next.cycleH;
+       });
+       opts.cssBefore.left = 0;
+       opts.cssBefore.top = 0;
+       opts.cssBefore.height = 0;
+       opts.animIn.height = 'show';
+       opts.animOut.height = 0;
+};
+
+// shuffle
+$.fn.cycle.transitions.shuffle = function($cont, $slides, opts) {
+       var i, w = $cont.css('overflow', 'visible').width();
+       $slides.css({left: 0, top: 0});
+       opts.before.push(function(curr,next,opts) {
+               $.fn.cycle.commonReset(curr,next,opts,true,true,true);
+       });
+       // only adjust speed once!
+       if (!opts.speedAdjusted) {
+               opts.speed = opts.speed / 2; // shuffle has 2 transitions
+               opts.speedAdjusted = true;
+       }
+       opts.random = 0;
+       opts.shuffle = opts.shuffle || {left:-w, top:15};
+       opts.els = [];
+       for (i=0; i < $slides.length; i++)
+               opts.els.push($slides[i]);
+
+       for (i=0; i < opts.currSlide; i++)
+               opts.els.push(opts.els.shift());
+
+       // custom transition fn (hat tip to Benjamin Sterling for this bit of sweetness!)
+       opts.fxFn = function(curr, next, opts, cb, fwd) {
+               if (opts.rev)
+                       fwd = !fwd;
+               var $el = fwd ? $(curr) : $(next);
+               $(next).css(opts.cssBefore);
+               var count = opts.slideCount;
+               $el.animate(opts.shuffle, opts.speedIn, opts.easeIn, function() {
+                       var hops = $.fn.cycle.hopsFromLast(opts, fwd);
+                       for (var k=0; k < hops; k++)
+                               fwd ? opts.els.push(opts.els.shift()) : opts.els.unshift(opts.els.pop());
+                       if (fwd) {
+                               for (var i=0, len=opts.els.length; i < len; i++)
+                                       $(opts.els[i]).css('z-index', len-i+count);
+                       }
+                       else {
+                               var z = $(curr).css('z-index');
+                               $el.css('z-index', parseInt(z,10)+1+count);
+                       }
+                       $el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() {
+                               $(fwd ? this : curr).hide();
+                               if (cb) cb();
+                       });
+               });
+       };
+       $.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
+};
+
+// turnUp/Down/Left/Right
+$.fn.cycle.transitions.turnUp = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,true,false);
+               opts.cssBefore.top = next.cycleH;
+               opts.animIn.height = next.cycleH;
+               opts.animOut.width = next.cycleW;
+       });
+       opts.cssFirst.top = 0;
+       opts.cssBefore.left = 0;
+       opts.cssBefore.height = 0;
+       opts.animIn.top = 0;
+       opts.animOut.height = 0;
+};
+$.fn.cycle.transitions.turnDown = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,true,false);
+               opts.animIn.height = next.cycleH;
+               opts.animOut.top   = curr.cycleH;
+       });
+       opts.cssFirst.top = 0;
+       opts.cssBefore.left = 0;
+       opts.cssBefore.top = 0;
+       opts.cssBefore.height = 0;
+       opts.animOut.height = 0;
+};
+$.fn.cycle.transitions.turnLeft = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,false,true);
+               opts.cssBefore.left = next.cycleW;
+               opts.animIn.width = next.cycleW;
+       });
+       opts.cssBefore.top = 0;
+       opts.cssBefore.width = 0;
+       opts.animIn.left = 0;
+       opts.animOut.width = 0;
+};
+$.fn.cycle.transitions.turnRight = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,false,true);
+               opts.animIn.width = next.cycleW;
+               opts.animOut.left = curr.cycleW;
+       });
+       $.extend(opts.cssBefore, { top: 0, left: 0, width: 0 });
+       opts.animIn.left = 0;
+       opts.animOut.width = 0;
+};
+
+// zoom
+$.fn.cycle.transitions.zoom = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,false,false,true);
+               opts.cssBefore.top = next.cycleH/2;
+               opts.cssBefore.left = next.cycleW/2;
+               $.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
+               $.extend(opts.animOut, { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 });
+       });
+       opts.cssFirst.top = 0;
+       opts.cssFirst.left = 0;
+       opts.cssBefore.width = 0;
+       opts.cssBefore.height = 0;
+};
+
+// fadeZoom
+$.fn.cycle.transitions.fadeZoom = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,false,false);
+               opts.cssBefore.left = next.cycleW/2;
+               opts.cssBefore.top = next.cycleH/2;
+               $.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
+       });
+       opts.cssBefore.width = 0;
+       opts.cssBefore.height = 0;
+       opts.animOut.opacity = 0;
+};
+
+// blindX
+$.fn.cycle.transitions.blindX = function($cont, $slides, opts) {
+       var w = $cont.css('overflow','hidden').width();
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts);
+               opts.animIn.width = next.cycleW;
+               opts.animOut.left   = curr.cycleW;
+       });
+       opts.cssBefore.left = w;
+       opts.cssBefore.top = 0;
+       opts.animIn.left = 0;
+       opts.animOut.left = w;
+};
+// blindY
+$.fn.cycle.transitions.blindY = function($cont, $slides, opts) {
+       var h = $cont.css('overflow','hidden').height();
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts);
+               opts.animIn.height = next.cycleH;
+               opts.animOut.top   = curr.cycleH;
+       });
+       opts.cssBefore.top = h;
+       opts.cssBefore.left = 0;
+       opts.animIn.top = 0;
+       opts.animOut.top = h;
+};
+// blindZ
+$.fn.cycle.transitions.blindZ = function($cont, $slides, opts) {
+       var h = $cont.css('overflow','hidden').height();
+       var w = $cont.width();
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts);
+               opts.animIn.height = next.cycleH;
+               opts.animOut.top   = curr.cycleH;
+       });
+       opts.cssBefore.top = h;
+       opts.cssBefore.left = w;
+       opts.animIn.top = 0;
+       opts.animIn.left = 0;
+       opts.animOut.top = h;
+       opts.animOut.left = w;
+};
+
+// growX - grow horizontally from centered 0 width
+$.fn.cycle.transitions.growX = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,false,true);
+               opts.cssBefore.left = this.cycleW/2;
+               opts.animIn.left = 0;
+               opts.animIn.width = this.cycleW;
+               opts.animOut.left = 0;
+       });
+       opts.cssBefore.top = 0;
+       opts.cssBefore.width = 0;
+};
+// growY - grow vertically from centered 0 height
+$.fn.cycle.transitions.growY = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,true,false);
+               opts.cssBefore.top = this.cycleH/2;
+               opts.animIn.top = 0;
+               opts.animIn.height = this.cycleH;
+               opts.animOut.top = 0;
+       });
+       opts.cssBefore.height = 0;
+       opts.cssBefore.left = 0;
+};
+
+// curtainX - squeeze in both edges horizontally
+$.fn.cycle.transitions.curtainX = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,false,true,true);
+               opts.cssBefore.left = next.cycleW/2;
+               opts.animIn.left = 0;
+               opts.animIn.width = this.cycleW;
+               opts.animOut.left = curr.cycleW/2;
+               opts.animOut.width = 0;
+       });
+       opts.cssBefore.top = 0;
+       opts.cssBefore.width = 0;
+};
+// curtainY - squeeze in both edges vertically
+$.fn.cycle.transitions.curtainY = function($cont, $slides, opts) {
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,true,false,true);
+               opts.cssBefore.top = next.cycleH/2;
+               opts.animIn.top = 0;
+               opts.animIn.height = next.cycleH;
+               opts.animOut.top = curr.cycleH/2;
+               opts.animOut.height = 0;
+       });
+       opts.cssBefore.height = 0;
+       opts.cssBefore.left = 0;
+};
+
+// cover - curr slide covered by next slide
+$.fn.cycle.transitions.cover = function($cont, $slides, opts) {
+       var d = opts.direction || 'left';
+       var w = $cont.css('overflow','hidden').width();
+       var h = $cont.height();
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts);
+               if (d == 'right')
+                       opts.cssBefore.left = -w;
+               else if (d == 'up')
+                       opts.cssBefore.top = h;
+               else if (d == 'down')
+                       opts.cssBefore.top = -h;
+               else
+                       opts.cssBefore.left = w;
+       });
+       opts.animIn.left = 0;
+       opts.animIn.top = 0;
+       opts.cssBefore.top = 0;
+       opts.cssBefore.left = 0;
+};
+
+// uncover - curr slide moves off next slide
+$.fn.cycle.transitions.uncover = function($cont, $slides, opts) {
+       var d = opts.direction || 'left';
+       var w = $cont.css('overflow','hidden').width();
+       var h = $cont.height();
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,true,true,true);
+               if (d == 'right')
+                       opts.animOut.left = w;
+               else if (d == 'up')
+                       opts.animOut.top = -h;
+               else if (d == 'down')
+                       opts.animOut.top = h;
+               else
+                       opts.animOut.left = -w;
+       });
+       opts.animIn.left = 0;
+       opts.animIn.top = 0;
+       opts.cssBefore.top = 0;
+       opts.cssBefore.left = 0;
+};
+
+// toss - move top slide and fade away
+$.fn.cycle.transitions.toss = function($cont, $slides, opts) {
+       var w = $cont.css('overflow','visible').width();
+       var h = $cont.height();
+       opts.before.push(function(curr, next, opts) {
+               $.fn.cycle.commonReset(curr,next,opts,true,true,true);
+               // provide default toss settings if animOut not provided
+               if (!opts.animOut.left && !opts.animOut.top)
+                       $.extend(opts.animOut, { left: w*2, top: -h/2, opacity: 0 });
+               else
+                       opts.animOut.opacity = 0;
+       });
+       opts.cssBefore.left = 0;
+       opts.cssBefore.top = 0;
+       opts.animIn.left = 0;
+};
+
+// wipe - clip animation
+$.fn.cycle.transitions.wipe = function($cont, $slides, opts) {
+       var w = $cont.css('overflow','hidden').width();
+       var h = $cont.height();
+       opts.cssBefore = opts.cssBefore || {};
+       var clip;
+       if (opts.clip) {
+               if (/l2r/.test(opts.clip))
+                       clip = 'rect(0px 0px '+h+'px 0px)';
+               else if (/r2l/.test(opts.clip))
+                       clip = 'rect(0px '+w+'px '+h+'px '+w+'px)';
+               else if (/t2b/.test(opts.clip))
+                       clip = 'rect(0px '+w+'px 0px 0px)';
+               else if (/b2t/.test(opts.clip))
+                       clip = 'rect('+h+'px '+w+'px '+h+'px 0px)';
+               else if (/zoom/.test(opts.clip)) {
+                       var top = parseInt(h/2,10);
+                       var left = parseInt(w/2,10);
+                       clip = 'rect('+top+'px '+left+'px '+top+'px '+left+'px)';
+               }
+       }
+
+       opts.cssBefore.clip = opts.cssBefore.clip || clip || 'rect(0px 0px 0px 0px)';
+
+       var d = opts.cssBefore.clip.match(/(\d+)/g);
+       var t = parseInt(d[0],10), r = parseInt(d[1],10), b = parseInt(d[2],10), l = parseInt(d[3],10);
+
+       opts.before.push(function(curr, next, opts) {
+               if (curr == next) return;
+               var $curr = $(curr), $next = $(next);
+               $.fn.cycle.commonReset(curr,next,opts,true,true,false);
+               opts.cssAfter.display = 'block';
+
+               var step = 1, count = parseInt((opts.speedIn / 13),10) - 1;
+               (function f() {
+                       var tt = t ? t - parseInt(step * (t/count),10) : 0;
+                       var ll = l ? l - parseInt(step * (l/count),10) : 0;
+                       var bb = b < h ? b + parseInt(step * ((h-b)/count || 1),10) : h;
+                       var rr = r < w ? r + parseInt(step * ((w-r)/count || 1),10) : w;
+                       $next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' });
+                       (step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none');
+               })();
+       });
+       $.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
+       opts.animIn        = { left: 0 };
+       opts.animOut   = { left: 0 };
+};
+
+})(jQuery);
diff --git a/resources/lib/jquery/jquery.form.js b/resources/lib/jquery/jquery.form.js
new file mode 100644 (file)
index 0000000..13e9a55
--- /dev/null
@@ -0,0 +1,1089 @@
+/*!
+ * jQuery Form Plugin
+ * version: 3.14 (30-JUL-2012)
+ * @requires jQuery v1.3.2 or later
+ *
+ * Examples and documentation at: http://malsup.com/jquery/form/
+ * Project repository: https://github.com/malsup/form
+ * Dual licensed under the MIT and GPL licenses:
+ *    http://malsup.github.com/mit-license.txt
+ *    http://malsup.github.com/gpl-license-v2.txt
+ */
+/*global ActiveXObject alert */
+;(function($) {
+"use strict";
+
+/*
+    Usage Note:
+    -----------
+    Do not use both ajaxSubmit and ajaxForm on the same form.  These
+    functions are mutually exclusive.  Use ajaxSubmit if you want
+    to bind your own submit handler to the form.  For example,
+
+    $(document).ready(function() {
+        $('#myForm').on('submit', function(e) {
+            e.preventDefault(); // <-- important
+            $(this).ajaxSubmit({
+                target: '#output'
+            });
+        });
+    });
+
+    Use ajaxForm when you want the plugin to manage all the event binding
+    for you.  For example,
+
+    $(document).ready(function() {
+        $('#myForm').ajaxForm({
+            target: '#output'
+        });
+    });
+    
+    You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
+    form does not have to exist when you invoke ajaxForm:
+
+    $('#myForm').ajaxForm({
+        delegation: true,
+        target: '#output'
+    });
+    
+    When using ajaxForm, the ajaxSubmit function will be invoked for you
+    at the appropriate time.
+*/
+
+/**
+ * Feature detection
+ */
+var feature = {};
+feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
+feature.formdata = window.FormData !== undefined;
+
+/**
+ * ajaxSubmit() provides a mechanism for immediately submitting
+ * an HTML form using AJAX.
+ */
+$.fn.ajaxSubmit = function(options) {
+    /*jshint scripturl:true */
+
+    // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
+    if (!this.length) {
+        log('ajaxSubmit: skipping submit process - no element selected');
+        return this;
+    }
+    
+    var method, action, url, $form = this;
+
+    if (typeof options == 'function') {
+        options = { success: options };
+    }
+
+    method = this.attr('method');
+    action = this.attr('action');
+    url = (typeof action === 'string') ? $.trim(action) : '';
+    url = url || window.location.href || '';
+    if (url) {
+        // clean url (don't include hash vaue)
+        url = (url.match(/^([^#]+)/)||[])[1];
+    }
+
+    options = $.extend(true, {
+        url:  url,
+        success: $.ajaxSettings.success,
+        type: method || 'GET',
+        iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
+    }, options);
+
+    // hook for manipulating the form data before it is extracted;
+    // convenient for use with rich editors like tinyMCE or FCKEditor
+    var veto = {};
+    this.trigger('form-pre-serialize', [this, options, veto]);
+    if (veto.veto) {
+        log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
+        return this;
+    }
+
+    // provide opportunity to alter form data before it is serialized
+    if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
+        log('ajaxSubmit: submit aborted via beforeSerialize callback');
+        return this;
+    }
+
+    var traditional = options.traditional;
+    if ( traditional === undefined ) {
+        traditional = $.ajaxSettings.traditional;
+    }
+    
+    var elements = [];
+    var qx, a = this.formToArray(options.semantic, elements);
+    if (options.data) {
+        options.extraData = options.data;
+        qx = $.param(options.data, traditional);
+    }
+
+    // give pre-submit callback an opportunity to abort the submit
+    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
+        log('ajaxSubmit: submit aborted via beforeSubmit callback');
+        return this;
+    }
+
+    // fire vetoable 'validate' event
+    this.trigger('form-submit-validate', [a, this, options, veto]);
+    if (veto.veto) {
+        log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
+        return this;
+    }
+
+    var q = $.param(a, traditional);
+    if (qx) {
+        q = ( q ? (q + '&' + qx) : qx );
+    }    
+    if (options.type.toUpperCase() == 'GET') {
+        options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
+        options.data = null;  // data is null for 'get'
+    }
+    else {
+        options.data = q; // data is the query string for 'post'
+    }
+
+    var callbacks = [];
+    if (options.resetForm) {
+        callbacks.push(function() { $form.resetForm(); });
+    }
+    if (options.clearForm) {
+        callbacks.push(function() { $form.clearForm(options.includeHidden); });
+    }
+
+    // perform a load on the target only if dataType is not provided
+    if (!options.dataType && options.target) {
+        var oldSuccess = options.success || function(){};
+        callbacks.push(function(data) {
+            var fn = options.replaceTarget ? 'replaceWith' : 'html';
+            $(options.target)[fn](data).each(oldSuccess, arguments);
+        });
+    }
+    else if (options.success) {
+        callbacks.push(options.success);
+    }
+
+    options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
+        var context = options.context || this ;    // jQuery 1.4+ supports scope context 
+        for (var i=0, max=callbacks.length; i < max; i++) {
+            callbacks[i].apply(context, [data, status, xhr || $form, $form]);
+        }
+    };
+
+    // are there files to upload?
+    var fileInputs = $('input:file:enabled[value]', this); // [value] (issue #113)
+    var hasFileInputs = fileInputs.length > 0;
+    var mp = 'multipart/form-data';
+    var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
+
+    var fileAPI = feature.fileapi && feature.formdata;
+    log("fileAPI :" + fileAPI);
+    var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
+
+    // options.iframe allows user to force iframe mode
+    // 06-NOV-09: now defaulting to iframe mode if file input is detected
+    if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
+        // hack to fix Safari hang (thanks to Tim Molendijk for this)
+        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
+        if (options.closeKeepAlive) {
+            $.get(options.closeKeepAlive, function() {
+                fileUploadIframe(a);
+            });
+        }
+          else {
+            fileUploadIframe(a);
+          }
+    }
+    else if ((hasFileInputs || multipart) && fileAPI) {
+        fileUploadXhr(a);
+    }
+    else {
+        $.ajax(options);
+    }
+
+    // clear element array
+    for (var k=0; k < elements.length; k++)
+        elements[k] = null;
+
+    // fire 'notify' event
+    this.trigger('form-submit-notify', [this, options]);
+    return this;
+
+     // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
+    function fileUploadXhr(a) {
+        var formdata = new FormData();
+
+        for (var i=0; i < a.length; i++) {
+            formdata.append(a[i].name, a[i].value);
+        }
+
+        if (options.extraData) {
+            for (var p in options.extraData)
+                if (options.extraData.hasOwnProperty(p))
+                    formdata.append(p, options.extraData[p]);
+        }
+
+        options.data = null;
+
+        var s = $.extend(true, {}, $.ajaxSettings, options, {
+            contentType: false,
+            processData: false,
+            cache: false,
+            type: 'POST'
+        });
+        
+        if (options.uploadProgress) {
+            // workaround because jqXHR does not expose upload property
+            s.xhr = function() {
+                var xhr = jQuery.ajaxSettings.xhr();
+                if (xhr.upload) {
+                    xhr.upload.onprogress = function(event) {
+                        var percent = 0;
+                        var position = event.loaded || event.position; /*event.position is deprecated*/
+                        var total = event.total;
+                        if (event.lengthComputable) {
+                            percent = Math.ceil(position / total * 100);
+                        }
+                        options.uploadProgress(event, position, total, percent);
+                    };
+                }
+                return xhr;
+            };
+        }
+
+        s.data = null;
+            var beforeSend = s.beforeSend;
+            s.beforeSend = function(xhr, o) {
+                o.data = formdata;
+                if(beforeSend)
+                    beforeSend.call(this, xhr, o);
+        };
+        $.ajax(s);
+    }
+
+    // private function for handling file uploads (hat tip to YAHOO!)
+    function fileUploadIframe(a) {
+        var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
+        var useProp = !!$.fn.prop;
+
+        if ($(':input[name=submit],:input[id=submit]', form).length) {
+            // if there is an input with a name or id of 'submit' then we won't be
+            // able to invoke the submit fn on the form (at least not x-browser)
+            alert('Error: Form elements must not have name or id of "submit".');
+            return;
+        }
+        
+        if (a) {
+            // ensure that every serialized input is still enabled
+            for (i=0; i < elements.length; i++) {
+                el = $(elements[i]);
+                if ( useProp )
+                    el.prop('disabled', false);
+                else
+                    el.removeAttr('disabled');
+            }
+        }
+
+        s = $.extend(true, {}, $.ajaxSettings, options);
+        s.context = s.context || s;
+        id = 'jqFormIO' + (new Date().getTime());
+        if (s.iframeTarget) {
+            $io = $(s.iframeTarget);
+            n = $io.attr('name');
+            if (!n)
+                 $io.attr('name', id);
+            else
+                id = n;
+        }
+        else {
+            $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
+            $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
+        }
+        io = $io[0];
+
+
+        xhr = { // mock object
+            aborted: 0,
+            responseText: null,
+            responseXML: null,
+            status: 0,
+            statusText: 'n/a',
+            getAllResponseHeaders: function() {},
+            getResponseHeader: function() {},
+            setRequestHeader: function() {},
+            abort: function(status) {
+                var e = (status === 'timeout' ? 'timeout' : 'aborted');
+                log('aborting upload... ' + e);
+                this.aborted = 1;
+                // #214
+                if (io.contentWindow.document.execCommand) {
+                    try { // #214
+                        io.contentWindow.document.execCommand('Stop');
+                    } catch(ignore) {}
+                }
+                $io.attr('src', s.iframeSrc); // abort op in progress
+                xhr.error = e;
+                if (s.error)
+                    s.error.call(s.context, xhr, e, status);
+                if (g)
+                    $.event.trigger("ajaxError", [xhr, s, e]);
+                if (s.complete)
+                    s.complete.call(s.context, xhr, e);
+            }
+        };
+
+        g = s.global;
+        // trigger ajax global events so that activity/block indicators work like normal
+        if (g && 0 === $.active++) {
+            $.event.trigger("ajaxStart");
+        }
+        if (g) {
+            $.event.trigger("ajaxSend", [xhr, s]);
+        }
+
+        if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
+            if (s.global) {
+                $.active--;
+            }
+            return;
+        }
+        if (xhr.aborted) {
+            return;
+        }
+
+        // add submitting element to data if we know it
+        sub = form.clk;
+        if (sub) {
+            n = sub.name;
+            if (n && !sub.disabled) {
+                s.extraData = s.extraData || {};
+                s.extraData[n] = sub.value;
+                if (sub.type == "image") {
+                    s.extraData[n+'.x'] = form.clk_x;
+                    s.extraData[n+'.y'] = form.clk_y;
+                }
+            }
+        }
+        
+        var CLIENT_TIMEOUT_ABORT = 1;
+        var SERVER_ABORT = 2;
+
+        function getDoc(frame) {
+            var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
+            return doc;
+        }
+        
+        // Rails CSRF hack (thanks to Yvan Barthelemy)
+        var csrf_token = $('meta[name=csrf-token]').attr('content');
+        var csrf_param = $('meta[name=csrf-param]').attr('content');
+        if (csrf_param && csrf_token) {
+            s.extraData = s.extraData || {};
+            s.extraData[csrf_param] = csrf_token;
+        }
+
+        // take a breath so that pending repaints get some cpu time before the upload starts
+        function doSubmit() {
+            // make sure form attrs are set
+            var t = $form.attr('target'), a = $form.attr('action');
+
+            // update form attrs in IE friendly way
+            form.setAttribute('target',id);
+            if (!method) {
+                form.setAttribute('method', 'POST');
+            }
+            if (a != s.url) {
+                form.setAttribute('action', s.url);
+            }
+
+            // ie borks in some cases when setting encoding
+            if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
+                $form.attr({
+                    encoding: 'multipart/form-data',
+                    enctype:  'multipart/form-data'
+                });
+            }
+
+            // support timout
+            if (s.timeout) {
+                timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
+            }
+            
+            // look for server aborts
+            function checkState() {
+                try {
+                    var state = getDoc(io).readyState;
+                    log('state = ' + state);
+                    if (state && state.toLowerCase() == 'uninitialized')
+                        setTimeout(checkState,50);
+                }
+                catch(e) {
+                    log('Server abort: ' , e, ' (', e.name, ')');
+                    cb(SERVER_ABORT);
+                    if (timeoutHandle)
+                        clearTimeout(timeoutHandle);
+                    timeoutHandle = undefined;
+                }
+            }
+
+            // add "extra" data to form if provided in options
+            var extraInputs = [];
+            try {
+                if (s.extraData) {
+                    for (var n in s.extraData) {
+                        if (s.extraData.hasOwnProperty(n)) {
+                           // if using the $.param format that allows for multiple values with the same name
+                           if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
+                               extraInputs.push(
+                               $('<input type="hidden" name="'+s.extraData[n].name+'">').attr('value',s.extraData[n].value)
+                                   .appendTo(form)[0]);
+                           } else {
+                               extraInputs.push(
+                               $('<input type="hidden" name="'+n+'">').attr('value',s.extraData[n])
+                                   .appendTo(form)[0]);
+                           }
+                        }
+                    }
+                }
+
+                if (!s.iframeTarget) {
+                    // add iframe to doc and submit the form
+                    $io.appendTo('body');
+                    if (io.attachEvent)
+                        io.attachEvent('onload', cb);
+                    else
+                        io.addEventListener('load', cb, false);
+                }
+                setTimeout(checkState,15);
+                form.submit();
+            }
+            finally {
+                // reset attrs and remove "extra" input elements
+                form.setAttribute('action',a);
+                if(t) {
+                    form.setAttribute('target', t);
+                } else {
+                    $form.removeAttr('target');
+                }
+                $(extraInputs).remove();
+            }
+        }
+
+        if (s.forceSync) {
+            doSubmit();
+        }
+        else {
+            setTimeout(doSubmit, 10); // this lets dom updates render
+        }
+
+        var data, doc, domCheckCount = 50, callbackProcessed;
+
+        function cb(e) {
+            if (xhr.aborted || callbackProcessed) {
+                return;
+            }
+            try {
+                doc = getDoc(io);
+            }
+            catch(ex) {
+                log('cannot access response document: ', ex);
+                e = SERVER_ABORT;
+            }
+            if (e === CLIENT_TIMEOUT_ABORT && xhr) {
+                xhr.abort('timeout');
+                return;
+            }
+            else if (e == SERVER_ABORT && xhr) {
+                xhr.abort('server abort');
+                return;
+            }
+
+            if (!doc || doc.location.href == s.iframeSrc) {
+                // response not received yet
+                if (!timedOut)
+                    return;
+            }
+            if (io.detachEvent)
+                io.detachEvent('onload', cb);
+            else    
+                io.removeEventListener('load', cb, false);
+
+            var status = 'success', errMsg;
+            try {
+                if (timedOut) {
+                    throw 'timeout';
+                }
+
+                var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
+                log('isXml='+isXml);
+                if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
+                    if (--domCheckCount) {
+                        // in some browsers (Opera) the iframe DOM is not always traversable when
+                        // the onload callback fires, so we loop a bit to accommodate
+                        log('requeing onLoad callback, DOM not available');
+                        setTimeout(cb, 250);
+                        return;
+                    }
+                    // let this fall through because server response could be an empty document
+                    //log('Could not access iframe DOM after mutiple tries.');
+                    //throw 'DOMException: not available';
+                }
+
+                //log('response detected');
+                var docRoot = doc.body ? doc.body : doc.documentElement;
+                xhr.responseText = docRoot ? docRoot.innerHTML : null;
+                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
+                if (isXml)
+                    s.dataType = 'xml';
+                xhr.getResponseHeader = function(header){
+                    var headers = {'content-type': s.dataType};
+                    return headers[header];
+                };
+                // support for XHR 'status' & 'statusText' emulation :
+                if (docRoot) {
+                    xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
+                    xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
+                }
+
+                var dt = (s.dataType || '').toLowerCase();
+                var scr = /(json|script|text)/.test(dt);
+                if (scr || s.textarea) {
+                    // see if user embedded response in textarea
+                    var ta = doc.getElementsByTagName('textarea')[0];
+                    if (ta) {
+                        xhr.responseText = ta.value;
+                        // support for XHR 'status' & 'statusText' emulation :
+                        xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
+                        xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
+                    }
+                    else if (scr) {
+                        // account for browsers injecting pre around json response
+                        var pre = doc.getElementsByTagName('pre')[0];
+                        var b = doc.getElementsByTagName('body')[0];
+                        if (pre) {
+                            xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
+                        }
+                        else if (b) {
+                            xhr.responseText = b.textContent ? b.textContent : b.innerText;
+                        }
+                    }
+                }
+                else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
+                    xhr.responseXML = toXml(xhr.responseText);
+                }
+
+                try {
+                    data = httpData(xhr, dt, s);
+                }
+                catch (e) {
+                    status = 'parsererror';
+                    xhr.error = errMsg = (e || status);
+                }
+            }
+            catch (e) {
+                log('error caught: ',e);
+                status = 'error';
+                xhr.error = errMsg = (e || status);
+            }
+
+            if (xhr.aborted) {
+                log('upload aborted');
+                status = null;
+            }
+
+            if (xhr.status) { // we've set xhr.status
+                status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
+            }
+
+            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
+            if (status === 'success') {
+                if (s.success)
+                    s.success.call(s.context, data, 'success', xhr);
+                if (g)
+                    $.event.trigger("ajaxSuccess", [xhr, s]);
+            }
+            else if (status) {
+                if (errMsg === undefined)
+                    errMsg = xhr.statusText;
+                if (s.error)
+                    s.error.call(s.context, xhr, status, errMsg);
+                if (g)
+                    $.event.trigger("ajaxError", [xhr, s, errMsg]);
+            }
+
+            if (g)
+                $.event.trigger("ajaxComplete", [xhr, s]);
+
+            if (g && ! --$.active) {
+                $.event.trigger("ajaxStop");
+            }
+
+            if (s.complete)
+                s.complete.call(s.context, xhr, status);
+
+            callbackProcessed = true;
+            if (s.timeout)
+                clearTimeout(timeoutHandle);
+
+            // clean up
+            setTimeout(function() {
+                if (!s.iframeTarget)
+                    $io.remove();
+                xhr.responseXML = null;
+            }, 100);
+        }
+
+        var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
+            if (window.ActiveXObject) {
+                doc = new ActiveXObject('Microsoft.XMLDOM');
+                doc.async = 'false';
+                doc.loadXML(s);
+            }
+            else {
+                doc = (new DOMParser()).parseFromString(s, 'text/xml');
+            }
+            return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
+        };
+        var parseJSON = $.parseJSON || function(s) {
+            /*jslint evil:true */
+            return window['eval']('(' + s + ')');
+        };
+
+        var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
+
+            var ct = xhr.getResponseHeader('content-type') || '',
+                xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
+                data = xml ? xhr.responseXML : xhr.responseText;
+
+            if (xml && data.documentElement.nodeName === 'parsererror') {
+                if ($.error)
+                    $.error('parsererror');
+            }
+            if (s && s.dataFilter) {
+                data = s.dataFilter(data, type);
+            }
+            if (typeof data === 'string') {
+                if (type === 'json' || !type && ct.indexOf('json') >= 0) {
+                    data = parseJSON(data);
+                } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
+                    $.globalEval(data);
+                }
+            }
+            return data;
+        };
+    }
+};
+
+/**
+ * ajaxForm() provides a mechanism for fully automating form submission.
+ *
+ * The advantages of using this method instead of ajaxSubmit() are:
+ *
+ * 1: This method will include coordinates for <input type="image" /> elements (if the element
+ *    is used to submit the form).
+ * 2. This method will include the submit element's name/value data (for the element that was
+ *    used to submit the form).
+ * 3. This method binds the submit() method to the form for you.
+ *
+ * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
+ * passes the options argument along after properly binding events for submit elements and
+ * the form itself.
+ */
+$.fn.ajaxForm = function(options) {
+    options = options || {};
+    options.delegation = options.delegation && $.isFunction($.fn.on);
+    
+    // in jQuery 1.3+ we can fix mistakes with the ready state
+    if (!options.delegation && this.length === 0) {
+        var o = { s: this.selector, c: this.context };
+        if (!$.isReady && o.s) {
+            log('DOM not ready, queuing ajaxForm');
+            $(function() {
+                $(o.s,o.c).ajaxForm(options);
+            });
+            return this;
+        }
+        // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
+        log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
+        return this;
+    }
+
+    if ( options.delegation ) {
+        $(document)
+            .off('submit.form-plugin', this.selector, doAjaxSubmit)
+            .off('click.form-plugin', this.selector, captureSubmittingElement)
+            .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
+            .on('click.form-plugin', this.selector, options, captureSubmittingElement);
+        return this;
+    }
+
+    return this.ajaxFormUnbind()
+        .bind('submit.form-plugin', options, doAjaxSubmit)
+        .bind('click.form-plugin', options, captureSubmittingElement);
+};
+
+// private event handlers    
+function doAjaxSubmit(e) {
+    /*jshint validthis:true */
+    var options = e.data;
+    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
+        e.preventDefault();
+        $(this).ajaxSubmit(options);
+    }
+}
+    
+function captureSubmittingElement(e) {
+    /*jshint validthis:true */
+    var target = e.target;
+    var $el = $(target);
+    if (!($el.is(":submit,input:image"))) {
+        // is this a child element of the submit el?  (ex: a span within a button)
+        var t = $el.closest(':submit');
+        if (t.length === 0) {
+            return;
+        }
+        target = t[0];
+    }
+    var form = this;
+    form.clk = target;
+    if (target.type == 'image') {
+        if (e.offsetX !== undefined) {
+            form.clk_x = e.offsetX;
+            form.clk_y = e.offsetY;
+        } else if (typeof $.fn.offset == 'function') {
+            var offset = $el.offset();
+            form.clk_x = e.pageX - offset.left;
+            form.clk_y = e.pageY - offset.top;
+        } else {
+            form.clk_x = e.pageX - target.offsetLeft;
+            form.clk_y = e.pageY - target.offsetTop;
+        }
+    }
+    // clear form vars
+    setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
+}
+
+
+// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
+$.fn.ajaxFormUnbind = function() {
+    return this.unbind('submit.form-plugin click.form-plugin');
+};
+
+/**
+ * formToArray() gathers form element data into an array of objects that can
+ * be passed to any of the following ajax functions: $.get, $.post, or load.
+ * Each object in the array has both a 'name' and 'value' property.  An example of
+ * an array for a simple login form might be:
+ *
+ * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
+ *
+ * It is this array that is passed to pre-submit callback functions provided to the
+ * ajaxSubmit() and ajaxForm() methods.
+ */
+$.fn.formToArray = function(semantic, elements) {
+    var a = [];
+    if (this.length === 0) {
+        return a;
+    }
+
+    var form = this[0];
+    var els = semantic ? form.getElementsByTagName('*') : form.elements;
+    if (!els) {
+        return a;
+    }
+
+    var i,j,n,v,el,max,jmax;
+    for(i=0, max=els.length; i < max; i++) {
+        el = els[i];
+        n = el.name;
+        if (!n) {
+            continue;
+        }
+
+        if (semantic && form.clk && el.type == "image") {
+            // handle image inputs on the fly when semantic == true
+            if(!el.disabled && form.clk == el) {
+                a.push({name: n, value: $(el).val(), type: el.type });
+                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+            }
+            continue;
+        }
+
+        v = $.fieldValue(el, true);
+        if (v && v.constructor == Array) {
+            if (elements) 
+                elements.push(el);
+            for(j=0, jmax=v.length; j < jmax; j++) {
+                a.push({name: n, value: v[j]});
+            }
+        }
+        else if (feature.fileapi && el.type == 'file' && !el.disabled) {
+            if (elements) 
+                elements.push(el);
+            var files = el.files;
+            if (files.length) {
+                for (j=0; j < files.length; j++) {
+                    a.push({name: n, value: files[j], type: el.type});
+                }
+            }
+            else {
+                // #180
+                a.push({ name: n, value: '', type: el.type });
+            }
+        }
+        else if (v !== null && typeof v != 'undefined') {
+            if (elements) 
+                elements.push(el);
+            a.push({name: n, value: v, type: el.type, required: el.required});
+        }
+    }
+
+    if (!semantic && form.clk) {
+        // input type=='image' are not found in elements array! handle it here
+        var $input = $(form.clk), input = $input[0];
+        n = input.name;
+        if (n && !input.disabled && input.type == 'image') {
+            a.push({name: n, value: $input.val()});
+            a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+        }
+    }
+    return a;
+};
+
+/**
+ * Serializes form data into a 'submittable' string. This method will return a string
+ * in the format: name1=value1&amp;name2=value2
+ */
+$.fn.formSerialize = function(semantic) {
+    //hand off to jQuery.param for proper encoding
+    return $.param(this.formToArray(semantic));
+};
+
+/**
+ * Serializes all field elements in the jQuery object into a query string.
+ * This method will return a string in the format: name1=value1&amp;name2=value2
+ */
+$.fn.fieldSerialize = function(successful) {
+    var a = [];
+    this.each(function() {
+        var n = this.name;
+        if (!n) {
+            return;
+        }
+        var v = $.fieldValue(this, successful);
+        if (v && v.constructor == Array) {
+            for (var i=0,max=v.length; i < max; i++) {
+                a.push({name: n, value: v[i]});
+            }
+        }
+        else if (v !== null && typeof v != 'undefined') {
+            a.push({name: this.name, value: v});
+        }
+    });
+    //hand off to jQuery.param for proper encoding
+    return $.param(a);
+};
+
+/**
+ * Returns the value(s) of the element in the matched set.  For example, consider the following form:
+ *
+ *  <form><fieldset>
+ *      <input name="A" type="text" />
+ *      <input name="A" type="text" />
+ *      <input name="B" type="checkbox" value="B1" />
+ *      <input name="B" type="checkbox" value="B2"/>
+ *      <input name="C" type="radio" value="C1" />
+ *      <input name="C" type="radio" value="C2" />
+ *  </fieldset></form>
+ *
+ *  var v = $(':text').fieldValue();
+ *  // if no values are entered into the text inputs
+ *  v == ['','']
+ *  // if values entered into the text inputs are 'foo' and 'bar'
+ *  v == ['foo','bar']
+ *
+ *  var v = $(':checkbox').fieldValue();
+ *  // if neither checkbox is checked
+ *  v === undefined
+ *  // if both checkboxes are checked
+ *  v == ['B1', 'B2']
+ *
+ *  var v = $(':radio').fieldValue();
+ *  // if neither radio is checked
+ *  v === undefined
+ *  // if first radio is checked
+ *  v == ['C1']
+ *
+ * The successful argument controls whether or not the field element must be 'successful'
+ * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
+ * The default value of the successful argument is true.  If this value is false the value(s)
+ * for each element is returned.
+ *
+ * Note: This method *always* returns an array.  If no valid value can be determined the
+ *    array will be empty, otherwise it will contain one or more values.
+ */
+$.fn.fieldValue = function(successful) {
+    for (var val=[], i=0, max=this.length; i < max; i++) {
+        var el = this[i];
+        var v = $.fieldValue(el, successful);
+        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
+            continue;
+        }
+        if (v.constructor == Array)
+            $.merge(val, v);
+        else
+            val.push(v);
+    }
+    return val;
+};
+
+/**
+ * Returns the value of the field element.
+ */
+$.fieldValue = function(el, successful) {
+    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
+    if (successful === undefined) {
+        successful = true;
+    }
+
+    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
+        (t == 'checkbox' || t == 'radio') && !el.checked ||
+        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
+        tag == 'select' && el.selectedIndex == -1)) {
+            return null;
+    }
+
+    if (tag == 'select') {
+        var index = el.selectedIndex;
+        if (index < 0) {
+            return null;
+        }
+        var a = [], ops = el.options;
+        var one = (t == 'select-one');
+        var max = (one ? index+1 : ops.length);
+        for(var i=(one ? index : 0); i < max; i++) {
+            var op = ops[i];
+            if (op.selected) {
+                var v = op.value;
+                if (!v) { // extra pain for IE...
+                    v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
+                }
+                if (one) {
+                    return v;
+                }
+                a.push(v);
+            }
+        }
+        return a;
+    }
+    return $(el).val();
+};
+
+/**
+ * Clears the form data.  Takes the following actions on the form's input fields:
+ *  - input text fields will have their 'value' property set to the empty string
+ *  - select elements will have their 'selectedIndex' property set to -1
+ *  - checkbox and radio inputs will have their 'checked' property set to false
+ *  - inputs of type submit, button, reset, and hidden will *not* be effected
+ *  - button elements will *not* be effected
+ */
+$.fn.clearForm = function(includeHidden) {
+    return this.each(function() {
+        $('input,select,textarea', this).clearFields(includeHidden);
+    });
+};
+
+/**
+ * Clears the selected form elements.
+ */
+$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
+    var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
+    return this.each(function() {
+        var t = this.type, tag = this.tagName.toLowerCase();
+        if (re.test(t) || tag == 'textarea') {
+            this.value = '';
+        }
+        else if (t == 'checkbox' || t == 'radio') {
+            this.checked = false;
+        }
+        else if (tag == 'select') {
+            this.selectedIndex = -1;
+        }
+        else if (includeHidden) {
+            // includeHidden can be the value true, or it can be a selector string
+            // indicating a special test; for example:
+            //  $('#myForm').clearForm('.special:hidden')
+            // the above would clean hidden inputs that have the class of 'special'
+            if ( (includeHidden === true && /hidden/.test(t)) ||
+                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) )
+                this.value = '';
+        }
+    });
+};
+
+/**
+ * Resets the form data.  Causes all form elements to be reset to their original value.
+ */
+$.fn.resetForm = function() {
+    return this.each(function() {
+        // guard against an input with the name of 'reset'
+        // note that IE reports the reset function as an 'object'
+        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
+            this.reset();
+        }
+    });
+};
+
+/**
+ * Enables or disables any matching elements.
+ */
+$.fn.enable = function(b) {
+    if (b === undefined) {
+        b = true;
+    }
+    return this.each(function() {
+        this.disabled = !b;
+    });
+};
+
+/**
+ * Checks/unchecks any matching checkboxes or radio buttons and
+ * selects/deselects and matching option elements.
+ */
+$.fn.selected = function(select) {
+    if (select === undefined) {
+        select = true;
+    }
+    return this.each(function() {
+        var t = this.type;
+        if (t == 'checkbox' || t == 'radio') {
+            this.checked = select;
+        }
+        else if (this.tagName.toLowerCase() == 'option') {
+            var $sel = $(this).parent('select');
+            if (select && $sel[0] && $sel[0].type == 'select-one') {
+                // deselect all other options
+                $sel.find('option').selected(false);
+            }
+            this.selected = select;
+        }
+    });
+};
+
+// expose debug var
+$.fn.ajaxSubmit.debug = false;
+
+// helper fn for console logging
+function log() {
+    if (!$.fn.ajaxSubmit.debug) 
+        return;
+    var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
+    if (window.console && window.console.log) {
+        window.console.log(msg);
+    }
+    else if (window.opera && window.opera.postError) {
+        window.opera.postError(msg);
+    }
+}
+
+})(jQuery);
diff --git a/resources/lib/jquery/jquery.fullscreen.js b/resources/lib/jquery/jquery.fullscreen.js
new file mode 100644 (file)
index 0000000..30e4484
--- /dev/null
@@ -0,0 +1,175 @@
+/**
+ * jQuery fullscreen plugin v2.0.0-git (9f8f97d127)
+ * https://github.com/theopolisme/jquery-fullscreen
+ *
+ * Copyright (c) 2013 Theopolisme <theopolismewiki@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+( function ( $ ) {
+       var setupFullscreen,
+               fsClass = 'jq-fullscreened';
+
+       /**
+        * On fullscreenchange, trigger a jq-fullscreen-change event
+        * The event is given an object, which contains the fullscreened DOM element (element), if any
+        * and a boolean value (fullscreen) indicating if we've entered or exited fullscreen mode
+        * Also remove the 'fullscreened' class from elements that are no longer fullscreen
+        */
+       function handleFullscreenChange () {
+               var fullscreenElement = document.fullscreenElement ||
+                       document.mozFullScreenElement ||
+                       document.webkitFullscreenElement ||
+                       document.msFullscreenElement;
+
+               if ( !fullscreenElement ) {
+                       $( '.' + fsClass ).data( 'isFullscreened', false ).removeClass( fsClass );
+               }
+
+               $( document ).trigger( $.Event( 'jq-fullscreen-change', { element: fullscreenElement, fullscreen: !!fullscreenElement } ) );
+       }
+
+       /**
+        * Enters full screen with the "this" element in focus.
+        * Check the .data( 'isFullscreened' ) of the return value to check
+        * success or failure, if you're into that sort of thing.
+        * @chainable
+        * @return {jQuery}
+        */
+       function enterFullscreen () {
+               var element = this.get(0),
+                       $element = this.first();
+               if ( element ) {
+                       if ( element.requestFullscreen ) {
+                               element.requestFullscreen();
+                       } else if ( element.mozRequestFullScreen ) {
+                               element.mozRequestFullScreen();
+                       } else if ( element.webkitRequestFullscreen ) {
+                               element.webkitRequestFullscreen();
+                       } else if ( element.msRequestFullscreen ) {
+                               element.msRequestFullscreen();
+                       } else {
+                               // Unable to make fullscreen
+                               $element.data( 'isFullscreened', false );
+                               return this;
+                       }
+                       // Add the fullscreen class and data attribute to `element`
+                       $element.addClass( fsClass ).data( 'isFullscreened', true );
+                       return this;
+               } else {
+                       $element.data( 'isFullscreened', false );
+                       return this;
+               }
+       }
+
+       /**
+        * Brings the "this" element out of fullscreen.
+        * Check the .data( 'isFullscreened' ) of the return value to check
+        * success or failure, if you're into that sort of thing.
+        * @chainable
+        * @return {jQuery}
+        */
+       function exitFullscreen () {
+               var fullscreenElement = ( document.fullscreenElement ||
+                               document.mozFullScreenElement ||
+                               document.webkitFullscreenElement ||
+                               document.msFullscreenElement );
+
+               // Ensure that we only exit fullscreen if exitFullscreen() is being called on the same element that is currently fullscreen
+               if ( fullscreenElement && this.get(0) === fullscreenElement ) {
+                       if ( document.exitFullscreen ) {
+                               document.exitFullscreen();
+                       } else if ( document.mozCancelFullScreen ) {
+                               document.mozCancelFullScreen();
+                       } else if ( document.webkitCancelFullScreen ) {
+                               document.webkitCancelFullScreen();
+                       } else if ( document.msExitFullscreen ) {
+                               document.msExitFullscreen();
+                       } else {
+                               // Unable to cancel fullscreen mode
+                               return this;
+                       }
+                       // We don't need to remove the fullscreen class here,
+                       // because it will be removed in handleFullscreenChange.
+                       // But we should change the data on the element so the
+                       // caller can check for success.
+                       this.first().data( 'isFullscreened', false );
+               }
+
+               return this;
+       }
+
+       /**
+        * Set up fullscreen handling and install necessary event handlers.
+        * Return false if fullscreen is not supported.
+        */
+       setupFullscreen = function () {
+               if ( $.support.fullscreen ) {
+                       // When the fullscreen mode is changed, trigger the
+                       // fullscreen events (and when exiting,
+                       // also remove the fullscreen class)
+                       $( document ).on( 'fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange', handleFullscreenChange);
+                       // Convenience wrapper so that one only needs to listen for
+                       // 'fullscreenerror', not all of the prefixed versions
+                       $( document ).on( 'webkitfullscreenerror mozfullscreenerror MSFullscreenError', function () {
+                               $( document ).trigger( $.Event( 'fullscreenerror' ) );
+                       } );
+                       // Fullscreen has been set up, so always return true
+                       setupFullscreen = function () { return true; };
+                       return true;
+               } else {
+                       // Always return false from now on, since fullscreen is not supported
+                       setupFullscreen = function () { return false; };
+                       return false;
+               }
+       };
+
+       /**
+        * Set up fullscreen handling if necessary, then make the first element
+        * matching the given selector fullscreen
+        * @chainable
+        * @return {jQuery}
+        */
+       $.fn.enterFullscreen = function () {
+               if ( setupFullscreen() ) {
+                       $.fn.enterFullscreen = enterFullscreen;
+                       return this.enterFullscreen();
+               } else {
+                       $.fn.enterFullscreen = function () { return this; };
+                       return this;
+               }
+       };
+
+       /**
+        * Set up fullscreen handling if necessary, then cancel fullscreen mode
+        * for the first element matching the given selector.
+        * @chainable
+        * @return {jQuery}
+        */
+       $.fn.exitFullscreen = function () {
+               if ( setupFullscreen() ) {
+                       $.fn.exitFullscreen = exitFullscreen;
+                       return this.exitFullscreen();
+               } else {
+                       $.fn.exitFullscreen = function () { return this; };
+                       return this;
+               }
+       };
+
+       $.support.fullscreen = document.fullscreenEnabled ||
+               document.webkitFullscreenEnabled ||
+               document.mozFullScreenEnabled ||
+               document.msFullscreenEnabled;
+}( jQuery ) );
diff --git a/resources/lib/jquery/jquery.hoverIntent.js b/resources/lib/jquery/jquery.hoverIntent.js
new file mode 100644 (file)
index 0000000..adf948d
--- /dev/null
@@ -0,0 +1,111 @@
+/**
+* hoverIntent is similar to jQuery's built-in "hover" function except that
+* instead of firing the onMouseOver event immediately, hoverIntent checks
+* to see if the user's mouse has slowed down (beneath the sensitivity
+* threshold) before firing the onMouseOver event.
+* 
+* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
+* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
+* 
+* hoverIntent is currently available for use in all personal or commercial 
+* projects under both MIT and GPL licenses. This means that you can choose 
+* the license that best suits your project, and use it accordingly.
+* 
+* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions
+* $("ul li").hoverIntent( showNav , hideNav );
+* 
+* // advanced usage receives configuration object only
+* $("ul li").hoverIntent({
+*      sensitivity: 7, // number = sensitivity threshold (must be 1 or higher)
+*      interval: 100,   // number = milliseconds of polling interval
+*      over: showNav,  // function = onMouseOver callback (required)
+*      timeout: 0,   // number = milliseconds delay before onMouseOut function call
+*      out: hideNav    // function = onMouseOut callback (required)
+* });
+* 
+* @param  f  onMouseOver function || An object with configuration options
+* @param  g  onMouseOut function  || Nothing (use configuration options object)
+* @author    Brian Cherne <brian@cherne.net>
+*/
+(function($) {
+       $.fn.hoverIntent = function(f,g) {
+               // default configuration options
+               var cfg = {
+                       sensitivity: 7,
+                       interval: 100,
+                       timeout: 0
+               };
+               // override configuration options with user supplied object
+               cfg = $.extend(cfg, g ? { over: f, out: g } : f );
+
+               // instantiate variables
+               // cX, cY = current X and Y position of mouse, updated by mousemove event
+               // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
+               var cX, cY, pX, pY;
+
+               // A private function for getting mouse position
+               var track = function(ev) {
+                       cX = ev.pageX;
+                       cY = ev.pageY;
+               };
+
+               // A private function for comparing current and previous mouse position
+               var compare = function(ev,ob) {
+                       ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
+                       // compare mouse positions to see if they've crossed the threshold
+                       if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
+                               $(ob).unbind("mousemove",track);
+                               // set hoverIntent state to true (so mouseOut can be called)
+                               ob.hoverIntent_s = 1;
+                               return cfg.over.apply(ob,[ev]);
+                       } else {
+                               // set previous coordinates for next time
+                               pX = cX; pY = cY;
+                               // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
+                               ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
+                       }
+               };
+
+               // A private function for delaying the mouseOut function
+               var delay = function(ev,ob) {
+                       ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
+                       ob.hoverIntent_s = 0;
+                       return cfg.out.apply(ob,[ev]);
+               };
+
+               // A private function for handling mouse 'hovering'
+               var handleHover = function(e) {
+                       // next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
+                       var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
+                       while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
+                       if ( p == this ) { return false; }
+
+                       // copy objects to be passed into t (required for event object to be passed in IE)
+                       var ev = $.extend({},e);
+                       var ob = this;
+
+                       // cancel hoverIntent timer if it exists
+                       if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
+
+                       // else e.type == "onmouseover"
+                       if (e.type == "mouseover") {
+                               // set "previous" X and Y position based on initial entry point
+                               pX = ev.pageX; pY = ev.pageY;
+                               // update "current" X and Y position based on mousemove
+                               $(ob).bind("mousemove",track);
+                               // start polling interval (self-calling timeout) to compare mouse coordinates over time
+                               if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
+
+                       // else e.type == "onmouseout"
+                       } else {
+                               // unbind expensive mousemove event
+                               $(ob).unbind("mousemove",track);
+                               // if hoverIntent state is true, then call the mouseOut function after the specified delay
+                               if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
+                       }
+               };
+
+               // bind the function to the two event listeners
+               return this.mouseover(handleHover).mouseout(handleHover);
+       };
+})(jQuery);
\ No newline at end of file
diff --git a/resources/lib/jquery/jquery.jStorage.js b/resources/lib/jquery/jquery.jStorage.js
new file mode 100644 (file)
index 0000000..324833c
--- /dev/null
@@ -0,0 +1,960 @@
+/*
+ * ----------------------------- JSTORAGE -------------------------------------
+ * Simple local storage wrapper to save data on the browser side, supporting
+ * all major browsers - IE6+, Firefox2+, Safari4+, Chrome4+ and Opera 10.5+
+ *
+ * Author: Andris Reinman, andris.reinman@gmail.com
+ * Project homepage: www.jstorage.info
+ *
+ * Licensed under Unlicense:
+ *
+ * This is free and unencumbered software released into the public domain.
+ * 
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ * 
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ * 
+ * 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 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.
+ * 
+ * For more information, please refer to <http://unlicense.org/>
+ */
+
+ (function(){
+    var
+        /* jStorage version */
+        JSTORAGE_VERSION = "0.4.8",
+
+        /* detect a dollar object or create one if not found */
+        $ = window.jQuery || window.$ || (window.$ = {}),
+
+        /* check for a JSON handling support */
+        JSON = {
+            parse:
+                window.JSON && (window.JSON.parse || window.JSON.decode) ||
+                String.prototype.evalJSON && function(str){return String(str).evalJSON();} ||
+                $.parseJSON ||
+                $.evalJSON,
+            stringify:
+                Object.toJSON ||
+                window.JSON && (window.JSON.stringify || window.JSON.encode) ||
+                $.toJSON
+        };
+
+    // Break if no JSON support was found
+    if(!("parse" in JSON) || !("stringify" in JSON)){
+        throw new Error("No JSON support found, include //cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js to page");
+    }
+
+    var
+        /* This is the object, that holds the cached values */
+        _storage = {__jstorage_meta:{CRC32:{}}},
+
+        /* Actual browser storage (localStorage or globalStorage["domain"]) */
+        _storage_service = {jStorage:"{}"},
+
+        /* DOM element for older IE versions, holds userData behavior */
+        _storage_elm = null,
+
+        /* How much space does the storage take */
+        _storage_size = 0,
+
+        /* which backend is currently used */
+        _backend = false,
+
+        /* onchange observers */
+        _observers = {},
+
+        /* timeout to wait after onchange event */
+        _observer_timeout = false,
+
+        /* last update time */
+        _observer_update = 0,
+
+        /* pubsub observers */
+        _pubsub_observers = {},
+
+        /* skip published items older than current timestamp */
+        _pubsub_last = +new Date(),
+
+        /* Next check for TTL */
+        _ttl_timeout,
+
+        /**
+         * XML encoding and decoding as XML nodes can't be JSON'ized
+         * XML nodes are encoded and decoded if the node is the value to be saved
+         * but not if it's as a property of another object
+         * Eg. -
+         *   $.jStorage.set("key", xmlNode);        // IS OK
+         *   $.jStorage.set("key", {xml: xmlNode}); // NOT OK
+         */
+        _XMLService = {
+
+            /**
+             * Validates a XML node to be XML
+             * based on jQuery.isXML function
+             */
+            isXML: function(elm){
+                var documentElement = (elm ? elm.ownerDocument || elm : 0).documentElement;
+                return documentElement ? documentElement.nodeName !== "HTML" : false;
+            },
+
+            /**
+             * Encodes a XML node to string
+             * based on http://www.mercurytide.co.uk/news/article/issues-when-working-ajax/
+             */
+            encode: function(xmlNode) {
+                if(!this.isXML(xmlNode)){
+                    return false;
+                }
+                try{ // Mozilla, Webkit, Opera
+                    return new XMLSerializer().serializeToString(xmlNode);
+                }catch(E1) {
+                    try {  // IE
+                        return xmlNode.xml;
+                    }catch(E2){}
+                }
+                return false;
+            },
+
+            /**
+             * Decodes a XML node from string
+             * loosely based on http://outwestmedia.com/jquery-plugins/xmldom/
+             */
+            decode: function(xmlString){
+                var dom_parser = ("DOMParser" in window && (new DOMParser()).parseFromString) ||
+                        (window.ActiveXObject && function(_xmlString) {
+                    var xml_doc = new ActiveXObject("Microsoft.XMLDOM");
+                    xml_doc.async = "false";
+                    xml_doc.loadXML(_xmlString);
+                    return xml_doc;
+                }),
+                resultXML;
+                if(!dom_parser){
+                    return false;
+                }
+                resultXML = dom_parser.call("DOMParser" in window && (new DOMParser()) || window, xmlString, "text/xml");
+                return this.isXML(resultXML)?resultXML:false;
+            }
+        };
+
+
+    ////////////////////////// PRIVATE METHODS ////////////////////////
+
+    /**
+     * Initialization function. Detects if the browser supports DOM Storage
+     * or userData behavior and behaves accordingly.
+     */
+    function _init(){
+        /* Check if browser supports localStorage */
+        var localStorageReallyWorks = false;
+        if("localStorage" in window){
+            try {
+                window.localStorage.setItem("_tmptest", "tmpval");
+                localStorageReallyWorks = true;
+                window.localStorage.removeItem("_tmptest");
+            } catch(BogusQuotaExceededErrorOnIos5) {
+                // Thanks be to iOS5 Private Browsing mode which throws
+                // QUOTA_EXCEEDED_ERRROR DOM Exception 22.
+            }
+        }
+
+        if(localStorageReallyWorks){
+            try {
+                if(window.localStorage) {
+                    _storage_service = window.localStorage;
+                    _backend = "localStorage";
+                    _observer_update = _storage_service.jStorage_update;
+                }
+            } catch(E3) {/* Firefox fails when touching localStorage and cookies are disabled */}
+        }
+        /* Check if browser supports globalStorage */
+        else if("globalStorage" in window){
+            try {
+                if(window.globalStorage) {
+                    if(window.location.hostname == "localhost"){
+                        _storage_service = window.globalStorage["localhost.localdomain"];
+                    }
+                    else{
+                        _storage_service = window.globalStorage[window.location.hostname];
+                    }
+                    _backend = "globalStorage";
+                    _observer_update = _storage_service.jStorage_update;
+                }
+            } catch(E4) {/* Firefox fails when touching localStorage and cookies are disabled */}
+        }
+        /* Check if browser supports userData behavior */
+        else {
+            _storage_elm = document.createElement("link");
+            if(_storage_elm.addBehavior){
+
+                /* Use a DOM element to act as userData storage */
+                _storage_elm.style.behavior = "url(#default#userData)";
+
+                /* userData element needs to be inserted into the DOM! */
+                document.getElementsByTagName("head")[0].appendChild(_storage_elm);
+
+                try{
+                    _storage_elm.load("jStorage");
+                }catch(E){
+                    // try to reset cache
+                    _storage_elm.setAttribute("jStorage", "{}");
+                    _storage_elm.save("jStorage");
+                    _storage_elm.load("jStorage");
+                }
+
+                var data = "{}";
+                try{
+                    data = _storage_elm.getAttribute("jStorage");
+                }catch(E5){}
+
+                try{
+                    _observer_update = _storage_elm.getAttribute("jStorage_update");
+                }catch(E6){}
+
+                _storage_service.jStorage = data;
+                _backend = "userDataBehavior";
+            }else{
+                _storage_elm = null;
+                return;
+            }
+        }
+
+        // Load data from storage
+        _load_storage();
+
+        // remove dead keys
+        _handleTTL();
+
+        // start listening for changes
+        _setupObserver();
+
+        // initialize publish-subscribe service
+        _handlePubSub();
+
+        // handle cached navigation
+        if("addEventListener" in window){
+            window.addEventListener("pageshow", function(event){
+                if(event.persisted){
+                    _storageObserver();
+                }
+            }, false);
+        }
+    }
+
+    /**
+     * Reload data from storage when needed
+     */
+    function _reloadData(){
+        var data = "{}";
+
+        if(_backend == "userDataBehavior"){
+            _storage_elm.load("jStorage");
+
+            try{
+                data = _storage_elm.getAttribute("jStorage");
+            }catch(E5){}
+
+            try{
+                _observer_update = _storage_elm.getAttribute("jStorage_update");
+            }catch(E6){}
+
+            _storage_service.jStorage = data;
+        }
+
+        _load_storage();
+
+        // remove dead keys
+        _handleTTL();
+
+        _handlePubSub();
+    }
+
+    /**
+     * Sets up a storage change observer
+     */
+    function _setupObserver(){
+        if(_backend == "localStorage" || _backend == "globalStorage"){
+            if("addEventListener" in window){
+                window.addEventListener("storage", _storageObserver, false);
+            }else{
+                document.attachEvent("onstorage", _storageObserver);
+            }
+        }else if(_backend == "userDataBehavior"){
+            setInterval(_storageObserver, 1000);
+        }
+    }
+
+    /**
+     * Fired on any kind of data change, needs to check if anything has
+     * really been changed
+     */
+    function _storageObserver(){
+        var updateTime;
+        // cumulate change notifications with timeout
+        clearTimeout(_observer_timeout);
+        _observer_timeout = setTimeout(function(){
+
+            if(_backend == "localStorage" || _backend == "globalStorage"){
+                updateTime = _storage_service.jStorage_update;
+            }else if(_backend == "userDataBehavior"){
+                _storage_elm.load("jStorage");
+                try{
+                    updateTime = _storage_elm.getAttribute("jStorage_update");
+                }catch(E5){}
+            }
+
+            if(updateTime && updateTime != _observer_update){
+                _observer_update = updateTime;
+                _checkUpdatedKeys();
+            }
+
+        }, 25);
+    }
+
+    /**
+     * Reloads the data and checks if any keys are changed
+     */
+    function _checkUpdatedKeys(){
+        var oldCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)),
+            newCrc32List;
+
+        _reloadData();
+        newCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32));
+
+        var key,
+            updated = [],
+            removed = [];
+
+        for(key in oldCrc32List){
+            if(oldCrc32List.hasOwnProperty(key)){
+                if(!newCrc32List[key]){
+                    removed.push(key);
+                    continue;
+                }
+                if(oldCrc32List[key] != newCrc32List[key] && String(oldCrc32List[key]).substr(0,2) == "2."){
+                    updated.push(key);
+                }
+            }
+        }
+
+        for(key in newCrc32List){
+            if(newCrc32List.hasOwnProperty(key)){
+                if(!oldCrc32List[key]){
+                    updated.push(key);
+                }
+            }
+        }
+
+        _fireObservers(updated, "updated");
+        _fireObservers(removed, "deleted");
+    }
+
+    /**
+     * Fires observers for updated keys
+     *
+     * @param {Array|String} keys Array of key names or a key
+     * @param {String} action What happened with the value (updated, deleted, flushed)
+     */
+    function _fireObservers(keys, action){
+        keys = [].concat(keys || []);
+        if(action == "flushed"){
+            keys = [];
+            for(var key in _observers){
+                if(_observers.hasOwnProperty(key)){
+                    keys.push(key);
+                }
+            }
+            action = "deleted";
+        }
+        for(var i=0, len = keys.length; i<len; i++){
+            if(_observers[keys[i]]){
+                for(var j=0, jlen = _observers[keys[i]].length; j<jlen; j++){
+                    _observers[keys[i]][j](keys[i], action);
+                }
+            }
+            if(_observers["*"]){
+                for(var j=0, jlen = _observers["*"].length; j<jlen; j++){
+                    _observers["*"][j](keys[i], action);
+                }
+            }
+        }
+    }
+
+    /**
+     * Publishes key change to listeners
+     */
+    function _publishChange(){
+        var updateTime = (+new Date()).toString();
+
+        if(_backend == "localStorage" || _backend == "globalStorage"){
+            try {
+                _storage_service.jStorage_update = updateTime;
+            } catch (E8) {
+                // safari private mode has been enabled after the jStorage initialization
+                _backend = false;
+            }
+        }else if(_backend == "userDataBehavior"){
+            _storage_elm.setAttribute("jStorage_update", updateTime);
+            _storage_elm.save("jStorage");
+        }
+
+        _storageObserver();
+    }
+
+    /**
+     * Loads the data from the storage based on the supported mechanism
+     */
+    function _load_storage(){
+        /* if jStorage string is retrieved, then decode it */
+        if(_storage_service.jStorage){
+            try{
+                _storage = JSON.parse(String(_storage_service.jStorage));
+            }catch(E6){_storage_service.jStorage = "{}";}
+        }else{
+            _storage_service.jStorage = "{}";
+        }
+        _storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0;
+
+        if(!_storage.__jstorage_meta){
+            _storage.__jstorage_meta = {};
+        }
+        if(!_storage.__jstorage_meta.CRC32){
+            _storage.__jstorage_meta.CRC32 = {};
+        }
+    }
+
+    /**
+     * This functions provides the "save" mechanism to store the jStorage object
+     */
+    function _save(){
+        _dropOldEvents(); // remove expired events
+        try{
+            _storage_service.jStorage = JSON.stringify(_storage);
+            // If userData is used as the storage engine, additional
+            if(_storage_elm) {
+                _storage_elm.setAttribute("jStorage",_storage_service.jStorage);
+                _storage_elm.save("jStorage");
+            }
+            _storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0;
+        }catch(E7){/* probably cache is full, nothing is saved this way*/}
+    }
+
+    /**
+     * Function checks if a key is set and is string or numberic
+     *
+     * @param {String} key Key name
+     */
+    function _checkKey(key){
+        if(typeof key != "string" && typeof key != "number"){
+            throw new TypeError("Key name must be string or numeric");
+        }
+        if(key == "__jstorage_meta"){
+            throw new TypeError("Reserved key name");
+        }
+        return true;
+    }
+
+    /**
+     * Removes expired keys
+     */
+    function _handleTTL(){
+        var curtime, i, TTL, CRC32, nextExpire = Infinity, changed = false, deleted = [];
+
+        clearTimeout(_ttl_timeout);
+
+        if(!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL != "object"){
+            // nothing to do here
+            return;
+        }
+
+        curtime = +new Date();
+        TTL = _storage.__jstorage_meta.TTL;
+
+        CRC32 = _storage.__jstorage_meta.CRC32;
+        for(i in TTL){
+            if(TTL.hasOwnProperty(i)){
+                if(TTL[i] <= curtime){
+                    delete TTL[i];
+                    delete CRC32[i];
+                    delete _storage[i];
+                    changed = true;
+                    deleted.push(i);
+                }else if(TTL[i] < nextExpire){
+                    nextExpire = TTL[i];
+                }
+            }
+        }
+
+        // set next check
+        if(nextExpire != Infinity){
+            _ttl_timeout = setTimeout(_handleTTL, nextExpire - curtime);
+        }
+
+        // save changes
+        if(changed){
+            _save();
+            _publishChange();
+            _fireObservers(deleted, "deleted");
+        }
+    }
+
+    /**
+     * Checks if there's any events on hold to be fired to listeners
+     */
+    function _handlePubSub(){
+        var i, len;
+        if(!_storage.__jstorage_meta.PubSub){
+            return;
+        }
+        var pubelm,
+            _pubsubCurrent = _pubsub_last;
+
+        for(i=len=_storage.__jstorage_meta.PubSub.length-1; i>=0; i--){
+            pubelm = _storage.__jstorage_meta.PubSub[i];
+            if(pubelm[0] > _pubsub_last){
+                _pubsubCurrent = pubelm[0];
+                _fireSubscribers(pubelm[1], pubelm[2]);
+            }
+        }
+
+        _pubsub_last = _pubsubCurrent;
+    }
+
+    /**
+     * Fires all subscriber listeners for a pubsub channel
+     *
+     * @param {String} channel Channel name
+     * @param {Mixed} payload Payload data to deliver
+     */
+    function _fireSubscribers(channel, payload){
+        if(_pubsub_observers[channel]){
+            for(var i=0, len = _pubsub_observers[channel].length; i<len; i++){
+                // send immutable data that can't be modified by listeners
+                try{
+                    _pubsub_observers[channel][i](channel, JSON.parse(JSON.stringify(payload)));
+                }catch(E){};
+            }
+        }
+    }
+
+    /**
+     * Remove old events from the publish stream (at least 2sec old)
+     */
+    function _dropOldEvents(){
+        if(!_storage.__jstorage_meta.PubSub){
+            return;
+        }
+
+        var retire = +new Date() - 2000;
+
+        for(var i=0, len = _storage.__jstorage_meta.PubSub.length; i<len; i++){
+            if(_storage.__jstorage_meta.PubSub[i][0] <= retire){
+                // deleteCount is needed for IE6
+                _storage.__jstorage_meta.PubSub.splice(i, _storage.__jstorage_meta.PubSub.length - i);
+                break;
+            }
+        }
+
+        if(!_storage.__jstorage_meta.PubSub.length){
+            delete _storage.__jstorage_meta.PubSub;
+        }
+
+    }
+
+    /**
+     * Publish payload to a channel
+     *
+     * @param {String} channel Channel name
+     * @param {Mixed} payload Payload to send to the subscribers
+     */
+    function _publish(channel, payload){
+        if(!_storage.__jstorage_meta){
+            _storage.__jstorage_meta = {};
+        }
+        if(!_storage.__jstorage_meta.PubSub){
+            _storage.__jstorage_meta.PubSub = [];
+        }
+
+        _storage.__jstorage_meta.PubSub.unshift([+new Date, channel, payload]);
+
+        _save();
+        _publishChange();
+    }
+
+
+    /**
+     * JS Implementation of MurmurHash2
+     *
+     *  SOURCE: https://github.com/garycourt/murmurhash-js (MIT licensed)
+     *
+     * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
+     * @see http://github.com/garycourt/murmurhash-js
+     * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
+     * @see http://sites.google.com/site/murmurhash/
+     *
+     * @param {string} str ASCII only
+     * @param {number} seed Positive integer only
+     * @return {number} 32-bit positive integer hash
+     */
+
+    function murmurhash2_32_gc(str, seed) {
+        var
+            l = str.length,
+            h = seed ^ l,
+            i = 0,
+            k;
+
+        while (l >= 4) {
+            k =
+                ((str.charCodeAt(i) & 0xff)) |
+                ((str.charCodeAt(++i) & 0xff) << 8) |
+                ((str.charCodeAt(++i) & 0xff) << 16) |
+                ((str.charCodeAt(++i) & 0xff) << 24);
+
+            k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
+            k ^= k >>> 24;
+            k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
+
+            h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
+
+            l -= 4;
+            ++i;
+        }
+
+        switch (l) {
+            case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
+            case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
+            case 1: h ^= (str.charCodeAt(i) & 0xff);
+                h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
+        }
+
+        h ^= h >>> 13;
+        h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
+        h ^= h >>> 15;
+
+        return h >>> 0;
+    }
+
+    ////////////////////////// PUBLIC INTERFACE /////////////////////////
+
+    $.jStorage = {
+        /* Version number */
+        version: JSTORAGE_VERSION,
+
+        /**
+         * Sets a key's value.
+         *
+         * @param {String} key Key to set. If this value is not set or not
+         *              a string an exception is raised.
+         * @param {Mixed} value Value to set. This can be any value that is JSON
+         *              compatible (Numbers, Strings, Objects etc.).
+         * @param {Object} [options] - possible options to use
+         * @param {Number} [options.TTL] - optional TTL value
+         * @return {Mixed} the used value
+         */
+        set: function(key, value, options){
+            _checkKey(key);
+
+            options = options || {};
+
+            // undefined values are deleted automatically
+            if(typeof value == "undefined"){
+                this.deleteKey(key);
+                return value;
+            }
+
+            if(_XMLService.isXML(value)){
+                value = {_is_xml:true,xml:_XMLService.encode(value)};
+            }else if(typeof value == "function"){
+                return undefined; // functions can't be saved!
+            }else if(value && typeof value == "object"){
+                // clone the object before saving to _storage tree
+                value = JSON.parse(JSON.stringify(value));
+            }
+
+            _storage[key] = value;
+
+            _storage.__jstorage_meta.CRC32[key] = "2." + murmurhash2_32_gc(JSON.stringify(value), 0x9747b28c);
+
+            this.setTTL(key, options.TTL || 0); // also handles saving and _publishChange
+
+            _fireObservers(key, "updated");
+            return value;
+        },
+
+        /**
+         * Looks up a key in cache
+         *
+         * @param {String} key - Key to look up.
+         * @param {mixed} def - Default value to return, if key didn't exist.
+         * @return {Mixed} the key value, default value or null
+         */
+        get: function(key, def){
+            _checkKey(key);
+            if(key in _storage){
+                if(_storage[key] && typeof _storage[key] == "object" && _storage[key]._is_xml) {
+                    return _XMLService.decode(_storage[key].xml);
+                }else{
+                    return _storage[key];
+                }
+            }
+            return typeof(def) == "undefined" ? null : def;
+        },
+
+        /**
+         * Deletes a key from cache.
+         *
+         * @param {String} key - Key to delete.
+         * @return {Boolean} true if key existed or false if it didn't
+         */
+        deleteKey: function(key){
+            _checkKey(key);
+            if(key in _storage){
+                delete _storage[key];
+                // remove from TTL list
+                if(typeof _storage.__jstorage_meta.TTL == "object" &&
+                  key in _storage.__jstorage_meta.TTL){
+                    delete _storage.__jstorage_meta.TTL[key];
+                }
+
+                delete _storage.__jstorage_meta.CRC32[key];
+
+                _save();
+                _publishChange();
+                _fireObservers(key, "deleted");
+                return true;
+            }
+            return false;
+        },
+
+        /**
+         * Sets a TTL for a key, or remove it if ttl value is 0 or below
+         *
+         * @param {String} key - key to set the TTL for
+         * @param {Number} ttl - TTL timeout in milliseconds
+         * @return {Boolean} true if key existed or false if it didn't
+         */
+        setTTL: function(key, ttl){
+            var curtime = +new Date();
+            _checkKey(key);
+            ttl = Number(ttl) || 0;
+            if(key in _storage){
+
+                if(!_storage.__jstorage_meta.TTL){
+                    _storage.__jstorage_meta.TTL = {};
+                }
+
+                // Set TTL value for the key
+                if(ttl>0){
+                    _storage.__jstorage_meta.TTL[key] = curtime + ttl;
+                }else{
+                    delete _storage.__jstorage_meta.TTL[key];
+                }
+
+                _save();
+
+                _handleTTL();
+
+                _publishChange();
+                return true;
+            }
+            return false;
+        },
+
+        /**
+         * Gets remaining TTL (in milliseconds) for a key or 0 when no TTL has been set
+         *
+         * @param {String} key Key to check
+         * @return {Number} Remaining TTL in milliseconds
+         */
+        getTTL: function(key){
+            var curtime = +new Date(), ttl;
+            _checkKey(key);
+            if(key in _storage && _storage.__jstorage_meta.TTL && _storage.__jstorage_meta.TTL[key]){
+                ttl = _storage.__jstorage_meta.TTL[key] - curtime;
+                return ttl || 0;
+            }
+            return 0;
+        },
+
+        /**
+         * Deletes everything in cache.
+         *
+         * @return {Boolean} Always true
+         */
+        flush: function(){
+            _storage = {__jstorage_meta:{CRC32:{}}};
+            _save();
+            _publishChange();
+            _fireObservers(null, "flushed");
+            return true;
+        },
+
+        /**
+         * Returns a read-only copy of _storage
+         *
+         * @return {Object} Read-only copy of _storage
+        */
+        storageObj: function(){
+            function F() {}
+            F.prototype = _storage;
+            return new F();
+        },
+
+        /**
+         * Returns an index of all used keys as an array
+         * ["key1", "key2",.."keyN"]
+         *
+         * @return {Array} Used keys
+        */
+        index: function(){
+            var index = [], i;
+            for(i in _storage){
+                if(_storage.hasOwnProperty(i) && i != "__jstorage_meta"){
+                    index.push(i);
+                }
+            }
+            return index;
+        },
+
+        /**
+         * How much space in bytes does the storage take?
+         *
+         * @return {Number} Storage size in chars (not the same as in bytes,
+         *                  since some chars may take several bytes)
+         */
+        storageSize: function(){
+            return _storage_size;
+        },
+
+        /**
+         * Which backend is currently in use?
+         *
+         * @return {String} Backend name
+         */
+        currentBackend: function(){
+            return _backend;
+        },
+
+        /**
+         * Test if storage is available
+         *
+         * @return {Boolean} True if storage can be used
+         */
+        storageAvailable: function(){
+            return !!_backend;
+        },
+
+        /**
+         * Register change listeners
+         *
+         * @param {String} key Key name
+         * @param {Function} callback Function to run when the key changes
+         */
+        listenKeyChange: function(key, callback){
+            _checkKey(key);
+            if(!_observers[key]){
+                _observers[key] = [];
+            }
+            _observers[key].push(callback);
+        },
+
+        /**
+         * Remove change listeners
+         *
+         * @param {String} key Key name to unregister listeners against
+         * @param {Function} [callback] If set, unregister the callback, if not - unregister all
+         */
+        stopListening: function(key, callback){
+            _checkKey(key);
+
+            if(!_observers[key]){
+                return;
+            }
+
+            if(!callback){
+                delete _observers[key];
+                return;
+            }
+
+            for(var i = _observers[key].length - 1; i>=0; i--){
+                if(_observers[key][i] == callback){
+                    _observers[key].splice(i,1);
+                }
+            }
+        },
+
+        /**
+         * Subscribe to a Publish/Subscribe event stream
+         *
+         * @param {String} channel Channel name
+         * @param {Function} callback Function to run when the something is published to the channel
+         */
+        subscribe: function(channel, callback){
+            channel = (channel || "").toString();
+            if(!channel){
+                throw new TypeError("Channel not defined");
+            }
+            if(!_pubsub_observers[channel]){
+                _pubsub_observers[channel] = [];
+            }
+            _pubsub_observers[channel].push(callback);
+        },
+
+        /**
+         * Publish data to an event stream
+         *
+         * @param {String} channel Channel name
+         * @param {Mixed} payload Payload to deliver
+         */
+        publish: function(channel, payload){
+            channel = (channel || "").toString();
+            if(!channel){
+                throw new TypeError("Channel not defined");
+            }
+
+            _publish(channel, payload);
+        },
+
+        /**
+         * Reloads the data from browser storage
+         */
+        reInit: function(){
+            _reloadData();
+        },
+
+        /**
+         * Removes reference from global objects and saves it as jStorage
+         *
+         * @param {Boolean} option if needed to save object as simple "jStorage" in windows context
+         */
+         noConflict: function( saveInGlobal ) {
+            delete window.$.jStorage
+
+            if ( saveInGlobal ) {
+                window.jStorage = this;
+            }
+
+            return this;
+         }
+    };
+
+    // Initialize jStorage
+    _init();
+
+})();
diff --git a/resources/lib/jquery/jquery.js b/resources/lib/jquery/jquery.js
new file mode 100644 (file)
index 0000000..a86bf79
--- /dev/null
@@ -0,0 +1,9472 @@
+/*!
+ * jQuery JavaScript Library v1.8.3
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: Tue Nov 13 2012 08:20:33 GMT-0500 (Eastern Standard Time)
+ */
+(function( window, undefined ) {
+var
+       // A central reference to the root jQuery(document)
+       rootjQuery,
+
+       // The deferred used on DOM ready
+       readyList,
+
+       // Use the correct document accordingly with window argument (sandbox)
+       document = window.document,
+       location = window.location,
+       navigator = window.navigator,
+
+       // Map over jQuery in case of overwrite
+       _jQuery = window.jQuery,
+
+       // Map over the $ in case of overwrite
+       _$ = window.$,
+
+       // Save a reference to some core methods
+       core_push = Array.prototype.push,
+       core_slice = Array.prototype.slice,
+       core_indexOf = Array.prototype.indexOf,
+       core_toString = Object.prototype.toString,
+       core_hasOwn = Object.prototype.hasOwnProperty,
+       core_trim = String.prototype.trim,
+
+       // Define a local copy of jQuery
+       jQuery = function( selector, context ) {
+               // The jQuery object is actually just the init constructor 'enhanced'
+               return new jQuery.fn.init( selector, context, rootjQuery );
+       },
+
+       // Used for matching numbers
+       core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,
+
+       // Used for detecting and trimming whitespace
+       core_rnotwhite = /\S/,
+       core_rspace = /\s+/,
+
+       // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
+       rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+       // A simple way to check for HTML strings
+       // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+       rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
+
+       // Match a standalone tag
+       rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
+
+       // JSON RegExp
+       rvalidchars = /^[\],:{}\s]*$/,
+       rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+       rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
+       rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,
+
+       // Matches dashed string for camelizing
+       rmsPrefix = /^-ms-/,
+       rdashAlpha = /-([\da-z])/gi,
+
+       // Used by jQuery.camelCase as callback to replace()
+       fcamelCase = function( all, letter ) {
+               return ( letter + "" ).toUpperCase();
+       },
+
+       // The ready event handler and self cleanup method
+       DOMContentLoaded = function() {
+               if ( document.addEventListener ) {
+                       document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+                       jQuery.ready();
+               } else if ( document.readyState === "complete" ) {
+                       // we're here because readyState === "complete" in oldIE
+                       // which is good enough for us to call the dom ready!
+                       document.detachEvent( "onreadystatechange", DOMContentLoaded );
+                       jQuery.ready();
+               }
+       },
+
+       // [[Class]] -> type pairs
+       class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+       constructor: jQuery,
+       init: function( selector, context, rootjQuery ) {
+               var match, elem, ret, doc;
+
+               // Handle $(""), $(null), $(undefined), $(false)
+               if ( !selector ) {
+                       return this;
+               }
+
+               // Handle $(DOMElement)
+               if ( selector.nodeType ) {
+                       this.context = this[0] = selector;
+                       this.length = 1;
+                       return this;
+               }
+
+               // Handle HTML strings
+               if ( typeof selector === "string" ) {
+                       if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+                               // Assume that strings that start and end with <> are HTML and skip the regex check
+                               match = [ null, selector, null ];
+
+                       } else {
+                               match = rquickExpr.exec( selector );
+                       }
+
+                       // Match html or make sure no context is specified for #id
+                       if ( match && (match[1] || !context) ) {
+
+                               // HANDLE: $(html) -> $(array)
+                               if ( match[1] ) {
+                                       context = context instanceof jQuery ? context[0] : context;
+                                       doc = ( context && context.nodeType ? context.ownerDocument || context : document );
+
+                                       // scripts is true for back-compat
+                                       selector = jQuery.parseHTML( match[1], doc, true );
+                                       if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+                                               this.attr.call( selector, context, true );
+                                       }
+
+                                       return jQuery.merge( this, selector );
+
+                               // HANDLE: $(#id)
+                               } else {
+                                       elem = document.getElementById( match[2] );
+
+                                       // Check parentNode to catch when Blackberry 4.6 returns
+                                       // nodes that are no longer in the document #6963
+                                       if ( elem && elem.parentNode ) {
+                                               // Handle the case where IE and Opera return items
+                                               // by name instead of ID
+                                               if ( elem.id !== match[2] ) {
+                                                       return rootjQuery.find( selector );
+                                               }
+
+                                               // Otherwise, we inject the element directly into the jQuery object
+                                               this.length = 1;
+                                               this[0] = elem;
+                                       }
+
+                                       this.context = document;
+                                       this.selector = selector;
+                                       return this;
+                               }
+
+                       // HANDLE: $(expr, $(...))
+                       } else if ( !context || context.jquery ) {
+                               return ( context || rootjQuery ).find( selector );
+
+                       // HANDLE: $(expr, context)
+                       // (which is just equivalent to: $(context).find(expr)
+                       } else {
+                               return this.constructor( context ).find( selector );
+                       }
+
+               // HANDLE: $(function)
+               // Shortcut for document ready
+               } else if ( jQuery.isFunction( selector ) ) {
+                       return rootjQuery.ready( selector );
+               }
+
+               if ( selector.selector !== undefined ) {
+                       this.selector = selector.selector;
+                       this.context = selector.context;
+               }
+
+               return jQuery.makeArray( selector, this );
+       },
+
+       // Start with an empty selector
+       selector: "",
+
+       // The current version of jQuery being used
+       jquery: "1.8.3",
+
+       // The default length of a jQuery object is 0
+       length: 0,
+
+       // The number of elements contained in the matched element set
+       size: function() {
+               return this.length;
+       },
+
+       toArray: function() {
+               return core_slice.call( this );
+       },
+
+       // Get the Nth element in the matched element set OR
+       // Get the whole matched element set as a clean array
+       get: function( num ) {
+               return num == null ?
+
+                       // Return a 'clean' array
+                       this.toArray() :
+
+                       // Return just the object
+                       ( num < 0 ? this[ this.length + num ] : this[ num ] );
+       },
+
+       // Take an array of elements and push it onto the stack
+       // (returning the new matched element set)
+       pushStack: function( elems, name, selector ) {
+
+               // Build a new jQuery matched element set
+               var ret = jQuery.merge( this.constructor(), elems );
+
+               // Add the old object onto the stack (as a reference)
+               ret.prevObject = this;
+
+               ret.context = this.context;
+
+               if ( name === "find" ) {
+                       ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
+               } else if ( name ) {
+                       ret.selector = this.selector + "." + name + "(" + selector + ")";
+               }
+
+               // Return the newly-formed element set
+               return ret;
+       },
+
+       // Execute a callback for every element in the matched set.
+       // (You can seed the arguments with an array of args, but this is
+       // only used internally.)
+       each: function( callback, args ) {
+               return jQuery.each( this, callback, args );
+       },
+
+       ready: function( fn ) {
+               // Add the callback
+               jQuery.ready.promise().done( fn );
+
+               return this;
+       },
+
+       eq: function( i ) {
+               i = +i;
+               return i === -1 ?
+                       this.slice( i ) :
+                       this.slice( i, i + 1 );
+       },
+
+       first: function() {
+               return this.eq( 0 );
+       },
+
+       last: function() {
+               return this.eq( -1 );
+       },
+
+       slice: function() {
+               return this.pushStack( core_slice.apply( this, arguments ),
+                       "slice", core_slice.call(arguments).join(",") );
+       },
+
+       map: function( callback ) {
+               return this.pushStack( jQuery.map(this, function( elem, i ) {
+                       return callback.call( elem, i, elem );
+               }));
+       },
+
+       end: function() {
+               return this.prevObject || this.constructor(null);
+       },
+
+       // For internal use only.
+       // Behaves like an Array's method, not like a jQuery method.
+       push: core_push,
+       sort: [].sort,
+       splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+       var options, name, src, copy, copyIsArray, clone,
+               target = arguments[0] || {},
+               i = 1,
+               length = arguments.length,
+               deep = false;
+
+       // Handle a deep copy situation
+       if ( typeof target === "boolean" ) {
+               deep = target;
+               target = arguments[1] || {};
+               // skip the boolean and the target
+               i = 2;
+       }
+
+       // Handle case when target is a string or something (possible in deep copy)
+       if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+               target = {};
+       }
+
+       // extend jQuery itself if only one argument is passed
+       if ( length === i ) {
+               target = this;
+               --i;
+       }
+
+       for ( ; i < length; i++ ) {
+               // Only deal with non-null/undefined values
+               if ( (options = arguments[ i ]) != null ) {
+                       // Extend the base object
+                       for ( name in options ) {
+                               src = target[ name ];
+                               copy = options[ name ];
+
+                               // Prevent never-ending loop
+                               if ( target === copy ) {
+                                       continue;
+                               }
+
+                               // Recurse if we're merging plain objects or arrays
+                               if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+                                       if ( copyIsArray ) {
+                                               copyIsArray = false;
+                                               clone = src && jQuery.isArray(src) ? src : [];
+
+                                       } else {
+                                               clone = src && jQuery.isPlainObject(src) ? src : {};
+                                       }
+
+                                       // Never move original objects, clone them
+                                       target[ name ] = jQuery.extend( deep, clone, copy );
+
+                               // Don't bring in undefined values
+                               } else if ( copy !== undefined ) {
+                                       target[ name ] = copy;
+                               }
+                       }
+               }
+       }
+
+       // Return the modified object
+       return target;
+};
+
+jQuery.extend({
+       noConflict: function( deep ) {
+               if ( window.$ === jQuery ) {
+                       window.$ = _$;
+               }
+
+               if ( deep && window.jQuery === jQuery ) {
+                       window.jQuery = _jQuery;
+               }
+
+               return jQuery;
+       },
+
+       // Is the DOM ready to be used? Set to true once it occurs.
+       isReady: false,
+
+       // A counter to track how many items to wait for before
+       // the ready event fires. See #6781
+       readyWait: 1,
+
+       // Hold (or release) the ready event
+       holdReady: function( hold ) {
+               if ( hold ) {
+                       jQuery.readyWait++;
+               } else {
+                       jQuery.ready( true );
+               }
+       },
+
+       // Handle when the DOM is ready
+       ready: function( wait ) {
+
+               // Abort if there are pending holds or we're already ready
+               if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+                       return;
+               }
+
+               // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+               if ( !document.body ) {
+                       return setTimeout( jQuery.ready, 1 );
+               }
+
+               // Remember that the DOM is ready
+               jQuery.isReady = true;
+
+               // If a normal DOM Ready event fired, decrement, and wait if need be
+               if ( wait !== true && --jQuery.readyWait > 0 ) {
+                       return;
+               }
+
+               // If there are functions bound, to execute
+               readyList.resolveWith( document, [ jQuery ] );
+
+               // Trigger any bound ready events
+               if ( jQuery.fn.trigger ) {
+                       jQuery( document ).trigger("ready").off("ready");
+               }
+       },
+
+       // See test/unit/core.js for details concerning isFunction.
+       // Since version 1.3, DOM methods and functions like alert
+       // aren't supported. They return false on IE (#2968).
+       isFunction: function( obj ) {
+               return jQuery.type(obj) === "function";
+       },
+
+       isArray: Array.isArray || function( obj ) {
+               return jQuery.type(obj) === "array";
+       },
+
+       isWindow: function( obj ) {
+               return obj != null && obj == obj.window;
+       },
+
+       isNumeric: function( obj ) {
+               return !isNaN( parseFloat(obj) ) && isFinite( obj );
+       },
+
+       type: function( obj ) {
+               return obj == null ?
+                       String( obj ) :
+                       class2type[ core_toString.call(obj) ] || "object";
+       },
+
+       isPlainObject: function( obj ) {
+               // Must be an Object.
+               // Because of IE, we also have to check the presence of the constructor property.
+               // Make sure that DOM nodes and window objects don't pass through, as well
+               if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+                       return false;
+               }
+
+               try {
+                       // Not own constructor property must be Object
+                       if ( obj.constructor &&
+                               !core_hasOwn.call(obj, "constructor") &&
+                               !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+                               return false;
+                       }
+               } catch ( e ) {
+                       // IE8,9 Will throw exceptions on certain host objects #9897
+                       return false;
+               }
+
+               // Own properties are enumerated firstly, so to speed up,
+               // if last one is own, then all properties are own.
+
+               var key;
+               for ( key in obj ) {}
+
+               return key === undefined || core_hasOwn.call( obj, key );
+       },
+
+       isEmptyObject: function( obj ) {
+               var name;
+               for ( name in obj ) {
+                       return false;
+               }
+               return true;
+       },
+
+       error: function( msg ) {
+               throw new Error( msg );
+       },
+
+       // data: string of html
+       // context (optional): If specified, the fragment will be created in this context, defaults to document
+       // scripts (optional): If true, will include scripts passed in the html string
+       parseHTML: function( data, context, scripts ) {
+               var parsed;
+               if ( !data || typeof data !== "string" ) {
+                       return null;
+               }
+               if ( typeof context === "boolean" ) {
+                       scripts = context;
+                       context = 0;
+               }
+               context = context || document;
+
+               // Single tag
+               if ( (parsed = rsingleTag.exec( data )) ) {
+                       return [ context.createElement( parsed[1] ) ];
+               }
+
+               parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );
+               return jQuery.merge( [],
+                       (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );
+       },
+
+       parseJSON: function( data ) {
+               if ( !data || typeof data !== "string") {
+                       return null;
+               }
+
+               // Make sure leading/trailing whitespace is removed (IE can't handle it)
+               data = jQuery.trim( data );
+
+               // Attempt to parse using the native JSON parser first
+               if ( window.JSON && window.JSON.parse ) {
+                       return window.JSON.parse( data );
+               }
+
+               // Make sure the incoming data is actual JSON
+               // Logic borrowed from http://json.org/json2.js
+               if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+                       .replace( rvalidtokens, "]" )
+                       .replace( rvalidbraces, "")) ) {
+
+                       return ( new Function( "return " + data ) )();
+
+               }
+               jQuery.error( "Invalid JSON: " + data );
+       },
+
+       // Cross-browser xml parsing
+       parseXML: function( data ) {
+               var xml, tmp;
+               if ( !data || typeof data !== "string" ) {
+                       return null;
+               }
+               try {
+                       if ( window.DOMParser ) { // Standard
+                               tmp = new DOMParser();
+                               xml = tmp.parseFromString( data , "text/xml" );
+                       } else { // IE
+                               xml = new ActiveXObject( "Microsoft.XMLDOM" );
+                               xml.async = "false";
+                               xml.loadXML( data );
+                       }
+               } catch( e ) {
+                       xml = undefined;
+               }
+               if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+                       jQuery.error( "Invalid XML: " + data );
+               }
+               return xml;
+       },
+
+       noop: function() {},
+
+       // Evaluates a script in a global context
+       // Workarounds based on findings by Jim Driscoll
+       // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+       globalEval: function( data ) {
+               if ( data && core_rnotwhite.test( data ) ) {
+                       // We use execScript on Internet Explorer
+                       // We use an anonymous function so that context is window
+                       // rather than jQuery in Firefox
+                       ( window.execScript || function( data ) {
+                               window[ "eval" ].call( window, data );
+                       } )( data );
+               }
+       },
+
+       // Convert dashed to camelCase; used by the css and data modules
+       // Microsoft forgot to hump their vendor prefix (#9572)
+       camelCase: function( string ) {
+               return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+       },
+
+       nodeName: function( elem, name ) {
+               return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+       },
+
+       // args is for internal usage only
+       each: function( obj, callback, args ) {
+               var name,
+                       i = 0,
+                       length = obj.length,
+                       isObj = length === undefined || jQuery.isFunction( obj );
+
+               if ( args ) {
+                       if ( isObj ) {
+                               for ( name in obj ) {
+                                       if ( callback.apply( obj[ name ], args ) === false ) {
+                                               break;
+                                       }
+                               }
+                       } else {
+                               for ( ; i < length; ) {
+                                       if ( callback.apply( obj[ i++ ], args ) === false ) {
+                                               break;
+                                       }
+                               }
+                       }
+
+               // A special, fast, case for the most common use of each
+               } else {
+                       if ( isObj ) {
+                               for ( name in obj ) {
+                                       if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {
+                                               break;
+                                       }
+                               }
+                       } else {
+                               for ( ; i < length; ) {
+                                       if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               return obj;
+       },
+
+       // Use native String.trim function wherever possible
+       trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
+               function( text ) {
+                       return text == null ?
+                               "" :
+                               core_trim.call( text );
+               } :
+
+               // Otherwise use our own trimming functionality
+               function( text ) {
+                       return text == null ?
+                               "" :
+                               ( text + "" ).replace( rtrim, "" );
+               },
+
+       // results is for internal usage only
+       makeArray: function( arr, results ) {
+               var type,
+                       ret = results || [];
+
+               if ( arr != null ) {
+                       // The window, strings (and functions) also have 'length'
+                       // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+                       type = jQuery.type( arr );
+
+                       if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) {
+                               core_push.call( ret, arr );
+                       } else {
+                               jQuery.merge( ret, arr );
+                       }
+               }
+
+               return ret;
+       },
+
+       inArray: function( elem, arr, i ) {
+               var len;
+
+               if ( arr ) {
+                       if ( core_indexOf ) {
+                               return core_indexOf.call( arr, elem, i );
+                       }
+
+                       len = arr.length;
+                       i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+                       for ( ; i < len; i++ ) {
+                               // Skip accessing in sparse arrays
+                               if ( i in arr && arr[ i ] === elem ) {
+                                       return i;
+                               }
+                       }
+               }
+
+               return -1;
+       },
+
+       merge: function( first, second ) {
+               var l = second.length,
+                       i = first.length,
+                       j = 0;
+
+               if ( typeof l === "number" ) {
+                       for ( ; j < l; j++ ) {
+                               first[ i++ ] = second[ j ];
+                       }
+
+               } else {
+                       while ( second[j] !== undefined ) {
+                               first[ i++ ] = second[ j++ ];
+                       }
+               }
+
+               first.length = i;
+
+               return first;
+       },
+
+       grep: function( elems, callback, inv ) {
+               var retVal,
+                       ret = [],
+                       i = 0,
+                       length = elems.length;
+               inv = !!inv;
+
+               // Go through the array, only saving the items
+               // that pass the validator function
+               for ( ; i < length; i++ ) {
+                       retVal = !!callback( elems[ i ], i );
+                       if ( inv !== retVal ) {
+                               ret.push( elems[ i ] );
+                       }
+               }
+
+               return ret;
+       },
+
+       // arg is for internal usage only
+       map: function( elems, callback, arg ) {
+               var value, key,
+                       ret = [],
+                       i = 0,
+                       length = elems.length,
+                       // jquery objects are treated as arrays
+                       isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+               // Go through the array, translating each of the items to their
+               if ( isArray ) {
+                       for ( ; i < length; i++ ) {
+                               value = callback( elems[ i ], i, arg );
+
+                               if ( value != null ) {
+                                       ret[ ret.length ] = value;
+                               }
+                       }
+
+               // Go through every key on the object,
+               } else {
+                       for ( key in elems ) {
+                               value = callback( elems[ key ], key, arg );
+
+                               if ( value != null ) {
+                                       ret[ ret.length ] = value;
+                               }
+                       }
+               }
+
+               // Flatten any nested arrays
+               return ret.concat.apply( [], ret );
+       },
+
+       // A global GUID counter for objects
+       guid: 1,
+
+       // Bind a function to a context, optionally partially applying any
+       // arguments.
+       proxy: function( fn, context ) {
+               var tmp, args, proxy;
+
+               if ( typeof context === "string" ) {
+                       tmp = fn[ context ];
+                       context = fn;
+                       fn = tmp;
+               }
+
+               // Quick check to determine if target is callable, in the spec
+               // this throws a TypeError, but we will just return undefined.
+               if ( !jQuery.isFunction( fn ) ) {
+                       return undefined;
+               }
+
+               // Simulated bind
+               args = core_slice.call( arguments, 2 );
+               proxy = function() {
+                       return fn.apply( context, args.concat( core_slice.call( arguments ) ) );
+               };
+
+               // Set the guid of unique handler to the same of original handler, so it can be removed
+               proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+               return proxy;
+       },
+
+       // Multifunctional method to get and set values of a collection
+       // The value/s can optionally be executed if it's a function
+       access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
+               var exec,
+                       bulk = key == null,
+                       i = 0,
+                       length = elems.length;
+
+               // Sets many values
+               if ( key && typeof key === "object" ) {
+                       for ( i in key ) {
+                               jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
+                       }
+                       chainable = 1;
+
+               // Sets one value
+               } else if ( value !== undefined ) {
+                       // Optionally, function values get executed if exec is true
+                       exec = pass === undefined && jQuery.isFunction( value );
+
+                       if ( bulk ) {
+                               // Bulk operations only iterate when executing function values
+                               if ( exec ) {
+                                       exec = fn;
+                                       fn = function( elem, key, value ) {
+                                               return exec.call( jQuery( elem ), value );
+                                       };
+
+                               // Otherwise they run against the entire set
+                               } else {
+                                       fn.call( elems, value );
+                                       fn = null;
+                               }
+                       }
+
+                       if ( fn ) {
+                               for (; i < length; i++ ) {
+                                       fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+                               }
+                       }
+
+                       chainable = 1;
+               }
+
+               return chainable ?
+                       elems :
+
+                       // Gets
+                       bulk ?
+                               fn.call( elems ) :
+                               length ? fn( elems[0], key ) : emptyGet;
+       },
+
+       now: function() {
+               return ( new Date() ).getTime();
+       }
+});
+
+jQuery.ready.promise = function( obj ) {
+       if ( !readyList ) {
+
+               readyList = jQuery.Deferred();
+
+               // Catch cases where $(document).ready() is called after the browser event has already occurred.
+               // we once tried to use readyState "interactive" here, but it caused issues like the one
+               // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+               if ( document.readyState === "complete" ) {
+                       // Handle it asynchronously to allow scripts the opportunity to delay ready
+                       setTimeout( jQuery.ready, 1 );
+
+               // Standards-based browsers support DOMContentLoaded
+               } else if ( document.addEventListener ) {
+                       // Use the handy event callback
+                       document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+                       // A fallback to window.onload, that will always work
+                       window.addEventListener( "load", jQuery.ready, false );
+
+               // If IE event model is used
+               } else {
+                       // Ensure firing before onload, maybe late but safe also for iframes
+                       document.attachEvent( "onreadystatechange", DOMContentLoaded );
+
+                       // A fallback to window.onload, that will always work
+                       window.attachEvent( "onload", jQuery.ready );
+
+                       // If IE and not a frame
+                       // continually check to see if the document is ready
+                       var top = false;
+
+                       try {
+                               top = window.frameElement == null && document.documentElement;
+                       } catch(e) {}
+
+                       if ( top && top.doScroll ) {
+                               (function doScrollCheck() {
+                                       if ( !jQuery.isReady ) {
+
+                                               try {
+                                                       // Use the trick by Diego Perini
+                                                       // http://javascript.nwbox.com/IEContentLoaded/
+                                                       top.doScroll("left");
+                                               } catch(e) {
+                                                       return setTimeout( doScrollCheck, 50 );
+                                               }
+
+                                               // and execute any waiting functions
+                                               jQuery.ready();
+                                       }
+                               })();
+                       }
+               }
+       }
+       return readyList.promise( obj );
+};
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+       class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+       var object = optionsCache[ options ] = {};
+       jQuery.each( options.split( core_rspace ), function( _, flag ) {
+               object[ flag ] = true;
+       });
+       return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *     options: an optional list of space-separated options that will change how
+ *                     the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ *     once:                   will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *     memory:                 will keep track of previous values and will call any callback added
+ *                                     after the list has been fired right away with the latest "memorized"
+ *                                     values (like a Deferred)
+ *
+ *     unique:                 will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *     stopOnFalse:    interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+       // Convert options from String-formatted to Object-formatted if needed
+       // (we check in cache first)
+       options = typeof options === "string" ?
+               ( optionsCache[ options ] || createOptions( options ) ) :
+               jQuery.extend( {}, options );
+
+       var // Last fire value (for non-forgettable lists)
+               memory,
+               // Flag to know if list was already fired
+               fired,
+               // Flag to know if list is currently firing
+               firing,
+               // First callback to fire (used internally by add and fireWith)
+               firingStart,
+               // End of the loop when firing
+               firingLength,
+               // Index of currently firing callback (modified by remove if needed)
+               firingIndex,
+               // Actual callback list
+               list = [],
+               // Stack of fire calls for repeatable lists
+               stack = !options.once && [],
+               // Fire callbacks
+               fire = function( data ) {
+                       memory = options.memory && data;
+                       fired = true;
+                       firingIndex = firingStart || 0;
+                       firingStart = 0;
+                       firingLength = list.length;
+                       firing = true;
+                       for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+                               if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+                                       memory = false; // To prevent further calls using add
+                                       break;
+                               }
+                       }
+                       firing = false;
+                       if ( list ) {
+                               if ( stack ) {
+                                       if ( stack.length ) {
+                                               fire( stack.shift() );
+                                       }
+                               } else if ( memory ) {
+                                       list = [];
+                               } else {
+                                       self.disable();
+                               }
+                       }
+               },
+               // Actual Callbacks object
+               self = {
+                       // Add a callback or a collection of callbacks to the list
+                       add: function() {
+                               if ( list ) {
+                                       // First, we save the current length
+                                       var start = list.length;
+                                       (function add( args ) {
+                                               jQuery.each( args, function( _, arg ) {
+                                                       var type = jQuery.type( arg );
+                                                       if ( type === "function" ) {
+                                                               if ( !options.unique || !self.has( arg ) ) {
+                                                                       list.push( arg );
+                                                               }
+                                                       } else if ( arg && arg.length && type !== "string" ) {
+                                                               // Inspect recursively
+                                                               add( arg );
+                                                       }
+                                               });
+                                       })( arguments );
+                                       // Do we need to add the callbacks to the
+                                       // current firing batch?
+                                       if ( firing ) {
+                                               firingLength = list.length;
+                                       // With memory, if we're not firing then
+                                       // we should call right away
+                                       } else if ( memory ) {
+                                               firingStart = start;
+                                               fire( memory );
+                                       }
+                               }
+                               return this;
+                       },
+                       // Remove a callback from the list
+                       remove: function() {
+                               if ( list ) {
+                                       jQuery.each( arguments, function( _, arg ) {
+                                               var index;
+                                               while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+                                                       list.splice( index, 1 );
+                                                       // Handle firing indexes
+                                                       if ( firing ) {
+                                                               if ( index <= firingLength ) {
+                                                                       firingLength--;
+                                                               }
+                                                               if ( index <= firingIndex ) {
+                                                                       firingIndex--;
+                                                               }
+                                                       }
+                                               }
+                                       });
+                               }
+                               return this;
+                       },
+                       // Control if a given callback is in the list
+                       has: function( fn ) {
+                               return jQuery.inArray( fn, list ) > -1;
+                       },
+                       // Remove all callbacks from the list
+                       empty: function() {
+                               list = [];
+                               return this;
+                       },
+                       // Have the list do nothing anymore
+                       disable: function() {
+                               list = stack = memory = undefined;
+                               return this;
+                       },
+                       // Is it disabled?
+                       disabled: function() {
+                               return !list;
+                       },
+                       // Lock the list in its current state
+                       lock: function() {
+                               stack = undefined;
+                               if ( !memory ) {
+                                       self.disable();
+                               }
+                               return this;
+                       },
+                       // Is it locked?
+                       locked: function() {
+                               return !stack;
+                       },
+                       // Call all callbacks with the given context and arguments
+                       fireWith: function( context, args ) {
+                               args = args || [];
+                               args = [ context, args.slice ? args.slice() : args ];
+                               if ( list && ( !fired || stack ) ) {
+                                       if ( firing ) {
+                                               stack.push( args );
+                                       } else {
+                                               fire( args );
+                                       }
+                               }
+                               return this;
+                       },
+                       // Call all the callbacks with the given arguments
+                       fire: function() {
+                               self.fireWith( this, arguments );
+                               return this;
+                       },
+                       // To know if the callbacks have already been called at least once
+                       fired: function() {
+                               return !!fired;
+                       }
+               };
+
+       return self;
+};
+jQuery.extend({
+
+       Deferred: function( func ) {
+               var tuples = [
+                               // action, add listener, listener list, final state
+                               [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+                               [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+                               [ "notify", "progress", jQuery.Callbacks("memory") ]
+                       ],
+                       state = "pending",
+                       promise = {
+                               state: function() {
+                                       return state;
+                               },
+                               always: function() {
+                                       deferred.done( arguments ).fail( arguments );
+                                       return this;
+                               },
+                               then: function( /* fnDone, fnFail, fnProgress */ ) {
+                                       var fns = arguments;
+                                       return jQuery.Deferred(function( newDefer ) {
+                                               jQuery.each( tuples, function( i, tuple ) {
+                                                       var action = tuple[ 0 ],
+                                                               fn = fns[ i ];
+                                                       // deferred[ done | fail | progress ] for forwarding actions to newDefer
+                                                       deferred[ tuple[1] ]( jQuery.isFunction( fn ) ?
+                                                               function() {
+                                                                       var returned = fn.apply( this, arguments );
+                                                                       if ( returned && jQuery.isFunction( returned.promise ) ) {
+                                                                               returned.promise()
+                                                                                       .done( newDefer.resolve )
+                                                                                       .fail( newDefer.reject )
+                                                                                       .progress( newDefer.notify );
+                                                                       } else {
+                                                                               newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+                                                                       }
+                                                               } :
+                                                               newDefer[ action ]
+                                                       );
+                                               });
+                                               fns = null;
+                                       }).promise();
+                               },
+                               // Get a promise for this deferred
+                               // If obj is provided, the promise aspect is added to the object
+                               promise: function( obj ) {
+                                       return obj != null ? jQuery.extend( obj, promise ) : promise;
+                               }
+                       },
+                       deferred = {};
+
+               // Keep pipe for back-compat
+               promise.pipe = promise.then;
+
+               // Add list-specific methods
+               jQuery.each( tuples, function( i, tuple ) {
+                       var list = tuple[ 2 ],
+                               stateString = tuple[ 3 ];
+
+                       // promise[ done | fail | progress ] = list.add
+                       promise[ tuple[1] ] = list.add;
+
+                       // Handle state
+                       if ( stateString ) {
+                               list.add(function() {
+                                       // state = [ resolved | rejected ]
+                                       state = stateString;
+
+                               // [ reject_list | resolve_list ].disable; progress_list.lock
+                               }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+                       }
+
+                       // deferred[ resolve | reject | notify ] = list.fire
+                       deferred[ tuple[0] ] = list.fire;
+                       deferred[ tuple[0] + "With" ] = list.fireWith;
+               });
+
+               // Make the deferred a promise
+               promise.promise( deferred );
+
+               // Call given func if any
+               if ( func ) {
+                       func.call( deferred, deferred );
+               }
+
+               // All done!
+               return deferred;
+       },
+
+       // Deferred helper
+       when: function( subordinate /* , ..., subordinateN */ ) {
+               var i = 0,
+                       resolveValues = core_slice.call( arguments ),
+                       length = resolveValues.length,
+
+                       // the count of uncompleted subordinates
+                       remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+                       // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+                       deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+                       // Update function for both resolve and progress values
+                       updateFunc = function( i, contexts, values ) {
+                               return function( value ) {
+                                       contexts[ i ] = this;
+                                       values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
+                                       if( values === progressValues ) {
+                                               deferred.notifyWith( contexts, values );
+                                       } else if ( !( --remaining ) ) {
+                                               deferred.resolveWith( contexts, values );
+                                       }
+                               };
+                       },
+
+                       progressValues, progressContexts, resolveContexts;
+
+               // add listeners to Deferred subordinates; treat others as resolved
+               if ( length > 1 ) {
+                       progressValues = new Array( length );
+                       progressContexts = new Array( length );
+                       resolveContexts = new Array( length );
+                       for ( ; i < length; i++ ) {
+                               if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+                                       resolveValues[ i ].promise()
+                                               .done( updateFunc( i, resolveContexts, resolveValues ) )
+                                               .fail( deferred.reject )
+                                               .progress( updateFunc( i, progressContexts, progressValues ) );
+                               } else {
+                                       --remaining;
+                               }
+                       }
+               }
+
+               // if we're not waiting on anything, resolve the master
+               if ( !remaining ) {
+                       deferred.resolveWith( resolveContexts, resolveValues );
+               }
+
+               return deferred.promise();
+       }
+});
+jQuery.support = (function() {
+
+       var support,
+               all,
+               a,
+               select,
+               opt,
+               input,
+               fragment,
+               eventName,
+               i,
+               isSupported,
+               clickFn,
+               div = document.createElement("div");
+
+       // Setup
+       div.setAttribute( "className", "t" );
+       div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+
+       // Support tests won't run in some limited or non-browser environments
+       all = div.getElementsByTagName("*");
+       a = div.getElementsByTagName("a")[ 0 ];
+       if ( !all || !a || !all.length ) {
+               return {};
+       }
+
+       // First batch of tests
+       select = document.createElement("select");
+       opt = select.appendChild( document.createElement("option") );
+       input = div.getElementsByTagName("input")[ 0 ];
+
+       a.style.cssText = "top:1px;float:left;opacity:.5";
+       support = {
+               // IE strips leading whitespace when .innerHTML is used
+               leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+               // Make sure that tbody elements aren't automatically inserted
+               // IE will insert them into empty tables
+               tbody: !div.getElementsByTagName("tbody").length,
+
+               // Make sure that link elements get serialized correctly by innerHTML
+               // This requires a wrapper element in IE
+               htmlSerialize: !!div.getElementsByTagName("link").length,
+
+               // Get the style information from getAttribute
+               // (IE uses .cssText instead)
+               style: /top/.test( a.getAttribute("style") ),
+
+               // Make sure that URLs aren't manipulated
+               // (IE normalizes it by default)
+               hrefNormalized: ( a.getAttribute("href") === "/a" ),
+
+               // Make sure that element opacity exists
+               // (IE uses filter instead)
+               // Use a regex to work around a WebKit issue. See #5145
+               opacity: /^0.5/.test( a.style.opacity ),
+
+               // Verify style float existence
+               // (IE uses styleFloat instead of cssFloat)
+               cssFloat: !!a.style.cssFloat,
+
+               // Make sure that if no value is specified for a checkbox
+               // that it defaults to "on".
+               // (WebKit defaults to "" instead)
+               checkOn: ( input.value === "on" ),
+
+               // Make sure that a selected-by-default option has a working selected property.
+               // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+               optSelected: opt.selected,
+
+               // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+               getSetAttribute: div.className !== "t",
+
+               // Tests for enctype support on a form (#6743)
+               enctype: !!document.createElement("form").enctype,
+
+               // Makes sure cloning an html5 element does not cause problems
+               // Where outerHTML is undefined, this still works
+               html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+               // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
+               boxModel: ( document.compatMode === "CSS1Compat" ),
+
+               // Will be defined later
+               submitBubbles: true,
+               changeBubbles: true,
+               focusinBubbles: false,
+               deleteExpando: true,
+               noCloneEvent: true,
+               inlineBlockNeedsLayout: false,
+               shrinkWrapBlocks: false,
+               reliableMarginRight: true,
+               boxSizingReliable: true,
+               pixelPosition: false
+       };
+
+       // Make sure checked status is properly cloned
+       input.checked = true;
+       support.noCloneChecked = input.cloneNode( true ).checked;
+
+       // Make sure that the options inside disabled selects aren't marked as disabled
+       // (WebKit marks them as disabled)
+       select.disabled = true;
+       support.optDisabled = !opt.disabled;
+
+       // Test to see if it's possible to delete an expando from an element
+       // Fails in Internet Explorer
+       try {
+               delete div.test;
+       } catch( e ) {
+               support.deleteExpando = false;
+       }
+
+       if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+               div.attachEvent( "onclick", clickFn = function() {
+                       // Cloning a node shouldn't copy over any
+                       // bound event handlers (IE does this)
+                       support.noCloneEvent = false;
+               });
+               div.cloneNode( true ).fireEvent("onclick");
+               div.detachEvent( "onclick", clickFn );
+       }
+
+       // Check if a radio maintains its value
+       // after being appended to the DOM
+       input = document.createElement("input");
+       input.value = "t";
+       input.setAttribute( "type", "radio" );
+       support.radioValue = input.value === "t";
+
+       input.setAttribute( "checked", "checked" );
+
+       // #11217 - WebKit loses check when the name is after the checked attribute
+       input.setAttribute( "name", "t" );
+
+       div.appendChild( input );
+       fragment = document.createDocumentFragment();
+       fragment.appendChild( div.lastChild );
+
+       // WebKit doesn't clone checked state correctly in fragments
+       support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+       // Check if a disconnected checkbox will retain its checked
+       // value of true after appended to the DOM (IE6/7)
+       support.appendChecked = input.checked;
+
+       fragment.removeChild( input );
+       fragment.appendChild( div );
+
+       // Technique from Juriy Zaytsev
+       // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+       // We only care about the case where non-standard event systems
+       // are used, namely in IE. Short-circuiting here helps us to
+       // avoid an eval call (in setAttribute) which can cause CSP
+       // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+       if ( div.attachEvent ) {
+               for ( i in {
+                       submit: true,
+                       change: true,
+                       focusin: true
+               }) {
+                       eventName = "on" + i;
+                       isSupported = ( eventName in div );
+                       if ( !isSupported ) {
+                               div.setAttribute( eventName, "return;" );
+                               isSupported = ( typeof div[ eventName ] === "function" );
+                       }
+                       support[ i + "Bubbles" ] = isSupported;
+               }
+       }
+
+       // Run tests that need a body at doc ready
+       jQuery(function() {
+               var container, div, tds, marginDiv,
+                       divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;",
+                       body = document.getElementsByTagName("body")[0];
+
+               if ( !body ) {
+                       // Return for frameset docs that don't have a body
+                       return;
+               }
+
+               container = document.createElement("div");
+               container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px";
+               body.insertBefore( container, body.firstChild );
+
+               // Construct the test element
+               div = document.createElement("div");
+               container.appendChild( div );
+
+               // Check if table cells still have offsetWidth/Height when they are set
+               // to display:none and there are still other visible table cells in a
+               // table row; if so, offsetWidth/Height are not reliable for use when
+               // determining if an element has been hidden directly using
+               // display:none (it is still safe to use offsets if a parent element is
+               // hidden; don safety goggles and see bug #4512 for more information).
+               // (only IE 8 fails this test)
+               div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
+               tds = div.getElementsByTagName("td");
+               tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
+               isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+               tds[ 0 ].style.display = "";
+               tds[ 1 ].style.display = "none";
+
+               // Check if empty table cells still have offsetWidth/Height
+               // (IE <= 8 fail this test)
+               support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+               // Check box-sizing and margin behavior
+               div.innerHTML = "";
+               div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
+               support.boxSizing = ( div.offsetWidth === 4 );
+               support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
+
+               // NOTE: To any future maintainer, we've window.getComputedStyle
+               // because jsdom on node.js will break without it.
+               if ( window.getComputedStyle ) {
+                       support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+                       support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+                       // Check if div with explicit width and no margin-right incorrectly
+                       // gets computed margin-right based on width of container. For more
+                       // info see bug #3333
+                       // Fails in WebKit before Feb 2011 nightlies
+                       // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+                       marginDiv = document.createElement("div");
+                       marginDiv.style.cssText = div.style.cssText = divReset;
+                       marginDiv.style.marginRight = marginDiv.style.width = "0";
+                       div.style.width = "1px";
+                       div.appendChild( marginDiv );
+                       support.reliableMarginRight =
+                               !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
+               }
+
+               if ( typeof div.style.zoom !== "undefined" ) {
+                       // Check if natively block-level elements act like inline-block
+                       // elements when setting their display to 'inline' and giving
+                       // them layout
+                       // (IE < 8 does this)
+                       div.innerHTML = "";
+                       div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
+                       support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
+
+                       // Check if elements with layout shrink-wrap their children
+                       // (IE 6 does this)
+                       div.style.display = "block";
+                       div.style.overflow = "visible";
+                       div.innerHTML = "<div></div>";
+                       div.firstChild.style.width = "5px";
+                       support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
+
+                       container.style.zoom = 1;
+               }
+
+               // Null elements to avoid leaks in IE
+               body.removeChild( container );
+               container = div = tds = marginDiv = null;
+       });
+
+       // Null elements to avoid leaks in IE
+       fragment.removeChild( div );
+       all = a = select = opt = input = fragment = div = null;
+
+       return support;
+})();
+var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
+       rmultiDash = /([A-Z])/g;
+
+jQuery.extend({
+       cache: {},
+
+       deletedIds: [],
+
+       // Remove at next major release (1.9/2.0)
+       uuid: 0,
+
+       // Unique for each copy of jQuery on the page
+       // Non-digits removed to match rinlinejQuery
+       expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+       // The following elements throw uncatchable exceptions if you
+       // attempt to add expando properties to them.
+       noData: {
+               "embed": true,
+               // Ban all objects except for Flash (which handle expandos)
+               "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+               "applet": true
+       },
+
+       hasData: function( elem ) {
+               elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+               return !!elem && !isEmptyDataObject( elem );
+       },
+
+       data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+               if ( !jQuery.acceptData( elem ) ) {
+                       return;
+               }
+
+               var thisCache, ret,
+                       internalKey = jQuery.expando,
+                       getByName = typeof name === "string",
+
+                       // We have to handle DOM nodes and JS objects differently because IE6-7
+                       // can't GC object references properly across the DOM-JS boundary
+                       isNode = elem.nodeType,
+
+                       // Only DOM nodes need the global jQuery cache; JS object data is
+                       // attached directly to the object so GC can occur automatically
+                       cache = isNode ? jQuery.cache : elem,
+
+                       // Only defining an ID for JS objects if its cache already exists allows
+                       // the code to shortcut on the same path as a DOM node with no cache
+                       id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+               // Avoid doing any more work than we need to when trying to get data on an
+               // object that has no data at all
+               if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
+                       return;
+               }
+
+               if ( !id ) {
+                       // Only DOM nodes need a new unique ID for each element since their data
+                       // ends up in the global cache
+                       if ( isNode ) {
+                               elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++;
+                       } else {
+                               id = internalKey;
+                       }
+               }
+
+               if ( !cache[ id ] ) {
+                       cache[ id ] = {};
+
+                       // Avoids exposing jQuery metadata on plain JS objects when the object
+                       // is serialized using JSON.stringify
+                       if ( !isNode ) {
+                               cache[ id ].toJSON = jQuery.noop;
+                       }
+               }
+
+               // An object can be passed to jQuery.data instead of a key/value pair; this gets
+               // shallow copied over onto the existing cache
+               if ( typeof name === "object" || typeof name === "function" ) {
+                       if ( pvt ) {
+                               cache[ id ] = jQuery.extend( cache[ id ], name );
+                       } else {
+                               cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+                       }
+               }
+
+               thisCache = cache[ id ];
+
+               // jQuery data() is stored in a separate object inside the object's internal data
+               // cache in order to avoid key collisions between internal data and user-defined
+               // data.
+               if ( !pvt ) {
+                       if ( !thisCache.data ) {
+                               thisCache.data = {};
+                       }
+
+                       thisCache = thisCache.data;
+               }
+
+               if ( data !== undefined ) {
+                       thisCache[ jQuery.camelCase( name ) ] = data;
+               }
+
+               // Check for both converted-to-camel and non-converted data property names
+               // If a data property was specified
+               if ( getByName ) {
+
+                       // First Try to find as-is property data
+                       ret = thisCache[ name ];
+
+                       // Test for null|undefined property data
+                       if ( ret == null ) {
+
+                               // Try to find the camelCased property
+                               ret = thisCache[ jQuery.camelCase( name ) ];
+                       }
+               } else {
+                       ret = thisCache;
+               }
+
+               return ret;
+       },
+
+       removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+               if ( !jQuery.acceptData( elem ) ) {
+                       return;
+               }
+
+               var thisCache, i, l,
+
+                       isNode = elem.nodeType,
+
+                       // See jQuery.data for more information
+                       cache = isNode ? jQuery.cache : elem,
+                       id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+               // If there is already no cache entry for this object, there is no
+               // purpose in continuing
+               if ( !cache[ id ] ) {
+                       return;
+               }
+
+               if ( name ) {
+
+                       thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+                       if ( thisCache ) {
+
+                               // Support array or space separated string names for data keys
+                               if ( !jQuery.isArray( name ) ) {
+
+                                       // try the string as a key before any manipulation
+                                       if ( name in thisCache ) {
+                                               name = [ name ];
+                                       } else {
+
+                                               // split the camel cased version by spaces unless a key with the spaces exists
+                                               name = jQuery.camelCase( name );
+                                               if ( name in thisCache ) {
+                                                       name = [ name ];
+                                               } else {
+                                                       name = name.split(" ");
+                                               }
+                                       }
+                               }
+
+                               for ( i = 0, l = name.length; i < l; i++ ) {
+                                       delete thisCache[ name[i] ];
+                               }
+
+                               // If there is no data left in the cache, we want to continue
+                               // and let the cache object itself get destroyed
+                               if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+                                       return;
+                               }
+                       }
+               }
+
+               // See jQuery.data for more information
+               if ( !pvt ) {
+                       delete cache[ id ].data;
+
+                       // Don't destroy the parent cache unless the internal data object
+                       // had been the only thing left in it
+                       if ( !isEmptyDataObject( cache[ id ] ) ) {
+                               return;
+                       }
+               }
+
+               // Destroy the cache
+               if ( isNode ) {
+                       jQuery.cleanData( [ elem ], true );
+
+               // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+               } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
+                       delete cache[ id ];
+
+               // When all else fails, null
+               } else {
+                       cache[ id ] = null;
+               }
+       },
+
+       // For internal use only.
+       _data: function( elem, name, data ) {
+               return jQuery.data( elem, name, data, true );
+       },
+
+       // A method for determining if a DOM node can handle the data expando
+       acceptData: function( elem ) {
+               var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+               // nodes accept data unless otherwise specified; rejection can be conditional
+               return !noData || noData !== true && elem.getAttribute("classid") === noData;
+       }
+});
+
+jQuery.fn.extend({
+       data: function( key, value ) {
+               var parts, part, attr, name, l,
+                       elem = this[0],
+                       i = 0,
+                       data = null;
+
+               // Gets all values
+               if ( key === undefined ) {
+                       if ( this.length ) {
+                               data = jQuery.data( elem );
+
+                               if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+                                       attr = elem.attributes;
+                                       for ( l = attr.length; i < l; i++ ) {
+                                               name = attr[i].name;
+
+                                               if ( !name.indexOf( "data-" ) ) {
+                                                       name = jQuery.camelCase( name.substring(5) );
+
+                                                       dataAttr( elem, name, data[ name ] );
+                                               }
+                                       }
+                                       jQuery._data( elem, "parsedAttrs", true );
+                               }
+                       }
+
+                       return data;
+               }
+
+               // Sets multiple values
+               if ( typeof key === "object" ) {
+                       return this.each(function() {
+                               jQuery.data( this, key );
+                       });
+               }
+
+               parts = key.split( ".", 2 );
+               parts[1] = parts[1] ? "." + parts[1] : "";
+               part = parts[1] + "!";
+
+               return jQuery.access( this, function( value ) {
+
+                       if ( value === undefined ) {
+                               data = this.triggerHandler( "getData" + part, [ parts[0] ] );
+
+                               // Try to fetch any internally stored data first
+                               if ( data === undefined && elem ) {
+                                       data = jQuery.data( elem, key );
+                                       data = dataAttr( elem, key, data );
+                               }
+
+                               return data === undefined && parts[1] ?
+                                       this.data( parts[0] ) :
+                                       data;
+                       }
+
+                       parts[1] = value;
+                       this.each(function() {
+                               var self = jQuery( this );
+
+                               self.triggerHandler( "setData" + part, parts );
+                               jQuery.data( this, key, value );
+                               self.triggerHandler( "changeData" + part, parts );
+                       });
+               }, null, value, arguments.length > 1, null, false );
+       },
+
+       removeData: function( key ) {
+               return this.each(function() {
+                       jQuery.removeData( this, key );
+               });
+       }
+});
+
+function dataAttr( elem, key, data ) {
+       // If nothing was found internally, try to fetch any
+       // data from the HTML5 data-* attribute
+       if ( data === undefined && elem.nodeType === 1 ) {
+
+               var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+               data = elem.getAttribute( name );
+
+               if ( typeof data === "string" ) {
+                       try {
+                               data = data === "true" ? true :
+                               data === "false" ? false :
+                               data === "null" ? null :
+                               // Only convert to a number if it doesn't change the string
+                               +data + "" === data ? +data :
+                               rbrace.test( data ) ? jQuery.parseJSON( data ) :
+                                       data;
+                       } catch( e ) {}
+
+                       // Make sure we set the data so it isn't changed later
+                       jQuery.data( elem, key, data );
+
+               } else {
+                       data = undefined;
+               }
+       }
+
+       return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+       var name;
+       for ( name in obj ) {
+
+               // if the public data object is empty, the private is still empty
+               if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+                       continue;
+               }
+               if ( name !== "toJSON" ) {
+                       return false;
+               }
+       }
+
+       return true;
+}
+jQuery.extend({
+       queue: function( elem, type, data ) {
+               var queue;
+
+               if ( elem ) {
+                       type = ( type || "fx" ) + "queue";
+                       queue = jQuery._data( elem, type );
+
+                       // Speed up dequeue by getting out quickly if this is just a lookup
+                       if ( data ) {
+                               if ( !queue || jQuery.isArray(data) ) {
+                                       queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+                               } else {
+                                       queue.push( data );
+                               }
+                       }
+                       return queue || [];
+               }
+       },
+
+       dequeue: function( elem, type ) {
+               type = type || "fx";
+
+               var queue = jQuery.queue( elem, type ),
+                       startLength = queue.length,
+                       fn = queue.shift(),
+                       hooks = jQuery._queueHooks( elem, type ),
+                       next = function() {
+                               jQuery.dequeue( elem, type );
+                       };
+
+               // If the fx queue is dequeued, always remove the progress sentinel
+               if ( fn === "inprogress" ) {
+                       fn = queue.shift();
+                       startLength--;
+               }
+
+               if ( fn ) {
+
+                       // Add a progress sentinel to prevent the fx queue from being
+                       // automatically dequeued
+                       if ( type === "fx" ) {
+                               queue.unshift( "inprogress" );
+                       }
+
+                       // clear up the last queue stop function
+                       delete hooks.stop;
+                       fn.call( elem, next, hooks );
+               }
+
+               if ( !startLength && hooks ) {
+                       hooks.empty.fire();
+               }
+       },
+
+       // not intended for public consumption - generates a queueHooks object, or returns the current one
+       _queueHooks: function( elem, type ) {
+               var key = type + "queueHooks";
+               return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+                       empty: jQuery.Callbacks("once memory").add(function() {
+                               jQuery.removeData( elem, type + "queue", true );
+                               jQuery.removeData( elem, key, true );
+                       })
+               });
+       }
+});
+
+jQuery.fn.extend({
+       queue: function( type, data ) {
+               var setter = 2;
+
+               if ( typeof type !== "string" ) {
+                       data = type;
+                       type = "fx";
+                       setter--;
+               }
+
+               if ( arguments.length < setter ) {
+                       return jQuery.queue( this[0], type );
+               }
+
+               return data === undefined ?
+                       this :
+                       this.each(function() {
+                               var queue = jQuery.queue( this, type, data );
+
+                               // ensure a hooks for this queue
+                               jQuery._queueHooks( this, type );
+
+                               if ( type === "fx" && queue[0] !== "inprogress" ) {
+                                       jQuery.dequeue( this, type );
+                               }
+                       });
+       },
+       dequeue: function( type ) {
+               return this.each(function() {
+                       jQuery.dequeue( this, type );
+               });
+       },
+       // Based off of the plugin by Clint Helfers, with permission.
+       // http://blindsignals.com/index.php/2009/07/jquery-delay/
+       delay: function( time, type ) {
+               time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+               type = type || "fx";
+
+               return this.queue( type, function( next, hooks ) {
+                       var timeout = setTimeout( next, time );
+                       hooks.stop = function() {
+                               clearTimeout( timeout );
+                       };
+               });
+       },
+       clearQueue: function( type ) {
+               return this.queue( type || "fx", [] );
+       },
+       // Get a promise resolved when queues of a certain type
+       // are emptied (fx is the type by default)
+       promise: function( type, obj ) {
+               var tmp,
+                       count = 1,
+                       defer = jQuery.Deferred(),
+                       elements = this,
+                       i = this.length,
+                       resolve = function() {
+                               if ( !( --count ) ) {
+                                       defer.resolveWith( elements, [ elements ] );
+                               }
+                       };
+
+               if ( typeof type !== "string" ) {
+                       obj = type;
+                       type = undefined;
+               }
+               type = type || "fx";
+
+               while( i-- ) {
+                       tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+                       if ( tmp && tmp.empty ) {
+                               count++;
+                               tmp.empty.add( resolve );
+                       }
+               }
+               resolve();
+               return defer.promise( obj );
+       }
+});
+var nodeHook, boolHook, fixSpecified,
+       rclass = /[\t\r\n]/g,
+       rreturn = /\r/g,
+       rtype = /^(?:button|input)$/i,
+       rfocusable = /^(?:button|input|object|select|textarea)$/i,
+       rclickable = /^a(?:rea|)$/i,
+       rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+       getSetAttribute = jQuery.support.getSetAttribute;
+
+jQuery.fn.extend({
+       attr: function( name, value ) {
+               return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+       },
+
+       removeAttr: function( name ) {
+               return this.each(function() {
+                       jQuery.removeAttr( this, name );
+               });
+       },
+
+       prop: function( name, value ) {
+               return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+       },
+
+       removeProp: function( name ) {
+               name = jQuery.propFix[ name ] || name;
+               return this.each(function() {
+                       // try/catch handles cases where IE balks (such as removing a property on window)
+                       try {
+                               this[ name ] = undefined;
+                               delete this[ name ];
+                       } catch( e ) {}
+               });
+       },
+
+       addClass: function( value ) {
+               var classNames, i, l, elem,
+                       setClass, c, cl;
+
+               if ( jQuery.isFunction( value ) ) {
+                       return this.each(function( j ) {
+                               jQuery( this ).addClass( value.call(this, j, this.className) );
+                       });
+               }
+
+               if ( value && typeof value === "string" ) {
+                       classNames = value.split( core_rspace );
+
+                       for ( i = 0, l = this.length; i < l; i++ ) {
+                               elem = this[ i ];
+
+                               if ( elem.nodeType === 1 ) {
+                                       if ( !elem.className && classNames.length === 1 ) {
+                                               elem.className = value;
+
+                                       } else {
+                                               setClass = " " + elem.className + " ";
+
+                                               for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+                                                       if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) {
+                                                               setClass += classNames[ c ] + " ";
+                                                       }
+                                               }
+                                               elem.className = jQuery.trim( setClass );
+                                       }
+                               }
+                       }
+               }
+
+               return this;
+       },
+
+       removeClass: function( value ) {
+               var removes, className, elem, c, cl, i, l;
+
+               if ( jQuery.isFunction( value ) ) {
+                       return this.each(function( j ) {
+                               jQuery( this ).removeClass( value.call(this, j, this.className) );
+                       });
+               }
+               if ( (value && typeof value === "string") || value === undefined ) {
+                       removes = ( value || "" ).split( core_rspace );
+
+                       for ( i = 0, l = this.length; i < l; i++ ) {
+                               elem = this[ i ];
+                               if ( elem.nodeType === 1 && elem.className ) {
+
+                                       className = (" " + elem.className + " ").replace( rclass, " " );
+
+                                       // loop over each item in the removal list
+                                       for ( c = 0, cl = removes.length; c < cl; c++ ) {
+                                               // Remove until there is nothing to remove,
+                                               while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) {
+                                                       className = className.replace( " " + removes[ c ] + " " , " " );
+                                               }
+                                       }
+                                       elem.className = value ? jQuery.trim( className ) : "";
+                               }
+                       }
+               }
+
+               return this;
+       },
+
+       toggleClass: function( value, stateVal ) {
+               var type = typeof value,
+                       isBool = typeof stateVal === "boolean";
+
+               if ( jQuery.isFunction( value ) ) {
+                       return this.each(function( i ) {
+                               jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+                       });
+               }
+
+               return this.each(function() {
+                       if ( type === "string" ) {
+                               // toggle individual class names
+                               var className,
+                                       i = 0,
+                                       self = jQuery( this ),
+                                       state = stateVal,
+                                       classNames = value.split( core_rspace );
+
+                               while ( (className = classNames[ i++ ]) ) {
+                                       // check each className given, space separated list
+                                       state = isBool ? state : !self.hasClass( className );
+                                       self[ state ? "addClass" : "removeClass" ]( className );
+                               }
+
+                       } else if ( type === "undefined" || type === "boolean" ) {
+                               if ( this.className ) {
+                                       // store className if set
+                                       jQuery._data( this, "__className__", this.className );
+                               }
+
+                               // toggle whole className
+                               this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+                       }
+               });
+       },
+
+       hasClass: function( selector ) {
+               var className = " " + selector + " ",
+                       i = 0,
+                       l = this.length;
+               for ( ; i < l; i++ ) {
+                       if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+                               return true;
+                       }
+               }
+
+               return false;
+       },
+
+       val: function( value ) {
+               var hooks, ret, isFunction,
+                       elem = this[0];
+
+               if ( !arguments.length ) {
+                       if ( elem ) {
+                               hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+                               if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+                                       return ret;
+                               }
+
+                               ret = elem.value;
+
+                               return typeof ret === "string" ?
+                                       // handle most common string cases
+                                       ret.replace(rreturn, "") :
+                                       // handle cases where value is null/undef or number
+                                       ret == null ? "" : ret;
+                       }
+
+                       return;
+               }
+
+               isFunction = jQuery.isFunction( value );
+
+               return this.each(function( i ) {
+                       var val,
+                               self = jQuery(this);
+
+                       if ( this.nodeType !== 1 ) {
+                               return;
+                       }
+
+                       if ( isFunction ) {
+                               val = value.call( this, i, self.val() );
+                       } else {
+                               val = value;
+                       }
+
+                       // Treat null/undefined as ""; convert numbers to string
+                       if ( val == null ) {
+                               val = "";
+                       } else if ( typeof val === "number" ) {
+                               val += "";
+                       } else if ( jQuery.isArray( val ) ) {
+                               val = jQuery.map(val, function ( value ) {
+                                       return value == null ? "" : value + "";
+                               });
+                       }
+
+                       hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+                       // If set returns undefined, fall back to normal setting
+                       if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+                               this.value = val;
+                       }
+               });
+       }
+});
+
+jQuery.extend({
+       valHooks: {
+               option: {
+                       get: function( elem ) {
+                               // attributes.value is undefined in Blackberry 4.7 but
+                               // uses .value. See #6932
+                               var val = elem.attributes.value;
+                               return !val || val.specified ? elem.value : elem.text;
+                       }
+               },
+               select: {
+                       get: function( elem ) {
+                               var value, option,
+                                       options = elem.options,
+                                       index = elem.selectedIndex,
+                                       one = elem.type === "select-one" || index < 0,
+                                       values = one ? null : [],
+                                       max = one ? index + 1 : options.length,
+                                       i = index < 0 ?
+                                               max :
+                                               one ? index : 0;
+
+                               // Loop through all the selected options
+                               for ( ; i < max; i++ ) {
+                                       option = options[ i ];
+
+                                       // oldIE doesn't update selected after form reset (#2551)
+                                       if ( ( option.selected || i === index ) &&
+                                                       // Don't return options that are disabled or in a disabled optgroup
+                                                       ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
+                                                       ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+                                               // Get the specific value for the option
+                                               value = jQuery( option ).val();
+
+                                               // We don't need an array for one selects
+                                               if ( one ) {
+                                                       return value;
+                                               }
+
+                                               // Multi-Selects return an array
+                                               values.push( value );
+                                       }
+                               }
+
+                               return values;
+                       },
+
+                       set: function( elem, value ) {
+                               var values = jQuery.makeArray( value );
+
+                               jQuery(elem).find("option").each(function() {
+                                       this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+                               });
+
+                               if ( !values.length ) {
+                                       elem.selectedIndex = -1;
+                               }
+                               return values;
+                       }
+               }
+       },
+
+       // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9
+       attrFn: {},
+
+       attr: function( elem, name, value, pass ) {
+               var ret, hooks, notxml,
+                       nType = elem.nodeType;
+
+               // don't get/set attributes on text, comment and attribute nodes
+               if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+                       return;
+               }
+
+               if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
+                       return jQuery( elem )[ name ]( value );
+               }
+
+               // Fallback to prop when attributes are not supported
+               if ( typeof elem.getAttribute === "undefined" ) {
+                       return jQuery.prop( elem, name, value );
+               }
+
+               notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+               // All attributes are lowercase
+               // Grab necessary hook if one is defined
+               if ( notxml ) {
+                       name = name.toLowerCase();
+                       hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+               }
+
+               if ( value !== undefined ) {
+
+                       if ( value === null ) {
+                               jQuery.removeAttr( elem, name );
+                               return;
+
+                       } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+                               return ret;
+
+                       } else {
+                               elem.setAttribute( name, value + "" );
+                               return value;
+                       }
+
+               } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+                       return ret;
+
+               } else {
+
+                       ret = elem.getAttribute( name );
+
+                       // Non-existent attributes return null, we normalize to undefined
+                       return ret === null ?
+                               undefined :
+                               ret;
+               }
+       },
+
+       removeAttr: function( elem, value ) {
+               var propName, attrNames, name, isBool,
+                       i = 0;
+
+               if ( value && elem.nodeType === 1 ) {
+
+                       attrNames = value.split( core_rspace );
+
+                       for ( ; i < attrNames.length; i++ ) {
+                               name = attrNames[ i ];
+
+                               if ( name ) {
+                                       propName = jQuery.propFix[ name ] || name;
+                                       isBool = rboolean.test( name );
+
+                                       // See #9699 for explanation of this approach (setting first, then removal)
+                                       // Do not do this for boolean attributes (see #10870)
+                                       if ( !isBool ) {
+                                               jQuery.attr( elem, name, "" );
+                                       }
+                                       elem.removeAttribute( getSetAttribute ? name : propName );
+
+                                       // Set corresponding property to false for boolean attributes
+                                       if ( isBool && propName in elem ) {
+                                               elem[ propName ] = false;
+                                       }
+                               }
+                       }
+               }
+       },
+
+       attrHooks: {
+               type: {
+                       set: function( elem, value ) {
+                               // We can't allow the type property to be changed (since it causes problems in IE)
+                               if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+                                       jQuery.error( "type property can't be changed" );
+                               } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+                                       // Setting the type on a radio button after the value resets the value in IE6-9
+                                       // Reset value to it's default in case type is set after value
+                                       // This is for element creation
+                                       var val = elem.value;
+                                       elem.setAttribute( "type", value );
+                                       if ( val ) {
+                                               elem.value = val;
+                                       }
+                                       return value;
+                               }
+                       }
+               },
+               // Use the value property for back compat
+               // Use the nodeHook for button elements in IE6/7 (#1954)
+               value: {
+                       get: function( elem, name ) {
+                               if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+                                       return nodeHook.get( elem, name );
+                               }
+                               return name in elem ?
+                                       elem.value :
+                                       null;
+                       },
+                       set: function( elem, value, name ) {
+                               if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+                                       return nodeHook.set( elem, value, name );
+                               }
+                               // Does not return so that setAttribute is also used
+                               elem.value = value;
+                       }
+               }
+       },
+
+       propFix: {
+               tabindex: "tabIndex",
+               readonly: "readOnly",
+               "for": "htmlFor",
+               "class": "className",
+               maxlength: "maxLength",
+               cellspacing: "cellSpacing",
+               cellpadding: "cellPadding",
+               rowspan: "rowSpan",
+               colspan: "colSpan",
+               usemap: "useMap",
+               frameborder: "frameBorder",
+               contenteditable: "contentEditable"
+       },
+
+       prop: function( elem, name, value ) {
+               var ret, hooks, notxml,
+                       nType = elem.nodeType;
+
+               // don't get/set properties on text, comment and attribute nodes
+               if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+                       return;
+               }
+
+               notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+               if ( notxml ) {
+                       // Fix name and attach hooks
+                       name = jQuery.propFix[ name ] || name;
+                       hooks = jQuery.propHooks[ name ];
+               }
+
+               if ( value !== undefined ) {
+                       if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+                               return ret;
+
+                       } else {
+                               return ( elem[ name ] = value );
+                       }
+
+               } else {
+                       if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+                               return ret;
+
+                       } else {
+                               return elem[ name ];
+                       }
+               }
+       },
+
+       propHooks: {
+               tabIndex: {
+                       get: function( elem ) {
+                               // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+                               // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+                               var attributeNode = elem.getAttributeNode("tabindex");
+
+                               return attributeNode && attributeNode.specified ?
+                                       parseInt( attributeNode.value, 10 ) :
+                                       rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+                                               0 :
+                                               undefined;
+                       }
+               }
+       }
+});
+
+// Hook for boolean attributes
+boolHook = {
+       get: function( elem, name ) {
+               // Align boolean attributes with corresponding properties
+               // Fall back to attribute presence where some booleans are not supported
+               var attrNode,
+                       property = jQuery.prop( elem, name );
+               return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+                       name.toLowerCase() :
+                       undefined;
+       },
+       set: function( elem, value, name ) {
+               var propName;
+               if ( value === false ) {
+                       // Remove boolean attributes when set to false
+                       jQuery.removeAttr( elem, name );
+               } else {
+                       // value is true since we know at this point it's type boolean and not false
+                       // Set boolean attributes to the same name and set the DOM property
+                       propName = jQuery.propFix[ name ] || name;
+                       if ( propName in elem ) {
+                               // Only set the IDL specifically if it already exists on the element
+                               elem[ propName ] = true;
+                       }
+
+                       elem.setAttribute( name, name.toLowerCase() );
+               }
+               return name;
+       }
+};
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+       fixSpecified = {
+               name: true,
+               id: true,
+               coords: true
+       };
+
+       // Use this for any attribute in IE6/7
+       // This fixes almost every IE6/7 issue
+       nodeHook = jQuery.valHooks.button = {
+               get: function( elem, name ) {
+                       var ret;
+                       ret = elem.getAttributeNode( name );
+                       return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ?
+                               ret.value :
+                               undefined;
+               },
+               set: function( elem, value, name ) {
+                       // Set the existing or create a new attribute node
+                       var ret = elem.getAttributeNode( name );
+                       if ( !ret ) {
+                               ret = document.createAttribute( name );
+                               elem.setAttributeNode( ret );
+                       }
+                       return ( ret.value = value + "" );
+               }
+       };
+
+       // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+       // This is for removals
+       jQuery.each([ "width", "height" ], function( i, name ) {
+               jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+                       set: function( elem, value ) {
+                               if ( value === "" ) {
+                                       elem.setAttribute( name, "auto" );
+                                       return value;
+                               }
+                       }
+               });
+       });
+
+       // Set contenteditable to false on removals(#10429)
+       // Setting to empty string throws an error as an invalid value
+       jQuery.attrHooks.contenteditable = {
+               get: nodeHook.get,
+               set: function( elem, value, name ) {
+                       if ( value === "" ) {
+                               value = "false";
+                       }
+                       nodeHook.set( elem, value, name );
+               }
+       };
+}
+
+
+// Some attributes require a special call on IE
+if ( !jQuery.support.hrefNormalized ) {
+       jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+               jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+                       get: function( elem ) {
+                               var ret = elem.getAttribute( name, 2 );
+                               return ret === null ? undefined : ret;
+                       }
+               });
+       });
+}
+
+if ( !jQuery.support.style ) {
+       jQuery.attrHooks.style = {
+               get: function( elem ) {
+                       // Return undefined in the case of empty string
+                       // Normalize to lowercase since IE uppercases css property names
+                       return elem.style.cssText.toLowerCase() || undefined;
+               },
+               set: function( elem, value ) {
+                       return ( elem.style.cssText = value + "" );
+               }
+       };
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+       jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+               get: function( elem ) {
+                       var parent = elem.parentNode;
+
+                       if ( parent ) {
+                               parent.selectedIndex;
+
+                               // Make sure that it also works with optgroups, see #5701
+                               if ( parent.parentNode ) {
+                                       parent.parentNode.selectedIndex;
+                               }
+                       }
+                       return null;
+               }
+       });
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+       jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+       jQuery.each([ "radio", "checkbox" ], function() {
+               jQuery.valHooks[ this ] = {
+                       get: function( elem ) {
+                               // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+                               return elem.getAttribute("value") === null ? "on" : elem.value;
+                       }
+               };
+       });
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+       jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+               set: function( elem, value ) {
+                       if ( jQuery.isArray( value ) ) {
+                               return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+                       }
+               }
+       });
+});
+var rformElems = /^(?:textarea|input|select)$/i,
+       rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/,
+       rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
+       rkeyEvent = /^key/,
+       rmouseEvent = /^(?:mouse|contextmenu)|click/,
+       rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+       hoverHack = function( events ) {
+               return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+       };
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+       add: function( elem, types, handler, data, selector ) {
+
+               var elemData, eventHandle, events,
+                       t, tns, type, namespaces, handleObj,
+                       handleObjIn, handlers, special;
+
+               // Don't attach events to noData or text/comment nodes (allow plain objects tho)
+               if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
+                       return;
+               }
+
+               // Caller can pass in an object of custom data in lieu of the handler
+               if ( handler.handler ) {
+                       handleObjIn = handler;
+                       handler = handleObjIn.handler;
+                       selector = handleObjIn.selector;
+               }
+
+               // Make sure that the handler has a unique ID, used to find/remove it later
+               if ( !handler.guid ) {
+                       handler.guid = jQuery.guid++;
+               }
+
+               // Init the element's event structure and main handler, if this is the first
+               events = elemData.events;
+               if ( !events ) {
+                       elemData.events = events = {};
+               }
+               eventHandle = elemData.handle;
+               if ( !eventHandle ) {
+                       elemData.handle = eventHandle = function( e ) {
+                               // Discard the second event of a jQuery.event.trigger() and
+                               // when an event is called after a page has unloaded
+                               return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+                                       jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+                                       undefined;
+                       };
+                       // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+                       eventHandle.elem = elem;
+               }
+
+               // Handle multiple events separated by a space
+               // jQuery(...).bind("mouseover mouseout", fn);
+               types = jQuery.trim( hoverHack(types) ).split( " " );
+               for ( t = 0; t < types.length; t++ ) {
+
+                       tns = rtypenamespace.exec( types[t] ) || [];
+                       type = tns[1];
+                       namespaces = ( tns[2] || "" ).split( "." ).sort();
+
+                       // If event changes its type, use the special event handlers for the changed type
+                       special = jQuery.event.special[ type ] || {};
+
+                       // If selector defined, determine special event api type, otherwise given type
+                       type = ( selector ? special.delegateType : special.bindType ) || type;
+
+                       // Update special based on newly reset type
+                       special = jQuery.event.special[ type ] || {};
+
+                       // handleObj is passed to all event handlers
+                       handleObj = jQuery.extend({
+                               type: type,
+                               origType: tns[1],
+                               data: data,
+                               handler: handler,
+                               guid: handler.guid,
+                               selector: selector,
+                               needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+                               namespace: namespaces.join(".")
+                       }, handleObjIn );
+
+                       // Init the event handler queue if we're the first
+                       handlers = events[ type ];
+                       if ( !handlers ) {
+                               handlers = events[ type ] = [];
+                               handlers.delegateCount = 0;
+
+                               // Only use addEventListener/attachEvent if the special events handler returns false
+                               if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+                                       // Bind the global event handler to the element
+                                       if ( elem.addEventListener ) {
+                                               elem.addEventListener( type, eventHandle, false );
+
+                                       } else if ( elem.attachEvent ) {
+                                               elem.attachEvent( "on" + type, eventHandle );
+                                       }
+                               }
+                       }
+
+                       if ( special.add ) {
+                               special.add.call( elem, handleObj );
+
+                               if ( !handleObj.handler.guid ) {
+                                       handleObj.handler.guid = handler.guid;
+                               }
+                       }
+
+                       // Add to the element's handler list, delegates in front
+                       if ( selector ) {
+                               handlers.splice( handlers.delegateCount++, 0, handleObj );
+                       } else {
+                               handlers.push( handleObj );
+                       }
+
+                       // Keep track of which events have ever been used, for event optimization
+                       jQuery.event.global[ type ] = true;
+               }
+
+               // Nullify elem to prevent memory leaks in IE
+               elem = null;
+       },
+
+       global: {},
+
+       // Detach an event or set of events from an element
+       remove: function( elem, types, handler, selector, mappedTypes ) {
+
+               var t, tns, type, origType, namespaces, origCount,
+                       j, events, special, eventType, handleObj,
+                       elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+               if ( !elemData || !(events = elemData.events) ) {
+                       return;
+               }
+
+               // Once for each type.namespace in types; type may be omitted
+               types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
+               for ( t = 0; t < types.length; t++ ) {
+                       tns = rtypenamespace.exec( types[t] ) || [];
+                       type = origType = tns[1];
+                       namespaces = tns[2];
+
+                       // Unbind all events (on this namespace, if provided) for the element
+                       if ( !type ) {
+                               for ( type in events ) {
+                                       jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+                               }
+                               continue;
+                       }
+
+                       special = jQuery.event.special[ type ] || {};
+                       type = ( selector? special.delegateType : special.bindType ) || type;
+                       eventType = events[ type ] || [];
+                       origCount = eventType.length;
+                       namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
+
+                       // Remove matching events
+                       for ( j = 0; j < eventType.length; j++ ) {
+                               handleObj = eventType[ j ];
+
+                               if ( ( mappedTypes || origType === handleObj.origType ) &&
+                                        ( !handler || handler.guid === handleObj.guid ) &&
+                                        ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
+                                        ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+                                       eventType.splice( j--, 1 );
+
+                                       if ( handleObj.selector ) {
+                                               eventType.delegateCount--;
+                                       }
+                                       if ( special.remove ) {
+                                               special.remove.call( elem, handleObj );
+                                       }
+                               }
+                       }
+
+                       // Remove generic event handler if we removed something and no more handlers exist
+                       // (avoids potential for endless recursion during removal of special event handlers)
+                       if ( eventType.length === 0 && origCount !== eventType.length ) {
+                               if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+                                       jQuery.removeEvent( elem, type, elemData.handle );
+                               }
+
+                               delete events[ type ];
+                       }
+               }
+
+               // Remove the expando if it's no longer used
+               if ( jQuery.isEmptyObject( events ) ) {
+                       delete elemData.handle;
+
+                       // removeData also checks for emptiness and clears the expando if empty
+                       // so use it instead of delete
+                       jQuery.removeData( elem, "events", true );
+               }
+       },
+
+       // Events that are safe to short-circuit if no handlers are attached.
+       // Native DOM events should not be added, they may have inline handlers.
+       customEvent: {
+               "getData": true,
+               "setData": true,
+               "changeData": true
+       },
+
+       trigger: function( event, data, elem, onlyHandlers ) {
+               // Don't do events on text and comment nodes
+               if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
+                       return;
+               }
+
+               // Event object or event type
+               var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType,
+                       type = event.type || event,
+                       namespaces = [];
+
+               // focus/blur morphs to focusin/out; ensure we're not firing them right now
+               if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+                       return;
+               }
+
+               if ( type.indexOf( "!" ) >= 0 ) {
+                       // Exclusive events trigger only for the exact event (no namespaces)
+                       type = type.slice(0, -1);
+                       exclusive = true;
+               }
+
+               if ( type.indexOf( "." ) >= 0 ) {
+                       // Namespaced trigger; create a regexp to match event type in handle()
+                       namespaces = type.split(".");
+                       type = namespaces.shift();
+                       namespaces.sort();
+               }
+
+               if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+                       // No jQuery handlers for this event type, and it can't have inline handlers
+                       return;
+               }
+
+               // Caller can pass in an Event, Object, or just an event type string
+               event = typeof event === "object" ?
+                       // jQuery.Event object
+                       event[ jQuery.expando ] ? event :
+                       // Object literal
+                       new jQuery.Event( type, event ) :
+                       // Just the event type (string)
+                       new jQuery.Event( type );
+
+               event.type = type;
+               event.isTrigger = true;
+               event.exclusive = exclusive;
+               event.namespace = namespaces.join( "." );
+               event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
+               ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+
+               // Handle a global trigger
+               if ( !elem ) {
+
+                       // TODO: Stop taunting the data cache; remove global events and always attach to document
+                       cache = jQuery.cache;
+                       for ( i in cache ) {
+                               if ( cache[ i ].events && cache[ i ].events[ type ] ) {
+                                       jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
+                               }
+                       }
+                       return;
+               }
+
+               // Clean up the event in case it is being reused
+               event.result = undefined;
+               if ( !event.target ) {
+                       event.target = elem;
+               }
+
+               // Clone any incoming data and prepend the event, creating the handler arg list
+               data = data != null ? jQuery.makeArray( data ) : [];
+               data.unshift( event );
+
+               // Allow special events to draw outside the lines
+               special = jQuery.event.special[ type ] || {};
+               if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
+                       return;
+               }
+
+               // Determine event propagation path in advance, per W3C events spec (#9951)
+               // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+               eventPath = [[ elem, special.bindType || type ]];
+               if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+                       bubbleType = special.delegateType || type;
+                       cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
+                       for ( old = elem; cur; cur = cur.parentNode ) {
+                               eventPath.push([ cur, bubbleType ]);
+                               old = cur;
+                       }
+
+                       // Only add window if we got to document (e.g., not plain obj or detached DOM)
+                       if ( old === (elem.ownerDocument || document) ) {
+                               eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
+                       }
+               }
+
+               // Fire handlers on the event path
+               for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
+
+                       cur = eventPath[i][0];
+                       event.type = eventPath[i][1];
+
+                       handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+                       if ( handle ) {
+                               handle.apply( cur, data );
+                       }
+                       // Note that this is a bare JS function and not a jQuery handler
+                       handle = ontype && cur[ ontype ];
+                       if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
+                               event.preventDefault();
+                       }
+               }
+               event.type = type;
+
+               // If nobody prevented the default action, do it now
+               if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+                       if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+                               !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+                               // Call a native DOM method on the target with the same name name as the event.
+                               // Can't use an .isFunction() check here because IE6/7 fails that test.
+                               // Don't do default actions on window, that's where global variables be (#6170)
+                               // IE<9 dies on focus/blur to hidden element (#1486)
+                               if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
+
+                                       // Don't re-trigger an onFOO event when we call its FOO() method
+                                       old = elem[ ontype ];
+
+                                       if ( old ) {
+                                               elem[ ontype ] = null;
+                                       }
+
+                                       // Prevent re-triggering of the same event, since we already bubbled it above
+                                       jQuery.event.triggered = type;
+                                       elem[ type ]();
+                                       jQuery.event.triggered = undefined;
+
+                                       if ( old ) {
+                                               elem[ ontype ] = old;
+                                       }
+                               }
+                       }
+               }
+
+               return event.result;
+       },
+
+       dispatch: function( event ) {
+
+               // Make a writable jQuery.Event from the native event object
+               event = jQuery.event.fix( event || window.event );
+
+               var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related,
+                       handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
+                       delegateCount = handlers.delegateCount,
+                       args = core_slice.call( arguments ),
+                       run_all = !event.exclusive && !event.namespace,
+                       special = jQuery.event.special[ event.type ] || {},
+                       handlerQueue = [];
+
+               // Use the fix-ed jQuery.Event rather than the (read-only) native event
+               args[0] = event;
+               event.delegateTarget = this;
+
+               // Call the preDispatch hook for the mapped type, and let it bail if desired
+               if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+                       return;
+               }
+
+               // Determine handlers that should run if there are delegated events
+               // Avoid non-left-click bubbling in Firefox (#3861)
+               if ( delegateCount && !(event.button && event.type === "click") ) {
+
+                       for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
+
+                               // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764)
+                               if ( cur.disabled !== true || event.type !== "click" ) {
+                                       selMatch = {};
+                                       matches = [];
+                                       for ( i = 0; i < delegateCount; i++ ) {
+                                               handleObj = handlers[ i ];
+                                               sel = handleObj.selector;
+
+                                               if ( selMatch[ sel ] === undefined ) {
+                                                       selMatch[ sel ] = handleObj.needsContext ?
+                                                               jQuery( sel, this ).index( cur ) >= 0 :
+                                                               jQuery.find( sel, this, null, [ cur ] ).length;
+                                               }
+                                               if ( selMatch[ sel ] ) {
+                                                       matches.push( handleObj );
+                                               }
+                                       }
+                                       if ( matches.length ) {
+                                               handlerQueue.push({ elem: cur, matches: matches });
+                                       }
+                               }
+                       }
+               }
+
+               // Add the remaining (directly-bound) handlers
+               if ( handlers.length > delegateCount ) {
+                       handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
+               }
+
+               // Run delegates first; they may want to stop propagation beneath us
+               for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
+                       matched = handlerQueue[ i ];
+                       event.currentTarget = matched.elem;
+
+                       for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
+                               handleObj = matched.matches[ j ];
+
+                               // Triggered event must either 1) be non-exclusive and have no namespace, or
+                               // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+                               if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
+
+                                       event.data = handleObj.data;
+                                       event.handleObj = handleObj;
+
+                                       ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+                                                       .apply( matched.elem, args );
+
+                                       if ( ret !== undefined ) {
+                                               event.result = ret;
+                                               if ( ret === false ) {
+                                                       event.preventDefault();
+                                                       event.stopPropagation();
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               // Call the postDispatch hook for the mapped type
+               if ( special.postDispatch ) {
+                       special.postDispatch.call( this, event );
+               }
+
+               return event.result;
+       },
+
+       // Includes some event props shared by KeyEvent and MouseEvent
+       // *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
+       props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+       fixHooks: {},
+
+       keyHooks: {
+               props: "char charCode key keyCode".split(" "),
+               filter: function( event, original ) {
+
+                       // Add which for key events
+                       if ( event.which == null ) {
+                               event.which = original.charCode != null ? original.charCode : original.keyCode;
+                       }
+
+                       return event;
+               }
+       },
+
+       mouseHooks: {
+               props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+               filter: function( event, original ) {
+                       var eventDoc, doc, body,
+                               button = original.button,
+                               fromElement = original.fromElement;
+
+                       // Calculate pageX/Y if missing and clientX/Y available
+                       if ( event.pageX == null && original.clientX != null ) {
+                               eventDoc = event.target.ownerDocument || document;
+                               doc = eventDoc.documentElement;
+                               body = eventDoc.body;
+
+                               event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+                               event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
+                       }
+
+                       // Add relatedTarget, if necessary
+                       if ( !event.relatedTarget && fromElement ) {
+                               event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+                       }
+
+                       // Add which for click: 1 === left; 2 === middle; 3 === right
+                       // Note: button is not normalized, so don't use it
+                       if ( !event.which && button !== undefined ) {
+                               event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+                       }
+
+                       return event;
+               }
+       },
+
+       fix: function( event ) {
+               if ( event[ jQuery.expando ] ) {
+                       return event;
+               }
+
+               // Create a writable copy of the event object and normalize some properties
+               var i, prop,
+                       originalEvent = event,
+                       fixHook = jQuery.event.fixHooks[ event.type ] || {},
+                       copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+               event = jQuery.Event( originalEvent );
+
+               for ( i = copy.length; i; ) {
+                       prop = copy[ --i ];
+                       event[ prop ] = originalEvent[ prop ];
+               }
+
+               // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
+               if ( !event.target ) {
+                       event.target = originalEvent.srcElement || document;
+               }
+
+               // Target should not be a text node (#504, Safari)
+               if ( event.target.nodeType === 3 ) {
+                       event.target = event.target.parentNode;
+               }
+
+               // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8)
+               event.metaKey = !!event.metaKey;
+
+               return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
+       },
+
+       special: {
+               load: {
+                       // Prevent triggered image.load events from bubbling to window.load
+                       noBubble: true
+               },
+
+               focus: {
+                       delegateType: "focusin"
+               },
+               blur: {
+                       delegateType: "focusout"
+               },
+
+               beforeunload: {
+                       setup: function( data, namespaces, eventHandle ) {
+                               // We only want to do this special case on windows
+                               if ( jQuery.isWindow( this ) ) {
+                                       this.onbeforeunload = eventHandle;
+                               }
+                       },
+
+                       teardown: function( namespaces, eventHandle ) {
+                               if ( this.onbeforeunload === eventHandle ) {
+                                       this.onbeforeunload = null;
+                               }
+                       }
+               }
+       },
+
+       simulate: function( type, elem, event, bubble ) {
+               // Piggyback on a donor event to simulate a different one.
+               // Fake originalEvent to avoid donor's stopPropagation, but if the
+               // simulated event prevents default then we do the same on the donor.
+               var e = jQuery.extend(
+                       new jQuery.Event(),
+                       event,
+                       { type: type,
+                               isSimulated: true,
+                               originalEvent: {}
+                       }
+               );
+               if ( bubble ) {
+                       jQuery.event.trigger( e, null, elem );
+               } else {
+                       jQuery.event.dispatch.call( elem, e );
+               }
+               if ( e.isDefaultPrevented() ) {
+                       event.preventDefault();
+               }
+       }
+};
+
+// Some plugins are using, but it's undocumented/deprecated and will be removed.
+// The 1.7 special event interface should provide all the hooks needed now.
+jQuery.event.handle = jQuery.event.dispatch;
+
+jQuery.removeEvent = document.removeEventListener ?
+       function( elem, type, handle ) {
+               if ( elem.removeEventListener ) {
+                       elem.removeEventListener( type, handle, false );
+               }
+       } :
+       function( elem, type, handle ) {
+               var name = "on" + type;
+
+               if ( elem.detachEvent ) {
+
+                       // #8545, #7054, preventing memory leaks for custom events in IE6-8
+                       // detachEvent needed property on element, by name of that event, to properly expose it to GC
+                       if ( typeof elem[ name ] === "undefined" ) {
+                               elem[ name ] = null;
+                       }
+
+                       elem.detachEvent( name, handle );
+               }
+       };
+
+jQuery.Event = function( src, props ) {
+       // Allow instantiation without the 'new' keyword
+       if ( !(this instanceof jQuery.Event) ) {
+               return new jQuery.Event( src, props );
+       }
+
+       // Event object
+       if ( src && src.type ) {
+               this.originalEvent = src;
+               this.type = src.type;
+
+               // Events bubbling up the document may have been marked as prevented
+               // by a handler lower down the tree; reflect the correct value.
+               this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+                       src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+       // Event type
+       } else {
+               this.type = src;
+       }
+
+       // Put explicitly provided properties onto the event object
+       if ( props ) {
+               jQuery.extend( this, props );
+       }
+
+       // Create a timestamp if incoming event doesn't have one
+       this.timeStamp = src && src.timeStamp || jQuery.now();
+
+       // Mark it as fixed
+       this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+       return false;
+}
+function returnTrue() {
+       return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+       preventDefault: function() {
+               this.isDefaultPrevented = returnTrue;
+
+               var e = this.originalEvent;
+               if ( !e ) {
+                       return;
+               }
+
+               // if preventDefault exists run it on the original event
+               if ( e.preventDefault ) {
+                       e.preventDefault();
+
+               // otherwise set the returnValue property of the original event to false (IE)
+               } else {
+                       e.returnValue = false;
+               }
+       },
+       stopPropagation: function() {
+               this.isPropagationStopped = returnTrue;
+
+               var e = this.originalEvent;
+               if ( !e ) {
+                       return;
+               }
+               // if stopPropagation exists run it on the original event
+               if ( e.stopPropagation ) {
+                       e.stopPropagation();
+               }
+               // otherwise set the cancelBubble property of the original event to true (IE)
+               e.cancelBubble = true;
+       },
+       stopImmediatePropagation: function() {
+               this.isImmediatePropagationStopped = returnTrue;
+               this.stopPropagation();
+       },
+       isDefaultPrevented: returnFalse,
+       isPropagationStopped: returnFalse,
+       isImmediatePropagationStopped: returnFalse
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+       mouseenter: "mouseover",
+       mouseleave: "mouseout"
+}, function( orig, fix ) {
+       jQuery.event.special[ orig ] = {
+               delegateType: fix,
+               bindType: fix,
+
+               handle: function( event ) {
+                       var ret,
+                               target = this,
+                               related = event.relatedTarget,
+                               handleObj = event.handleObj,
+                               selector = handleObj.selector;
+
+                       // For mousenter/leave call the handler if related is outside the target.
+                       // NB: No relatedTarget if the mouse left/entered the browser window
+                       if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+                               event.type = handleObj.origType;
+                               ret = handleObj.handler.apply( this, arguments );
+                               event.type = fix;
+                       }
+                       return ret;
+               }
+       };
+});
+
+// IE submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+       jQuery.event.special.submit = {
+               setup: function() {
+                       // Only need this for delegated form submit events
+                       if ( jQuery.nodeName( this, "form" ) ) {
+                               return false;
+                       }
+
+                       // Lazy-add a submit handler when a descendant form may potentially be submitted
+                       jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+                               // Node name check avoids a VML-related crash in IE (#9807)
+                               var elem = e.target,
+                                       form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+                               if ( form && !jQuery._data( form, "_submit_attached" ) ) {
+                                       jQuery.event.add( form, "submit._submit", function( event ) {
+                                               event._submit_bubble = true;
+                                       });
+                                       jQuery._data( form, "_submit_attached", true );
+                               }
+                       });
+                       // return undefined since we don't need an event listener
+               },
+
+               postDispatch: function( event ) {
+                       // If form was submitted by the user, bubble the event up the tree
+                       if ( event._submit_bubble ) {
+                               delete event._submit_bubble;
+                               if ( this.parentNode && !event.isTrigger ) {
+                                       jQuery.event.simulate( "submit", this.parentNode, event, true );
+                               }
+                       }
+               },
+
+               teardown: function() {
+                       // Only need this for delegated form submit events
+                       if ( jQuery.nodeName( this, "form" ) ) {
+                               return false;
+                       }
+
+                       // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+                       jQuery.event.remove( this, "._submit" );
+               }
+       };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !jQuery.support.changeBubbles ) {
+
+       jQuery.event.special.change = {
+
+               setup: function() {
+
+                       if ( rformElems.test( this.nodeName ) ) {
+                               // IE doesn't fire change on a check/radio until blur; trigger it on click
+                               // after a propertychange. Eat the blur-change in special.change.handle.
+                               // This still fires onchange a second time for check/radio after blur.
+                               if ( this.type === "checkbox" || this.type === "radio" ) {
+                                       jQuery.event.add( this, "propertychange._change", function( event ) {
+                                               if ( event.originalEvent.propertyName === "checked" ) {
+                                                       this._just_changed = true;
+                                               }
+                                       });
+                                       jQuery.event.add( this, "click._change", function( event ) {
+                                               if ( this._just_changed && !event.isTrigger ) {
+                                                       this._just_changed = false;
+                                               }
+                                               // Allow triggered, simulated change events (#11500)
+                                               jQuery.event.simulate( "change", this, event, true );
+                                       });
+                               }
+                               return false;
+                       }
+                       // Delegated event; lazy-add a change handler on descendant inputs
+                       jQuery.event.add( this, "beforeactivate._change", function( e ) {
+                               var elem = e.target;
+
+                               if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "_change_attached" ) ) {
+                                       jQuery.event.add( elem, "change._change", function( event ) {
+                                               if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+                                                       jQuery.event.simulate( "change", this.parentNode, event, true );
+                                               }
+                                       });
+                                       jQuery._data( elem, "_change_attached", true );
+                               }
+                       });
+               },
+
+               handle: function( event ) {
+                       var elem = event.target;
+
+                       // Swallow native change events from checkbox/radio, we already triggered them above
+                       if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+                               return event.handleObj.handler.apply( this, arguments );
+                       }
+               },
+
+               teardown: function() {
+                       jQuery.event.remove( this, "._change" );
+
+                       return !rformElems.test( this.nodeName );
+               }
+       };
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+       jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+               // Attach a single capturing handler while someone wants focusin/focusout
+               var attaches = 0,
+                       handler = function( event ) {
+                               jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+                       };
+
+               jQuery.event.special[ fix ] = {
+                       setup: function() {
+                               if ( attaches++ === 0 ) {
+                                       document.addEventListener( orig, handler, true );
+                               }
+                       },
+                       teardown: function() {
+                               if ( --attaches === 0 ) {
+                                       document.removeEventListener( orig, handler, true );
+                               }
+                       }
+               };
+       });
+}
+
+jQuery.fn.extend({
+
+       on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+               var origFn, type;
+
+               // Types can be a map of types/handlers
+               if ( typeof types === "object" ) {
+                       // ( types-Object, selector, data )
+                       if ( typeof selector !== "string" ) { // && selector != null
+                               // ( types-Object, data )
+                               data = data || selector;
+                               selector = undefined;
+                       }
+                       for ( type in types ) {
+                               this.on( type, selector, data, types[ type ], one );
+                       }
+                       return this;
+               }
+
+               if ( data == null && fn == null ) {
+                       // ( types, fn )
+                       fn = selector;
+                       data = selector = undefined;
+               } else if ( fn == null ) {
+                       if ( typeof selector === "string" ) {
+                               // ( types, selector, fn )
+                               fn = data;
+                               data = undefined;
+                       } else {
+                               // ( types, data, fn )
+                               fn = data;
+                               data = selector;
+                               selector = undefined;
+                       }
+               }
+               if ( fn === false ) {
+                       fn = returnFalse;
+               } else if ( !fn ) {
+                       return this;
+               }
+
+               if ( one === 1 ) {
+                       origFn = fn;
+                       fn = function( event ) {
+                               // Can use an empty set, since event contains the info
+                               jQuery().off( event );
+                               return origFn.apply( this, arguments );
+                       };
+                       // Use same guid so caller can remove using origFn
+                       fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+               }
+               return this.each( function() {
+                       jQuery.event.add( this, types, fn, data, selector );
+               });
+       },
+       one: function( types, selector, data, fn ) {
+               return this.on( types, selector, data, fn, 1 );
+       },
+       off: function( types, selector, fn ) {
+               var handleObj, type;
+               if ( types && types.preventDefault && types.handleObj ) {
+                       // ( event )  dispatched jQuery.Event
+                       handleObj = types.handleObj;
+                       jQuery( types.delegateTarget ).off(
+                               handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+                               handleObj.selector,
+                               handleObj.handler
+                       );
+                       return this;
+               }
+               if ( typeof types === "object" ) {
+                       // ( types-object [, selector] )
+                       for ( type in types ) {
+                               this.off( type, selector, types[ type ] );
+                       }
+                       return this;
+               }
+               if ( selector === false || typeof selector === "function" ) {
+                       // ( types [, fn] )
+                       fn = selector;
+                       selector = undefined;
+               }
+               if ( fn === false ) {
+                       fn = returnFalse;
+               }
+               return this.each(function() {
+                       jQuery.event.remove( this, types, fn, selector );
+               });
+       },
+
+       bind: function( types, data, fn ) {
+               return this.on( types, null, data, fn );
+       },
+       unbind: function( types, fn ) {
+               return this.off( types, null, fn );
+       },
+
+       live: function( types, data, fn ) {
+               jQuery( this.context ).on( types, this.selector, data, fn );
+               return this;
+       },
+       die: function( types, fn ) {
+               jQuery( this.context ).off( types, this.selector || "**", fn );
+               return this;
+       },
+
+       delegate: function( selector, types, data, fn ) {
+               return this.on( types, selector, data, fn );
+       },
+       undelegate: function( selector, types, fn ) {
+               // ( namespace ) or ( selector, types [, fn] )
+               return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+       },
+
+       trigger: function( type, data ) {
+               return this.each(function() {
+                       jQuery.event.trigger( type, data, this );
+               });
+       },
+       triggerHandler: function( type, data ) {
+               if ( this[0] ) {
+                       return jQuery.event.trigger( type, data, this[0], true );
+               }
+       },
+
+       toggle: function( fn ) {
+               // Save reference to arguments for access in closure
+               var args = arguments,
+                       guid = fn.guid || jQuery.guid++,
+                       i = 0,
+                       toggler = function( event ) {
+                               // Figure out which function to execute
+                               var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+                               jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+                               // Make sure that clicks stop
+                               event.preventDefault();
+
+                               // and execute the function
+                               return args[ lastToggle ].apply( this, arguments ) || false;
+                       };
+
+               // link all the functions, so any of them can unbind this click handler
+               toggler.guid = guid;
+               while ( i < args.length ) {
+                       args[ i++ ].guid = guid;
+               }
+
+               return this.click( toggler );
+       },
+
+       hover: function( fnOver, fnOut ) {
+               return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+       }
+});
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+       "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+       "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+       // Handle event binding
+       jQuery.fn[ name ] = function( data, fn ) {
+               if ( fn == null ) {
+                       fn = data;
+                       data = null;
+               }
+
+               return arguments.length > 0 ?
+                       this.on( name, null, data, fn ) :
+                       this.trigger( name );
+       };
+
+       if ( rkeyEvent.test( name ) ) {
+               jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
+       }
+
+       if ( rmouseEvent.test( name ) ) {
+               jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
+       }
+});
+/*!\r
+ * Sizzle CSS Selector Engine\r
+ * Copyright 2012 jQuery Foundation and other contributors\r
+ * Released under the MIT license\r
+ * http://sizzlejs.com/\r
+ */\r
+(function( window, undefined ) {\r
+\r
+var cachedruns,\r
+       assertGetIdNotName,\r
+       Expr,\r
+       getText,\r
+       isXML,\r
+       contains,\r
+       compile,\r
+       sortOrder,\r
+       hasDuplicate,\r
+       outermostContext,\r
+\r
+       baseHasDuplicate = true,\r
+       strundefined = "undefined",\r
+\r
+       expando = ( "sizcache" + Math.random() ).replace( ".", "" ),\r
+\r
+       Token = String,\r
+       document = window.document,\r
+       docElem = document.documentElement,\r
+       dirruns = 0,\r
+       done = 0,\r
+       pop = [].pop,\r
+       push = [].push,\r
+       slice = [].slice,\r
+       // Use a stripped-down indexOf if a native one is unavailable\r
+       indexOf = [].indexOf || function( elem ) {\r
+               var i = 0,\r
+                       len = this.length;\r
+               for ( ; i < len; i++ ) {\r
+                       if ( this[i] === elem ) {\r
+                               return i;\r
+                       }\r
+               }\r
+               return -1;\r
+       },\r
+\r
+       // Augment a function for special use by Sizzle\r
+       markFunction = function( fn, value ) {\r
+               fn[ expando ] = value == null || value;\r
+               return fn;\r
+       },\r
+\r
+       createCache = function() {\r
+               var cache = {},\r
+                       keys = [];\r
+\r
+               return markFunction(function( key, value ) {\r
+                       // Only keep the most recent entries\r
+                       if ( keys.push( key ) > Expr.cacheLength ) {\r
+                               delete cache[ keys.shift() ];\r
+                       }\r
+\r
+                       // Retrieve with (key + " ") to avoid collision with native Object.prototype properties (see Issue #157)\r
+                       return (cache[ key + " " ] = value);\r
+               }, cache );\r
+       },\r
+\r
+       classCache = createCache(),\r
+       tokenCache = createCache(),\r
+       compilerCache = createCache(),\r
+\r
+       // Regex\r
+\r
+       // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\r
+       whitespace = "[\\x20\\t\\r\\n\\f]",\r
+       // http://www.w3.org/TR/css3-syntax/#characters\r
+       characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",\r
+\r
+       // Loosely modeled on CSS identifier characters\r
+       // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)\r
+       // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\r
+       identifier = characterEncoding.replace( "w", "w#" ),\r
+\r
+       // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\r
+       operators = "([*^$|!~]?=)",\r
+       attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +\r
+               "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",\r
+\r
+       // Prefer arguments not in parens/brackets,\r
+       //   then attribute selectors and non-pseudos (denoted by :),\r
+       //   then anything else\r
+       // These preferences are here to reduce the number of selectors\r
+       //   needing tokenize in the PSEUDO preFilter\r
+       pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)",\r
+\r
+       // For matchExpr.POS and matchExpr.needsContext\r
+       pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +\r
+               "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)",\r
+\r
+       // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\r
+       rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),\r
+\r
+       rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),\r
+       rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),\r
+       rpseudo = new RegExp( pseudos ),\r
+\r
+       // Easily-parseable/retrievable ID or TAG or CLASS selectors\r
+       rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,\r
+\r
+       rnot = /^:not/,\r
+       rsibling = /[\x20\t\r\n\f]*[+~]/,\r
+       rendsWithNot = /:not\($/,\r
+\r
+       rheader = /h\d/i,\r
+       rinputs = /input|select|textarea|button/i,\r
+\r
+       rbackslash = /\\(?!\\)/g,\r
+\r
+       matchExpr = {\r
+               "ID": new RegExp( "^#(" + characterEncoding + ")" ),\r
+               "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),\r
+               "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),\r
+               "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),\r
+               "ATTR": new RegExp( "^" + attributes ),\r
+               "PSEUDO": new RegExp( "^" + pseudos ),\r
+               "POS": new RegExp( pos, "i" ),\r
+               "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace +\r
+                       "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +\r
+                       "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),\r
+               // For use in libraries implementing .is()\r
+               "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" )\r
+       },\r
+\r
+       // Support\r
+\r
+       // Used for testing something on an element\r
+       assert = function( fn ) {\r
+               var div = document.createElement("div");\r
+\r
+               try {\r
+                       return fn( div );\r
+               } catch (e) {\r
+                       return false;\r
+               } finally {\r
+                       // release memory in IE\r
+                       div = null;\r
+               }\r
+       },\r
+\r
+       // Check if getElementsByTagName("*") returns only elements\r
+       assertTagNameNoComments = assert(function( div ) {\r
+               div.appendChild( document.createComment("") );\r
+               return !div.getElementsByTagName("*").length;\r
+       }),\r
+\r
+       // Check if getAttribute returns normalized href attributes\r
+       assertHrefNotNormalized = assert(function( div ) {\r
+               div.innerHTML = "<a href='#'></a>";\r
+               return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&\r
+                       div.firstChild.getAttribute("href") === "#";\r
+       }),\r
+\r
+       // Check if attributes should be retrieved by attribute nodes\r
+       assertAttributes = assert(function( div ) {\r
+               div.innerHTML = "<select></select>";\r
+               var type = typeof div.lastChild.getAttribute("multiple");\r
+               // IE8 returns a string for some attributes even when not present\r
+               return type !== "boolean" && type !== "string";\r
+       }),\r
+\r
+       // Check if getElementsByClassName can be trusted\r
+       assertUsableClassName = assert(function( div ) {\r
+               // Opera can't find a second classname (in 9.6)\r
+               div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";\r
+               if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {\r
+                       return false;\r
+               }\r
+\r
+               // Safari 3.2 caches class attributes and doesn't catch changes\r
+               div.lastChild.className = "e";\r
+               return div.getElementsByClassName("e").length === 2;\r
+       }),\r
+\r
+       // Check if getElementById returns elements by name\r
+       // Check if getElementsByName privileges form controls or returns elements by ID\r
+       assertUsableName = assert(function( div ) {\r
+               // Inject content\r
+               div.id = expando + 0;\r
+               div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";\r
+               docElem.insertBefore( div, docElem.firstChild );\r
+\r
+               // Test\r
+               var pass = document.getElementsByName &&\r
+                       // buggy browsers will return fewer than the correct 2\r
+                       document.getElementsByName( expando ).length === 2 +\r
+                       // buggy browsers will return more than the correct 0\r
+                       document.getElementsByName( expando + 0 ).length;\r
+               assertGetIdNotName = !document.getElementById( expando );\r
+\r
+               // Cleanup\r
+               docElem.removeChild( div );\r
+\r
+               return pass;\r
+       });\r
+\r
+// If slice is not available, provide a backup\r
+try {\r
+       slice.call( docElem.childNodes, 0 )[0].nodeType;\r
+} catch ( e ) {\r
+       slice = function( i ) {\r
+               var elem,\r
+                       results = [];\r
+               for ( ; (elem = this[i]); i++ ) {\r
+                       results.push( elem );\r
+               }\r
+               return results;\r
+       };\r
+}\r
+\r
+function Sizzle( selector, context, results, seed ) {\r
+       results = results || [];\r
+       context = context || document;\r
+       var match, elem, xml, m,\r
+               nodeType = context.nodeType;\r
+\r
+       if ( !selector || typeof selector !== "string" ) {\r
+               return results;\r
+       }\r
+\r
+       if ( nodeType !== 1 && nodeType !== 9 ) {\r
+               return [];\r
+       }\r
+\r
+       xml = isXML( context );\r
+\r
+       if ( !xml && !seed ) {\r
+               if ( (match = rquickExpr.exec( selector )) ) {\r
+                       // Speed-up: Sizzle("#ID")\r
+                       if ( (m = match[1]) ) {\r
+                               if ( nodeType === 9 ) {\r
+                                       elem = context.getElementById( m );\r
+                                       // Check parentNode to catch when Blackberry 4.6 returns\r
+                                       // nodes that are no longer in the document #6963\r
+                                       if ( elem && elem.parentNode ) {\r
+                                               // Handle the case where IE, Opera, and Webkit return items\r
+                                               // by name instead of ID\r
+                                               if ( elem.id === m ) {\r
+                                                       results.push( elem );\r
+                                                       return results;\r
+                                               }\r
+                                       } else {\r
+                                               return results;\r
+                                       }\r
+                               } else {\r
+                                       // Context is not a document\r
+                                       if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\r
+                                               contains( context, elem ) && elem.id === m ) {\r
+                                               results.push( elem );\r
+                                               return results;\r
+                                       }\r
+                               }\r
+\r
+                       // Speed-up: Sizzle("TAG")\r
+                       } else if ( match[2] ) {\r
+                               push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );\r
+                               return results;\r
+\r
+                       // Speed-up: Sizzle(".CLASS")\r
+                       } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) {\r
+                               push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );\r
+                               return results;\r
+                       }\r
+               }\r
+       }\r
+\r
+       // All others\r
+       return select( selector.replace( rtrim, "$1" ), context, results, seed, xml );\r
+}\r
+\r
+Sizzle.matches = function( expr, elements ) {\r
+       return Sizzle( expr, null, null, elements );\r
+};\r
+\r
+Sizzle.matchesSelector = function( elem, expr ) {\r
+       return Sizzle( expr, null, null, [ elem ] ).length > 0;\r
+};\r
+\r
+// Returns a function to use in pseudos for input types\r
+function createInputPseudo( type ) {\r
+       return function( elem ) {\r
+               var name = elem.nodeName.toLowerCase();\r
+               return name === "input" && elem.type === type;\r
+       };\r
+}\r
+\r
+// Returns a function to use in pseudos for buttons\r
+function createButtonPseudo( type ) {\r
+       return function( elem ) {\r
+               var name = elem.nodeName.toLowerCase();\r
+               return (name === "input" || name === "button") && elem.type === type;\r
+       };\r
+}\r
+\r
+// Returns a function to use in pseudos for positionals\r
+function createPositionalPseudo( fn ) {\r
+       return markFunction(function( argument ) {\r
+               argument = +argument;\r
+               return markFunction(function( seed, matches ) {\r
+                       var j,\r
+                               matchIndexes = fn( [], seed.length, argument ),\r
+                               i = matchIndexes.length;\r
+\r
+                       // Match elements found at the specified indexes\r
+                       while ( i-- ) {\r
+                               if ( seed[ (j = matchIndexes[i]) ] ) {\r
+                                       seed[j] = !(matches[j] = seed[j]);\r
+                               }\r
+                       }\r
+               });\r
+       });\r
+}\r
+\r
+/**\r
+ * Utility function for retrieving the text value of an array of DOM nodes\r
+ * @param {Array|Element} elem\r
+ */\r
+getText = Sizzle.getText = function( elem ) {\r
+       var node,\r
+               ret = "",\r
+               i = 0,\r
+               nodeType = elem.nodeType;\r
+\r
+       if ( nodeType ) {\r
+               if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\r
+                       // Use textContent for elements\r
+                       // innerText usage removed for consistency of new lines (see #11153)\r
+                       if ( typeof elem.textContent === "string" ) {\r
+                               return elem.textContent;\r
+                       } else {\r
+                               // Traverse its children\r
+                               for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\r
+                                       ret += getText( elem );\r
+                               }\r
+                       }\r
+               } else if ( nodeType === 3 || nodeType === 4 ) {\r
+                       return elem.nodeValue;\r
+               }\r
+               // Do not include comment or processing instruction nodes\r
+       } else {\r
+\r
+               // If no nodeType, this is expected to be an array\r
+               for ( ; (node = elem[i]); i++ ) {\r
+                       // Do not traverse comment nodes\r
+                       ret += getText( node );\r
+               }\r
+       }\r
+       return ret;\r
+};\r
+\r
+isXML = Sizzle.isXML = function( elem ) {\r
+       // documentElement is verified for cases where it doesn't yet exist\r
+       // (such as loading iframes in IE - #4833)\r
+       var documentElement = elem && (elem.ownerDocument || elem).documentElement;\r
+       return documentElement ? documentElement.nodeName !== "HTML" : false;\r
+};\r
+\r
+// Element contains another\r
+contains = Sizzle.contains = docElem.contains ?\r
+       function( a, b ) {\r
+               var adown = a.nodeType === 9 ? a.documentElement : a,\r
+                       bup = b && b.parentNode;\r
+               return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );\r
+       } :\r
+       docElem.compareDocumentPosition ?\r
+       function( a, b ) {\r
+               return b && !!( a.compareDocumentPosition( b ) & 16 );\r
+       } :\r
+       function( a, b ) {\r
+               while ( (b = b.parentNode) ) {\r
+                       if ( b === a ) {\r
+                               return true;\r
+                       }\r
+               }\r
+               return false;\r
+       };\r
+\r
+Sizzle.attr = function( elem, name ) {\r
+       var val,\r
+               xml = isXML( elem );\r
+\r
+       if ( !xml ) {\r
+               name = name.toLowerCase();\r
+       }\r
+       if ( (val = Expr.attrHandle[ name ]) ) {\r
+               return val( elem );\r
+       }\r
+       if ( xml || assertAttributes ) {\r
+               return elem.getAttribute( name );\r
+       }\r
+       val = elem.getAttributeNode( name );\r
+       return val ?\r
+               typeof elem[ name ] === "boolean" ?\r
+                       elem[ name ] ? name : null :\r
+                       val.specified ? val.value : null :\r
+               null;\r
+};\r
+\r
+Expr = Sizzle.selectors = {\r
+\r
+       // Can be adjusted by the user\r
+       cacheLength: 50,\r
+\r
+       createPseudo: markFunction,\r
+\r
+       match: matchExpr,\r
+\r
+       // IE6/7 return a modified href\r
+       attrHandle: assertHrefNotNormalized ?\r
+               {} :\r
+               {\r
+                       "href": function( elem ) {\r
+                               return elem.getAttribute( "href", 2 );\r
+                       },\r
+                       "type": function( elem ) {\r
+                               return elem.getAttribute("type");\r
+                       }\r
+               },\r
+\r
+       find: {\r
+               "ID": assertGetIdNotName ?\r
+                       function( id, context, xml ) {\r
+                               if ( typeof context.getElementById !== strundefined && !xml ) {\r
+                                       var m = context.getElementById( id );\r
+                                       // Check parentNode to catch when Blackberry 4.6 returns\r
+                                       // nodes that are no longer in the document #6963\r
+                                       return m && m.parentNode ? [m] : [];\r
+                               }\r
+                       } :\r
+                       function( id, context, xml ) {\r
+                               if ( typeof context.getElementById !== strundefined && !xml ) {\r
+                                       var m = context.getElementById( id );\r
+\r
+                                       return m ?\r
+                                               m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?\r
+                                                       [m] :\r
+                                                       undefined :\r
+                                               [];\r
+                               }\r
+                       },\r
+\r
+               "TAG": assertTagNameNoComments ?\r
+                       function( tag, context ) {\r
+                               if ( typeof context.getElementsByTagName !== strundefined ) {\r
+                                       return context.getElementsByTagName( tag );\r
+                               }\r
+                       } :\r
+                       function( tag, context ) {\r
+                               var results = context.getElementsByTagName( tag );\r
+\r
+                               // Filter out possible comments\r
+                               if ( tag === "*" ) {\r
+                                       var elem,\r
+                                               tmp = [],\r
+                                               i = 0;\r
+\r
+                                       for ( ; (elem = results[i]); i++ ) {\r
+                                               if ( elem.nodeType === 1 ) {\r
+                                                       tmp.push( elem );\r
+                                               }\r
+                                       }\r
+\r
+                                       return tmp;\r
+                               }\r
+                               return results;\r
+                       },\r
+\r
+               "NAME": assertUsableName && function( tag, context ) {\r
+                       if ( typeof context.getElementsByName !== strundefined ) {\r
+                               return context.getElementsByName( name );\r
+                       }\r
+               },\r
+\r
+               "CLASS": assertUsableClassName && function( className, context, xml ) {\r
+                       if ( typeof context.getElementsByClassName !== strundefined && !xml ) {\r
+                               return context.getElementsByClassName( className );\r
+                       }\r
+               }\r
+       },\r
+\r
+       relative: {\r
+               ">": { dir: "parentNode", first: true },\r
+               " ": { dir: "parentNode" },\r
+               "+": { dir: "previousSibling", first: true },\r
+               "~": { dir: "previousSibling" }\r
+       },\r
+\r
+       preFilter: {\r
+               "ATTR": function( match ) {\r
+                       match[1] = match[1].replace( rbackslash, "" );\r
+\r
+                       // Move the given value to match[3] whether quoted or unquoted\r
+                       match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" );\r
+\r
+                       if ( match[2] === "~=" ) {\r
+                               match[3] = " " + match[3] + " ";\r
+                       }\r
+\r
+                       return match.slice( 0, 4 );\r
+               },\r
+\r
+               "CHILD": function( match ) {\r
+                       /* matches from matchExpr["CHILD"]\r
+                               1 type (only|nth|...)\r
+                               2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)\r
+                               3 xn-component of xn+y argument ([+-]?\d*n|)\r
+                               4 sign of xn-component\r
+                               5 x of xn-component\r
+                               6 sign of y-component\r
+                               7 y of y-component\r
+                       */\r
+                       match[1] = match[1].toLowerCase();\r
+\r
+                       if ( match[1] === "nth" ) {\r
+                               // nth-child requires argument\r
+                               if ( !match[2] ) {\r
+                                       Sizzle.error( match[0] );\r
+                               }\r
+\r
+                               // numeric x and y parameters for Expr.filter.CHILD\r
+                               // remember that false/true cast respectively to 0/1\r
+                               match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) );\r
+                               match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" );\r
+\r
+                       // other types prohibit arguments\r
+                       } else if ( match[2] ) {\r
+                               Sizzle.error( match[0] );\r
+                       }\r
+\r
+                       return match;\r
+               },\r
+\r
+               "PSEUDO": function( match ) {\r
+                       var unquoted, excess;\r
+                       if ( matchExpr["CHILD"].test( match[0] ) ) {\r
+                               return null;\r
+                       }\r
+\r
+                       if ( match[3] ) {\r
+                               match[2] = match[3];\r
+                       } else if ( (unquoted = match[4]) ) {\r
+                               // Only check arguments that contain a pseudo\r
+                               if ( rpseudo.test(unquoted) &&\r
+                                       // Get excess from tokenize (recursively)\r
+                                       (excess = tokenize( unquoted, true )) &&\r
+                                       // advance to the next closing parenthesis\r
+                                       (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {\r
+\r
+                                       // excess is a negative index\r
+                                       unquoted = unquoted.slice( 0, excess );\r
+                                       match[0] = match[0].slice( 0, excess );\r
+                               }\r
+                               match[2] = unquoted;\r
+                       }\r
+\r
+                       // Return only captures needed by the pseudo filter method (type and argument)\r
+                       return match.slice( 0, 3 );\r
+               }\r
+       },\r
+\r
+       filter: {\r
+               "ID": assertGetIdNotName ?\r
+                       function( id ) {\r
+                               id = id.replace( rbackslash, "" );\r
+                               return function( elem ) {\r
+                                       return elem.getAttribute("id") === id;\r
+                               };\r
+                       } :\r
+                       function( id ) {\r
+                               id = id.replace( rbackslash, "" );\r
+                               return function( elem ) {\r
+                                       var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");\r
+                                       return node && node.value === id;\r
+                               };\r
+                       },\r
+\r
+               "TAG": function( nodeName ) {\r
+                       if ( nodeName === "*" ) {\r
+                               return function() { return true; };\r
+                       }\r
+                       nodeName = nodeName.replace( rbackslash, "" ).toLowerCase();\r
+\r
+                       return function( elem ) {\r
+                               return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\r
+                       };\r
+               },\r
+\r
+               "CLASS": function( className ) {\r
+                       var pattern = classCache[ expando ][ className + " " ];\r
+\r
+                       return pattern ||\r
+                               (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&\r
+                               classCache( className, function( elem ) {\r
+                                       return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );\r
+                               });\r
+               },\r
+\r
+               "ATTR": function( name, operator, check ) {\r
+                       return function( elem, context ) {\r
+                               var result = Sizzle.attr( elem, name );\r
+\r
+                               if ( result == null ) {\r
+                                       return operator === "!=";\r
+                               }\r
+                               if ( !operator ) {\r
+                                       return true;\r
+                               }\r
+\r
+                               result += "";\r
+\r
+                               return operator === "=" ? result === check :\r
+                                       operator === "!=" ? result !== check :\r
+                                       operator === "^=" ? check && result.indexOf( check ) === 0 :\r
+                                       operator === "*=" ? check && result.indexOf( check ) > -1 :\r
+                                       operator === "$=" ? check && result.substr( result.length - check.length ) === check :\r
+                                       operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :\r
+                                       operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" :\r
+                                       false;\r
+                       };\r
+               },\r
+\r
+               "CHILD": function( type, argument, first, last ) {\r
+\r
+                       if ( type === "nth" ) {\r
+                               return function( elem ) {\r
+                                       var node, diff,\r
+                                               parent = elem.parentNode;\r
+\r
+                                       if ( first === 1 && last === 0 ) {\r
+                                               return true;\r
+                                       }\r
+\r
+                                       if ( parent ) {\r
+                                               diff = 0;\r
+                                               for ( node = parent.firstChild; node; node = node.nextSibling ) {\r
+                                                       if ( node.nodeType === 1 ) {\r
+                                                               diff++;\r
+                                                               if ( elem === node ) {\r
+                                                                       break;\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+                                       }\r
+\r
+                                       // Incorporate the offset (or cast to NaN), then check against cycle size\r
+                                       diff -= last;\r
+                                       return diff === first || ( diff % first === 0 && diff / first >= 0 );\r
+                               };\r
+                       }\r
+\r
+                       return function( elem ) {\r
+                               var node = elem;\r
+\r
+                               switch ( type ) {\r
+                                       case "only":\r
+                                       case "first":\r
+                                               while ( (node = node.previousSibling) ) {\r
+                                                       if ( node.nodeType === 1 ) {\r
+                                                               return false;\r
+                                                       }\r
+                                               }\r
+\r
+                                               if ( type === "first" ) {\r
+                                                       return true;\r
+                                               }\r
+\r
+                                               node = elem;\r
+\r
+                                               /* falls through */\r
+                                       case "last":\r
+                                               while ( (node = node.nextSibling) ) {\r
+                                                       if ( node.nodeType === 1 ) {\r
+                                                               return false;\r
+                                                       }\r
+                                               }\r
+\r
+                                               return true;\r
+                               }\r
+                       };\r
+               },\r
+\r
+               "PSEUDO": function( pseudo, argument ) {\r
+                       // pseudo-class names are case-insensitive\r
+                       // http://www.w3.org/TR/selectors/#pseudo-classes\r
+                       // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\r
+                       // Remember that setFilters inherits from pseudos\r
+                       var args,\r
+                               fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\r
+                                       Sizzle.error( "unsupported pseudo: " + pseudo );\r
+\r
+                       // The user may use createPseudo to indicate that\r
+                       // arguments are needed to create the filter function\r
+                       // just as Sizzle does\r
+                       if ( fn[ expando ] ) {\r
+                               return fn( argument );\r
+                       }\r
+\r
+                       // But maintain support for old signatures\r
+                       if ( fn.length > 1 ) {\r
+                               args = [ pseudo, pseudo, "", argument ];\r
+                               return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\r
+                                       markFunction(function( seed, matches ) {\r
+                                               var idx,\r
+                                                       matched = fn( seed, argument ),\r
+                                                       i = matched.length;\r
+                                               while ( i-- ) {\r
+                                                       idx = indexOf.call( seed, matched[i] );\r
+                                                       seed[ idx ] = !( matches[ idx ] = matched[i] );\r
+                                               }\r
+                                       }) :\r
+                                       function( elem ) {\r
+                                               return fn( elem, 0, args );\r
+                                       };\r
+                       }\r
+\r
+                       return fn;\r
+               }\r
+       },\r
+\r
+       pseudos: {\r
+               "not": markFunction(function( selector ) {\r
+                       // Trim the selector passed to compile\r
+                       // to avoid treating leading and trailing\r
+                       // spaces as combinators\r
+                       var input = [],\r
+                               results = [],\r
+                               matcher = compile( selector.replace( rtrim, "$1" ) );\r
+\r
+                       return matcher[ expando ] ?\r
+                               markFunction(function( seed, matches, context, xml ) {\r
+                                       var elem,\r
+                                               unmatched = matcher( seed, null, xml, [] ),\r
+                                               i = seed.length;\r
+\r
+                                       // Match elements unmatched by `matcher`\r
+                                       while ( i-- ) {\r
+                                               if ( (elem = unmatched[i]) ) {\r
+                                                       seed[i] = !(matches[i] = elem);\r
+                                               }\r
+                                       }\r
+                               }) :\r
+                               function( elem, context, xml ) {\r
+                                       input[0] = elem;\r
+                                       matcher( input, null, xml, results );\r
+                                       return !results.pop();\r
+                               };\r
+               }),\r
+\r
+               "has": markFunction(function( selector ) {\r
+                       return function( elem ) {\r
+                               return Sizzle( selector, elem ).length > 0;\r
+                       };\r
+               }),\r
+\r
+               "contains": markFunction(function( text ) {\r
+                       return function( elem ) {\r
+                               return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\r
+                       };\r
+               }),\r
+\r
+               "enabled": function( elem ) {\r
+                       return elem.disabled === false;\r
+               },\r
+\r
+               "disabled": function( elem ) {\r
+                       return elem.disabled === true;\r
+               },\r
+\r
+               "checked": function( elem ) {\r
+                       // In CSS3, :checked should return both checked and selected elements\r
+                       // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\r
+                       var nodeName = elem.nodeName.toLowerCase();\r
+                       return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);\r
+               },\r
+\r
+               "selected": function( elem ) {\r
+                       // Accessing this property makes selected-by-default\r
+                       // options in Safari work properly\r
+                       if ( elem.parentNode ) {\r
+                               elem.parentNode.selectedIndex;\r
+                       }\r
+\r
+                       return elem.selected === true;\r
+               },\r
+\r
+               "parent": function( elem ) {\r
+                       return !Expr.pseudos["empty"]( elem );\r
+               },\r
+\r
+               "empty": function( elem ) {\r
+                       // http://www.w3.org/TR/selectors/#empty-pseudo\r
+                       // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),\r
+                       //   not comment, processing instructions, or others\r
+                       // Thanks to Diego Perini for the nodeName shortcut\r
+                       //   Greater than "@" means alpha characters (specifically not starting with "#" or "?")\r
+                       var nodeType;\r
+                       elem = elem.firstChild;\r
+                       while ( elem ) {\r
+                               if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) {\r
+                                       return false;\r
+                               }\r
+                               elem = elem.nextSibling;\r
+                       }\r
+                       return true;\r
+               },\r
+\r
+               "header": function( elem ) {\r
+                       return rheader.test( elem.nodeName );\r
+               },\r
+\r
+               "text": function( elem ) {\r
+                       var type, attr;\r
+                       // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\r
+                       // use getAttribute instead to test this case\r
+                       return elem.nodeName.toLowerCase() === "input" &&\r
+                               (type = elem.type) === "text" &&\r
+                               ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type );\r
+               },\r
+\r
+               // Input types\r
+               "radio": createInputPseudo("radio"),\r
+               "checkbox": createInputPseudo("checkbox"),\r
+               "file": createInputPseudo("file"),\r
+               "password": createInputPseudo("password"),\r
+               "image": createInputPseudo("image"),\r
+\r
+               "submit": createButtonPseudo("submit"),\r
+               "reset": createButtonPseudo("reset"),\r
+\r
+               "button": function( elem ) {\r
+                       var name = elem.nodeName.toLowerCase();\r
+                       return name === "input" && elem.type === "button" || name === "button";\r
+               },\r
+\r
+               "input": function( elem ) {\r
+                       return rinputs.test( elem.nodeName );\r
+               },\r
+\r
+               "focus": function( elem ) {\r
+                       var doc = elem.ownerDocument;\r
+                       return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\r
+               },\r
+\r
+               "active": function( elem ) {\r
+                       return elem === elem.ownerDocument.activeElement;\r
+               },\r
+\r
+               // Positional types\r
+               "first": createPositionalPseudo(function() {\r
+                       return [ 0 ];\r
+               }),\r
+\r
+               "last": createPositionalPseudo(function( matchIndexes, length ) {\r
+                       return [ length - 1 ];\r
+               }),\r
+\r
+               "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {\r
+                       return [ argument < 0 ? argument + length : argument ];\r
+               }),\r
+\r
+               "even": createPositionalPseudo(function( matchIndexes, length ) {\r
+                       for ( var i = 0; i < length; i += 2 ) {\r
+                               matchIndexes.push( i );\r
+                       }\r
+                       return matchIndexes;\r
+               }),\r
+\r
+               "odd": createPositionalPseudo(function( matchIndexes, length ) {\r
+                       for ( var i = 1; i < length; i += 2 ) {\r
+                               matchIndexes.push( i );\r
+                       }\r
+                       return matchIndexes;\r
+               }),\r
+\r
+               "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {\r
+                       for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) {\r
+                               matchIndexes.push( i );\r
+                       }\r
+                       return matchIndexes;\r
+               }),\r
+\r
+               "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {\r
+                       for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) {\r
+                               matchIndexes.push( i );\r
+                       }\r
+                       return matchIndexes;\r
+               })\r
+       }\r
+};\r
+\r
+function siblingCheck( a, b, ret ) {\r
+       if ( a === b ) {\r
+               return ret;\r
+       }\r
+\r
+       var cur = a.nextSibling;\r
+\r
+       while ( cur ) {\r
+               if ( cur === b ) {\r
+                       return -1;\r
+               }\r
+\r
+               cur = cur.nextSibling;\r
+       }\r
+\r
+       return 1;\r
+}\r
+\r
+sortOrder = docElem.compareDocumentPosition ?\r
+       function( a, b ) {\r
+               if ( a === b ) {\r
+                       hasDuplicate = true;\r
+                       return 0;\r
+               }\r
+\r
+               return ( !a.compareDocumentPosition || !b.compareDocumentPosition ?\r
+                       a.compareDocumentPosition :\r
+                       a.compareDocumentPosition(b) & 4\r
+               ) ? -1 : 1;\r
+       } :\r
+       function( a, b ) {\r
+               // The nodes are identical, we can exit early\r
+               if ( a === b ) {\r
+                       hasDuplicate = true;\r
+                       return 0;\r
+\r
+               // Fallback to using sourceIndex (in IE) if it's available on both nodes\r
+               } else if ( a.sourceIndex && b.sourceIndex ) {\r
+                       return a.sourceIndex - b.sourceIndex;\r
+               }\r
+\r
+               var al, bl,\r
+                       ap = [],\r
+                       bp = [],\r
+                       aup = a.parentNode,\r
+                       bup = b.parentNode,\r
+                       cur = aup;\r
+\r
+               // If the nodes are siblings (or identical) we can do a quick check\r
+               if ( aup === bup ) {\r
+                       return siblingCheck( a, b );\r
+\r
+               // If no parents were found then the nodes are disconnected\r
+               } else if ( !aup ) {\r
+                       return -1;\r
+\r
+               } else if ( !bup ) {\r
+                       return 1;\r
+               }\r
+\r
+               // Otherwise they're somewhere else in the tree so we need\r
+               // to build up a full list of the parentNodes for comparison\r
+               while ( cur ) {\r
+                       ap.unshift( cur );\r
+                       cur = cur.parentNode;\r
+               }\r
+\r
+               cur = bup;\r
+\r
+               while ( cur ) {\r
+                       bp.unshift( cur );\r
+                       cur = cur.parentNode;\r
+               }\r
+\r
+               al = ap.length;\r
+               bl = bp.length;\r
+\r
+               // Start walking down the tree looking for a discrepancy\r
+               for ( var i = 0; i < al && i < bl; i++ ) {\r
+                       if ( ap[i] !== bp[i] ) {\r
+                               return siblingCheck( ap[i], bp[i] );\r
+                       }\r
+               }\r
+\r
+               // We ended someplace up the tree so do a sibling check\r
+               return i === al ?\r
+                       siblingCheck( a, bp[i], -1 ) :\r
+                       siblingCheck( ap[i], b, 1 );\r
+       };\r
+\r
+// Always assume the presence of duplicates if sort doesn't\r
+// pass them to our comparison function (as in Google Chrome).\r
+[0, 0].sort( sortOrder );\r
+baseHasDuplicate = !hasDuplicate;\r
+\r
+// Document sorting and removing duplicates\r
+Sizzle.uniqueSort = function( results ) {\r
+       var elem,\r
+               duplicates = [],\r
+               i = 1,\r
+               j = 0;\r
+\r
+       hasDuplicate = baseHasDuplicate;\r
+       results.sort( sortOrder );\r
+\r
+       if ( hasDuplicate ) {\r
+               for ( ; (elem = results[i]); i++ ) {\r
+                       if ( elem === results[ i - 1 ] ) {\r
+                               j = duplicates.push( i );\r
+                       }\r
+               }\r
+               while ( j-- ) {\r
+                       results.splice( duplicates[ j ], 1 );\r
+               }\r
+       }\r
+\r
+       return results;\r
+};\r
+\r
+Sizzle.error = function( msg ) {\r
+       throw new Error( "Syntax error, unrecognized expression: " + msg );\r
+};\r
+\r
+function tokenize( selector, parseOnly ) {\r
+       var matched, match, tokens, type,\r
+               soFar, groups, preFilters,\r
+               cached = tokenCache[ expando ][ selector + " " ];\r
+\r
+       if ( cached ) {\r
+               return parseOnly ? 0 : cached.slice( 0 );\r
+       }\r
+\r
+       soFar = selector;\r
+       groups = [];\r
+       preFilters = Expr.preFilter;\r
+\r
+       while ( soFar ) {\r
+\r
+               // Comma and first run\r
+               if ( !matched || (match = rcomma.exec( soFar )) ) {\r
+                       if ( match ) {\r
+                               // Don't consume trailing commas as valid\r
+                               soFar = soFar.slice( match[0].length ) || soFar;\r
+                       }\r
+                       groups.push( tokens = [] );\r
+               }\r
+\r
+               matched = false;\r
+\r
+               // Combinators\r
+               if ( (match = rcombinators.exec( soFar )) ) {\r
+                       tokens.push( matched = new Token( match.shift() ) );\r
+                       soFar = soFar.slice( matched.length );\r
+\r
+                       // Cast descendant combinators to space\r
+                       matched.type = match[0].replace( rtrim, " " );\r
+               }\r
+\r
+               // Filters\r
+               for ( type in Expr.filter ) {\r
+                       if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\r
+                               (match = preFilters[ type ]( match ))) ) {\r
+\r
+                               tokens.push( matched = new Token( match.shift() ) );\r
+                               soFar = soFar.slice( matched.length );\r
+                               matched.type = type;\r
+                               matched.matches = match;\r
+                       }\r
+               }\r
+\r
+               if ( !matched ) {\r
+                       break;\r
+               }\r
+       }\r
+\r
+       // Return the length of the invalid excess\r
+       // if we're just parsing\r
+       // Otherwise, throw an error or return tokens\r
+       return parseOnly ?\r
+               soFar.length :\r
+               soFar ?\r
+                       Sizzle.error( selector ) :\r
+                       // Cache the tokens\r
+                       tokenCache( selector, groups ).slice( 0 );\r
+}\r
+\r
+function addCombinator( matcher, combinator, base ) {\r
+       var dir = combinator.dir,\r
+               checkNonElements = base && combinator.dir === "parentNode",\r
+               doneName = done++;\r
+\r
+       return combinator.first ?\r
+               // Check against closest ancestor/preceding element\r
+               function( elem, context, xml ) {\r
+                       while ( (elem = elem[ dir ]) ) {\r
+                               if ( checkNonElements || elem.nodeType === 1  ) {\r
+                                       return matcher( elem, context, xml );\r
+                               }\r
+                       }\r
+               } :\r
+\r
+               // Check against all ancestor/preceding elements\r
+               function( elem, context, xml ) {\r
+                       // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\r
+                       if ( !xml ) {\r
+                               var cache,\r
+                                       dirkey = dirruns + " " + doneName + " ",\r
+                                       cachedkey = dirkey + cachedruns;\r
+                               while ( (elem = elem[ dir ]) ) {\r
+                                       if ( checkNonElements || elem.nodeType === 1 ) {\r
+                                               if ( (cache = elem[ expando ]) === cachedkey ) {\r
+                                                       return elem.sizset;\r
+                                               } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) {\r
+                                                       if ( elem.sizset ) {\r
+                                                               return elem;\r
+                                                       }\r
+                                               } else {\r
+                                                       elem[ expando ] = cachedkey;\r
+                                                       if ( matcher( elem, context, xml ) ) {\r
+                                                               elem.sizset = true;\r
+                                                               return elem;\r
+                                                       }\r
+                                                       elem.sizset = false;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       } else {\r
+                               while ( (elem = elem[ dir ]) ) {\r
+                                       if ( checkNonElements || elem.nodeType === 1 ) {\r
+                                               if ( matcher( elem, context, xml ) ) {\r
+                                                       return elem;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+               };\r
+}\r
+\r
+function elementMatcher( matchers ) {\r
+       return matchers.length > 1 ?\r
+               function( elem, context, xml ) {\r
+                       var i = matchers.length;\r
+                       while ( i-- ) {\r
+                               if ( !matchers[i]( elem, context, xml ) ) {\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       return true;\r
+               } :\r
+               matchers[0];\r
+}\r
+\r
+function condense( unmatched, map, filter, context, xml ) {\r
+       var elem,\r
+               newUnmatched = [],\r
+               i = 0,\r
+               len = unmatched.length,\r
+               mapped = map != null;\r
+\r
+       for ( ; i < len; i++ ) {\r
+               if ( (elem = unmatched[i]) ) {\r
+                       if ( !filter || filter( elem, context, xml ) ) {\r
+                               newUnmatched.push( elem );\r
+                               if ( mapped ) {\r
+                                       map.push( i );\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       return newUnmatched;\r
+}\r
+\r
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\r
+       if ( postFilter && !postFilter[ expando ] ) {\r
+               postFilter = setMatcher( postFilter );\r
+       }\r
+       if ( postFinder && !postFinder[ expando ] ) {\r
+               postFinder = setMatcher( postFinder, postSelector );\r
+       }\r
+       return markFunction(function( seed, results, context, xml ) {\r
+               var temp, i, elem,\r
+                       preMap = [],\r
+                       postMap = [],\r
+                       preexisting = results.length,\r
+\r
+                       // Get initial elements from seed or context\r
+                       elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),\r
+\r
+                       // Prefilter to get matcher input, preserving a map for seed-results synchronization\r
+                       matcherIn = preFilter && ( seed || !selector ) ?\r
+                               condense( elems, preMap, preFilter, context, xml ) :\r
+                               elems,\r
+\r
+                       matcherOut = matcher ?\r
+                               // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\r
+                               postFinder || ( seed ? preFilter : preexisting || postFilter ) ?\r
+\r
+                                       // ...intermediate processing is necessary\r
+                                       [] :\r
+\r
+                                       // ...otherwise use results directly\r
+                                       results :\r
+                               matcherIn;\r
+\r
+               // Find primary matches\r
+               if ( matcher ) {\r
+                       matcher( matcherIn, matcherOut, context, xml );\r
+               }\r
+\r
+               // Apply postFilter\r
+               if ( postFilter ) {\r
+                       temp = condense( matcherOut, postMap );\r
+                       postFilter( temp, [], context, xml );\r
+\r
+                       // Un-match failing elements by moving them back to matcherIn\r
+                       i = temp.length;\r
+                       while ( i-- ) {\r
+                               if ( (elem = temp[i]) ) {\r
+                                       matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if ( seed ) {\r
+                       if ( postFinder || preFilter ) {\r
+                               if ( postFinder ) {\r
+                                       // Get the final matcherOut by condensing this intermediate into postFinder contexts\r
+                                       temp = [];\r
+                                       i = matcherOut.length;\r
+                                       while ( i-- ) {\r
+                                               if ( (elem = matcherOut[i]) ) {\r
+                                                       // Restore matcherIn since elem is not yet a final match\r
+                                                       temp.push( (matcherIn[i] = elem) );\r
+                                               }\r
+                                       }\r
+                                       postFinder( null, (matcherOut = []), temp, xml );\r
+                               }\r
+\r
+                               // Move matched elements from seed to results to keep them synchronized\r
+                               i = matcherOut.length;\r
+                               while ( i-- ) {\r
+                                       if ( (elem = matcherOut[i]) &&\r
+                                               (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {\r
+\r
+                                               seed[temp] = !(results[temp] = elem);\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+               // Add elements to results, through postFinder if defined\r
+               } else {\r
+                       matcherOut = condense(\r
+                               matcherOut === results ?\r
+                                       matcherOut.splice( preexisting, matcherOut.length ) :\r
+                                       matcherOut\r
+                       );\r
+                       if ( postFinder ) {\r
+                               postFinder( null, results, matcherOut, xml );\r
+                       } else {\r
+                               push.apply( results, matcherOut );\r
+                       }\r
+               }\r
+       });\r
+}\r
+\r
+function matcherFromTokens( tokens ) {\r
+       var checkContext, matcher, j,\r
+               len = tokens.length,\r
+               leadingRelative = Expr.relative[ tokens[0].type ],\r
+               implicitRelative = leadingRelative || Expr.relative[" "],\r
+               i = leadingRelative ? 1 : 0,\r
+\r
+               // The foundational matcher ensures that elements are reachable from top-level context(s)\r
+               matchContext = addCombinator( function( elem ) {\r
+                       return elem === checkContext;\r
+               }, implicitRelative, true ),\r
+               matchAnyContext = addCombinator( function( elem ) {\r
+                       return indexOf.call( checkContext, elem ) > -1;\r
+               }, implicitRelative, true ),\r
+               matchers = [ function( elem, context, xml ) {\r
+                       return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\r
+                               (checkContext = context).nodeType ?\r
+                                       matchContext( elem, context, xml ) :\r
+                                       matchAnyContext( elem, context, xml ) );\r
+               } ];\r
+\r
+       for ( ; i < len; i++ ) {\r
+               if ( (matcher = Expr.relative[ tokens[i].type ]) ) {\r
+                       matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];\r
+               } else {\r
+                       matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\r
+\r
+                       // Return special upon seeing a positional matcher\r
+                       if ( matcher[ expando ] ) {\r
+                               // Find the next relative operator (if any) for proper handling\r
+                               j = ++i;\r
+                               for ( ; j < len; j++ ) {\r
+                                       if ( Expr.relative[ tokens[j].type ] ) {\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               return setMatcher(\r
+                                       i > 1 && elementMatcher( matchers ),\r
+                                       i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ),\r
+                                       matcher,\r
+                                       i < j && matcherFromTokens( tokens.slice( i, j ) ),\r
+                                       j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\r
+                                       j < len && tokens.join("")\r
+                               );\r
+                       }\r
+                       matchers.push( matcher );\r
+               }\r
+       }\r
+\r
+       return elementMatcher( matchers );\r
+}\r
+\r
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {\r
+       var bySet = setMatchers.length > 0,\r
+               byElement = elementMatchers.length > 0,\r
+               superMatcher = function( seed, context, xml, results, expandContext ) {\r
+                       var elem, j, matcher,\r
+                               setMatched = [],\r
+                               matchedCount = 0,\r
+                               i = "0",\r
+                               unmatched = seed && [],\r
+                               outermost = expandContext != null,\r
+                               contextBackup = outermostContext,\r
+                               // We must always have either seed elements or context\r
+                               elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),\r
+                               // Nested matchers should use non-integer dirruns\r
+                               dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);\r
+\r
+                       if ( outermost ) {\r
+                               outermostContext = context !== document && context;\r
+                               cachedruns = superMatcher.el;\r
+                       }\r
+\r
+                       // Add elements passing elementMatchers directly to results\r
+                       for ( ; (elem = elems[i]) != null; i++ ) {\r
+                               if ( byElement && elem ) {\r
+                                       for ( j = 0; (matcher = elementMatchers[j]); j++ ) {\r
+                                               if ( matcher( elem, context, xml ) ) {\r
+                                                       results.push( elem );\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                                       if ( outermost ) {\r
+                                               dirruns = dirrunsUnique;\r
+                                               cachedruns = ++superMatcher.el;\r
+                                       }\r
+                               }\r
+\r
+                               // Track unmatched elements for set filters\r
+                               if ( bySet ) {\r
+                                       // They will have gone through all possible matchers\r
+                                       if ( (elem = !matcher && elem) ) {\r
+                                               matchedCount--;\r
+                                       }\r
+\r
+                                       // Lengthen the array for every element, matched or not\r
+                                       if ( seed ) {\r
+                                               unmatched.push( elem );\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       // Apply set filters to unmatched elements\r
+                       matchedCount += i;\r
+                       if ( bySet && i !== matchedCount ) {\r
+                               for ( j = 0; (matcher = setMatchers[j]); j++ ) {\r
+                                       matcher( unmatched, setMatched, context, xml );\r
+                               }\r
+\r
+                               if ( seed ) {\r
+                                       // Reintegrate element matches to eliminate the need for sorting\r
+                                       if ( matchedCount > 0 ) {\r
+                                               while ( i-- ) {\r
+                                                       if ( !(unmatched[i] || setMatched[i]) ) {\r
+                                                               setMatched[i] = pop.call( results );\r
+                                                       }\r
+                                               }\r
+                                       }\r
+\r
+                                       // Discard index placeholder values to get only actual matches\r
+                                       setMatched = condense( setMatched );\r
+                               }\r
+\r
+                               // Add matches to results\r
+                               push.apply( results, setMatched );\r
+\r
+                               // Seedless set matches succeeding multiple successful matchers stipulate sorting\r
+                               if ( outermost && !seed && setMatched.length > 0 &&\r
+                                       ( matchedCount + setMatchers.length ) > 1 ) {\r
+\r
+                                       Sizzle.uniqueSort( results );\r
+                               }\r
+                       }\r
+\r
+                       // Override manipulation of globals by nested matchers\r
+                       if ( outermost ) {\r
+                               dirruns = dirrunsUnique;\r
+                               outermostContext = contextBackup;\r
+                       }\r
+\r
+                       return unmatched;\r
+               };\r
+\r
+       superMatcher.el = 0;\r
+       return bySet ?\r
+               markFunction( superMatcher ) :\r
+               superMatcher;\r
+}\r
+\r
+compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {\r
+       var i,\r
+               setMatchers = [],\r
+               elementMatchers = [],\r
+               cached = compilerCache[ expando ][ selector + " " ];\r
+\r
+       if ( !cached ) {\r
+               // Generate a function of recursive functions that can be used to check each element\r
+               if ( !group ) {\r
+                       group = tokenize( selector );\r
+               }\r
+               i = group.length;\r
+               while ( i-- ) {\r
+                       cached = matcherFromTokens( group[i] );\r
+                       if ( cached[ expando ] ) {\r
+                               setMatchers.push( cached );\r
+                       } else {\r
+                               elementMatchers.push( cached );\r
+                       }\r
+               }\r
+\r
+               // Cache the compiled function\r
+               cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\r
+       }\r
+       return cached;\r
+};\r
+\r
+function multipleContexts( selector, contexts, results ) {\r
+       var i = 0,\r
+               len = contexts.length;\r
+       for ( ; i < len; i++ ) {\r
+               Sizzle( selector, contexts[i], results );\r
+       }\r
+       return results;\r
+}\r
+\r
+function select( selector, context, results, seed, xml ) {\r
+       var i, tokens, token, type, find,\r
+               match = tokenize( selector ),\r
+               j = match.length;\r
+\r
+       if ( !seed ) {\r
+               // Try to minimize operations if there is only one group\r
+               if ( match.length === 1 ) {\r
+\r
+                       // Take a shortcut and set the context if the root selector is an ID\r
+                       tokens = match[0] = match[0].slice( 0 );\r
+                       if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&\r
+                                       context.nodeType === 9 && !xml &&\r
+                                       Expr.relative[ tokens[1].type ] ) {\r
+\r
+                               context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0];\r
+                               if ( !context ) {\r
+                                       return results;\r
+                               }\r
+\r
+                               selector = selector.slice( tokens.shift().length );\r
+                       }\r
+\r
+                       // Fetch a seed set for right-to-left matching\r
+                       for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) {\r
+                               token = tokens[i];\r
+\r
+                               // Abort if we hit a combinator\r
+                               if ( Expr.relative[ (type = token.type) ] ) {\r
+                                       break;\r
+                               }\r
+                               if ( (find = Expr.find[ type ]) ) {\r
+                                       // Search, expanding context for leading sibling combinators\r
+                                       if ( (seed = find(\r
+                                               token.matches[0].replace( rbackslash, "" ),\r
+                                               rsibling.test( tokens[0].type ) && context.parentNode || context,\r
+                                               xml\r
+                                       )) ) {\r
+\r
+                                               // If seed is empty or no tokens remain, we can return early\r
+                                               tokens.splice( i, 1 );\r
+                                               selector = seed.length && tokens.join("");\r
+                                               if ( !selector ) {\r
+                                                       push.apply( results, slice.call( seed, 0 ) );\r
+                                                       return results;\r
+                                               }\r
+\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       // Compile and execute a filtering function\r
+       // Provide `match` to avoid retokenization if we modified the selector above\r
+       compile( selector, match )(\r
+               seed,\r
+               context,\r
+               xml,\r
+               results,\r
+               rsibling.test( selector )\r
+       );\r
+       return results;\r
+}\r
+\r
+if ( document.querySelectorAll ) {\r
+       (function() {\r
+               var disconnectedMatch,\r
+                       oldSelect = select,\r
+                       rescape = /'|\\/g,\r
+                       rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,\r
+\r
+                       // qSa(:focus) reports false when true (Chrome 21), no need to also add to buggyMatches since matches checks buggyQSA\r
+                       // A support test would require too much code (would include document ready)\r
+                       rbuggyQSA = [ ":focus" ],\r
+\r
+                       // matchesSelector(:active) reports false when true (IE9/Opera 11.5)\r
+                       // A support test would require too much code (would include document ready)\r
+                       // just skip matchesSelector for :active\r
+                       rbuggyMatches = [ ":active" ],\r
+                       matches = docElem.matchesSelector ||\r
+                               docElem.mozMatchesSelector ||\r
+                               docElem.webkitMatchesSelector ||\r
+                               docElem.oMatchesSelector ||\r
+                               docElem.msMatchesSelector;\r
+\r
+               // Build QSA regex\r
+               // Regex strategy adopted from Diego Perini\r
+               assert(function( div ) {\r
+                       // Select is set to empty string on purpose\r
+                       // This is to test IE's treatment of not explictly\r
+                       // setting a boolean content attribute,\r
+                       // since its presence should be enough\r
+                       // http://bugs.jquery.com/ticket/12359\r
+                       div.innerHTML = "<select><option selected=''></option></select>";\r
+\r
+                       // IE8 - Some boolean attributes are not treated correctly\r
+                       if ( !div.querySelectorAll("[selected]").length ) {\r
+                               rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );\r
+                       }\r
+\r
+                       // Webkit/Opera - :checked should return selected option elements\r
+                       // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\r
+                       // IE8 throws error here (do not put tests after this one)\r
+                       if ( !div.querySelectorAll(":checked").length ) {\r
+                               rbuggyQSA.push(":checked");\r
+                       }\r
+               });\r
+\r
+               assert(function( div ) {\r
+\r
+                       // Opera 10-12/IE9 - ^= $= *= and empty values\r
+                       // Should not select anything\r
+                       div.innerHTML = "<p test=''></p>";\r
+                       if ( div.querySelectorAll("[test^='']").length ) {\r
+                               rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );\r
+                       }\r
+\r
+                       // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\r
+                       // IE8 throws error here (do not put tests after this one)\r
+                       div.innerHTML = "<input type='hidden'/>";\r
+                       if ( !div.querySelectorAll(":enabled").length ) {\r
+                               rbuggyQSA.push(":enabled", ":disabled");\r
+                       }\r
+               });\r
+\r
+               // rbuggyQSA always contains :focus, so no need for a length check\r
+               rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") );\r
+\r
+               select = function( selector, context, results, seed, xml ) {\r
+                       // Only use querySelectorAll when not filtering,\r
+                       // when this is not xml,\r
+                       // and when no QSA bugs apply\r
+                       if ( !seed && !xml && !rbuggyQSA.test( selector ) ) {\r
+                               var groups, i,\r
+                                       old = true,\r
+                                       nid = expando,\r
+                                       newContext = context,\r
+                                       newSelector = context.nodeType === 9 && selector;\r
+\r
+                               // qSA works strangely on Element-rooted queries\r
+                               // We can work around this by specifying an extra ID on the root\r
+                               // and working up from there (Thanks to Andrew Dupont for the technique)\r
+                               // IE 8 doesn't work on object elements\r
+                               if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {\r
+                                       groups = tokenize( selector );\r
+\r
+                                       if ( (old = context.getAttribute("id")) ) {\r
+                                               nid = old.replace( rescape, "\\$&" );\r
+                                       } else {\r
+                                               context.setAttribute( "id", nid );\r
+                                       }\r
+                                       nid = "[id='" + nid + "'] ";\r
+\r
+                                       i = groups.length;\r
+                                       while ( i-- ) {\r
+                                               groups[i] = nid + groups[i].join("");\r
+                                       }\r
+                                       newContext = rsibling.test( selector ) && context.parentNode || context;\r
+                                       newSelector = groups.join(",");\r
+                               }\r
+\r
+                               if ( newSelector ) {\r
+                                       try {\r
+                                               push.apply( results, slice.call( newContext.querySelectorAll(\r
+                                                       newSelector\r
+                                               ), 0 ) );\r
+                                               return results;\r
+                                       } catch(qsaError) {\r
+                                       } finally {\r
+                                               if ( !old ) {\r
+                                                       context.removeAttribute("id");\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       return oldSelect( selector, context, results, seed, xml );\r
+               };\r
+\r
+               if ( matches ) {\r
+                       assert(function( div ) {\r
+                               // Check to see if it's possible to do matchesSelector\r
+                               // on a disconnected node (IE 9)\r
+                               disconnectedMatch = matches.call( div, "div" );\r
+\r
+                               // This should fail with an exception\r
+                               // Gecko does not error, returns false instead\r
+                               try {\r
+                                       matches.call( div, "[test!='']:sizzle" );\r
+                                       rbuggyMatches.push( "!=", pseudos );\r
+                               } catch ( e ) {}\r
+                       });\r
+\r
+                       // rbuggyMatches always contains :active and :focus, so no need for a length check\r
+                       rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") );\r
+\r
+                       Sizzle.matchesSelector = function( elem, expr ) {\r
+                               // Make sure that attribute selectors are quoted\r
+                               expr = expr.replace( rattributeQuotes, "='$1']" );\r
+\r
+                               // rbuggyMatches always contains :active, so no need for an existence check\r
+                               if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && !rbuggyQSA.test( expr ) ) {\r
+                                       try {\r
+                                               var ret = matches.call( elem, expr );\r
+\r
+                                               // IE 9's matchesSelector returns false on disconnected nodes\r
+                                               if ( ret || disconnectedMatch ||\r
+                                                               // As well, disconnected nodes are said to be in a document\r
+                                                               // fragment in IE 9\r
+                                                               elem.document && elem.document.nodeType !== 11 ) {\r
+                                                       return ret;\r
+                                               }\r
+                                       } catch(e) {}\r
+                               }\r
+\r
+                               return Sizzle( expr, null, null, [ elem ] ).length > 0;\r
+                       };\r
+               }\r
+       })();\r
+}\r
+\r
+// Deprecated\r
+Expr.pseudos["nth"] = Expr.pseudos["eq"];\r
+\r
+// Back-compat\r
+function setFilters() {}\r
+Expr.filters = setFilters.prototype = Expr.pseudos;\r
+Expr.setFilters = new setFilters();\r
+\r
+// Override sizzle attribute retrieval
+Sizzle.attr = jQuery.attr;
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+\r
+\r
+})( window );\r
+var runtil = /Until$/,
+       rparentsprev = /^(?:parents|prev(?:Until|All))/,
+       isSimple = /^.[^:#\[\.,]*$/,
+       rneedsContext = jQuery.expr.match.needsContext,
+       // methods guaranteed to produce a unique set when starting from a unique set
+       guaranteedUnique = {
+               children: true,
+               contents: true,
+               next: true,
+               prev: true
+       };
+
+jQuery.fn.extend({
+       find: function( selector ) {
+               var i, l, length, n, r, ret,
+                       self = this;
+
+               if ( typeof selector !== "string" ) {
+                       return jQuery( selector ).filter(function() {
+                               for ( i = 0, l = self.length; i < l; i++ ) {
+                                       if ( jQuery.contains( self[ i ], this ) ) {
+                                               return true;
+                                       }
+                               }
+                       });
+               }
+
+               ret = this.pushStack( "", "find", selector );
+
+               for ( i = 0, l = this.length; i < l; i++ ) {
+                       length = ret.length;
+                       jQuery.find( selector, this[i], ret );
+
+                       if ( i > 0 ) {
+                               // Make sure that the results are unique
+                               for ( n = length; n < ret.length; n++ ) {
+                                       for ( r = 0; r < length; r++ ) {
+                                               if ( ret[r] === ret[n] ) {
+                                                       ret.splice(n--, 1);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return ret;
+       },
+
+       has: function( target ) {
+               var i,
+                       targets = jQuery( target, this ),
+                       len = targets.length;
+
+               return this.filter(function() {
+                       for ( i = 0; i < len; i++ ) {
+                               if ( jQuery.contains( this, targets[i] ) ) {
+                                       return true;
+                               }
+                       }
+               });
+       },
+
+       not: function( selector ) {
+               return this.pushStack( winnow(this, selector, false), "not", selector);
+       },
+
+       filter: function( selector ) {
+               return this.pushStack( winnow(this, selector, true), "filter", selector );
+       },
+
+       is: function( selector ) {
+               return !!selector && (
+                       typeof selector === "string" ?
+                               // If this is a positional/relative selector, check membership in the returned set
+                               // so $("p:first").is("p:last") won't return true for a doc with two "p".
+                               rneedsContext.test( selector ) ?
+                                       jQuery( selector, this.context ).index( this[0] ) >= 0 :
+                                       jQuery.filter( selector, this ).length > 0 :
+                               this.filter( selector ).length > 0 );
+       },
+
+       closest: function( selectors, context ) {
+               var cur,
+                       i = 0,
+                       l = this.length,
+                       ret = [],
+                       pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+                               jQuery( selectors, context || this.context ) :
+                               0;
+
+               for ( ; i < l; i++ ) {
+                       cur = this[i];
+
+                       while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
+                               if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+                                       ret.push( cur );
+                                       break;
+                               }
+                               cur = cur.parentNode;
+                       }
+               }
+
+               ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
+
+               return this.pushStack( ret, "closest", selectors );
+       },
+
+       // Determine the position of an element within
+       // the matched set of elements
+       index: function( elem ) {
+
+               // No argument, return index in parent
+               if ( !elem ) {
+                       return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
+               }
+
+               // index in selector
+               if ( typeof elem === "string" ) {
+                       return jQuery.inArray( this[0], jQuery( elem ) );
+               }
+
+               // Locate the position of the desired element
+               return jQuery.inArray(
+                       // If it receives a jQuery object, the first element is used
+                       elem.jquery ? elem[0] : elem, this );
+       },
+
+       add: function( selector, context ) {
+               var set = typeof selector === "string" ?
+                               jQuery( selector, context ) :
+                               jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+                       all = jQuery.merge( this.get(), set );
+
+               return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+                       all :
+                       jQuery.unique( all ) );
+       },
+
+       addBack: function( selector ) {
+               return this.add( selector == null ?
+                       this.prevObject : this.prevObject.filter(selector)
+               );
+       }
+});
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+       return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+function sibling( cur, dir ) {
+       do {
+               cur = cur[ dir ];
+       } while ( cur && cur.nodeType !== 1 );
+
+       return cur;
+}
+
+jQuery.each({
+       parent: function( elem ) {
+               var parent = elem.parentNode;
+               return parent && parent.nodeType !== 11 ? parent : null;
+       },
+       parents: function( elem ) {
+               return jQuery.dir( elem, "parentNode" );
+       },
+       parentsUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "parentNode", until );
+       },
+       next: function( elem ) {
+               return sibling( elem, "nextSibling" );
+       },
+       prev: function( elem ) {
+               return sibling( elem, "previousSibling" );
+       },
+       nextAll: function( elem ) {
+               return jQuery.dir( elem, "nextSibling" );
+       },
+       prevAll: function( elem ) {
+               return jQuery.dir( elem, "previousSibling" );
+       },
+       nextUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "nextSibling", until );
+       },
+       prevUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "previousSibling", until );
+       },
+       siblings: function( elem ) {
+               return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+       },
+       children: function( elem ) {
+               return jQuery.sibling( elem.firstChild );
+       },
+       contents: function( elem ) {
+               return jQuery.nodeName( elem, "iframe" ) ?
+                       elem.contentDocument || elem.contentWindow.document :
+                       jQuery.merge( [], elem.childNodes );
+       }
+}, function( name, fn ) {
+       jQuery.fn[ name ] = function( until, selector ) {
+               var ret = jQuery.map( this, fn, until );
+
+               if ( !runtil.test( name ) ) {
+                       selector = until;
+               }
+
+               if ( selector && typeof selector === "string" ) {
+                       ret = jQuery.filter( selector, ret );
+               }
+
+               ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+               if ( this.length > 1 && rparentsprev.test( name ) ) {
+                       ret = ret.reverse();
+               }
+
+               return this.pushStack( ret, name, core_slice.call( arguments ).join(",") );
+       };
+});
+
+jQuery.extend({
+       filter: function( expr, elems, not ) {
+               if ( not ) {
+                       expr = ":not(" + expr + ")";
+               }
+
+               return elems.length === 1 ?
+                       jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+                       jQuery.find.matches(expr, elems);
+       },
+
+       dir: function( elem, dir, until ) {
+               var matched = [],
+                       cur = elem[ dir ];
+
+               while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+                       if ( cur.nodeType === 1 ) {
+                               matched.push( cur );
+                       }
+                       cur = cur[dir];
+               }
+               return matched;
+       },
+
+       sibling: function( n, elem ) {
+               var r = [];
+
+               for ( ; n; n = n.nextSibling ) {
+                       if ( n.nodeType === 1 && n !== elem ) {
+                               r.push( n );
+                       }
+               }
+
+               return r;
+       }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+       // Can't pass null or undefined to indexOf in Firefox 4
+       // Set to 0 to skip string check
+       qualifier = qualifier || 0;
+
+       if ( jQuery.isFunction( qualifier ) ) {
+               return jQuery.grep(elements, function( elem, i ) {
+                       var retVal = !!qualifier.call( elem, i, elem );
+                       return retVal === keep;
+               });
+
+       } else if ( qualifier.nodeType ) {
+               return jQuery.grep(elements, function( elem, i ) {
+                       return ( elem === qualifier ) === keep;
+               });
+
+       } else if ( typeof qualifier === "string" ) {
+               var filtered = jQuery.grep(elements, function( elem ) {
+                       return elem.nodeType === 1;
+               });
+
+               if ( isSimple.test( qualifier ) ) {
+                       return jQuery.filter(qualifier, filtered, !keep);
+               } else {
+                       qualifier = jQuery.filter( qualifier, filtered );
+               }
+       }
+
+       return jQuery.grep(elements, function( elem, i ) {
+               return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+       });
+}
+function createSafeFragment( document ) {
+       var list = nodeNames.split( "|" ),
+       safeFrag = document.createDocumentFragment();
+
+       if ( safeFrag.createElement ) {
+               while ( list.length ) {
+                       safeFrag.createElement(
+                               list.pop()
+                       );
+               }
+       }
+       return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+               "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+       rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+       rleadingWhitespace = /^\s+/,
+       rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+       rtagName = /<([\w:]+)/,
+       rtbody = /<tbody/i,
+       rhtml = /<|&#?\w+;/,
+       rnoInnerhtml = /<(?:script|style|link)/i,
+       rnocache = /<(?:script|object|embed|option|style)/i,
+       rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+       rcheckableType = /^(?:checkbox|radio)$/,
+       // checked="checked" or checked
+       rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+       rscriptType = /\/(java|ecma)script/i,
+       rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,
+       wrapMap = {
+               option: [ 1, "<select multiple='multiple'>", "</select>" ],
+               legend: [ 1, "<fieldset>", "</fieldset>" ],
+               thead: [ 1, "<table>", "</table>" ],
+               tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+               td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+               col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+               area: [ 1, "<map>", "</map>" ],
+               _default: [ 0, "", "" ]
+       },
+       safeFragment = createSafeFragment( document ),
+       fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+// unless wrapped in a div with non-breaking characters in front of it.
+if ( !jQuery.support.htmlSerialize ) {
+       wrapMap._default = [ 1, "X<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+       text: function( value ) {
+               return jQuery.access( this, function( value ) {
+                       return value === undefined ?
+                               jQuery.text( this ) :
+                               this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+               }, null, value, arguments.length );
+       },
+
+       wrapAll: function( html ) {
+               if ( jQuery.isFunction( html ) ) {
+                       return this.each(function(i) {
+                               jQuery(this).wrapAll( html.call(this, i) );
+                       });
+               }
+
+               if ( this[0] ) {
+                       // The elements to wrap the target around
+                       var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+                       if ( this[0].parentNode ) {
+                               wrap.insertBefore( this[0] );
+                       }
+
+                       wrap.map(function() {
+                               var elem = this;
+
+                               while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+                                       elem = elem.firstChild;
+                               }
+
+                               return elem;
+                       }).append( this );
+               }
+
+               return this;
+       },
+
+       wrapInner: function( html ) {
+               if ( jQuery.isFunction( html ) ) {
+                       return this.each(function(i) {
+                               jQuery(this).wrapInner( html.call(this, i) );
+                       });
+               }
+
+               return this.each(function() {
+                       var self = jQuery( this ),
+                               contents = self.contents();
+
+                       if ( contents.length ) {
+                               contents.wrapAll( html );
+
+                       } else {
+                               self.append( html );
+                       }
+               });
+       },
+
+       wrap: function( html ) {
+               var isFunction = jQuery.isFunction( html );
+
+               return this.each(function(i) {
+                       jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+               });
+       },
+
+       unwrap: function() {
+               return this.parent().each(function() {
+                       if ( !jQuery.nodeName( this, "body" ) ) {
+                               jQuery( this ).replaceWith( this.childNodes );
+                       }
+               }).end();
+       },
+
+       append: function() {
+               return this.domManip(arguments, true, function( elem ) {
+                       if ( this.nodeType === 1 || this.nodeType === 11 ) {
+                               this.appendChild( elem );
+                       }
+               });
+       },
+
+       prepend: function() {
+               return this.domManip(arguments, true, function( elem ) {
+                       if ( this.nodeType === 1 || this.nodeType === 11 ) {
+                               this.insertBefore( elem, this.firstChild );
+                       }
+               });
+       },
+
+       before: function() {
+               if ( !isDisconnected( this[0] ) ) {
+                       return this.domManip(arguments, false, function( elem ) {
+                               this.parentNode.insertBefore( elem, this );
+                       });
+               }
+
+               if ( arguments.length ) {
+                       var set = jQuery.clean( arguments );
+                       return this.pushStack( jQuery.merge( set, this ), "before", this.selector );
+               }
+       },
+
+       after: function() {
+               if ( !isDisconnected( this[0] ) ) {
+                       return this.domManip(arguments, false, function( elem ) {
+                               this.parentNode.insertBefore( elem, this.nextSibling );
+                       });
+               }
+
+               if ( arguments.length ) {
+                       var set = jQuery.clean( arguments );
+                       return this.pushStack( jQuery.merge( this, set ), "after", this.selector );
+               }
+       },
+
+       // keepData is for internal use only--do not document
+       remove: function( selector, keepData ) {
+               var elem,
+                       i = 0;
+
+               for ( ; (elem = this[i]) != null; i++ ) {
+                       if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+                               if ( !keepData && elem.nodeType === 1 ) {
+                                       jQuery.cleanData( elem.getElementsByTagName("*") );
+                                       jQuery.cleanData( [ elem ] );
+                               }
+
+                               if ( elem.parentNode ) {
+                                       elem.parentNode.removeChild( elem );
+                               }
+                       }
+               }
+
+               return this;
+       },
+
+       empty: function() {
+               var elem,
+                       i = 0;
+
+               for ( ; (elem = this[i]) != null; i++ ) {
+                       // Remove element nodes and prevent memory leaks
+                       if ( elem.nodeType === 1 ) {
+                               jQuery.cleanData( elem.getElementsByTagName("*") );
+                       }
+
+                       // Remove any remaining nodes
+                       while ( elem.firstChild ) {
+                               elem.removeChild( elem.firstChild );
+                       }
+               }
+
+               return this;
+       },
+
+       clone: function( dataAndEvents, deepDataAndEvents ) {
+               dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+               deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+               return this.map( function () {
+                       return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+               });
+       },
+
+       html: function( value ) {
+               return jQuery.access( this, function( value ) {
+                       var elem = this[0] || {},
+                               i = 0,
+                               l = this.length;
+
+                       if ( value === undefined ) {
+                               return elem.nodeType === 1 ?
+                                       elem.innerHTML.replace( rinlinejQuery, "" ) :
+                                       undefined;
+                       }
+
+                       // See if we can take a shortcut and just use innerHTML
+                       if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+                               ( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&
+                               ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+                               !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
+
+                               value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+                               try {
+                                       for (; i < l; i++ ) {
+                                               // Remove element nodes and prevent memory leaks
+                                               elem = this[i] || {};
+                                               if ( elem.nodeType === 1 ) {
+                                                       jQuery.cleanData( elem.getElementsByTagName( "*" ) );
+                                                       elem.innerHTML = value;
+                                               }
+                                       }
+
+                                       elem = 0;
+
+                               // If using innerHTML throws an exception, use the fallback method
+                               } catch(e) {}
+                       }
+
+                       if ( elem ) {
+                               this.empty().append( value );
+                       }
+               }, null, value, arguments.length );
+       },
+
+       replaceWith: function( value ) {
+               if ( !isDisconnected( this[0] ) ) {
+                       // Make sure that the elements are removed from the DOM before they are inserted
+                       // this can help fix replacing a parent with child elements
+                       if ( jQuery.isFunction( value ) ) {
+                               return this.each(function(i) {
+                                       var self = jQuery(this), old = self.html();
+                                       self.replaceWith( value.call( this, i, old ) );
+                               });
+                       }
+
+                       if ( typeof value !== "string" ) {
+                               value = jQuery( value ).detach();
+                       }
+
+                       return this.each(function() {
+                               var next = this.nextSibling,
+                                       parent = this.parentNode;
+
+                               jQuery( this ).remove();
+
+                               if ( next ) {
+                                       jQuery(next).before( value );
+                               } else {
+                                       jQuery(parent).append( value );
+                               }
+                       });
+               }
+
+               return this.length ?
+                       this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
+                       this;
+       },
+
+       detach: function( selector ) {
+               return this.remove( selector, true );
+       },
+
+       domManip: function( args, table, callback ) {
+
+               // Flatten any nested arrays
+               args = [].concat.apply( [], args );
+
+               var results, first, fragment, iNoClone,
+                       i = 0,
+                       value = args[0],
+                       scripts = [],
+                       l = this.length;
+
+               // We can't cloneNode fragments that contain checked, in WebKit
+               if ( !jQuery.support.checkClone && l > 1 && typeof value === "string" && rchecked.test( value ) ) {
+                       return this.each(function() {
+                               jQuery(this).domManip( args, table, callback );
+                       });
+               }
+
+               if ( jQuery.isFunction(value) ) {
+                       return this.each(function(i) {
+                               var self = jQuery(this);
+                               args[0] = value.call( this, i, table ? self.html() : undefined );
+                               self.domManip( args, table, callback );
+                       });
+               }
+
+               if ( this[0] ) {
+                       results = jQuery.buildFragment( args, this, scripts );
+                       fragment = results.fragment;
+                       first = fragment.firstChild;
+
+                       if ( fragment.childNodes.length === 1 ) {
+                               fragment = first;
+                       }
+
+                       if ( first ) {
+                               table = table && jQuery.nodeName( first, "tr" );
+
+                               // Use the original fragment for the last item instead of the first because it can end up
+                               // being emptied incorrectly in certain situations (#8070).
+                               // Fragments from the fragment cache must always be cloned and never used in place.
+                               for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) {
+                                       callback.call(
+                                               table && jQuery.nodeName( this[i], "table" ) ?
+                                                       findOrAppend( this[i], "tbody" ) :
+                                                       this[i],
+                                               i === iNoClone ?
+                                                       fragment :
+                                                       jQuery.clone( fragment, true, true )
+                                       );
+                               }
+                       }
+
+                       // Fix #11809: Avoid leaking memory
+                       fragment = first = null;
+
+                       if ( scripts.length ) {
+                               jQuery.each( scripts, function( i, elem ) {
+                                       if ( elem.src ) {
+                                               if ( jQuery.ajax ) {
+                                                       jQuery.ajax({
+                                                               url: elem.src,
+                                                               type: "GET",
+                                                               dataType: "script",
+                                                               async: false,
+                                                               global: false,
+                                                               "throws": true
+                                                       });
+                                               } else {
+                                                       jQuery.error("no ajax");
+                                               }
+                                       } else {
+                                               jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "" ) );
+                                       }
+
+                                       if ( elem.parentNode ) {
+                                               elem.parentNode.removeChild( elem );
+                                       }
+                               });
+                       }
+               }
+
+               return this;
+       }
+});
+
+function findOrAppend( elem, tag ) {
+       return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
+}
+
+function cloneCopyEvent( src, dest ) {
+
+       if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+               return;
+       }
+
+       var type, i, l,
+               oldData = jQuery._data( src ),
+               curData = jQuery._data( dest, oldData ),
+               events = oldData.events;
+
+       if ( events ) {
+               delete curData.handle;
+               curData.events = {};
+
+               for ( type in events ) {
+                       for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+                               jQuery.event.add( dest, type, events[ type ][ i ] );
+                       }
+               }
+       }
+
+       // make the cloned public data object a copy from the original
+       if ( curData.data ) {
+               curData.data = jQuery.extend( {}, curData.data );
+       }
+}
+
+function cloneFixAttributes( src, dest ) {
+       var nodeName;
+
+       // We do not need to do anything for non-Elements
+       if ( dest.nodeType !== 1 ) {
+               return;
+       }
+
+       // clearAttributes removes the attributes, which we don't want,
+       // but also removes the attachEvent events, which we *do* want
+       if ( dest.clearAttributes ) {
+               dest.clearAttributes();
+       }
+
+       // mergeAttributes, in contrast, only merges back on the
+       // original attributes, not the events
+       if ( dest.mergeAttributes ) {
+               dest.mergeAttributes( src );
+       }
+
+       nodeName = dest.nodeName.toLowerCase();
+
+       if ( nodeName === "object" ) {
+               // IE6-10 improperly clones children of object elements using classid.
+               // IE10 throws NoModificationAllowedError if parent is null, #12132.
+               if ( dest.parentNode ) {
+                       dest.outerHTML = src.outerHTML;
+               }
+
+               // This path appears unavoidable for IE9. When cloning an object
+               // element in IE9, the outerHTML strategy above is not sufficient.
+               // If the src has innerHTML and the destination does not,
+               // copy the src.innerHTML into the dest.innerHTML. #10324
+               if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) {
+                       dest.innerHTML = src.innerHTML;
+               }
+
+       } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+               // IE6-8 fails to persist the checked state of a cloned checkbox
+               // or radio button. Worse, IE6-7 fail to give the cloned element
+               // a checked appearance if the defaultChecked value isn't also set
+
+               dest.defaultChecked = dest.checked = src.checked;
+
+               // IE6-7 get confused and end up setting the value of a cloned
+               // checkbox/radio button to an empty string instead of "on"
+               if ( dest.value !== src.value ) {
+                       dest.value = src.value;
+               }
+
+       // IE6-8 fails to return the selected option to the default selected
+       // state when cloning options
+       } else if ( nodeName === "option" ) {
+               dest.selected = src.defaultSelected;
+
+       // IE6-8 fails to set the defaultValue to the correct value when
+       // cloning other types of input fields
+       } else if ( nodeName === "input" || nodeName === "textarea" ) {
+               dest.defaultValue = src.defaultValue;
+
+       // IE blanks contents when cloning scripts
+       } else if ( nodeName === "script" && dest.text !== src.text ) {
+               dest.text = src.text;
+       }
+
+       // Event data gets referenced instead of copied if the expando
+       // gets copied too
+       dest.removeAttribute( jQuery.expando );
+}
+
+jQuery.buildFragment = function( args, context, scripts ) {
+       var fragment, cacheable, cachehit,
+               first = args[ 0 ];
+
+       // Set context from what may come in as undefined or a jQuery collection or a node
+       // Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 &
+       // also doubles as fix for #8950 where plain objects caused createDocumentFragment exception
+       context = context || document;
+       context = !context.nodeType && context[0] || context;
+       context = context.ownerDocument || context;
+
+       // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
+       // Cloning options loses the selected state, so don't cache them
+       // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+       // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+       // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
+       if ( args.length === 1 && typeof first === "string" && first.length < 512 && context === document &&
+               first.charAt(0) === "<" && !rnocache.test( first ) &&
+               (jQuery.support.checkClone || !rchecked.test( first )) &&
+               (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
+
+               // Mark cacheable and look for a hit
+               cacheable = true;
+               fragment = jQuery.fragments[ first ];
+               cachehit = fragment !== undefined;
+       }
+
+       if ( !fragment ) {
+               fragment = context.createDocumentFragment();
+               jQuery.clean( args, context, fragment, scripts );
+
+               // Update the cache, but only store false
+               // unless this is a second parsing of the same content
+               if ( cacheable ) {
+                       jQuery.fragments[ first ] = cachehit && fragment;
+               }
+       }
+
+       return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+       appendTo: "append",
+       prependTo: "prepend",
+       insertBefore: "before",
+       insertAfter: "after",
+       replaceAll: "replaceWith"
+}, function( name, original ) {
+       jQuery.fn[ name ] = function( selector ) {
+               var elems,
+                       i = 0,
+                       ret = [],
+                       insert = jQuery( selector ),
+                       l = insert.length,
+                       parent = this.length === 1 && this[0].parentNode;
+
+               if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) {
+                       insert[ original ]( this[0] );
+                       return this;
+               } else {
+                       for ( ; i < l; i++ ) {
+                               elems = ( i > 0 ? this.clone(true) : this ).get();
+                               jQuery( insert[i] )[ original ]( elems );
+                               ret = ret.concat( elems );
+                       }
+
+                       return this.pushStack( ret, name, insert.selector );
+               }
+       };
+});
+
+function getAll( elem ) {
+       if ( typeof elem.getElementsByTagName !== "undefined" ) {
+               return elem.getElementsByTagName( "*" );
+
+       } else if ( typeof elem.querySelectorAll !== "undefined" ) {
+               return elem.querySelectorAll( "*" );
+
+       } else {
+               return [];
+       }
+}
+
+// Used in clean, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+       if ( rcheckableType.test( elem.type ) ) {
+               elem.defaultChecked = elem.checked;
+       }
+}
+
+jQuery.extend({
+       clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+               var srcElements,
+                       destElements,
+                       i,
+                       clone;
+
+               if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+                       clone = elem.cloneNode( true );
+
+               // IE<=8 does not properly clone detached, unknown element nodes
+               } else {
+                       fragmentDiv.innerHTML = elem.outerHTML;
+                       fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+               }
+
+               if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+                               (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+                       // IE copies events bound via attachEvent when using cloneNode.
+                       // Calling detachEvent on the clone will also remove the events
+                       // from the original. In order to get around this, we use some
+                       // proprietary methods to clear the events. Thanks to MooTools
+                       // guys for this hotness.
+
+                       cloneFixAttributes( elem, clone );
+
+                       // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
+                       srcElements = getAll( elem );
+                       destElements = getAll( clone );
+
+                       // Weird iteration because IE will replace the length property
+                       // with an element if you are cloning the body and one of the
+                       // elements on the page has a name or id of "length"
+                       for ( i = 0; srcElements[i]; ++i ) {
+                               // Ensure that the destination node is not null; Fixes #9587
+                               if ( destElements[i] ) {
+                                       cloneFixAttributes( srcElements[i], destElements[i] );
+                               }
+                       }
+               }
+
+               // Copy the events from the original to the clone
+               if ( dataAndEvents ) {
+                       cloneCopyEvent( elem, clone );
+
+                       if ( deepDataAndEvents ) {
+                               srcElements = getAll( elem );
+                               destElements = getAll( clone );
+
+                               for ( i = 0; srcElements[i]; ++i ) {
+                                       cloneCopyEvent( srcElements[i], destElements[i] );
+                               }
+                       }
+               }
+
+               srcElements = destElements = null;
+
+               // Return the cloned set
+               return clone;
+       },
+
+       clean: function( elems, context, fragment, scripts ) {
+               var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags,
+                       safe = context === document && safeFragment,
+                       ret = [];
+
+               // Ensure that context is a document
+               if ( !context || typeof context.createDocumentFragment === "undefined" ) {
+                       context = document;
+               }
+
+               // Use the already-created safe fragment if context permits
+               for ( i = 0; (elem = elems[i]) != null; i++ ) {
+                       if ( typeof elem === "number" ) {
+                               elem += "";
+                       }
+
+                       if ( !elem ) {
+                               continue;
+                       }
+
+                       // Convert html string into DOM nodes
+                       if ( typeof elem === "string" ) {
+                               if ( !rhtml.test( elem ) ) {
+                                       elem = context.createTextNode( elem );
+                               } else {
+                                       // Ensure a safe container in which to render the html
+                                       safe = safe || createSafeFragment( context );
+                                       div = context.createElement("div");
+                                       safe.appendChild( div );
+
+                                       // Fix "XHTML"-style tags in all browsers
+                                       elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+                                       // Go to html and back, then peel off extra wrappers
+                                       tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
+                                       wrap = wrapMap[ tag ] || wrapMap._default;
+                                       depth = wrap[0];
+                                       div.innerHTML = wrap[1] + elem + wrap[2];
+
+                                       // Move to the right depth
+                                       while ( depth-- ) {
+                                               div = div.lastChild;
+                                       }
+
+                                       // Remove IE's autoinserted <tbody> from table fragments
+                                       if ( !jQuery.support.tbody ) {
+
+                                               // String was a <table>, *may* have spurious <tbody>
+                                               hasBody = rtbody.test(elem);
+                                                       tbody = tag === "table" && !hasBody ?
+                                                               div.firstChild && div.firstChild.childNodes :
+
+                                                               // String was a bare <thead> or <tfoot>
+                                                               wrap[1] === "<table>" && !hasBody ?
+                                                                       div.childNodes :
+                                                                       [];
+
+                                               for ( j = tbody.length - 1; j >= 0 ; --j ) {
+                                                       if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+                                                               tbody[ j ].parentNode.removeChild( tbody[ j ] );
+                                                       }
+                                               }
+                                       }
+
+                                       // IE completely kills leading whitespace when innerHTML is used
+                                       if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+                                               div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+                                       }
+
+                                       elem = div.childNodes;
+
+                                       // Take out of fragment container (we need a fresh div each time)
+                                       div.parentNode.removeChild( div );
+                               }
+                       }
+
+                       if ( elem.nodeType ) {
+                               ret.push( elem );
+                       } else {
+                               jQuery.merge( ret, elem );
+                       }
+               }
+
+               // Fix #11356: Clear elements from safeFragment
+               if ( div ) {
+                       elem = div = safe = null;
+               }
+
+               // Reset defaultChecked for any radios and checkboxes
+               // about to be appended to the DOM in IE 6/7 (#8060)
+               if ( !jQuery.support.appendChecked ) {
+                       for ( i = 0; (elem = ret[i]) != null; i++ ) {
+                               if ( jQuery.nodeName( elem, "input" ) ) {
+                                       fixDefaultChecked( elem );
+                               } else if ( typeof elem.getElementsByTagName !== "undefined" ) {
+                                       jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
+                               }
+                       }
+               }
+
+               // Append elements to a provided document fragment
+               if ( fragment ) {
+                       // Special handling of each script element
+                       handleScript = function( elem ) {
+                               // Check if we consider it executable
+                               if ( !elem.type || rscriptType.test( elem.type ) ) {
+                                       // Detach the script and store it in the scripts array (if provided) or the fragment
+                                       // Return truthy to indicate that it has been handled
+                                       return scripts ?
+                                               scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
+                                               fragment.appendChild( elem );
+                               }
+                       };
+
+                       for ( i = 0; (elem = ret[i]) != null; i++ ) {
+                               // Check if we're done after handling an executable script
+                               if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
+                                       // Append to fragment and handle embedded scripts
+                                       fragment.appendChild( elem );
+                                       if ( typeof elem.getElementsByTagName !== "undefined" ) {
+                                               // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
+                                               jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
+
+                                               // Splice the scripts into ret after their former ancestor and advance our index beyond them
+                                               ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+                                               i += jsTags.length;
+                                       }
+                               }
+                       }
+               }
+
+               return ret;
+       },
+
+       cleanData: function( elems, /* internal */ acceptData ) {
+               var data, id, elem, type,
+                       i = 0,
+                       internalKey = jQuery.expando,
+                       cache = jQuery.cache,
+                       deleteExpando = jQuery.support.deleteExpando,
+                       special = jQuery.event.special;
+
+               for ( ; (elem = elems[i]) != null; i++ ) {
+
+                       if ( acceptData || jQuery.acceptData( elem ) ) {
+
+                               id = elem[ internalKey ];
+                               data = id && cache[ id ];
+
+                               if ( data ) {
+                                       if ( data.events ) {
+                                               for ( type in data.events ) {
+                                                       if ( special[ type ] ) {
+                                                               jQuery.event.remove( elem, type );
+
+                                                       // This is a shortcut to avoid jQuery.event.remove's overhead
+                                                       } else {
+                                                               jQuery.removeEvent( elem, type, data.handle );
+                                                       }
+                                               }
+                                       }
+
+                                       // Remove cache only if it was not already removed by jQuery.event.remove
+                                       if ( cache[ id ] ) {
+
+                                               delete cache[ id ];
+
+                                               // IE does not allow us to delete expando properties from nodes,
+                                               // nor does it have a removeAttribute function on Document nodes;
+                                               // we must handle all of these cases
+                                               if ( deleteExpando ) {
+                                                       delete elem[ internalKey ];
+
+                                               } else if ( elem.removeAttribute ) {
+                                                       elem.removeAttribute( internalKey );
+
+                                               } else {
+                                                       elem[ internalKey ] = null;
+                                               }
+
+                                               jQuery.deletedIds.push( id );
+                                       }
+                               }
+                       }
+               }
+       }
+});
+// Limit scope pollution from any deprecated API
+(function() {
+
+var matched, browser;
+
+// Use of jQuery.browser is frowned upon.
+// More details: http://api.jquery.com/jQuery.browser
+// jQuery.uaMatch maintained for back-compat
+jQuery.uaMatch = function( ua ) {
+       ua = ua.toLowerCase();
+
+       var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
+               /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
+               /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
+               /(msie) ([\w.]+)/.exec( ua ) ||
+               ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
+               [];
+
+       return {
+               browser: match[ 1 ] || "",
+               version: match[ 2 ] || "0"
+       };
+};
+
+matched = jQuery.uaMatch( navigator.userAgent );
+browser = {};
+
+if ( matched.browser ) {
+       browser[ matched.browser ] = true;
+       browser.version = matched.version;
+}
+
+// Chrome is Webkit, but Webkit is also Safari.
+if ( browser.chrome ) {
+       browser.webkit = true;
+} else if ( browser.webkit ) {
+       browser.safari = true;
+}
+
+jQuery.browser = browser;
+
+jQuery.sub = function() {
+       function jQuerySub( selector, context ) {
+               return new jQuerySub.fn.init( selector, context );
+       }
+       jQuery.extend( true, jQuerySub, this );
+       jQuerySub.superclass = this;
+       jQuerySub.fn = jQuerySub.prototype = this();
+       jQuerySub.fn.constructor = jQuerySub;
+       jQuerySub.sub = this.sub;
+       jQuerySub.fn.init = function init( selector, context ) {
+               if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+                       context = jQuerySub( context );
+               }
+
+               return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+       };
+       jQuerySub.fn.init.prototype = jQuerySub.fn;
+       var rootjQuerySub = jQuerySub(document);
+       return jQuerySub;
+};
+
+})();
+var curCSS, iframe, iframeDoc,
+       ralpha = /alpha\([^)]*\)/i,
+       ropacity = /opacity=([^)]*)/,
+       rposition = /^(top|right|bottom|left)$/,
+       // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+       // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+       rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+       rmargin = /^margin/,
+       rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
+       rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
+       rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ),
+       elemdisplay = { BODY: "block" },
+
+       cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+       cssNormalTransform = {
+               letterSpacing: 0,
+               fontWeight: 400
+       },
+
+       cssExpand = [ "Top", "Right", "Bottom", "Left" ],
+       cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
+
+       eventsToggle = jQuery.fn.toggle;
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+       // shortcut for names that are not vendor prefixed
+       if ( name in style ) {
+               return name;
+       }
+
+       // check for vendor prefixed names
+       var capName = name.charAt(0).toUpperCase() + name.slice(1),
+               origName = name,
+               i = cssPrefixes.length;
+
+       while ( i-- ) {
+               name = cssPrefixes[ i ] + capName;
+               if ( name in style ) {
+                       return name;
+               }
+       }
+
+       return origName;
+}
+
+function isHidden( elem, el ) {
+       elem = el || elem;
+       return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+}
+
+function showHide( elements, show ) {
+       var elem, display,
+               values = [],
+               index = 0,
+               length = elements.length;
+
+       for ( ; index < length; index++ ) {
+               elem = elements[ index ];
+               if ( !elem.style ) {
+                       continue;
+               }
+               values[ index ] = jQuery._data( elem, "olddisplay" );
+               if ( show ) {
+                       // Reset the inline display of this element to learn if it is
+                       // being hidden by cascaded rules or not
+                       if ( !values[ index ] && elem.style.display === "none" ) {
+                               elem.style.display = "";
+                       }
+
+                       // Set elements which have been overridden with display: none
+                       // in a stylesheet to whatever the default browser style is
+                       // for such an element
+                       if ( elem.style.display === "" && isHidden( elem ) ) {
+                               values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
+                       }
+               } else {
+                       display = curCSS( elem, "display" );
+
+                       if ( !values[ index ] && display !== "none" ) {
+                               jQuery._data( elem, "olddisplay", display );
+                       }
+               }
+       }
+
+       // Set the display of most of the elements in a second loop
+       // to avoid the constant reflow
+       for ( index = 0; index < length; index++ ) {
+               elem = elements[ index ];
+               if ( !elem.style ) {
+                       continue;
+               }
+               if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+                       elem.style.display = show ? values[ index ] || "" : "none";
+               }
+       }
+
+       return elements;
+}
+
+jQuery.fn.extend({
+       css: function( name, value ) {
+               return jQuery.access( this, function( elem, name, value ) {
+                       return value !== undefined ?
+                               jQuery.style( elem, name, value ) :
+                               jQuery.css( elem, name );
+               }, name, value, arguments.length > 1 );
+       },
+       show: function() {
+               return showHide( this, true );
+       },
+       hide: function() {
+               return showHide( this );
+       },
+       toggle: function( state, fn2 ) {
+               var bool = typeof state === "boolean";
+
+               if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {
+                       return eventsToggle.apply( this, arguments );
+               }
+
+               return this.each(function() {
+                       if ( bool ? state : isHidden( this ) ) {
+                               jQuery( this ).show();
+                       } else {
+                               jQuery( this ).hide();
+                       }
+               });
+       }
+});
+
+jQuery.extend({
+       // Add in style property hooks for overriding the default
+       // behavior of getting and setting a style property
+       cssHooks: {
+               opacity: {
+                       get: function( elem, computed ) {
+                               if ( computed ) {
+                                       // We should always get a number back from opacity
+                                       var ret = curCSS( elem, "opacity" );
+                                       return ret === "" ? "1" : ret;
+
+                               }
+                       }
+               }
+       },
+
+       // Exclude the following css properties to add px
+       cssNumber: {
+               "fillOpacity": true,
+               "fontWeight": true,
+               "lineHeight": true,
+               "opacity": true,
+               "orphans": true,
+               "widows": true,
+               "zIndex": true,
+               "zoom": true
+       },
+
+       // Add in properties whose names you wish to fix before
+       // setting or getting the value
+       cssProps: {
+               // normalize float css property
+               "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+       },
+
+       // Get and set the style property on a DOM Node
+       style: function( elem, name, value, extra ) {
+               // Don't set styles on text and comment nodes
+               if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+                       return;
+               }
+
+               // Make sure that we're working with the right name
+               var ret, type, hooks,
+                       origName = jQuery.camelCase( name ),
+                       style = elem.style;
+
+               name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+               // gets hook for the prefixed version
+               // followed by the unprefixed version
+               hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+               // Check if we're setting a value
+               if ( value !== undefined ) {
+                       type = typeof value;
+
+                       // convert relative number strings (+= or -=) to relative numbers. #7345
+                       if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+                               value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+                               // Fixes bug #9237
+                               type = "number";
+                       }
+
+                       // Make sure that NaN and null values aren't set. See: #7116
+                       if ( value == null || type === "number" && isNaN( value ) ) {
+                               return;
+                       }
+
+                       // If a number was passed in, add 'px' to the (except for certain CSS properties)
+                       if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+                               value += "px";
+                       }
+
+                       // If a hook was provided, use that value, otherwise just set the specified value
+                       if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+                               // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+                               // Fixes bug #5509
+                               try {
+                                       style[ name ] = value;
+                               } catch(e) {}
+                       }
+
+               } else {
+                       // If a hook was provided get the non-computed value from there
+                       if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+                               return ret;
+                       }
+
+                       // Otherwise just get the value from the style object
+                       return style[ name ];
+               }
+       },
+
+       css: function( elem, name, numeric, extra ) {
+               var val, num, hooks,
+                       origName = jQuery.camelCase( name );
+
+               // Make sure that we're working with the right name
+               name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+               // gets hook for the prefixed version
+               // followed by the unprefixed version
+               hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+               // If a hook was provided get the computed value from there
+               if ( hooks && "get" in hooks ) {
+                       val = hooks.get( elem, true, extra );
+               }
+
+               // Otherwise, if a way to get the computed value exists, use that
+               if ( val === undefined ) {
+                       val = curCSS( elem, name );
+               }
+
+               //convert "normal" to computed value
+               if ( val === "normal" && name in cssNormalTransform ) {
+                       val = cssNormalTransform[ name ];
+               }
+
+               // Return, converting to number if forced or a qualifier was provided and val looks numeric
+               if ( numeric || extra !== undefined ) {
+                       num = parseFloat( val );
+                       return numeric || jQuery.isNumeric( num ) ? num || 0 : val;
+               }
+               return val;
+       },
+
+       // A method for quickly swapping in/out CSS properties to get correct calculations
+       swap: function( elem, options, callback ) {
+               var ret, name,
+                       old = {};
+
+               // Remember the old values, and insert the new ones
+               for ( name in options ) {
+                       old[ name ] = elem.style[ name ];
+                       elem.style[ name ] = options[ name ];
+               }
+
+               ret = callback.call( elem );
+
+               // Revert the old values
+               for ( name in options ) {
+                       elem.style[ name ] = old[ name ];
+               }
+
+               return ret;
+       }
+});
+
+// NOTE: To any future maintainer, we've window.getComputedStyle
+// because jsdom on node.js will break without it.
+if ( window.getComputedStyle ) {
+       curCSS = function( elem, name ) {
+               var ret, width, minWidth, maxWidth,
+                       computed = window.getComputedStyle( elem, null ),
+                       style = elem.style;
+
+               if ( computed ) {
+
+                       // getPropertyValue is only needed for .css('filter') in IE9, see #12537
+                       ret = computed.getPropertyValue( name ) || computed[ name ];
+
+                       if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+                               ret = jQuery.style( elem, name );
+                       }
+
+                       // A tribute to the "awesome hack by Dean Edwards"
+                       // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+                       // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+                       // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+                       if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+                               width = style.width;
+                               minWidth = style.minWidth;
+                               maxWidth = style.maxWidth;
+
+                               style.minWidth = style.maxWidth = style.width = ret;
+                               ret = computed.width;
+
+                               style.width = width;
+                               style.minWidth = minWidth;
+                               style.maxWidth = maxWidth;
+                       }
+               }
+
+               return ret;
+       };
+} else if ( document.documentElement.currentStyle ) {
+       curCSS = function( elem, name ) {
+               var left, rsLeft,
+                       ret = elem.currentStyle && elem.currentStyle[ name ],
+                       style = elem.style;
+
+               // Avoid setting ret to empty string here
+               // so we don't default to auto
+               if ( ret == null && style && style[ name ] ) {
+                       ret = style[ name ];
+               }
+
+               // From the awesome hack by Dean Edwards
+               // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+               // If we're not dealing with a regular pixel number
+               // but a number that has a weird ending, we need to convert it to pixels
+               // but not position css attributes, as those are proportional to the parent element instead
+               // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+               if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+                       // Remember the original values
+                       left = style.left;
+                       rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
+
+                       // Put in the new values to get a computed value out
+                       if ( rsLeft ) {
+                               elem.runtimeStyle.left = elem.currentStyle.left;
+                       }
+                       style.left = name === "fontSize" ? "1em" : ret;
+                       ret = style.pixelLeft + "px";
+
+                       // Revert the changed values
+                       style.left = left;
+                       if ( rsLeft ) {
+                               elem.runtimeStyle.left = rsLeft;
+                       }
+               }
+
+               return ret === "" ? "auto" : ret;
+       };
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+       var matches = rnumsplit.exec( value );
+       return matches ?
+                       Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+                       value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox ) {
+       var i = extra === ( isBorderBox ? "border" : "content" ) ?
+               // If we already have the right measurement, avoid augmentation
+               4 :
+               // Otherwise initialize for horizontal or vertical properties
+               name === "width" ? 1 : 0,
+
+               val = 0;
+
+       for ( ; i < 4; i += 2 ) {
+               // both box models exclude margin, so add it if we want it
+               if ( extra === "margin" ) {
+                       // we use jQuery.css instead of curCSS here
+                       // because of the reliableMarginRight CSS hook!
+                       val += jQuery.css( elem, extra + cssExpand[ i ], true );
+               }
+
+               // From this point on we use curCSS for maximum performance (relevant in animations)
+               if ( isBorderBox ) {
+                       // border-box includes padding, so remove it if we want content
+                       if ( extra === "content" ) {
+                               val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
+                       }
+
+                       // at this point, extra isn't border nor margin, so remove border
+                       if ( extra !== "margin" ) {
+                               val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+                       }
+               } else {
+                       // at this point, extra isn't content, so add padding
+                       val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
+
+                       // at this point, extra isn't content nor padding, so add border
+                       if ( extra !== "padding" ) {
+                               val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
+                       }
+               }
+       }
+
+       return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+       // Start with offset property, which is equivalent to the border-box value
+       var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+               valueIsBorderBox = true,
+               isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box";
+
+       // some non-html elements return undefined for offsetWidth, so check for null/undefined
+       // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+       // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+       if ( val <= 0 || val == null ) {
+               // Fall back to computed then uncomputed css if necessary
+               val = curCSS( elem, name );
+               if ( val < 0 || val == null ) {
+                       val = elem.style[ name ];
+               }
+
+               // Computed unit is not pixels. Stop here and return.
+               if ( rnumnonpx.test(val) ) {
+                       return val;
+               }
+
+               // we need the check for style in case a browser which returns unreliable values
+               // for getComputedStyle silently falls back to the reliable elem.style
+               valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
+
+               // Normalize "", auto, and prepare for extra
+               val = parseFloat( val ) || 0;
+       }
+
+       // use the active box-sizing model to add/subtract irrelevant styles
+       return ( val +
+               augmentWidthOrHeight(
+                       elem,
+                       name,
+                       extra || ( isBorderBox ? "border" : "content" ),
+                       valueIsBorderBox
+               )
+       ) + "px";
+}
+
+
+// Try to determine the default display value of an element
+function css_defaultDisplay( nodeName ) {
+       if ( elemdisplay[ nodeName ] ) {
+               return elemdisplay[ nodeName ];
+       }
+
+       var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ),
+               display = elem.css("display");
+       elem.remove();
+
+       // If the simple way fails,
+       // get element's real default display by attaching it to a temp iframe
+       if ( display === "none" || display === "" ) {
+               // Use the already-created iframe if possible
+               iframe = document.body.appendChild(
+                       iframe || jQuery.extend( document.createElement("iframe"), {
+                               frameBorder: 0,
+                               width: 0,
+                               height: 0
+                       })
+               );
+
+               // Create a cacheable copy of the iframe document on first call.
+               // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
+               // document to it; WebKit & Firefox won't allow reusing the iframe document.
+               if ( !iframeDoc || !iframe.createElement ) {
+                       iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
+                       iframeDoc.write("<!doctype html><html><body>");
+                       iframeDoc.close();
+               }
+
+               elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) );
+
+               display = curCSS( elem, "display" );
+               document.body.removeChild( iframe );
+       }
+
+       // Store the correct default display
+       elemdisplay[ nodeName ] = display;
+
+       return display;
+}
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+       jQuery.cssHooks[ name ] = {
+               get: function( elem, computed, extra ) {
+                       if ( computed ) {
+                               // certain elements can have dimension info if we invisibly show them
+                               // however, it must have a current display style that would benefit from this
+                               if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, "display" ) ) ) {
+                                       return jQuery.swap( elem, cssShow, function() {
+                                               return getWidthOrHeight( elem, name, extra );
+                                       });
+                               } else {
+                                       return getWidthOrHeight( elem, name, extra );
+                               }
+                       }
+               },
+
+               set: function( elem, value, extra ) {
+                       return setPositiveNumber( elem, value, extra ?
+                               augmentWidthOrHeight(
+                                       elem,
+                                       name,
+                                       extra,
+                                       jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"
+                               ) : 0
+                       );
+               }
+       };
+});
+
+if ( !jQuery.support.opacity ) {
+       jQuery.cssHooks.opacity = {
+               get: function( elem, computed ) {
+                       // IE uses filters for opacity
+                       return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+                               ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+                               computed ? "1" : "";
+               },
+
+               set: function( elem, value ) {
+                       var style = elem.style,
+                               currentStyle = elem.currentStyle,
+                               opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+                               filter = currentStyle && currentStyle.filter || style.filter || "";
+
+                       // IE has trouble with opacity if it does not have layout
+                       // Force it by setting the zoom level
+                       style.zoom = 1;
+
+                       // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+                       if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+                               style.removeAttribute ) {
+
+                               // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+                               // if "filter:" is present at all, clearType is disabled, we want to avoid this
+                               // style.removeAttribute is IE Only, but so apparently is this code path...
+                               style.removeAttribute( "filter" );
+
+                               // if there there is no filter style applied in a css rule, we are done
+                               if ( currentStyle && !currentStyle.filter ) {
+                                       return;
+                               }
+                       }
+
+                       // otherwise, set new filter values
+                       style.filter = ralpha.test( filter ) ?
+                               filter.replace( ralpha, opacity ) :
+                               filter + " " + opacity;
+               }
+       };
+}
+
+// These hooks cannot be added until DOM ready because the support test
+// for it is not run until after DOM ready
+jQuery(function() {
+       if ( !jQuery.support.reliableMarginRight ) {
+               jQuery.cssHooks.marginRight = {
+                       get: function( elem, computed ) {
+                               // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+                               // Work around by temporarily setting element display to inline-block
+                               return jQuery.swap( elem, { "display": "inline-block" }, function() {
+                                       if ( computed ) {
+                                               return curCSS( elem, "marginRight" );
+                                       }
+                               });
+                       }
+               };
+       }
+
+       // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+       // getComputedStyle returns percent when specified for top/left/bottom/right
+       // rather than make the css module depend on the offset module, we just check for it here
+       if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
+               jQuery.each( [ "top", "left" ], function( i, prop ) {
+                       jQuery.cssHooks[ prop ] = {
+                               get: function( elem, computed ) {
+                                       if ( computed ) {
+                                               var ret = curCSS( elem, prop );
+                                               // if curCSS returns percentage, fallback to offset
+                                               return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + "px" : ret;
+                                       }
+                               }
+                       };
+               });
+       }
+
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+       jQuery.expr.filters.hidden = function( elem ) {
+               return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none");
+       };
+
+       jQuery.expr.filters.visible = function( elem ) {
+               return !jQuery.expr.filters.hidden( elem );
+       };
+}
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+       margin: "",
+       padding: "",
+       border: "Width"
+}, function( prefix, suffix ) {
+       jQuery.cssHooks[ prefix + suffix ] = {
+               expand: function( value ) {
+                       var i,
+
+                               // assumes a single number if not a string
+                               parts = typeof value === "string" ? value.split(" ") : [ value ],
+                               expanded = {};
+
+                       for ( i = 0; i < 4; i++ ) {
+                               expanded[ prefix + cssExpand[ i ] + suffix ] =
+                                       parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+                       }
+
+                       return expanded;
+               }
+       };
+
+       if ( !rmargin.test( prefix ) ) {
+               jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+       }
+});
+var r20 = /%20/g,
+       rbracket = /\[\]$/,
+       rCRLF = /\r?\n/g,
+       rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+       rselectTextarea = /^(?:select|textarea)/i;
+
+jQuery.fn.extend({
+       serialize: function() {
+               return jQuery.param( this.serializeArray() );
+       },
+       serializeArray: function() {
+               return this.map(function(){
+                       return this.elements ? jQuery.makeArray( this.elements ) : this;
+               })
+               .filter(function(){
+                       return this.name && !this.disabled &&
+                               ( this.checked || rselectTextarea.test( this.nodeName ) ||
+                                       rinput.test( this.type ) );
+               })
+               .map(function( i, elem ){
+                       var val = jQuery( this ).val();
+
+                       return val == null ?
+                               null :
+                               jQuery.isArray( val ) ?
+                                       jQuery.map( val, function( val, i ){
+                                               return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+                                       }) :
+                                       { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+               }).get();
+       }
+});
+
+//Serialize an array of form elements or a set of
+//key/values into a query string
+jQuery.param = function( a, traditional ) {
+       var prefix,
+               s = [],
+               add = function( key, value ) {
+                       // If value is a function, invoke it and return its value
+                       value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+                       s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+               };
+
+       // Set traditional to true for jQuery <= 1.3.2 behavior.
+       if ( traditional === undefined ) {
+               traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+       }
+
+       // If an array was passed in, assume that it is an array of form elements.
+       if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+               // Serialize the form elements
+               jQuery.each( a, function() {
+                       add( this.name, this.value );
+               });
+
+       } else {
+               // If traditional, encode the "old" way (the way 1.3.2 or older
+               // did it), otherwise encode params recursively.
+               for ( prefix in a ) {
+                       buildParams( prefix, a[ prefix ], traditional, add );
+               }
+       }
+
+       // Return the resulting serialization
+       return s.join( "&" ).replace( r20, "+" );
+};
+
+function buildParams( prefix, obj, traditional, add ) {
+       var name;
+
+       if ( jQuery.isArray( obj ) ) {
+               // Serialize array item.
+               jQuery.each( obj, function( i, v ) {
+                       if ( traditional || rbracket.test( prefix ) ) {
+                               // Treat each array item as a scalar.
+                               add( prefix, v );
+
+                       } else {
+                               // If array item is non-scalar (array or object), encode its
+                               // numeric index to resolve deserialization ambiguity issues.
+                               // Note that rack (as of 1.0.0) can't currently deserialize
+                               // nested arrays properly, and attempting to do so may cause
+                               // a server error. Possible fixes are to modify rack's
+                               // deserialization algorithm or to provide an option or flag
+                               // to force array serialization to be shallow.
+                               buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+                       }
+               });
+
+       } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+               // Serialize object item.
+               for ( name in obj ) {
+                       buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+               }
+
+       } else {
+               // Serialize scalar item.
+               add( prefix, obj );
+       }
+}
+var
+       // Document location
+       ajaxLocParts,
+       ajaxLocation,
+
+       rhash = /#.*$/,
+       rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+       // #7653, #8125, #8152: local protocol detection
+       rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
+       rnoContent = /^(?:GET|HEAD)$/,
+       rprotocol = /^\/\//,
+       rquery = /\?/,
+       rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+       rts = /([?&])_=[^&]*/,
+       rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
+
+       // Keep a copy of the old load method
+       _load = jQuery.fn.load,
+
+       /* Prefilters
+        * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+        * 2) These are called:
+        *    - BEFORE asking for a transport
+        *    - AFTER param serialization (s.data is a string if s.processData is true)
+        * 3) key is the dataType
+        * 4) the catchall symbol "*" can be used
+        * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+        */
+       prefilters = {},
+
+       /* Transports bindings
+        * 1) key is the dataType
+        * 2) the catchall symbol "*" can be used
+        * 3) selection will start with transport dataType and THEN go to "*" if needed
+        */
+       transports = {},
+
+       // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+       allTypes = ["*/"] + ["*"];
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+       ajaxLocation = location.href;
+} catch( e ) {
+       // Use the href attribute of an A element
+       // since IE will modify it given document.location
+       ajaxLocation = document.createElement( "a" );
+       ajaxLocation.href = "";
+       ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+       // dataTypeExpression is optional and defaults to "*"
+       return function( dataTypeExpression, func ) {
+
+               if ( typeof dataTypeExpression !== "string" ) {
+                       func = dataTypeExpression;
+                       dataTypeExpression = "*";
+               }
+
+               var dataType, list, placeBefore,
+                       dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ),
+                       i = 0,
+                       length = dataTypes.length;
+
+               if ( jQuery.isFunction( func ) ) {
+                       // For each dataType in the dataTypeExpression
+                       for ( ; i < length; i++ ) {
+                               dataType = dataTypes[ i ];
+                               // We control if we're asked to add before
+                               // any existing element
+                               placeBefore = /^\+/.test( dataType );
+                               if ( placeBefore ) {
+                                       dataType = dataType.substr( 1 ) || "*";
+                               }
+                               list = structure[ dataType ] = structure[ dataType ] || [];
+                               // then we add to the structure accordingly
+                               list[ placeBefore ? "unshift" : "push" ]( func );
+                       }
+               }
+       };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
+               dataType /* internal */, inspected /* internal */ ) {
+
+       dataType = dataType || options.dataTypes[ 0 ];
+       inspected = inspected || {};
+
+       inspected[ dataType ] = true;
+
+       var selection,
+               list = structure[ dataType ],
+               i = 0,
+               length = list ? list.length : 0,
+               executeOnly = ( structure === prefilters );
+
+       for ( ; i < length && ( executeOnly || !selection ); i++ ) {
+               selection = list[ i ]( options, originalOptions, jqXHR );
+               // If we got redirected to another dataType
+               // we try there if executing only and not done already
+               if ( typeof selection === "string" ) {
+                       if ( !executeOnly || inspected[ selection ] ) {
+                               selection = undefined;
+                       } else {
+                               options.dataTypes.unshift( selection );
+                               selection = inspectPrefiltersOrTransports(
+                                               structure, options, originalOptions, jqXHR, selection, inspected );
+                       }
+               }
+       }
+       // If we're only executing or nothing was selected
+       // we try the catchall dataType if not done already
+       if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
+               selection = inspectPrefiltersOrTransports(
+                               structure, options, originalOptions, jqXHR, "*", inspected );
+       }
+       // unnecessary when only executing (prefilters)
+       // but it'll be ignored by the caller in that case
+       return selection;
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+       var key, deep,
+               flatOptions = jQuery.ajaxSettings.flatOptions || {};
+       for ( key in src ) {
+               if ( src[ key ] !== undefined ) {
+                       ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+               }
+       }
+       if ( deep ) {
+               jQuery.extend( true, target, deep );
+       }
+}
+
+jQuery.fn.load = function( url, params, callback ) {
+       if ( typeof url !== "string" && _load ) {
+               return _load.apply( this, arguments );
+       }
+
+       // Don't do a request if no elements are being requested
+       if ( !this.length ) {
+               return this;
+       }
+
+       var selector, type, response,
+               self = this,
+               off = url.indexOf(" ");
+
+       if ( off >= 0 ) {
+               selector = url.slice( off, url.length );
+               url = url.slice( 0, off );
+       }
+
+       // If it's a function
+       if ( jQuery.isFunction( params ) ) {
+
+               // We assume that it's the callback
+               callback = params;
+               params = undefined;
+
+       // Otherwise, build a param string
+       } else if ( params && typeof params === "object" ) {
+               type = "POST";
+       }
+
+       // Request the remote document
+       jQuery.ajax({
+               url: url,
+
+               // if "type" variable is undefined, then "GET" method will be used
+               type: type,
+               dataType: "html",
+               data: params,
+               complete: function( jqXHR, status ) {
+                       if ( callback ) {
+                               self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+                       }
+               }
+       }).done(function( responseText ) {
+
+               // Save response for use in complete callback
+               response = arguments;
+
+               // See if a selector was specified
+               self.html( selector ?
+
+                       // Create a dummy div to hold the results
+                       jQuery("<div>")
+
+                               // inject the contents of the document in, removing the scripts
+                               // to avoid any 'Permission Denied' errors in IE
+                               .append( responseText.replace( rscript, "" ) )
+
+                               // Locate the specified elements
+                               .find( selector ) :
+
+                       // If not, just inject the full result
+                       responseText );
+
+       });
+
+       return this;
+};
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
+       jQuery.fn[ o ] = function( f ){
+               return this.on( o, f );
+       };
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+       jQuery[ method ] = function( url, data, callback, type ) {
+               // shift arguments if data argument was omitted
+               if ( jQuery.isFunction( data ) ) {
+                       type = type || callback;
+                       callback = data;
+                       data = undefined;
+               }
+
+               return jQuery.ajax({
+                       type: method,
+                       url: url,
+                       data: data,
+                       success: callback,
+                       dataType: type
+               });
+       };
+});
+
+jQuery.extend({
+
+       getScript: function( url, callback ) {
+               return jQuery.get( url, undefined, callback, "script" );
+       },
+
+       getJSON: function( url, data, callback ) {
+               return jQuery.get( url, data, callback, "json" );
+       },
+
+       // Creates a full fledged settings object into target
+       // with both ajaxSettings and settings fields.
+       // If target is omitted, writes into ajaxSettings.
+       ajaxSetup: function( target, settings ) {
+               if ( settings ) {
+                       // Building a settings object
+                       ajaxExtend( target, jQuery.ajaxSettings );
+               } else {
+                       // Extending ajaxSettings
+                       settings = target;
+                       target = jQuery.ajaxSettings;
+               }
+               ajaxExtend( target, settings );
+               return target;
+       },
+
+       ajaxSettings: {
+               url: ajaxLocation,
+               isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+               global: true,
+               type: "GET",
+               contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+               processData: true,
+               async: true,
+               /*
+               timeout: 0,
+               data: null,
+               dataType: null,
+               username: null,
+               password: null,
+               cache: null,
+               throws: false,
+               traditional: false,
+               headers: {},
+               */
+
+               accepts: {
+                       xml: "application/xml, text/xml",
+                       html: "text/html",
+                       text: "text/plain",
+                       json: "application/json, text/javascript",
+                       "*": allTypes
+               },
+
+               contents: {
+                       xml: /xml/,
+                       html: /html/,
+                       json: /json/
+               },
+
+               responseFields: {
+                       xml: "responseXML",
+                       text: "responseText"
+               },
+
+               // List of data converters
+               // 1) key format is "source_type destination_type" (a single space in-between)
+               // 2) the catchall symbol "*" can be used for source_type
+               converters: {
+
+                       // Convert anything to text
+                       "* text": window.String,
+
+                       // Text to html (true = no transformation)
+                       "text html": true,
+
+                       // Evaluate text as a json expression
+                       "text json": jQuery.parseJSON,
+
+                       // Parse text as xml
+                       "text xml": jQuery.parseXML
+               },
+
+               // For options that shouldn't be deep extended:
+               // you can add your own custom options here if
+               // and when you create one that shouldn't be
+               // deep extended (see ajaxExtend)
+               flatOptions: {
+                       context: true,
+                       url: true
+               }
+       },
+
+       ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+       ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+       // Main method
+       ajax: function( url, options ) {
+
+               // If url is an object, simulate pre-1.5 signature
+               if ( typeof url === "object" ) {
+                       options = url;
+                       url = undefined;
+               }
+
+               // Force options to be an object
+               options = options || {};
+
+               var // ifModified key
+                       ifModifiedKey,
+                       // Response headers
+                       responseHeadersString,
+                       responseHeaders,
+                       // transport
+                       transport,
+                       // timeout handle
+                       timeoutTimer,
+                       // Cross-domain detection vars
+                       parts,
+                       // To know if global events are to be dispatched
+                       fireGlobals,
+                       // Loop variable
+                       i,
+                       // Create the final options object
+                       s = jQuery.ajaxSetup( {}, options ),
+                       // Callbacks context
+                       callbackContext = s.context || s,
+                       // Context for global events
+                       // It's the callbackContext if one was provided in the options
+                       // and if it's a DOM node or a jQuery collection
+                       globalEventContext = callbackContext !== s &&
+                               ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
+                                               jQuery( callbackContext ) : jQuery.event,
+                       // Deferreds
+                       deferred = jQuery.Deferred(),
+                       completeDeferred = jQuery.Callbacks( "once memory" ),
+                       // Status-dependent callbacks
+                       statusCode = s.statusCode || {},
+                       // Headers (they are sent all at once)
+                       requestHeaders = {},
+                       requestHeadersNames = {},
+                       // The jqXHR state
+                       state = 0,
+                       // Default abort message
+                       strAbort = "canceled",
+                       // Fake xhr
+                       jqXHR = {
+
+                               readyState: 0,
+
+                               // Caches the header
+                               setRequestHeader: function( name, value ) {
+                                       if ( !state ) {
+                                               var lname = name.toLowerCase();
+                                               name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+                                               requestHeaders[ name ] = value;
+                                       }
+                                       return this;
+                               },
+
+                               // Raw string
+                               getAllResponseHeaders: function() {
+                                       return state === 2 ? responseHeadersString : null;
+                               },
+
+                               // Builds headers hashtable if needed
+                               getResponseHeader: function( key ) {
+                                       var match;
+                                       if ( state === 2 ) {
+                                               if ( !responseHeaders ) {
+                                                       responseHeaders = {};
+                                                       while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+                                                               responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+                                                       }
+                                               }
+                                               match = responseHeaders[ key.toLowerCase() ];
+                                       }
+                                       return match === undefined ? null : match;
+                               },
+
+                               // Overrides response content-type header
+                               overrideMimeType: function( type ) {
+                                       if ( !state ) {
+                                               s.mimeType = type;
+                                       }
+                                       return this;
+                               },
+
+                               // Cancel the request
+                               abort: function( statusText ) {
+                                       statusText = statusText || strAbort;
+                                       if ( transport ) {
+                                               transport.abort( statusText );
+                                       }
+                                       done( 0, statusText );
+                                       return this;
+                               }
+                       };
+
+               // Callback for when everything is done
+               // It is defined here because jslint complains if it is declared
+               // at the end of the function (which would be more logical and readable)
+               function done( status, nativeStatusText, responses, headers ) {
+                       var isSuccess, success, error, response, modified,
+                               statusText = nativeStatusText;
+
+                       // Called once
+                       if ( state === 2 ) {
+                               return;
+                       }
+
+                       // State is "done" now
+                       state = 2;
+
+                       // Clear timeout if it exists
+                       if ( timeoutTimer ) {
+                               clearTimeout( timeoutTimer );
+                       }
+
+                       // Dereference transport for early garbage collection
+                       // (no matter how long the jqXHR object will be used)
+                       transport = undefined;
+
+                       // Cache response headers
+                       responseHeadersString = headers || "";
+
+                       // Set readyState
+                       jqXHR.readyState = status > 0 ? 4 : 0;
+
+                       // Get response data
+                       if ( responses ) {
+                               response = ajaxHandleResponses( s, jqXHR, responses );
+                       }
+
+                       // If successful, handle type chaining
+                       if ( status >= 200 && status < 300 || status === 304 ) {
+
+                               // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+                               if ( s.ifModified ) {
+
+                                       modified = jqXHR.getResponseHeader("Last-Modified");
+                                       if ( modified ) {
+                                               jQuery.lastModified[ ifModifiedKey ] = modified;
+                                       }
+                                       modified = jqXHR.getResponseHeader("Etag");
+                                       if ( modified ) {
+                                               jQuery.etag[ ifModifiedKey ] = modified;
+                                       }
+                               }
+
+                               // If not modified
+                               if ( status === 304 ) {
+
+                                       statusText = "notmodified";
+                                       isSuccess = true;
+
+                               // If we have data
+                               } else {
+
+                                       isSuccess = ajaxConvert( s, response );
+                                       statusText = isSuccess.state;
+                                       success = isSuccess.data;
+                                       error = isSuccess.error;
+                                       isSuccess = !error;
+                               }
+                       } else {
+                               // We extract error from statusText
+                               // then normalize statusText and status for non-aborts
+                               error = statusText;
+                               if ( !statusText || status ) {
+                                       statusText = "error";
+                                       if ( status < 0 ) {
+                                               status = 0;
+                                       }
+                               }
+                       }
+
+                       // Set data for the fake xhr object
+                       jqXHR.status = status;
+                       jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+                       // Success/Error
+                       if ( isSuccess ) {
+                               deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+                       } else {
+                               deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+                       }
+
+                       // Status-dependent callbacks
+                       jqXHR.statusCode( statusCode );
+                       statusCode = undefined;
+
+                       if ( fireGlobals ) {
+                               globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
+                                               [ jqXHR, s, isSuccess ? success : error ] );
+                       }
+
+                       // Complete
+                       completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+                       if ( fireGlobals ) {
+                               globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+                               // Handle the global AJAX counter
+                               if ( !( --jQuery.active ) ) {
+                                       jQuery.event.trigger( "ajaxStop" );
+                               }
+                       }
+               }
+
+               // Attach deferreds
+               deferred.promise( jqXHR );
+               jqXHR.success = jqXHR.done;
+               jqXHR.error = jqXHR.fail;
+               jqXHR.complete = completeDeferred.add;
+
+               // Status-dependent callbacks
+               jqXHR.statusCode = function( map ) {
+                       if ( map ) {
+                               var tmp;
+                               if ( state < 2 ) {
+                                       for ( tmp in map ) {
+                                               statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
+                                       }
+                               } else {
+                                       tmp = map[ jqXHR.status ];
+                                       jqXHR.always( tmp );
+                               }
+                       }
+                       return this;
+               };
+
+               // Remove hash character (#7531: and string promotion)
+               // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+               // We also use the url parameter if available
+               s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+               // Extract dataTypes list
+               s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace );
+
+               // A cross-domain request is in order when we have a protocol:host:port mismatch
+               if ( s.crossDomain == null ) {
+                       parts = rurl.exec( s.url.toLowerCase() );
+                       s.crossDomain = !!( parts &&
+                               ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+                                       ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+                                               ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+                       );
+               }
+
+               // Convert data if not already a string
+               if ( s.data && s.processData && typeof s.data !== "string" ) {
+                       s.data = jQuery.param( s.data, s.traditional );
+               }
+
+               // Apply prefilters
+               inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+               // If request was aborted inside a prefilter, stop there
+               if ( state === 2 ) {
+                       return jqXHR;
+               }
+
+               // We can fire global events as of now if asked to
+               fireGlobals = s.global;
+
+               // Uppercase the type
+               s.type = s.type.toUpperCase();
+
+               // Determine if request has content
+               s.hasContent = !rnoContent.test( s.type );
+
+               // Watch for a new set of requests
+               if ( fireGlobals && jQuery.active++ === 0 ) {
+                       jQuery.event.trigger( "ajaxStart" );
+               }
+
+               // More options handling for requests with no content
+               if ( !s.hasContent ) {
+
+                       // If data is available, append data to url
+                       if ( s.data ) {
+                               s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
+                               // #9682: remove data so that it's not used in an eventual retry
+                               delete s.data;
+                       }
+
+                       // Get ifModifiedKey before adding the anti-cache parameter
+                       ifModifiedKey = s.url;
+
+                       // Add anti-cache in url if needed
+                       if ( s.cache === false ) {
+
+                               var ts = jQuery.now(),
+                                       // try replacing _= if it is there
+                                       ret = s.url.replace( rts, "$1_=" + ts );
+
+                               // if nothing was replaced, add timestamp to the end
+                               s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
+                       }
+               }
+
+               // Set the correct header, if data is being sent
+               if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+                       jqXHR.setRequestHeader( "Content-Type", s.contentType );
+               }
+
+               // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+               if ( s.ifModified ) {
+                       ifModifiedKey = ifModifiedKey || s.url;
+                       if ( jQuery.lastModified[ ifModifiedKey ] ) {
+                               jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
+                       }
+                       if ( jQuery.etag[ ifModifiedKey ] ) {
+                               jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
+                       }
+               }
+
+               // Set the Accepts header for the server, depending on the dataType
+               jqXHR.setRequestHeader(
+                       "Accept",
+                       s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+                               s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+                               s.accepts[ "*" ]
+               );
+
+               // Check for headers option
+               for ( i in s.headers ) {
+                       jqXHR.setRequestHeader( i, s.headers[ i ] );
+               }
+
+               // Allow custom headers/mimetypes and early abort
+               if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+                               // Abort if not done already and return
+                               return jqXHR.abort();
+
+               }
+
+               // aborting is no longer a cancellation
+               strAbort = "abort";
+
+               // Install callbacks on deferreds
+               for ( i in { success: 1, error: 1, complete: 1 } ) {
+                       jqXHR[ i ]( s[ i ] );
+               }
+
+               // Get transport
+               transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+               // If no transport, we auto-abort
+               if ( !transport ) {
+                       done( -1, "No Transport" );
+               } else {
+                       jqXHR.readyState = 1;
+                       // Send global event
+                       if ( fireGlobals ) {
+                               globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+                       }
+                       // Timeout
+                       if ( s.async && s.timeout > 0 ) {
+                               timeoutTimer = setTimeout( function(){
+                                       jqXHR.abort( "timeout" );
+                               }, s.timeout );
+                       }
+
+                       try {
+                               state = 1;
+                               transport.send( requestHeaders, done );
+                       } catch (e) {
+                               // Propagate exception as error if not done
+                               if ( state < 2 ) {
+                                       done( -1, e );
+                               // Simply rethrow otherwise
+                               } else {
+                                       throw e;
+                               }
+                       }
+               }
+
+               return jqXHR;
+       },
+
+       // Counter for holding the number of active queries
+       active: 0,
+
+       // Last-Modified header cache for next request
+       lastModified: {},
+       etag: {}
+
+});
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+       var ct, type, finalDataType, firstDataType,
+               contents = s.contents,
+               dataTypes = s.dataTypes,
+               responseFields = s.responseFields;
+
+       // Fill responseXXX fields
+       for ( type in responseFields ) {
+               if ( type in responses ) {
+                       jqXHR[ responseFields[type] ] = responses[ type ];
+               }
+       }
+
+       // Remove auto dataType and get content-type in the process
+       while( dataTypes[ 0 ] === "*" ) {
+               dataTypes.shift();
+               if ( ct === undefined ) {
+                       ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
+               }
+       }
+
+       // Check if we're dealing with a known content-type
+       if ( ct ) {
+               for ( type in contents ) {
+                       if ( contents[ type ] && contents[ type ].test( ct ) ) {
+                               dataTypes.unshift( type );
+                               break;
+                       }
+               }
+       }
+
+       // Check to see if we have a response for the expected dataType
+       if ( dataTypes[ 0 ] in responses ) {
+               finalDataType = dataTypes[ 0 ];
+       } else {
+               // Try convertible dataTypes
+               for ( type in responses ) {
+                       if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+                               finalDataType = type;
+                               break;
+                       }
+                       if ( !firstDataType ) {
+                               firstDataType = type;
+                       }
+               }
+               // Or just use first one
+               finalDataType = finalDataType || firstDataType;
+       }
+
+       // If we found a dataType
+       // We add the dataType to the list if needed
+       // and return the corresponding response
+       if ( finalDataType ) {
+               if ( finalDataType !== dataTypes[ 0 ] ) {
+                       dataTypes.unshift( finalDataType );
+               }
+               return responses[ finalDataType ];
+       }
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+
+       var conv, conv2, current, tmp,
+               // Work with a copy of dataTypes in case we need to modify it for conversion
+               dataTypes = s.dataTypes.slice(),
+               prev = dataTypes[ 0 ],
+               converters = {},
+               i = 0;
+
+       // Apply the dataFilter if provided
+       if ( s.dataFilter ) {
+               response = s.dataFilter( response, s.dataType );
+       }
+
+       // Create converters map with lowercased keys
+       if ( dataTypes[ 1 ] ) {
+               for ( conv in s.converters ) {
+                       converters[ conv.toLowerCase() ] = s.converters[ conv ];
+               }
+       }
+
+       // Convert to each sequential dataType, tolerating list modification
+       for ( ; (current = dataTypes[++i]); ) {
+
+               // There's only work to do if current dataType is non-auto
+               if ( current !== "*" ) {
+
+                       // Convert response if prev dataType is non-auto and differs from current
+                       if ( prev !== "*" && prev !== current ) {
+
+                               // Seek a direct converter
+                               conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+                               // If none found, seek a pair
+                               if ( !conv ) {
+                                       for ( conv2 in converters ) {
+
+                                               // If conv2 outputs current
+                                               tmp = conv2.split(" ");
+                                               if ( tmp[ 1 ] === current ) {
+
+                                                       // If prev can be converted to accepted input
+                                                       conv = converters[ prev + " " + tmp[ 0 ] ] ||
+                                                               converters[ "* " + tmp[ 0 ] ];
+                                                       if ( conv ) {
+                                                               // Condense equivalence converters
+                                                               if ( conv === true ) {
+                                                                       conv = converters[ conv2 ];
+
+                                                               // Otherwise, insert the intermediate dataType
+                                                               } else if ( converters[ conv2 ] !== true ) {
+                                                                       current = tmp[ 0 ];
+                                                                       dataTypes.splice( i--, 0, current );
+                                                               }
+
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               // Apply converter (if not an equivalence)
+                               if ( conv !== true ) {
+
+                                       // Unless errors are allowed to bubble, catch and return them
+                                       if ( conv && s["throws"] ) {
+                                               response = conv( response );
+                                       } else {
+                                               try {
+                                                       response = conv( response );
+                                               } catch ( e ) {
+                                                       return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+                                               }
+                                       }
+                               }
+                       }
+
+                       // Update prev for next iteration
+                       prev = current;
+               }
+       }
+
+       return { state: "success", data: response };
+}
+var oldCallbacks = [],
+       rquestion = /\?/,
+       rjsonp = /(=)\?(?=&|$)|\?\?/,
+       nonce = jQuery.now();
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+       jsonp: "callback",
+       jsonpCallback: function() {
+               var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+               this[ callback ] = true;
+               return callback;
+       }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+       var callbackName, overwritten, responseContainer,
+               data = s.data,
+               url = s.url,
+               hasCallback = s.jsonp !== false,
+               replaceInUrl = hasCallback && rjsonp.test( url ),
+               replaceInData = hasCallback && !replaceInUrl && typeof data === "string" &&
+                       !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") &&
+                       rjsonp.test( data );
+
+       // Handle iff the expected data type is "jsonp" or we have a parameter to set
+       if ( s.dataTypes[ 0 ] === "jsonp" || replaceInUrl || replaceInData ) {
+
+               // Get callback name, remembering preexisting value associated with it
+               callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+                       s.jsonpCallback() :
+                       s.jsonpCallback;
+               overwritten = window[ callbackName ];
+
+               // Insert callback into url or form data
+               if ( replaceInUrl ) {
+                       s.url = url.replace( rjsonp, "$1" + callbackName );
+               } else if ( replaceInData ) {
+                       s.data = data.replace( rjsonp, "$1" + callbackName );
+               } else if ( hasCallback ) {
+                       s.url += ( rquestion.test( url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+               }
+
+               // Use data converter to retrieve json after script execution
+               s.converters["script json"] = function() {
+                       if ( !responseContainer ) {
+                               jQuery.error( callbackName + " was not called" );
+                       }
+                       return responseContainer[ 0 ];
+               };
+
+               // force json dataType
+               s.dataTypes[ 0 ] = "json";
+
+               // Install callback
+               window[ callbackName ] = function() {
+                       responseContainer = arguments;
+               };
+
+               // Clean-up function (fires after converters)
+               jqXHR.always(function() {
+                       // Restore preexisting value
+                       window[ callbackName ] = overwritten;
+
+                       // Save back as free
+                       if ( s[ callbackName ] ) {
+                               // make sure that re-using the options doesn't screw things around
+                               s.jsonpCallback = originalSettings.jsonpCallback;
+
+                               // save the callback name for future use
+                               oldCallbacks.push( callbackName );
+                       }
+
+                       // Call if it was a function and we have a response
+                       if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+                               overwritten( responseContainer[ 0 ] );
+                       }
+
+                       responseContainer = overwritten = undefined;
+               });
+
+               // Delegate to script
+               return "script";
+       }
+});
+// Install script dataType
+jQuery.ajaxSetup({
+       accepts: {
+               script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+       },
+       contents: {
+               script: /javascript|ecmascript/
+       },
+       converters: {
+               "text script": function( text ) {
+                       jQuery.globalEval( text );
+                       return text;
+               }
+       }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+       if ( s.cache === undefined ) {
+               s.cache = false;
+       }
+       if ( s.crossDomain ) {
+               s.type = "GET";
+               s.global = false;
+       }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+       // This transport only deals with cross domain requests
+       if ( s.crossDomain ) {
+
+               var script,
+                       head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
+
+               return {
+
+                       send: function( _, callback ) {
+
+                               script = document.createElement( "script" );
+
+                               script.async = "async";
+
+                               if ( s.scriptCharset ) {
+                                       script.charset = s.scriptCharset;
+                               }
+
+                               script.src = s.url;
+
+                               // Attach handlers for all browsers
+                               script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+                                       if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+                                               // Handle memory leak in IE
+                                               script.onload = script.onreadystatechange = null;
+
+                                               // Remove the script
+                                               if ( head && script.parentNode ) {
+                                                       head.removeChild( script );
+                                               }
+
+                                               // Dereference the script
+                                               script = undefined;
+
+                                               // Callback if not abort
+                                               if ( !isAbort ) {
+                                                       callback( 200, "success" );
+                                               }
+                                       }
+                               };
+                               // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+                               // This arises when a base node is used (#2709 and #4378).
+                               head.insertBefore( script, head.firstChild );
+                       },
+
+                       abort: function() {
+                               if ( script ) {
+                                       script.onload( 0, 1 );
+                               }
+                       }
+               };
+       }
+});
+var xhrCallbacks,
+       // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+       xhrOnUnloadAbort = window.ActiveXObject ? function() {
+               // Abort all pending requests
+               for ( var key in xhrCallbacks ) {
+                       xhrCallbacks[ key ]( 0, 1 );
+               }
+       } : false,
+       xhrId = 0;
+
+// Functions to create xhrs
+function createStandardXHR() {
+       try {
+               return new window.XMLHttpRequest();
+       } catch( e ) {}
+}
+
+function createActiveXHR() {
+       try {
+               return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+       } catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+       /* Microsoft failed to properly
+        * implement the XMLHttpRequest in IE7 (can't request local files),
+        * so we use the ActiveXObject when it is available
+        * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+        * we need a fallback.
+        */
+       function() {
+               return !this.isLocal && createStandardXHR() || createActiveXHR();
+       } :
+       // For all other browsers, use the standard XMLHttpRequest object
+       createStandardXHR;
+
+// Determine support properties
+(function( xhr ) {
+       jQuery.extend( jQuery.support, {
+               ajax: !!xhr,
+               cors: !!xhr && ( "withCredentials" in xhr )
+       });
+})( jQuery.ajaxSettings.xhr() );
+
+// Create transport if the browser can provide an xhr
+if ( jQuery.support.ajax ) {
+
+       jQuery.ajaxTransport(function( s ) {
+               // Cross domain only allowed if supported through XMLHttpRequest
+               if ( !s.crossDomain || jQuery.support.cors ) {
+
+                       var callback;
+
+                       return {
+                               send: function( headers, complete ) {
+
+                                       // Get a new xhr
+                                       var handle, i,
+                                               xhr = s.xhr();
+
+                                       // Open the socket
+                                       // Passing null username, generates a login popup on Opera (#2865)
+                                       if ( s.username ) {
+                                               xhr.open( s.type, s.url, s.async, s.username, s.password );
+                                       } else {
+                                               xhr.open( s.type, s.url, s.async );
+                                       }
+
+                                       // Apply custom fields if provided
+                                       if ( s.xhrFields ) {
+                                               for ( i in s.xhrFields ) {
+                                                       xhr[ i ] = s.xhrFields[ i ];
+                                               }
+                                       }
+
+                                       // Override mime type if needed
+                                       if ( s.mimeType && xhr.overrideMimeType ) {
+                                               xhr.overrideMimeType( s.mimeType );
+                                       }
+
+                                       // X-Requested-With header
+                                       // For cross-domain requests, seeing as conditions for a preflight are
+                                       // akin to a jigsaw puzzle, we simply never set it to be sure.
+                                       // (it can always be set on a per-request basis or even using ajaxSetup)
+                                       // For same-domain requests, won't change header if already provided.
+                                       if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+                                               headers[ "X-Requested-With" ] = "XMLHttpRequest";
+                                       }
+
+                                       // Need an extra try/catch for cross domain requests in Firefox 3
+                                       try {
+                                               for ( i in headers ) {
+                                                       xhr.setRequestHeader( i, headers[ i ] );
+                                               }
+                                       } catch( _ ) {}
+
+                                       // Do send the request
+                                       // This may raise an exception which is actually
+                                       // handled in jQuery.ajax (so no try/catch here)
+                                       xhr.send( ( s.hasContent && s.data ) || null );
+
+                                       // Listener
+                                       callback = function( _, isAbort ) {
+
+                                               var status,
+                                                       statusText,
+                                                       responseHeaders,
+                                                       responses,
+                                                       xml;
+
+                                               // Firefox throws exceptions when accessing properties
+                                               // of an xhr when a network error occurred
+                                               // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+                                               try {
+
+                                                       // Was never called and is aborted or complete
+                                                       if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+                                                               // Only called once
+                                                               callback = undefined;
+
+                                                               // Do not keep as active anymore
+                                                               if ( handle ) {
+                                                                       xhr.onreadystatechange = jQuery.noop;
+                                                                       if ( xhrOnUnloadAbort ) {
+                                                                               delete xhrCallbacks[ handle ];
+                                                                       }
+                                                               }
+
+                                                               // If it's an abort
+                                                               if ( isAbort ) {
+                                                                       // Abort it manually if needed
+                                                                       if ( xhr.readyState !== 4 ) {
+                                                                               xhr.abort();
+                                                                       }
+                                                               } else {
+                                                                       status = xhr.status;
+                                                                       responseHeaders = xhr.getAllResponseHeaders();
+                                                                       responses = {};
+                                                                       xml = xhr.responseXML;
+
+                                                                       // Construct response list
+                                                                       if ( xml && xml.documentElement /* #4958 */ ) {
+                                                                               responses.xml = xml;
+                                                                       }
+
+                                                                       // When requesting binary data, IE6-9 will throw an exception
+                                                                       // on any attempt to access responseText (#11426)
+                                                                       try {
+                                                                               responses.text = xhr.responseText;
+                                                                       } catch( e ) {
+                                                                       }
+
+                                                                       // Firefox throws an exception when accessing
+                                                                       // statusText for faulty cross-domain requests
+                                                                       try {
+                                                                               statusText = xhr.statusText;
+                                                                       } catch( e ) {
+                                                                               // We normalize with Webkit giving an empty statusText
+                                                                               statusText = "";
+                                                                       }
+
+                                                                       // Filter status for non standard behaviors
+
+                                                                       // If the request is local and we have data: assume a success
+                                                                       // (success with no data won't get notified, that's the best we
+                                                                       // can do given current implementations)
+                                                                       if ( !status && s.isLocal && !s.crossDomain ) {
+                                                                               status = responses.text ? 200 : 404;
+                                                                       // IE - #1450: sometimes returns 1223 when it should be 204
+                                                                       } else if ( status === 1223 ) {
+                                                                               status = 204;
+                                                                       }
+                                                               }
+                                                       }
+                                               } catch( firefoxAccessException ) {
+                                                       if ( !isAbort ) {
+                                                               complete( -1, firefoxAccessException );
+                                                       }
+                                               }
+
+                                               // Call complete if needed
+                                               if ( responses ) {
+                                                       complete( status, statusText, responses, responseHeaders );
+                                               }
+                                       };
+
+                                       if ( !s.async ) {
+                                               // if we're in sync mode we fire the callback
+                                               callback();
+                                       } else if ( xhr.readyState === 4 ) {
+                                               // (IE6 & IE7) if it's in cache and has been
+                                               // retrieved directly we need to fire the callback
+                                               setTimeout( callback, 0 );
+                                       } else {
+                                               handle = ++xhrId;
+                                               if ( xhrOnUnloadAbort ) {
+                                                       // Create the active xhrs callbacks list if needed
+                                                       // and attach the unload handler
+                                                       if ( !xhrCallbacks ) {
+                                                               xhrCallbacks = {};
+                                                               jQuery( window ).unload( xhrOnUnloadAbort );
+                                                       }
+                                                       // Add to list of active xhrs callbacks
+                                                       xhrCallbacks[ handle ] = callback;
+                                               }
+                                               xhr.onreadystatechange = callback;
+                                       }
+                               },
+
+                               abort: function() {
+                                       if ( callback ) {
+                                               callback(0,1);
+                                       }
+                               }
+                       };
+               }
+       });
+}
+var fxNow, timerId,
+       rfxtypes = /^(?:toggle|show|hide)$/,
+       rfxnum = new RegExp( "^(?:([-+])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
+       rrun = /queueHooks$/,
+       animationPrefilters = [ defaultPrefilter ],
+       tweeners = {
+               "*": [function( prop, value ) {
+                       var end, unit,
+                               tween = this.createTween( prop, value ),
+                               parts = rfxnum.exec( value ),
+                               target = tween.cur(),
+                               start = +target || 0,
+                               scale = 1,
+                               maxIterations = 20;
+
+                       if ( parts ) {
+                               end = +parts[2];
+                               unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+
+                               // We need to compute starting value
+                               if ( unit !== "px" && start ) {
+                                       // Iteratively approximate from a nonzero starting point
+                                       // Prefer the current property, because this process will be trivial if it uses the same units
+                                       // Fallback to end or a simple constant
+                                       start = jQuery.css( tween.elem, prop, true ) || end || 1;
+
+                                       do {
+                                               // If previous iteration zeroed out, double until we get *something*
+                                               // Use a string for doubling factor so we don't accidentally see scale as unchanged below
+                                               scale = scale || ".5";
+
+                                               // Adjust and apply
+                                               start = start / scale;
+                                               jQuery.style( tween.elem, prop, start + unit );
+
+                                       // Update scale, tolerating zero or NaN from tween.cur()
+                                       // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+                                       } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+                               }
+
+                               tween.unit = unit;
+                               tween.start = start;
+                               // If a +=/-= token was provided, we're doing a relative animation
+                               tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
+                       }
+                       return tween;
+               }]
+       };
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+       setTimeout(function() {
+               fxNow = undefined;
+       }, 0 );
+       return ( fxNow = jQuery.now() );
+}
+
+function createTweens( animation, props ) {
+       jQuery.each( props, function( prop, value ) {
+               var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+                       index = 0,
+                       length = collection.length;
+               for ( ; index < length; index++ ) {
+                       if ( collection[ index ].call( animation, prop, value ) ) {
+
+                               // we're done with this property
+                               return;
+                       }
+               }
+       });
+}
+
+function Animation( elem, properties, options ) {
+       var result,
+               index = 0,
+               tweenerIndex = 0,
+               length = animationPrefilters.length,
+               deferred = jQuery.Deferred().always( function() {
+                       // don't match elem in the :animated selector
+                       delete tick.elem;
+               }),
+               tick = function() {
+                       var currentTime = fxNow || createFxNow(),
+                               remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+                               // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+                               temp = remaining / animation.duration || 0,
+                               percent = 1 - temp,
+                               index = 0,
+                               length = animation.tweens.length;
+
+                       for ( ; index < length ; index++ ) {
+                               animation.tweens[ index ].run( percent );
+                       }
+
+                       deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+                       if ( percent < 1 && length ) {
+                               return remaining;
+                       } else {
+                               deferred.resolveWith( elem, [ animation ] );
+                               return false;
+                       }
+               },
+               animation = deferred.promise({
+                       elem: elem,
+                       props: jQuery.extend( {}, properties ),
+                       opts: jQuery.extend( true, { specialEasing: {} }, options ),
+                       originalProperties: properties,
+                       originalOptions: options,
+                       startTime: fxNow || createFxNow(),
+                       duration: options.duration,
+                       tweens: [],
+                       createTween: function( prop, end, easing ) {
+                               var tween = jQuery.Tween( elem, animation.opts, prop, end,
+                                               animation.opts.specialEasing[ prop ] || animation.opts.easing );
+                               animation.tweens.push( tween );
+                               return tween;
+                       },
+                       stop: function( gotoEnd ) {
+                               var index = 0,
+                                       // if we are going to the end, we want to run all the tweens
+                                       // otherwise we skip this part
+                                       length = gotoEnd ? animation.tweens.length : 0;
+
+                               for ( ; index < length ; index++ ) {
+                                       animation.tweens[ index ].run( 1 );
+                               }
+
+                               // resolve when we played the last frame
+                               // otherwise, reject
+                               if ( gotoEnd ) {
+                                       deferred.resolveWith( elem, [ animation, gotoEnd ] );
+                               } else {
+                                       deferred.rejectWith( elem, [ animation, gotoEnd ] );
+                               }
+                               return this;
+                       }
+               }),
+               props = animation.props;
+
+       propFilter( props, animation.opts.specialEasing );
+
+       for ( ; index < length ; index++ ) {
+               result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+               if ( result ) {
+                       return result;
+               }
+       }
+
+       createTweens( animation, props );
+
+       if ( jQuery.isFunction( animation.opts.start ) ) {
+               animation.opts.start.call( elem, animation );
+       }
+
+       jQuery.fx.timer(
+               jQuery.extend( tick, {
+                       anim: animation,
+                       queue: animation.opts.queue,
+                       elem: elem
+               })
+       );
+
+       // attach callbacks from options
+       return animation.progress( animation.opts.progress )
+               .done( animation.opts.done, animation.opts.complete )
+               .fail( animation.opts.fail )
+               .always( animation.opts.always );
+}
+
+function propFilter( props, specialEasing ) {
+       var index, name, easing, value, hooks;
+
+       // camelCase, specialEasing and expand cssHook pass
+       for ( index in props ) {
+               name = jQuery.camelCase( index );
+               easing = specialEasing[ name ];
+               value = props[ index ];
+               if ( jQuery.isArray( value ) ) {
+                       easing = value[ 1 ];
+                       value = props[ index ] = value[ 0 ];
+               }
+
+               if ( index !== name ) {
+                       props[ name ] = value;
+                       delete props[ index ];
+               }
+
+               hooks = jQuery.cssHooks[ name ];
+               if ( hooks && "expand" in hooks ) {
+                       value = hooks.expand( value );
+                       delete props[ name ];
+
+                       // not quite $.extend, this wont overwrite keys already present.
+                       // also - reusing 'index' from above because we have the correct "name"
+                       for ( index in value ) {
+                               if ( !( index in props ) ) {
+                                       props[ index ] = value[ index ];
+                                       specialEasing[ index ] = easing;
+                               }
+                       }
+               } else {
+                       specialEasing[ name ] = easing;
+               }
+       }
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+
+       tweener: function( props, callback ) {
+               if ( jQuery.isFunction( props ) ) {
+                       callback = props;
+                       props = [ "*" ];
+               } else {
+                       props = props.split(" ");
+               }
+
+               var prop,
+                       index = 0,
+                       length = props.length;
+
+               for ( ; index < length ; index++ ) {
+                       prop = props[ index ];
+                       tweeners[ prop ] = tweeners[ prop ] || [];
+                       tweeners[ prop ].unshift( callback );
+               }
+       },
+
+       prefilter: function( callback, prepend ) {
+               if ( prepend ) {
+                       animationPrefilters.unshift( callback );
+               } else {
+                       animationPrefilters.push( callback );
+               }
+       }
+});
+
+function defaultPrefilter( elem, props, opts ) {
+       var index, prop, value, length, dataShow, toggle, tween, hooks, oldfire,
+               anim = this,
+               style = elem.style,
+               orig = {},
+               handled = [],
+               hidden = elem.nodeType && isHidden( elem );
+
+       // handle queue: false promises
+       if ( !opts.queue ) {
+               hooks = jQuery._queueHooks( elem, "fx" );
+               if ( hooks.unqueued == null ) {
+                       hooks.unqueued = 0;
+                       oldfire = hooks.empty.fire;
+                       hooks.empty.fire = function() {
+                               if ( !hooks.unqueued ) {
+                                       oldfire();
+                               }
+                       };
+               }
+               hooks.unqueued++;
+
+               anim.always(function() {
+                       // doing this makes sure that the complete handler will be called
+                       // before this completes
+                       anim.always(function() {
+                               hooks.unqueued--;
+                               if ( !jQuery.queue( elem, "fx" ).length ) {
+                                       hooks.empty.fire();
+                               }
+                       });
+               });
+       }
+
+       // height/width overflow pass
+       if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+               // Make sure that nothing sneaks out
+               // Record all 3 overflow attributes because IE does not
+               // change the overflow attribute when overflowX and
+               // overflowY are set to the same value
+               opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+               // Set display property to inline-block for height/width
+               // animations on inline elements that are having width/height animated
+               if ( jQuery.css( elem, "display" ) === "inline" &&
+                               jQuery.css( elem, "float" ) === "none" ) {
+
+                       // inline-level elements accept inline-block;
+                       // block-level elements need to be inline with layout
+                       if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
+                               style.display = "inline-block";
+
+                       } else {
+                               style.zoom = 1;
+                       }
+               }
+       }
+
+       if ( opts.overflow ) {
+               style.overflow = "hidden";
+               if ( !jQuery.support.shrinkWrapBlocks ) {
+                       anim.done(function() {
+                               style.overflow = opts.overflow[ 0 ];
+                               style.overflowX = opts.overflow[ 1 ];
+                               style.overflowY = opts.overflow[ 2 ];
+                       });
+               }
+       }
+
+
+       // show/hide pass
+       for ( index in props ) {
+               value = props[ index ];
+               if ( rfxtypes.exec( value ) ) {
+                       delete props[ index ];
+                       toggle = toggle || value === "toggle";
+                       if ( value === ( hidden ? "hide" : "show" ) ) {
+                               continue;
+                       }
+                       handled.push( index );
+               }
+       }
+
+       length = handled.length;
+       if ( length ) {
+               dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
+               if ( "hidden" in dataShow ) {
+                       hidden = dataShow.hidden;
+               }
+
+               // store state if its toggle - enables .stop().toggle() to "reverse"
+               if ( toggle ) {
+                       dataShow.hidden = !hidden;
+               }
+               if ( hidden ) {
+                       jQuery( elem ).show();
+               } else {
+                       anim.done(function() {
+                               jQuery( elem ).hide();
+                       });
+               }
+               anim.done(function() {
+                       var prop;
+                       jQuery.removeData( elem, "fxshow", true );
+                       for ( prop in orig ) {
+                               jQuery.style( elem, prop, orig[ prop ] );
+                       }
+               });
+               for ( index = 0 ; index < length ; index++ ) {
+                       prop = handled[ index ];
+                       tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
+                       orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
+
+                       if ( !( prop in dataShow ) ) {
+                               dataShow[ prop ] = tween.start;
+                               if ( hidden ) {
+                                       tween.end = tween.start;
+                                       tween.start = prop === "width" || prop === "height" ? 1 : 0;
+                               }
+                       }
+               }
+       }
+}
+
+function Tween( elem, options, prop, end, easing ) {
+       return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+       constructor: Tween,
+       init: function( elem, options, prop, end, easing, unit ) {
+               this.elem = elem;
+               this.prop = prop;
+               this.easing = easing || "swing";
+               this.options = options;
+               this.start = this.now = this.cur();
+               this.end = end;
+               this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+       },
+       cur: function() {
+               var hooks = Tween.propHooks[ this.prop ];
+
+               return hooks && hooks.get ?
+                       hooks.get( this ) :
+                       Tween.propHooks._default.get( this );
+       },
+       run: function( percent ) {
+               var eased,
+                       hooks = Tween.propHooks[ this.prop ];
+
+               if ( this.options.duration ) {
+                       this.pos = eased = jQuery.easing[ this.easing ](
+                               percent, this.options.duration * percent, 0, 1, this.options.duration
+                       );
+               } else {
+                       this.pos = eased = percent;
+               }
+               this.now = ( this.end - this.start ) * eased + this.start;
+
+               if ( this.options.step ) {
+                       this.options.step.call( this.elem, this.now, this );
+               }
+
+               if ( hooks && hooks.set ) {
+                       hooks.set( this );
+               } else {
+                       Tween.propHooks._default.set( this );
+               }
+               return this;
+       }
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+       _default: {
+               get: function( tween ) {
+                       var result;
+
+                       if ( tween.elem[ tween.prop ] != null &&
+                               (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+                               return tween.elem[ tween.prop ];
+                       }
+
+                       // passing any value as a 4th parameter to .css will automatically
+                       // attempt a parseFloat and fallback to a string if the parse fails
+                       // so, simple values such as "10px" are parsed to Float.
+                       // complex values such as "rotate(1rad)" are returned as is.
+                       result = jQuery.css( tween.elem, tween.prop, false, "" );
+                       // Empty strings, null, undefined and "auto" are converted to 0.
+                       return !result || result === "auto" ? 0 : result;
+               },
+               set: function( tween ) {
+                       // use step hook for back compat - use cssHook if its there - use .style if its
+                       // available and use plain properties where available
+                       if ( jQuery.fx.step[ tween.prop ] ) {
+                               jQuery.fx.step[ tween.prop ]( tween );
+                       } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+                               jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+                       } else {
+                               tween.elem[ tween.prop ] = tween.now;
+                       }
+               }
+       }
+};
+
+// Remove in 2.0 - this supports IE8's panic based approach
+// to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+       set: function( tween ) {
+               if ( tween.elem.nodeType && tween.elem.parentNode ) {
+                       tween.elem[ tween.prop ] = tween.now;
+               }
+       }
+};
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+       var cssFn = jQuery.fn[ name ];
+       jQuery.fn[ name ] = function( speed, easing, callback ) {
+               return speed == null || typeof speed === "boolean" ||
+                       // special check for .toggle( handler, handler, ... )
+                       ( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ?
+                       cssFn.apply( this, arguments ) :
+                       this.animate( genFx( name, true ), speed, easing, callback );
+       };
+});
+
+jQuery.fn.extend({
+       fadeTo: function( speed, to, easing, callback ) {
+
+               // show any hidden elements after setting opacity to 0
+               return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+                       // animate to the value specified
+                       .end().animate({ opacity: to }, speed, easing, callback );
+       },
+       animate: function( prop, speed, easing, callback ) {
+               var empty = jQuery.isEmptyObject( prop ),
+                       optall = jQuery.speed( speed, easing, callback ),
+                       doAnimation = function() {
+                               // Operate on a copy of prop so per-property easing won't be lost
+                               var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+                               // Empty animations resolve immediately
+                               if ( empty ) {
+                                       anim.stop( true );
+                               }
+                       };
+
+               return empty || optall.queue === false ?
+                       this.each( doAnimation ) :
+                       this.queue( optall.queue, doAnimation );
+       },
+       stop: function( type, clearQueue, gotoEnd ) {
+               var stopQueue = function( hooks ) {
+                       var stop = hooks.stop;
+                       delete hooks.stop;
+                       stop( gotoEnd );
+               };
+
+               if ( typeof type !== "string" ) {
+                       gotoEnd = clearQueue;
+                       clearQueue = type;
+                       type = undefined;
+               }
+               if ( clearQueue && type !== false ) {
+                       this.queue( type || "fx", [] );
+               }
+
+               return this.each(function() {
+                       var dequeue = true,
+                               index = type != null && type + "queueHooks",
+                               timers = jQuery.timers,
+                               data = jQuery._data( this );
+
+                       if ( index ) {
+                               if ( data[ index ] && data[ index ].stop ) {
+                                       stopQueue( data[ index ] );
+                               }
+                       } else {
+                               for ( index in data ) {
+                                       if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+                                               stopQueue( data[ index ] );
+                                       }
+                               }
+                       }
+
+                       for ( index = timers.length; index--; ) {
+                               if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+                                       timers[ index ].anim.stop( gotoEnd );
+                                       dequeue = false;
+                                       timers.splice( index, 1 );
+                               }
+                       }
+
+                       // start the next in the queue if the last step wasn't forced
+                       // timers currently will call their complete callbacks, which will dequeue
+                       // but only if they were gotoEnd
+                       if ( dequeue || !gotoEnd ) {
+                               jQuery.dequeue( this, type );
+                       }
+               });
+       }
+});
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+       var which,
+               attrs = { height: type },
+               i = 0;
+
+       // if we include width, step value is 1 to do all cssExpand values,
+       // if we don't include width, step value is 2 to skip over Left and Right
+       includeWidth = includeWidth? 1 : 0;
+       for( ; i < 4 ; i += 2 - includeWidth ) {
+               which = cssExpand[ i ];
+               attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+       }
+
+       if ( includeWidth ) {
+               attrs.opacity = attrs.width = type;
+       }
+
+       return attrs;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+       slideDown: genFx("show"),
+       slideUp: genFx("hide"),
+       slideToggle: genFx("toggle"),
+       fadeIn: { opacity: "show" },
+       fadeOut: { opacity: "hide" },
+       fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+       jQuery.fn[ name ] = function( speed, easing, callback ) {
+               return this.animate( props, speed, easing, callback );
+       };
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+       var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+               complete: fn || !fn && easing ||
+                       jQuery.isFunction( speed ) && speed,
+               duration: speed,
+               easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+       };
+
+       opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+               opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+       // normalize opt.queue - true/undefined/null -> "fx"
+       if ( opt.queue == null || opt.queue === true ) {
+               opt.queue = "fx";
+       }
+
+       // Queueing
+       opt.old = opt.complete;
+
+       opt.complete = function() {
+               if ( jQuery.isFunction( opt.old ) ) {
+                       opt.old.call( this );
+               }
+
+               if ( opt.queue ) {
+                       jQuery.dequeue( this, opt.queue );
+               }
+       };
+
+       return opt;
+};
+
+jQuery.easing = {
+       linear: function( p ) {
+               return p;
+       },
+       swing: function( p ) {
+               return 0.5 - Math.cos( p*Math.PI ) / 2;
+       }
+};
+
+jQuery.timers = [];
+jQuery.fx = Tween.prototype.init;
+jQuery.fx.tick = function() {
+       var timer,
+               timers = jQuery.timers,
+               i = 0;
+
+       fxNow = jQuery.now();
+
+       for ( ; i < timers.length; i++ ) {
+               timer = timers[ i ];
+               // Checks the timer has not already been removed
+               if ( !timer() && timers[ i ] === timer ) {
+                       timers.splice( i--, 1 );
+               }
+       }
+
+       if ( !timers.length ) {
+               jQuery.fx.stop();
+       }
+       fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+       if ( timer() && jQuery.timers.push( timer ) && !timerId ) {
+               timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+       }
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.stop = function() {
+       clearInterval( timerId );
+       timerId = null;
+};
+
+jQuery.fx.speeds = {
+       slow: 600,
+       fast: 200,
+       // Default speed
+       _default: 400
+};
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+       jQuery.expr.filters.animated = function( elem ) {
+               return jQuery.grep(jQuery.timers, function( fn ) {
+                       return elem === fn.elem;
+               }).length;
+       };
+}
+var rroot = /^(?:body|html)$/i;
+
+jQuery.fn.offset = function( options ) {
+       if ( arguments.length ) {
+               return options === undefined ?
+                       this :
+                       this.each(function( i ) {
+                               jQuery.offset.setOffset( this, options, i );
+                       });
+       }
+
+       var docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft,
+               box = { top: 0, left: 0 },
+               elem = this[ 0 ],
+               doc = elem && elem.ownerDocument;
+
+       if ( !doc ) {
+               return;
+       }
+
+       if ( (body = doc.body) === elem ) {
+               return jQuery.offset.bodyOffset( elem );
+       }
+
+       docElem = doc.documentElement;
+
+       // Make sure it's not a disconnected DOM node
+       if ( !jQuery.contains( docElem, elem ) ) {
+               return box;
+       }
+
+       // If we don't have gBCR, just use 0,0 rather than error
+       // BlackBerry 5, iOS 3 (original iPhone)
+       if ( typeof elem.getBoundingClientRect !== "undefined" ) {
+               box = elem.getBoundingClientRect();
+       }
+       win = getWindow( doc );
+       clientTop  = docElem.clientTop  || body.clientTop  || 0;
+       clientLeft = docElem.clientLeft || body.clientLeft || 0;
+       scrollTop  = win.pageYOffset || docElem.scrollTop;
+       scrollLeft = win.pageXOffset || docElem.scrollLeft;
+       return {
+               top: box.top  + scrollTop  - clientTop,
+               left: box.left + scrollLeft - clientLeft
+       };
+};
+
+jQuery.offset = {
+
+       bodyOffset: function( body ) {
+               var top = body.offsetTop,
+                       left = body.offsetLeft;
+
+               if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
+                       top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+                       left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+               }
+
+               return { top: top, left: left };
+       },
+
+       setOffset: function( elem, options, i ) {
+               var position = jQuery.css( elem, "position" );
+
+               // set position first, in-case top/left are set even on static elem
+               if ( position === "static" ) {
+                       elem.style.position = "relative";
+               }
+
+               var curElem = jQuery( elem ),
+                       curOffset = curElem.offset(),
+                       curCSSTop = jQuery.css( elem, "top" ),
+                       curCSSLeft = jQuery.css( elem, "left" ),
+                       calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+                       props = {}, curPosition = {}, curTop, curLeft;
+
+               // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+               if ( calculatePosition ) {
+                       curPosition = curElem.position();
+                       curTop = curPosition.top;
+                       curLeft = curPosition.left;
+               } else {
+                       curTop = parseFloat( curCSSTop ) || 0;
+                       curLeft = parseFloat( curCSSLeft ) || 0;
+               }
+
+               if ( jQuery.isFunction( options ) ) {
+                       options = options.call( elem, i, curOffset );
+               }
+
+               if ( options.top != null ) {
+                       props.top = ( options.top - curOffset.top ) + curTop;
+               }
+               if ( options.left != null ) {
+                       props.left = ( options.left - curOffset.left ) + curLeft;
+               }
+
+               if ( "using" in options ) {
+                       options.using.call( elem, props );
+               } else {
+                       curElem.css( props );
+               }
+       }
+};
+
+
+jQuery.fn.extend({
+
+       position: function() {
+               if ( !this[0] ) {
+                       return;
+               }
+
+               var elem = this[0],
+
+               // Get *real* offsetParent
+               offsetParent = this.offsetParent(),
+
+               // Get correct offsets
+               offset       = this.offset(),
+               parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+               // Subtract element margins
+               // note: when an element has margin: auto the offsetLeft and marginLeft
+               // are the same in Safari causing offset.left to incorrectly be 0
+               offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+               offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+               // Add offsetParent borders
+               parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+               parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+
+               // Subtract the two offsets
+               return {
+                       top:  offset.top  - parentOffset.top,
+                       left: offset.left - parentOffset.left
+               };
+       },
+
+       offsetParent: function() {
+               return this.map(function() {
+                       var offsetParent = this.offsetParent || document.body;
+                       while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+                               offsetParent = offsetParent.offsetParent;
+                       }
+                       return offsetParent || document.body;
+               });
+       }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
+       var top = /Y/.test( prop );
+
+       jQuery.fn[ method ] = function( val ) {
+               return jQuery.access( this, function( elem, method, val ) {
+                       var win = getWindow( elem );
+
+                       if ( val === undefined ) {
+                               return win ? (prop in win) ? win[ prop ] :
+                                       win.document.documentElement[ method ] :
+                                       elem[ method ];
+                       }
+
+                       if ( win ) {
+                               win.scrollTo(
+                                       !top ? val : jQuery( win ).scrollLeft(),
+                                        top ? val : jQuery( win ).scrollTop()
+                               );
+
+                       } else {
+                               elem[ method ] = val;
+                       }
+               }, method, val, arguments.length, null );
+       };
+});
+
+function getWindow( elem ) {
+       return jQuery.isWindow( elem ) ?
+               elem :
+               elem.nodeType === 9 ?
+                       elem.defaultView || elem.parentWindow :
+                       false;
+}
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+       jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+               // margin is only for outerHeight, outerWidth
+               jQuery.fn[ funcName ] = function( margin, value ) {
+                       var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+                               extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+                       return jQuery.access( this, function( elem, type, value ) {
+                               var doc;
+
+                               if ( jQuery.isWindow( elem ) ) {
+                                       // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+                                       // isn't a whole lot we can do. See pull request at this URL for discussion:
+                                       // https://github.com/jquery/jquery/pull/764
+                                       return elem.document.documentElement[ "client" + name ];
+                               }
+
+                               // Get document width or height
+                               if ( elem.nodeType === 9 ) {
+                                       doc = elem.documentElement;
+
+                                       // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+                                       // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+                                       return Math.max(
+                                               elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+                                               elem.body[ "offset" + name ], doc[ "offset" + name ],
+                                               doc[ "client" + name ]
+                                       );
+                               }
+
+                               return value === undefined ?
+                                       // Get width or height on the element, requesting but not forcing parseFloat
+                                       jQuery.css( elem, type, value, extra ) :
+
+                                       // Set width or height on the element
+                                       jQuery.style( elem, type, value, extra );
+                       }, type, chainable ? margin : undefined, chainable, null );
+               };
+       });
+});
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+
+// Expose jQuery as an AMD module, but only for AMD loaders that
+// understand the issues with loading multiple versions of jQuery
+// in a page that all might call define(). The loader will indicate
+// they have special allowances for multiple jQuery versions by
+// specifying define.amd.jQuery = true. Register as a named module,
+// since jQuery can be concatenated with other files that may use define,
+// but not use a proper concatenation script that understands anonymous
+// AMD modules. A named AMD is safest and most robust way to register.
+// Lowercase jquery is used because AMD module names are derived from
+// file names, and jQuery is normally delivered in a lowercase file name.
+// Do this after creating the global so that if an AMD module wants to call
+// noConflict to hide this version of jQuery, it will work.
+if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+       define( "jquery", [], function () { return jQuery; } );
+}
+
+})( window );
diff --git a/resources/lib/jquery/jquery.json.js b/resources/lib/jquery/jquery.json.js
new file mode 100644 (file)
index 0000000..75953f4
--- /dev/null
@@ -0,0 +1,199 @@
+/**
+ * jQuery JSON plugin 2.4.0
+ *
+ * @author Brantley Harris, 2009-2011
+ * @author Timo Tijhof, 2011-2012
+ * @source This plugin is heavily influenced by MochiKit's serializeJSON, which is
+ *         copyrighted 2005 by Bob Ippolito.
+ * @source Brantley Harris wrote this plugin. It is based somewhat on the JSON.org
+ *         website's http://www.json.org/json2.js, which proclaims:
+ *         "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that
+ *         I uphold.
+ * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
+ */
+(function ($) {
+       'use strict';
+
+       var escape = /["\\\x00-\x1f\x7f-\x9f]/g,
+               meta = {
+                       '\b': '\\b',
+                       '\t': '\\t',
+                       '\n': '\\n',
+                       '\f': '\\f',
+                       '\r': '\\r',
+                       '"' : '\\"',
+                       '\\': '\\\\'
+               },
+               hasOwn = Object.prototype.hasOwnProperty;
+
+       /**
+        * jQuery.toJSON
+        * Converts the given argument into a JSON representation.
+        *
+        * @param o {Mixed} The json-serializable *thing* to be converted
+        *
+        * If an object has a toJSON prototype, that will be used to get the representation.
+        * Non-integer/string keys are skipped in the object, as are keys that point to a
+        * function.
+        *
+        */
+       $.toJSON = typeof JSON === 'object' && JSON.stringify ? JSON.stringify : function (o) {
+               if (o === null) {
+                       return 'null';
+               }
+
+               var pairs, k, name, val,
+                       type = $.type(o);
+
+               if (type === 'undefined') {
+                       return undefined;
+               }
+
+               // Also covers instantiated Number and Boolean objects,
+               // which are typeof 'object' but thanks to $.type, we
+               // catch them here. I don't know whether it is right
+               // or wrong that instantiated primitives are not
+               // exported to JSON as an {"object":..}.
+               // We choose this path because that's what the browsers did.
+               if (type === 'number' || type === 'boolean') {
+                       return String(o);
+               }
+               if (type === 'string') {
+                       return $.quoteString(o);
+               }
+               if (typeof o.toJSON === 'function') {
+                       return $.toJSON(o.toJSON());
+               }
+               if (type === 'date') {
+                       var month = o.getUTCMonth() + 1,
+                               day = o.getUTCDate(),
+                               year = o.getUTCFullYear(),
+                               hours = o.getUTCHours(),
+                               minutes = o.getUTCMinutes(),
+                               seconds = o.getUTCSeconds(),
+                               milli = o.getUTCMilliseconds();
+
+                       if (month < 10) {
+                               month = '0' + month;
+                       }
+                       if (day < 10) {
+                               day = '0' + day;
+                       }
+                       if (hours < 10) {
+                               hours = '0' + hours;
+                       }
+                       if (minutes < 10) {
+                               minutes = '0' + minutes;
+                       }
+                       if (seconds < 10) {
+                               seconds = '0' + seconds;
+                       }
+                       if (milli < 100) {
+                               milli = '0' + milli;
+                       }
+                       if (milli < 10) {
+                               milli = '0' + milli;
+                       }
+                       return '"' + year + '-' + month + '-' + day + 'T' +
+                               hours + ':' + minutes + ':' + seconds +
+                               '.' + milli + 'Z"';
+               }
+
+               pairs = [];
+
+               if ($.isArray(o)) {
+                       for (k = 0; k < o.length; k++) {
+                               pairs.push($.toJSON(o[k]) || 'null');
+                       }
+                       return '[' + pairs.join(',') + ']';
+               }
+
+               // Any other object (plain object, RegExp, ..)
+               // Need to do typeof instead of $.type, because we also
+               // want to catch non-plain objects.
+               if (typeof o === 'object') {
+                       for (k in o) {
+                               // Only include own properties,
+                               // Filter out inherited prototypes
+                               if (hasOwn.call(o, k)) {
+                                       // Keys must be numerical or string. Skip others
+                                       type = typeof k;
+                                       if (type === 'number') {
+                                               name = '"' + k + '"';
+                                       } else if (type === 'string') {
+                                               name = $.quoteString(k);
+                                       } else {
+                                               continue;
+                                       }
+                                       type = typeof o[k];
+
+                                       // Invalid values like these return undefined
+                                       // from toJSON, however those object members
+                                       // shouldn't be included in the JSON string at all.
+                                       if (type !== 'function' && type !== 'undefined') {
+                                               val = $.toJSON(o[k]);
+                                               pairs.push(name + ':' + val);
+                                       }
+                               }
+                       }
+                       return '{' + pairs.join(',') + '}';
+               }
+       };
+
+       /**
+        * jQuery.evalJSON
+        * Evaluates a given json string.
+        *
+        * @param str {String}
+        */
+       $.evalJSON = typeof JSON === 'object' && JSON.parse ? JSON.parse : function (str) {
+               /*jshint evil: true */
+               return eval('(' + str + ')');
+       };
+
+       /**
+        * jQuery.secureEvalJSON
+        * Evals JSON in a way that is *more* secure.
+        *
+        * @param str {String}
+        */
+       $.secureEvalJSON = typeof JSON === 'object' && JSON.parse ? JSON.parse : function (str) {
+               var filtered =
+                       str
+                       .replace(/\\["\\\/bfnrtu]/g, '@')
+                       .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
+                       .replace(/(?:^|:|,)(?:\s*\[)+/g, '');
+
+               if (/^[\],:{}\s]*$/.test(filtered)) {
+                       /*jshint evil: true */
+                       return eval('(' + str + ')');
+               }
+               throw new SyntaxError('Error parsing JSON, source is not valid.');
+       };
+
+       /**
+        * jQuery.quoteString
+        * Returns a string-repr of a string, escaping quotes intelligently.
+        * Mostly a support function for toJSON.
+        * Examples:
+        * >>> jQuery.quoteString('apple')
+        * "apple"
+        *
+        * >>> jQuery.quoteString('"Where are we going?", she asked.')
+        * "\"Where are we going?\", she asked."
+        */
+       $.quoteString = function (str) {
+               if (str.match(escape)) {
+                       return '"' + str.replace(escape, function (a) {
+                               var c = meta[a];
+                               if (typeof c === 'string') {
+                                       return c;
+                               }
+                               c = a.charCodeAt();
+                               return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
+                       }) + '"';
+               }
+               return '"' + str + '"';
+       };
+
+}(jQuery));
diff --git a/resources/lib/jquery/jquery.mockjax.js b/resources/lib/jquery/jquery.mockjax.js
new file mode 100644 (file)
index 0000000..5f6e130
--- /dev/null
@@ -0,0 +1,382 @@
+/*!
+ * MockJax - jQuery Plugin to Mock Ajax requests
+ *
+ * Version:  1.4.0
+ * Released: 2011-02-04
+ * Source:   http://github.com/appendto/jquery-mockjax
+ * Docs:     http://enterprisejquery.com/2010/07/mock-your-ajax-requests-with-mockjax-for-rapid-development
+ * Plugin:   mockjax
+ * Author:   Jonathan Sharp (http://jdsharp.com)
+ * License:  MIT,GPL
+ * 
+ * Copyright (c) 2010 appendTo LLC.
+ * Dual licensed under the MIT or GPL licenses.
+ * http://appendto.com/open-source-licenses
+ */
+(function($) {
+       var _ajax = $.ajax,
+               mockHandlers = [];
+       
+       function parseXML(xml) {
+               if ( window['DOMParser'] == undefined && window.ActiveXObject ) {
+                       DOMParser = function() { };
+                       DOMParser.prototype.parseFromString = function( xmlString ) {
+                               var doc = new ActiveXObject('Microsoft.XMLDOM');
+                       doc.async = 'false';
+                       doc.loadXML( xmlString );
+                               return doc;
+                       };
+               }
+               
+               try {
+                       var xmlDoc      = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
+                       if ( $.isXMLDoc( xmlDoc ) ) {
+                               var err = $('parsererror', xmlDoc);
+                               if ( err.length == 1 ) {
+                                       throw('Error: ' + $(xmlDoc).text() );
+                               }
+                       } else {
+                               throw('Unable to parse XML');
+                       }
+               } catch( e ) {
+                       var msg = ( e.name == undefined ? e : e.name + ': ' + e.message );
+                       $(document).trigger('xmlParseError', [ msg ]);
+                       return undefined;
+               }
+               return xmlDoc;
+       }
+       
+       $.extend({
+               ajax: function(origSettings) {
+                       var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings),
+                           mock = false;
+                       // Iterate over our mock handlers (in registration order) until we find
+                       // one that is willing to intercept the request
+                       $.each(mockHandlers, function(k, v) {
+                               if ( !mockHandlers[k] ) {
+                                       return;
+                               }
+                               var m = null;
+                               // If the mock was registered with a function, let the function decide if we 
+                               // want to mock this request
+                               if ( $.isFunction(mockHandlers[k]) ) {
+                                       m = mockHandlers[k](s);
+                               } else {
+                                       m = mockHandlers[k];
+                                       // Inspect the URL of the request and check if the mock handler's url 
+                                       // matches the url for this ajax request
+                                       if ( $.isFunction(m.url.test) ) {
+                                               // The user provided a regex for the url, test it
+                                               if ( !m.url.test( s.url ) ) {
+                                                       m = null;
+                                               }
+                                       } else {
+                                               // Look for a simple wildcard '*' or a direct URL match
+                                               var star = m.url.indexOf('*');
+                                               if ( ( m.url != '*' && m.url != s.url && star == -1 ) ||
+                                                       ( star > -1 && m.url.substr(0, star) != s.url.substr(0, star) ) ) {
+                                                        // The url we tested did not match the wildcard *
+                                                        m = null;
+                                               }
+                                       }
+                                       if ( m ) {
+                                               // Inspect the data submitted in the request (either POST body or GET query string)
+                                               if ( m.data && s.data ) {
+                                                       var identical = false;
+                                                       // Deep inspect the identity of the objects
+                                                       (function ident(mock, live) {
+                                                               // Test for situations where the data is a querystring (not an object)
+                                                               if (typeof live === 'string') {
+                                                                       // Querystring may be a regex
+                                                                       identical = $.isFunction( mock.test ) ? mock.test(live) : mock == live;
+                                                                       return identical;
+                                                               }
+                                                               $.each(mock, function(k, v) {
+                                                                       if ( live[k] === undefined ) {
+                                                                               identical = false;
+                                                                               return false;
+                                                                       } else {
+                                                                               identical = true;
+                                                                               if ( typeof live[k] == 'object' ) {
+                                                                                       return ident(mock[k], live[k]);
+                                                                               } else {
+                                                                                       if ( $.isFunction( mock[k].test ) ) {
+                                                                                               identical = mock[k].test(live[k]);
+                                                                                       } else {
+                                                                                               identical = ( mock[k] == live[k] );
+                                                                                       }
+                                                                                       return identical;
+                                                                               }
+                                                                       }
+                                                               });
+                                                       })(m.data, s.data);
+                                                       // They're not identical, do not mock this request
+                                                       if ( identical == false ) {
+                                                               m = null;
+                                                       }
+                                               }
+                                               // Inspect the request type
+                                               if ( m && m.type && m.type != s.type ) {
+                                                       // The request type doesn't match (GET vs. POST)
+                                                       m = null;
+                                               }
+                                       }
+                               }
+                               if ( m ) {
+                                       mock = true;
+
+                                       // Handle console logging
+                                       var c = $.extend({}, $.mockjaxSettings, m);
+                                       if ( c.log && $.isFunction(c.log) ) {
+                                               c.log('MOCK ' + s.type.toUpperCase() + ': ' + s.url, $.extend({}, s));
+                                       }
+                                       
+                                       var jsre = /=\?(&|$)/, jsc = (new Date()).getTime();
+
+                                       // Handle JSONP Parameter Callbacks, we need to replicate some of the jQuery core here
+                                       // because there isn't an easy hook for the cross domain script tag of jsonp
+                                       if ( s.dataType === "jsonp" ) {
+                                               if ( s.type.toUpperCase() === "GET" ) {
+                                                       if ( !jsre.test( s.url ) ) {
+                                                               s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+                                                       }
+                                               } else if ( !s.data || !jsre.test(s.data) ) {
+                                                       s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+                                               }
+                                               s.dataType = "json";
+                                       }
+                       
+                                       // Build temporary JSONP function
+                                       if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
+                                               jsonp = s.jsonpCallback || ("jsonp" + jsc++);
+                       
+                                               // Replace the =? sequence both in the query string and the data
+                                               if ( s.data ) {
+                                                       s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+                                               }
+                       
+                                               s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+                       
+                                               // We need to make sure
+                                               // that a JSONP style response is executed properly
+                                               s.dataType = "script";
+                       
+                                               // Handle JSONP-style loading
+                                               window[ jsonp ] = window[ jsonp ] || function( tmp ) {
+                                                       data = tmp;
+                                                       success();
+                                                       complete();
+                                                       // Garbage collect
+                                                       window[ jsonp ] = undefined;
+                       
+                                                       try {
+                                                               delete window[ jsonp ];
+                                                       } catch(e) {}
+                       
+                                                       if ( head ) {
+                                                               head.removeChild( script );
+                                                       }
+                                               };
+                                       }
+                                       
+                                       var rurl = /^(\w+:)?\/\/([^\/?#]+)/,
+                                               parts = rurl.exec( s.url ),
+                                               remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
+                                       
+                                       // Test if we are going to create a script tag (if so, intercept & mock)
+                                       if ( s.dataType === "script" && s.type.toUpperCase() === "GET" && remote ) {
+                                               // Synthesize the mock request for adding a script tag
+                                               var callbackContext = origSettings && origSettings.context || s;
+                                               
+                                               function success() {
+                                                       // If a local callback was specified, fire it and pass it the data
+                                                       if ( s.success ) {
+                                                               s.success.call( callbackContext, ( m.response ? m.response.toString() : m.responseText || ''), status, {} );
+                                                       }
+                               
+                                                       // Fire the global callback
+                                                       if ( s.global ) {
+                                                               trigger( "ajaxSuccess", [{}, s] );
+                                                       }
+                                               }
+                               
+                                               function complete() {
+                                                       // Process result
+                                                       if ( s.complete ) {
+                                                               s.complete.call( callbackContext, {} , status );
+                                                       }
+                               
+                                                       // The request was completed
+                                                       if ( s.global ) {
+                                                               trigger( "ajaxComplete", [{}, s] );
+                                                       }
+                               
+                                                       // Handle the global AJAX counter
+                                                       if ( s.global && ! --jQuery.active ) {
+                                                               jQuery.event.trigger( "ajaxStop" );
+                                                       }
+                                               }
+                                               
+                                               function trigger(type, args) {
+                                                       (s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
+                                               }
+                                               
+                                               if ( m.response && $.isFunction(m.response) ) {
+                                                       m.response(origSettings);
+                                               } else {
+                                                       $.globalEval(m.responseText);
+                                               }
+                                               success();
+                                               complete();
+                                               return false;
+                                       }
+                                       mock = _ajax.call($, $.extend(true, {}, origSettings, {
+                                               // Mock the XHR object
+                                               xhr: function() {
+                                                       // Extend with our default mockjax settings
+                                                       m = $.extend({}, $.mockjaxSettings, m);
+
+                                                       if ( m.contentType ) {
+                                                               m.headers['content-type'] = m.contentType;
+                                                       }
+
+                                                       // Return our mock xhr object
+                                                       return {
+                                                               status: m.status,
+                                                               readyState: 1,
+                                                               open: function() { },
+                                                               send: function() {
+                                                                       // This is a substitute for < 1.4 which lacks $.proxy
+                                                                       var process = (function(that) {
+                                                                               return function() {
+                                                                                       return (function() {
+                                                                                               // The request has returned
+                                                                                               this.status             = m.status;
+                                                                                               this.readyState         = 4;
+                                                                               
+                                                                                               // We have an executable function, call it to give 
+                                                                                               // the mock handler a chance to update it's data
+                                                                                               if ( $.isFunction(m.response) ) {
+                                                                                                       m.response(origSettings);
+                                                                                               }
+                                                                                               // Copy over our mock to our xhr object before passing control back to 
+                                                                                               // jQuery's onreadystatechange callback
+                                                                                               if ( s.dataType == 'json' && ( typeof m.responseText == 'object' ) ) {
+                                                                                                       this.responseText = JSON.stringify(m.responseText);
+                                                                                               } else if ( s.dataType == 'xml' ) {
+                                                                                                       if ( typeof m.responseXML == 'string' ) {
+                                                                                                               this.responseXML = parseXML(m.responseXML);
+                                                                                                       } else {
+                                                                                                               this.responseXML = m.responseXML;
+                                                                                                       }
+                                                                                               } else {
+                                                                                                       this.responseText = m.responseText;
+                                                                                               }
+                                                                                               // jQuery < 1.4 doesn't have onreadystate change for xhr
+                                                                                               if ( $.isFunction(this.onreadystatechange) ) {
+                                                                                                       this.onreadystatechange( m.isTimeout ? 'timeout' : undefined );
+                                                                                               }
+                                                                                       }).apply(that);
+                                                                               };
+                                                                       })(this);
+
+                                                                       if ( m.proxy ) {
+                                                                               // We're proxying this request and loading in an external file instead
+                                                                               _ajax({
+                                                                                       global: false,
+                                                                                       url: m.proxy,
+                                                                                       type: m.proxyType,
+                                                                                       data: m.data,
+                                                                                       dataType: s.dataType,
+                                                                                       complete: function(xhr, txt) {
+                                                                                               m.responseXML = xhr.responseXML;
+                                                                                               m.responseText = xhr.responseText;
+                                                                                               this.responseTimer = setTimeout(process, m.responseTime || 0);
+                                                                                       }
+                                                                               });
+                                                                       } else {
+                                                                               // type == 'POST' || 'GET' || 'DELETE'
+                                                                               if ( s.async === false ) {
+                                                                                       // TODO: Blocking delay
+                                                                                       process();
+                                                                               } else {
+                                                                                       this.responseTimer = setTimeout(process, m.responseTime || 50);
+                                                                               }
+                                                                       }
+                                                               },
+                                                               abort: function() {
+                                                                       clearTimeout(this.responseTimer);
+                                                               },
+                                                               setRequestHeader: function() { },
+                                                               getResponseHeader: function(header) {
+                                                                       // 'Last-modified', 'Etag', 'content-type' are all checked by jQuery
+                                                                       if ( m.headers && m.headers[header] ) {
+                                                                               // Return arbitrary headers
+                                                                               return m.headers[header];
+                                                                       } else if ( header.toLowerCase() == 'last-modified' ) {
+                                                                               return m.lastModified || (new Date()).toString();
+                                                                       } else if ( header.toLowerCase() == 'etag' ) {
+                                                                               return m.etag || '';
+                                                                       } else if ( header.toLowerCase() == 'content-type' ) {
+                                                                               return m.contentType || 'text/plain';
+                                                                       }
+                                                               },
+                                                               getAllResponseHeaders: function() {
+                                                                       var headers = '';
+                                                                       $.each(m.headers, function(k, v) {
+                                                                               headers += k + ': ' + v + "\n";
+                                                                       });
+                                                                       return headers;
+                                                               }
+                                                       };
+                                               }
+                                       }));
+                                       return false;
+                               }
+                       });
+                       // We don't have a mock request, trigger a normal request
+                       if ( !mock ) {
+                               return _ajax.apply($, arguments);
+                       } else {
+                               return mock;
+                       }
+               }
+       });
+
+       $.mockjaxSettings = {
+               //url:        null,
+               //type:       'GET',
+               log:          function(msg) {
+                               window['console'] && window.console.log && window.console.log(msg);
+                             },
+               status:       200,
+               responseTime: 500,
+               isTimeout:    false,
+               contentType:  'text/plain',
+               response:     '', 
+               responseText: '',
+               responseXML:  '',
+               proxy:        '',
+               proxyType:    'GET',
+               
+               lastModified: null,
+               etag:         '',
+               headers: {
+                       etag: 'IJF@H#@923uf8023hFO@I#H#',
+                       'content-type' : 'text/plain'
+               }
+       };
+
+       $.mockjax = function(settings) {
+               var i = mockHandlers.length;
+               mockHandlers[i] = settings;
+               return i;
+       };
+       $.mockjaxClear = function(i) {
+               if ( arguments.length == 1 ) {
+                       mockHandlers[i] = null;
+               } else {
+                       mockHandlers = [];
+               }
+       };
+})(jQuery);
diff --git a/resources/lib/jquery/jquery.qunit.css b/resources/lib/jquery/jquery.qunit.css
new file mode 100644 (file)
index 0000000..d7fc0c8
--- /dev/null
@@ -0,0 +1,244 @@
+/**
+ * QUnit v1.11.0 - A JavaScript Unit Testing Framework
+ *
+ * http://qunitjs.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+/** Font Family and Sizes */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
+       font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
+}
+
+#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
+#qunit-tests { font-size: smaller; }
+
+
+/** Resets */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
+       margin: 0;
+       padding: 0;
+}
+
+
+/** Header */
+
+#qunit-header {
+       padding: 0.5em 0 0.5em 1em;
+
+       color: #8699a4;
+       background-color: #0d3349;
+
+       font-size: 1.5em;
+       line-height: 1em;
+       font-weight: normal;
+
+       border-radius: 5px 5px 0 0;
+       -moz-border-radius: 5px 5px 0 0;
+       -webkit-border-top-right-radius: 5px;
+       -webkit-border-top-left-radius: 5px;
+}
+
+#qunit-header a {
+       text-decoration: none;
+       color: #c2ccd1;
+}
+
+#qunit-header a:hover,
+#qunit-header a:focus {
+       color: #fff;
+}
+
+#qunit-testrunner-toolbar label {
+       display: inline-block;
+       padding: 0 .5em 0 .1em;
+}
+
+#qunit-banner {
+       height: 5px;
+}
+
+#qunit-testrunner-toolbar {
+       padding: 0.5em 0 0.5em 2em;
+       color: #5E740B;
+       background-color: #eee;
+       overflow: hidden;
+}
+
+#qunit-userAgent {
+       padding: 0.5em 0 0.5em 2.5em;
+       background-color: #2b81af;
+       color: #fff;
+       text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
+}
+
+#qunit-modulefilter-container {
+       float: right;
+}
+
+/** Tests: Pass/Fail */
+
+#qunit-tests {
+       list-style-position: inside;
+}
+
+#qunit-tests li {
+       padding: 0.4em 0.5em 0.4em 2.5em;
+       border-bottom: 1px solid #fff;
+       list-style-position: inside;
+}
+
+#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {
+       display: none;
+}
+
+#qunit-tests li strong {
+       cursor: pointer;
+}
+
+#qunit-tests li a {
+       padding: 0.5em;
+       color: #c2ccd1;
+       text-decoration: none;
+}
+#qunit-tests li a:hover,
+#qunit-tests li a:focus {
+       color: #000;
+}
+
+#qunit-tests li .runtime {
+       float: right;
+       font-size: smaller;
+}
+
+.qunit-assert-list {
+       margin-top: 0.5em;
+       padding: 0.5em;
+
+       background-color: #fff;
+
+       border-radius: 5px;
+       -moz-border-radius: 5px;
+       -webkit-border-radius: 5px;
+}
+
+.qunit-collapsed {
+       display: none;
+}
+
+#qunit-tests table {
+       border-collapse: collapse;
+       margin-top: .2em;
+}
+
+#qunit-tests th {
+       text-align: right;
+       vertical-align: top;
+       padding: 0 .5em 0 0;
+}
+
+#qunit-tests td {
+       vertical-align: top;
+}
+
+#qunit-tests pre {
+       margin: 0;
+       white-space: pre-wrap;
+       word-wrap: break-word;
+}
+
+#qunit-tests del {
+       background-color: #e0f2be;
+       color: #374e0c;
+       text-decoration: none;
+}
+
+#qunit-tests ins {
+       background-color: #ffcaca;
+       color: #500;
+       text-decoration: none;
+}
+
+/*** Test Counts */
+
+#qunit-tests b.counts                       { color: black; }
+#qunit-tests b.passed                       { color: #5E740B; }
+#qunit-tests b.failed                       { color: #710909; }
+
+#qunit-tests li li {
+       padding: 5px;
+       background-color: #fff;
+       border-bottom: none;
+       list-style-position: inside;
+}
+
+/*** Passing Styles */
+
+#qunit-tests li li.pass {
+       color: #3c510c;
+       background-color: #fff;
+       border-left: 10px solid #C6E746;
+}
+
+#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }
+#qunit-tests .pass .test-name               { color: #366097; }
+
+#qunit-tests .pass .test-actual,
+#qunit-tests .pass .test-expected           { color: #999999; }
+
+#qunit-banner.qunit-pass                    { background-color: #C6E746; }
+
+/*** Failing Styles */
+
+#qunit-tests li li.fail {
+       color: #710909;
+       background-color: #fff;
+       border-left: 10px solid #EE5757;
+       white-space: pre;
+}
+
+#qunit-tests > li:last-child {
+       border-radius: 0 0 5px 5px;
+       -moz-border-radius: 0 0 5px 5px;
+       -webkit-border-bottom-right-radius: 5px;
+       -webkit-border-bottom-left-radius: 5px;
+}
+
+#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }
+#qunit-tests .fail .test-name,
+#qunit-tests .fail .module-name             { color: #000000; }
+
+#qunit-tests .fail .test-actual             { color: #EE5757; }
+#qunit-tests .fail .test-expected           { color: green;   }
+
+#qunit-banner.qunit-fail                    { background-color: #EE5757; }
+
+
+/** Result */
+
+#qunit-testresult {
+       padding: 0.5em 0.5em 0.5em 2.5em;
+
+       color: #2b81af;
+       background-color: #D2E0E6;
+
+       border-bottom: 1px solid white;
+}
+#qunit-testresult .module-name {
+       font-weight: bold;
+}
+
+/** Fixture */
+
+#qunit-fixture {
+       position: absolute;
+       top: -10000px;
+       left: -10000px;
+       width: 1000px;
+       height: 1000px;
+}
diff --git a/resources/lib/jquery/jquery.qunit.js b/resources/lib/jquery/jquery.qunit.js
new file mode 100644 (file)
index 0000000..302545f
--- /dev/null
@@ -0,0 +1,2152 @@
+/**
+ * QUnit v1.11.0 - A JavaScript Unit Testing Framework
+ *
+ * http://qunitjs.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+(function( window ) {
+
+var QUnit,
+       assert,
+       config,
+       onErrorFnPrev,
+       testId = 0,
+       fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
+       toString = Object.prototype.toString,
+       hasOwn = Object.prototype.hasOwnProperty,
+       // Keep a local reference to Date (GH-283)
+       Date = window.Date,
+       defined = {
+               setTimeout: typeof window.setTimeout !== "undefined",
+               sessionStorage: (function() {
+                       var x = "qunit-test-string";
+                       try {
+                               sessionStorage.setItem( x, x );
+                               sessionStorage.removeItem( x );
+                               return true;
+                       } catch( e ) {
+                               return false;
+                       }
+               }())
+       },
+       /**
+        * Provides a normalized error string, correcting an issue
+        * with IE 7 (and prior) where Error.prototype.toString is
+        * not properly implemented
+        *
+        * Based on http://es5.github.com/#x15.11.4.4
+        *
+        * @param {String|Error} error
+        * @return {String} error message
+        */
+       errorString = function( error ) {
+               var name, message,
+                       errorString = error.toString();
+               if ( errorString.substring( 0, 7 ) === "[object" ) {
+                       name = error.name ? error.name.toString() : "Error";
+                       message = error.message ? error.message.toString() : "";
+                       if ( name && message ) {
+                               return name + ": " + message;
+                       } else if ( name ) {
+                               return name;
+                       } else if ( message ) {
+                               return message;
+                       } else {
+                               return "Error";
+                       }
+               } else {
+                       return errorString;
+               }
+       },
+       /**
+        * Makes a clone of an object using only Array or Object as base,
+        * and copies over the own enumerable properties.
+        *
+        * @param {Object} obj
+        * @return {Object} New object with only the own properties (recursively).
+        */
+       objectValues = function( obj ) {
+               // Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.
+               /*jshint newcap: false */
+               var key, val,
+                       vals = QUnit.is( "array", obj ) ? [] : {};
+               for ( key in obj ) {
+                       if ( hasOwn.call( obj, key ) ) {
+                               val = obj[key];
+                               vals[key] = val === Object(val) ? objectValues(val) : val;
+                       }
+               }
+               return vals;
+       };
+
+function Test( settings ) {
+       extend( this, settings );
+       this.assertions = [];
+       this.testNumber = ++Test.count;
+}
+
+Test.count = 0;
+
+Test.prototype = {
+       init: function() {
+               var a, b, li,
+                       tests = id( "qunit-tests" );
+
+               if ( tests ) {
+                       b = document.createElement( "strong" );
+                       b.innerHTML = this.nameHtml;
+
+                       // `a` initialized at top of scope
+                       a = document.createElement( "a" );
+                       a.innerHTML = "Rerun";
+                       a.href = QUnit.url({ testNumber: this.testNumber });
+
+                       li = document.createElement( "li" );
+                       li.appendChild( b );
+                       li.appendChild( a );
+                       li.className = "running";
+                       li.id = this.id = "qunit-test-output" + testId++;
+
+                       tests.appendChild( li );
+               }
+       },
+       setup: function() {
+               if ( this.module !== config.previousModule ) {
+                       if ( config.previousModule ) {
+                               runLoggingCallbacks( "moduleDone", QUnit, {
+                                       name: config.previousModule,
+                                       failed: config.moduleStats.bad,
+                                       passed: config.moduleStats.all - config.moduleStats.bad,
+                                       total: config.moduleStats.all
+                               });
+                       }
+                       config.previousModule = this.module;
+                       config.moduleStats = { all: 0, bad: 0 };
+                       runLoggingCallbacks( "moduleStart", QUnit, {
+                               name: this.module
+                       });
+               } else if ( config.autorun ) {
+                       runLoggingCallbacks( "moduleStart", QUnit, {
+                               name: this.module
+                       });
+               }
+
+               config.current = this;
+
+               this.testEnvironment = extend({
+                       setup: function() {},
+                       teardown: function() {}
+               }, this.moduleTestEnvironment );
+
+               this.started = +new Date();
+               runLoggingCallbacks( "testStart", QUnit, {
+                       name: this.testName,
+                       module: this.module
+               });
+
+               // allow utility functions to access the current test environment
+               // TODO why??
+               QUnit.current_testEnvironment = this.testEnvironment;
+
+               if ( !config.pollution ) {
+                       saveGlobal();
+               }
+               if ( config.notrycatch ) {
+                       this.testEnvironment.setup.call( this.testEnvironment );
+                       return;
+               }
+               try {
+                       this.testEnvironment.setup.call( this.testEnvironment );
+               } catch( e ) {
+                       QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
+               }
+       },
+       run: function() {
+               config.current = this;
+
+               var running = id( "qunit-testresult" );
+
+               if ( running ) {
+                       running.innerHTML = "Running: <br/>" + this.nameHtml;
+               }
+
+               if ( this.async ) {
+                       QUnit.stop();
+               }
+
+               this.callbackStarted = +new Date();
+
+               if ( config.notrycatch ) {
+                       this.callback.call( this.testEnvironment, QUnit.assert );
+                       this.callbackRuntime = +new Date() - this.callbackStarted;
+                       return;
+               }
+
+               try {
+                       this.callback.call( this.testEnvironment, QUnit.assert );
+                       this.callbackRuntime = +new Date() - this.callbackStarted;
+               } catch( e ) {
+                       this.callbackRuntime = +new Date() - this.callbackStarted;
+
+                       QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
+                       // else next test will carry the responsibility
+                       saveGlobal();
+
+                       // Restart the tests if they're blocking
+                       if ( config.blocking ) {
+                               QUnit.start();
+                       }
+               }
+       },
+       teardown: function() {
+               config.current = this;
+               if ( config.notrycatch ) {
+                       if ( typeof this.callbackRuntime === "undefined" ) {
+                               this.callbackRuntime = +new Date() - this.callbackStarted;
+                       }
+                       this.testEnvironment.teardown.call( this.testEnvironment );
+                       return;
+               } else {
+                       try {
+                               this.testEnvironment.teardown.call( this.testEnvironment );
+                       } catch( e ) {
+                               QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
+                       }
+               }
+               checkPollution();
+       },
+       finish: function() {
+               config.current = this;
+               if ( config.requireExpects && this.expected === null ) {
+                       QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );
+               } else if ( this.expected !== null && this.expected !== this.assertions.length ) {
+                       QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );
+               } else if ( this.expected === null && !this.assertions.length ) {
+                       QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
+               }
+
+               var i, assertion, a, b, time, li, ol,
+                       test = this,
+                       good = 0,
+                       bad = 0,
+                       tests = id( "qunit-tests" );
+
+               this.runtime = +new Date() - this.started;
+               config.stats.all += this.assertions.length;
+               config.moduleStats.all += this.assertions.length;
+
+               if ( tests ) {
+                       ol = document.createElement( "ol" );
+                       ol.className = "qunit-assert-list";
+
+                       for ( i = 0; i < this.assertions.length; i++ ) {
+                               assertion = this.assertions[i];
+
+                               li = document.createElement( "li" );
+                               li.className = assertion.result ? "pass" : "fail";
+                               li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" );
+                               ol.appendChild( li );
+
+                               if ( assertion.result ) {
+                                       good++;
+                               } else {
+                                       bad++;
+                                       config.stats.bad++;
+                                       config.moduleStats.bad++;
+                               }
+                       }
+
+                       // store result when possible
+                       if ( QUnit.config.reorder && defined.sessionStorage ) {
+                               if ( bad ) {
+                                       sessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad );
+                               } else {
+                                       sessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName );
+                               }
+                       }
+
+                       if ( bad === 0 ) {
+                               addClass( ol, "qunit-collapsed" );
+                       }
+
+                       // `b` initialized at top of scope
+                       b = document.createElement( "strong" );
+                       b.innerHTML = this.nameHtml + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
+
+                       addEvent(b, "click", function() {
+                               var next = b.parentNode.lastChild,
+                                       collapsed = hasClass( next, "qunit-collapsed" );
+                               ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );
+                       });
+
+                       addEvent(b, "dblclick", function( e ) {
+                               var target = e && e.target ? e.target : window.event.srcElement;
+                               if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) {
+                                       target = target.parentNode;
+                               }
+                               if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
+                                       window.location = QUnit.url({ testNumber: test.testNumber });
+                               }
+                       });
+
+                       // `time` initialized at top of scope
+                       time = document.createElement( "span" );
+                       time.className = "runtime";
+                       time.innerHTML = this.runtime + " ms";
+
+                       // `li` initialized at top of scope
+                       li = id( this.id );
+                       li.className = bad ? "fail" : "pass";
+                       li.removeChild( li.firstChild );
+                       a = li.firstChild;
+                       li.appendChild( b );
+                       li.appendChild( a );
+                       li.appendChild( time );
+                       li.appendChild( ol );
+
+               } else {
+                       for ( i = 0; i < this.assertions.length; i++ ) {
+                               if ( !this.assertions[i].result ) {
+                                       bad++;
+                                       config.stats.bad++;
+                                       config.moduleStats.bad++;
+                               }
+                       }
+               }
+
+               runLoggingCallbacks( "testDone", QUnit, {
+                       name: this.testName,
+                       module: this.module,
+                       failed: bad,
+                       passed: this.assertions.length - bad,
+                       total: this.assertions.length,
+                       duration: this.runtime
+               });
+
+               QUnit.reset();
+
+               config.current = undefined;
+       },
+
+       queue: function() {
+               var bad,
+                       test = this;
+
+               synchronize(function() {
+                       test.init();
+               });
+               function run() {
+                       // each of these can by async
+                       synchronize(function() {
+                               test.setup();
+                       });
+                       synchronize(function() {
+                               test.run();
+                       });
+                       synchronize(function() {
+                               test.teardown();
+                       });
+                       synchronize(function() {
+                               test.finish();
+                       });
+               }
+
+               // `bad` initialized at top of scope
+               // defer when previous test run passed, if storage is available
+               bad = QUnit.config.reorder && defined.sessionStorage &&
+                                               +sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName );
+
+               if ( bad ) {
+                       run();
+               } else {
+                       synchronize( run, true );
+               }
+       }
+};
+
+// Root QUnit object.
+// `QUnit` initialized at top of scope
+QUnit = {
+
+       // call on start of module test to prepend name to all tests
+       module: function( name, testEnvironment ) {
+               config.currentModule = name;
+               config.currentModuleTestEnvironment = testEnvironment;
+               config.modules[name] = true;
+       },
+
+       asyncTest: function( testName, expected, callback ) {
+               if ( arguments.length === 2 ) {
+                       callback = expected;
+                       expected = null;
+               }
+
+               QUnit.test( testName, expected, callback, true );
+       },
+
+       test: function( testName, expected, callback, async ) {
+               var test,
+                       nameHtml = "<span class='test-name'>" + escapeText( testName ) + "</span>";
+
+               if ( arguments.length === 2 ) {
+                       callback = expected;
+                       expected = null;
+               }
+
+               if ( config.currentModule ) {
+                       nameHtml = "<span class='module-name'>" + escapeText( config.currentModule ) + "</span>: " + nameHtml;
+               }
+
+               test = new Test({
+                       nameHtml: nameHtml,
+                       testName: testName,
+                       expected: expected,
+                       async: async,
+                       callback: callback,
+                       module: config.currentModule,
+                       moduleTestEnvironment: config.currentModuleTestEnvironment,
+                       stack: sourceFromStacktrace( 2 )
+               });
+
+               if ( !validTest( test ) ) {
+                       return;
+               }
+
+               test.queue();
+       },
+
+       // Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
+       expect: function( asserts ) {
+               if (arguments.length === 1) {
+                       config.current.expected = asserts;
+               } else {
+                       return config.current.expected;
+               }
+       },
+
+       start: function( count ) {
+               // QUnit hasn't been initialized yet.
+               // Note: RequireJS (et al) may delay onLoad
+               if ( config.semaphore === undefined ) {
+                       QUnit.begin(function() {
+                               // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first
+                               setTimeout(function() {
+                                       QUnit.start( count );
+                               });
+                       });
+                       return;
+               }
+
+               config.semaphore -= count || 1;
+               // don't start until equal number of stop-calls
+               if ( config.semaphore > 0 ) {
+                       return;
+               }
+               // ignore if start is called more often then stop
+               if ( config.semaphore < 0 ) {
+                       config.semaphore = 0;
+                       QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) );
+                       return;
+               }
+               // A slight delay, to avoid any current callbacks
+               if ( defined.setTimeout ) {
+                       window.setTimeout(function() {
+                               if ( config.semaphore > 0 ) {
+                                       return;
+                               }
+                               if ( config.timeout ) {
+                                       clearTimeout( config.timeout );
+                               }
+
+                               config.blocking = false;
+                               process( true );
+                       }, 13);
+               } else {
+                       config.blocking = false;
+                       process( true );
+               }
+       },
+
+       stop: function( count ) {
+               config.semaphore += count || 1;
+               config.blocking = true;
+
+               if ( config.testTimeout && defined.setTimeout ) {
+                       clearTimeout( config.timeout );
+                       config.timeout = window.setTimeout(function() {
+                               QUnit.ok( false, "Test timed out" );
+                               config.semaphore = 1;
+                               QUnit.start();
+                       }, config.testTimeout );
+               }
+       }
+};
+
+// `assert` initialized at top of scope
+// Asssert helpers
+// All of these must either call QUnit.push() or manually do:
+// - runLoggingCallbacks( "log", .. );
+// - config.current.assertions.push({ .. });
+// We attach it to the QUnit object *after* we expose the public API,
+// otherwise `assert` will become a global variable in browsers (#341).
+assert = {
+       /**
+        * Asserts rough true-ish result.
+        * @name ok
+        * @function
+        * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
+        */
+       ok: function( result, msg ) {
+               if ( !config.current ) {
+                       throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) );
+               }
+               result = !!result;
+
+               var source,
+                       details = {
+                               module: config.current.module,
+                               name: config.current.testName,
+                               result: result,
+                               message: msg
+                       };
+
+               msg = escapeText( msg || (result ? "okay" : "failed" ) );
+               msg = "<span class='test-message'>" + msg + "</span>";
+
+               if ( !result ) {
+                       source = sourceFromStacktrace( 2 );
+                       if ( source ) {
+                               details.source = source;
+                               msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr></table>";
+                       }
+               }
+               runLoggingCallbacks( "log", QUnit, details );
+               config.current.assertions.push({
+                       result: result,
+                       message: msg
+               });
+       },
+
+       /**
+        * Assert that the first two arguments are equal, with an optional message.
+        * Prints out both actual and expected values.
+        * @name equal
+        * @function
+        * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
+        */
+       equal: function( actual, expected, message ) {
+               /*jshint eqeqeq:false */
+               QUnit.push( expected == actual, actual, expected, message );
+       },
+
+       /**
+        * @name notEqual
+        * @function
+        */
+       notEqual: function( actual, expected, message ) {
+               /*jshint eqeqeq:false */
+               QUnit.push( expected != actual, actual, expected, message );
+       },
+
+       /**
+        * @name propEqual
+        * @function
+        */
+       propEqual: function( actual, expected, message ) {
+               actual = objectValues(actual);
+               expected = objectValues(expected);
+               QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
+       },
+
+       /**
+        * @name notPropEqual
+        * @function
+        */
+       notPropEqual: function( actual, expected, message ) {
+               actual = objectValues(actual);
+               expected = objectValues(expected);
+               QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
+       },
+
+       /**
+        * @name deepEqual
+        * @function
+        */
+       deepEqual: function( actual, expected, message ) {
+               QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
+       },
+
+       /**
+        * @name notDeepEqual
+        * @function
+        */
+       notDeepEqual: function( actual, expected, message ) {
+               QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
+       },
+
+       /**
+        * @name strictEqual
+        * @function
+        */
+       strictEqual: function( actual, expected, message ) {
+               QUnit.push( expected === actual, actual, expected, message );
+       },
+
+       /**
+        * @name notStrictEqual
+        * @function
+        */
+       notStrictEqual: function( actual, expected, message ) {
+               QUnit.push( expected !== actual, actual, expected, message );
+       },
+
+       "throws": function( block, expected, message ) {
+               var actual,
+                       expectedOutput = expected,
+                       ok = false;
+
+               // 'expected' is optional
+               if ( typeof expected === "string" ) {
+                       message = expected;
+                       expected = null;
+               }
+
+               config.current.ignoreGlobalErrors = true;
+               try {
+                       block.call( config.current.testEnvironment );
+               } catch (e) {
+                       actual = e;
+               }
+               config.current.ignoreGlobalErrors = false;
+
+               if ( actual ) {
+                       // we don't want to validate thrown error
+                       if ( !expected ) {
+                               ok = true;
+                               expectedOutput = null;
+                       // expected is a regexp
+                       } else if ( QUnit.objectType( expected ) === "regexp" ) {
+                               ok = expected.test( errorString( actual ) );
+                       // expected is a constructor
+                       } else if ( actual instanceof expected ) {
+                               ok = true;
+                       // expected is a validation function which returns true is validation passed
+                       } else if ( expected.call( {}, actual ) === true ) {
+                               expectedOutput = null;
+                               ok = true;
+                       }
+
+                       QUnit.push( ok, actual, expectedOutput, message );
+               } else {
+                       QUnit.pushFailure( message, null, 'No exception was thrown.' );
+               }
+       }
+};
+
+/**
+ * @deprecate since 1.8.0
+ * Kept assertion helpers in root for backwards compatibility.
+ */
+extend( QUnit, assert );
+
+/**
+ * @deprecated since 1.9.0
+ * Kept root "raises()" for backwards compatibility.
+ * (Note that we don't introduce assert.raises).
+ */
+QUnit.raises = assert[ "throws" ];
+
+/**
+ * @deprecated since 1.0.0, replaced with error pushes since 1.3.0
+ * Kept to avoid TypeErrors for undefined methods.
+ */
+QUnit.equals = function() {
+       QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
+};
+QUnit.same = function() {
+       QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" );
+};
+
+// We want access to the constructor's prototype
+(function() {
+       function F() {}
+       F.prototype = QUnit;
+       QUnit = new F();
+       // Make F QUnit's constructor so that we can add to the prototype later
+       QUnit.constructor = F;
+}());
+
+/**
+ * Config object: Maintain internal state
+ * Later exposed as QUnit.config
+ * `config` initialized at top of scope
+ */
+config = {
+       // The queue of tests to run
+       queue: [],
+
+       // block until document ready
+       blocking: true,
+
+       // when enabled, show only failing tests
+       // gets persisted through sessionStorage and can be changed in UI via checkbox
+       hidepassed: false,
+
+       // by default, run previously failed tests first
+       // very useful in combination with "Hide passed tests" checked
+       reorder: true,
+
+       // by default, modify document.title when suite is done
+       altertitle: true,
+
+       // when enabled, all tests must call expect()
+       requireExpects: false,
+
+       // add checkboxes that are persisted in the query-string
+       // when enabled, the id is set to `true` as a `QUnit.config` property
+       urlConfig: [
+               {
+                       id: "noglobals",
+                       label: "Check for Globals",
+                       tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."
+               },
+               {
+                       id: "notrycatch",
+                       label: "No try-catch",
+                       tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."
+               }
+       ],
+
+       // Set of all modules.
+       modules: {},
+
+       // logging callback queues
+       begin: [],
+       done: [],
+       log: [],
+       testStart: [],
+       testDone: [],
+       moduleStart: [],
+       moduleDone: []
+};
+
+// Export global variables, unless an 'exports' object exists,
+// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
+if ( typeof exports === "undefined" ) {
+       extend( window, QUnit );
+
+       // Expose QUnit object
+       window.QUnit = QUnit;
+}
+
+// Initialize more QUnit.config and QUnit.urlParams
+(function() {
+       var i,
+               location = window.location || { search: "", protocol: "file:" },
+               params = location.search.slice( 1 ).split( "&" ),
+               length = params.length,
+               urlParams = {},
+               current;
+
+       if ( params[ 0 ] ) {
+               for ( i = 0; i < length; i++ ) {
+                       current = params[ i ].split( "=" );
+                       current[ 0 ] = decodeURIComponent( current[ 0 ] );
+                       // allow just a key to turn on a flag, e.g., test.html?noglobals
+                       current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
+                       urlParams[ current[ 0 ] ] = current[ 1 ];
+               }
+       }
+
+       QUnit.urlParams = urlParams;
+
+       // String search anywhere in moduleName+testName
+       config.filter = urlParams.filter;
+
+       // Exact match of the module name
+       config.module = urlParams.module;
+
+       config.testNumber = parseInt( urlParams.testNumber, 10 ) || null;
+
+       // Figure out if we're running the tests from a server or not
+       QUnit.isLocal = location.protocol === "file:";
+}());
+
+// Extend QUnit object,
+// these after set here because they should not be exposed as global functions
+extend( QUnit, {
+       assert: assert,
+
+       config: config,
+
+       // Initialize the configuration options
+       init: function() {
+               extend( config, {
+                       stats: { all: 0, bad: 0 },
+                       moduleStats: { all: 0, bad: 0 },
+                       started: +new Date(),
+                       updateRate: 1000,
+                       blocking: false,
+                       autostart: true,
+                       autorun: false,
+                       filter: "",
+                       queue: [],
+                       semaphore: 1
+               });
+
+               var tests, banner, result,
+                       qunit = id( "qunit" );
+
+               if ( qunit ) {
+                       qunit.innerHTML =
+                               "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
+                               "<h2 id='qunit-banner'></h2>" +
+                               "<div id='qunit-testrunner-toolbar'></div>" +
+                               "<h2 id='qunit-userAgent'></h2>" +
+                               "<ol id='qunit-tests'></ol>";
+               }
+
+               tests = id( "qunit-tests" );
+               banner = id( "qunit-banner" );
+               result = id( "qunit-testresult" );
+
+               if ( tests ) {
+                       tests.innerHTML = "";
+               }
+
+               if ( banner ) {
+                       banner.className = "";
+               }
+
+               if ( result ) {
+                       result.parentNode.removeChild( result );
+               }
+
+               if ( tests ) {
+                       result = document.createElement( "p" );
+                       result.id = "qunit-testresult";
+                       result.className = "result";
+                       tests.parentNode.insertBefore( result, tests );
+                       result.innerHTML = "Running...<br/>&nbsp;";
+               }
+       },
+
+       // Resets the test setup. Useful for tests that modify the DOM.
+       reset: function() {
+               var fixture = id( "qunit-fixture" );
+               if ( fixture ) {
+                       fixture.innerHTML = config.fixture;
+               }
+       },
+
+       // Trigger an event on an element.
+       // @example triggerEvent( document.body, "click" );
+       triggerEvent: function( elem, type, event ) {
+               if ( document.createEvent ) {
+                       event = document.createEvent( "MouseEvents" );
+                       event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
+                               0, 0, 0, 0, 0, false, false, false, false, 0, null);
+
+                       elem.dispatchEvent( event );
+               } else if ( elem.fireEvent ) {
+                       elem.fireEvent( "on" + type );
+               }
+       },
+
+       // Safe object type checking
+       is: function( type, obj ) {
+               return QUnit.objectType( obj ) === type;
+       },
+
+       objectType: function( obj ) {
+               if ( typeof obj === "undefined" ) {
+                               return "undefined";
+               // consider: typeof null === object
+               }
+               if ( obj === null ) {
+                               return "null";
+               }
+
+               var match = toString.call( obj ).match(/^\[object\s(.*)\]$/),
+                       type = match && match[1] || "";
+
+               switch ( type ) {
+                       case "Number":
+                               if ( isNaN(obj) ) {
+                                       return "nan";
+                               }
+                               return "number";
+                       case "String":
+                       case "Boolean":
+                       case "Array":
+                       case "Date":
+                       case "RegExp":
+                       case "Function":
+                               return type.toLowerCase();
+               }
+               if ( typeof obj === "object" ) {
+                       return "object";
+               }
+               return undefined;
+       },
+
+       push: function( result, actual, expected, message ) {
+               if ( !config.current ) {
+                       throw new Error( "assertion outside test context, was " + sourceFromStacktrace() );
+               }
+
+               var output, source,
+                       details = {
+                               module: config.current.module,
+                               name: config.current.testName,
+                               result: result,
+                               message: message,
+                               actual: actual,
+                               expected: expected
+                       };
+
+               message = escapeText( message ) || ( result ? "okay" : "failed" );
+               message = "<span class='test-message'>" + message + "</span>";
+               output = message;
+
+               if ( !result ) {
+                       expected = escapeText( QUnit.jsDump.parse(expected) );
+                       actual = escapeText( QUnit.jsDump.parse(actual) );
+                       output += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>";
+
+                       if ( actual !== expected ) {
+                               output += "<tr class='test-actual'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>";
+                               output += "<tr class='test-diff'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>";
+                       }
+
+                       source = sourceFromStacktrace();
+
+                       if ( source ) {
+                               details.source = source;
+                               output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
+                       }
+
+                       output += "</table>";
+               }
+
+               runLoggingCallbacks( "log", QUnit, details );
+
+               config.current.assertions.push({
+                       result: !!result,
+                       message: output
+               });
+       },
+
+       pushFailure: function( message, source, actual ) {
+               if ( !config.current ) {
+                       throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
+               }
+
+               var output,
+                       details = {
+                               module: config.current.module,
+                               name: config.current.testName,
+                               result: false,
+                               message: message
+                       };
+
+               message = escapeText( message ) || "error";
+               message = "<span class='test-message'>" + message + "</span>";
+               output = message;
+
+               output += "<table>";
+
+               if ( actual ) {
+                       output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>";
+               }
+
+               if ( source ) {
+                       details.source = source;
+                       output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
+               }
+
+               output += "</table>";
+
+               runLoggingCallbacks( "log", QUnit, details );
+
+               config.current.assertions.push({
+                       result: false,
+                       message: output
+               });
+       },
+
+       url: function( params ) {
+               params = extend( extend( {}, QUnit.urlParams ), params );
+               var key,
+                       querystring = "?";
+
+               for ( key in params ) {
+                       if ( !hasOwn.call( params, key ) ) {
+                               continue;
+                       }
+                       querystring += encodeURIComponent( key ) + "=" +
+                               encodeURIComponent( params[ key ] ) + "&";
+               }
+               return window.location.protocol + "//" + window.location.host +
+                       window.location.pathname + querystring.slice( 0, -1 );
+       },
+
+       extend: extend,
+       id: id,
+       addEvent: addEvent
+       // load, equiv, jsDump, diff: Attached later
+});
+
+/**
+ * @deprecated: Created for backwards compatibility with test runner that set the hook function
+ * into QUnit.{hook}, instead of invoking it and passing the hook function.
+ * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.
+ * Doing this allows us to tell if the following methods have been overwritten on the actual
+ * QUnit object.
+ */
+extend( QUnit.constructor.prototype, {
+
+       // Logging callbacks; all receive a single argument with the listed properties
+       // run test/logs.html for any related changes
+       begin: registerLoggingCallback( "begin" ),
+
+       // done: { failed, passed, total, runtime }
+       done: registerLoggingCallback( "done" ),
+
+       // log: { result, actual, expected, message }
+       log: registerLoggingCallback( "log" ),
+
+       // testStart: { name }
+       testStart: registerLoggingCallback( "testStart" ),
+
+       // testDone: { name, failed, passed, total, duration }
+       testDone: registerLoggingCallback( "testDone" ),
+
+       // moduleStart: { name }
+       moduleStart: registerLoggingCallback( "moduleStart" ),
+
+       // moduleDone: { name, failed, passed, total }
+       moduleDone: registerLoggingCallback( "moduleDone" )
+});
+
+if ( typeof document === "undefined" || document.readyState === "complete" ) {
+       config.autorun = true;
+}
+
+QUnit.load = function() {
+       runLoggingCallbacks( "begin", QUnit, {} );
+
+       // Initialize the config, saving the execution queue
+       var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
+               urlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,
+               numModules = 0,
+               moduleFilterHtml = "",
+               urlConfigHtml = "",
+               oldconfig = extend( {}, config );
+
+       QUnit.init();
+       extend(config, oldconfig);
+
+       config.blocking = false;
+
+       len = config.urlConfig.length;
+
+       for ( i = 0; i < len; i++ ) {
+               val = config.urlConfig[i];
+               if ( typeof val === "string" ) {
+                       val = {
+                               id: val,
+                               label: val,
+                               tooltip: "[no tooltip available]"
+                       };
+               }
+               config[ val.id ] = QUnit.urlParams[ val.id ];
+               urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
+                       "' name='" + escapeText( val.id ) +
+                       "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) +
+                       " title='" + escapeText( val.tooltip ) +
+                       "'><label for='qunit-urlconfig-" + escapeText( val.id ) +
+                       "' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
+       }
+
+       moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " +
+               ( config.module === undefined  ? "selected='selected'" : "" ) +
+               ">< All Modules ></option>";
+
+       for ( i in config.modules ) {
+               if ( config.modules.hasOwnProperty( i ) ) {
+                       numModules += 1;
+                       moduleFilterHtml += "<option value='" + escapeText( encodeURIComponent(i) ) + "' " +
+                               ( config.module === i ? "selected='selected'" : "" ) +
+                               ">" + escapeText(i) + "</option>";
+               }
+       }
+       moduleFilterHtml += "</select>";
+
+       // `userAgent` initialized at top of scope
+       userAgent = id( "qunit-userAgent" );
+       if ( userAgent ) {
+               userAgent.innerHTML = navigator.userAgent;
+       }
+
+       // `banner` initialized at top of scope
+       banner = id( "qunit-header" );
+       if ( banner ) {
+               banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "'>" + banner.innerHTML + "</a> ";
+       }
+
+       // `toolbar` initialized at top of scope
+       toolbar = id( "qunit-testrunner-toolbar" );
+       if ( toolbar ) {
+               // `filter` initialized at top of scope
+               filter = document.createElement( "input" );
+               filter.type = "checkbox";
+               filter.id = "qunit-filter-pass";
+
+               addEvent( filter, "click", function() {
+                       var tmp,
+                               ol = document.getElementById( "qunit-tests" );
+
+                       if ( filter.checked ) {
+                               ol.className = ol.className + " hidepass";
+                       } else {
+                               tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
+                               ol.className = tmp.replace( / hidepass /, " " );
+                       }
+                       if ( defined.sessionStorage ) {
+                               if (filter.checked) {
+                                       sessionStorage.setItem( "qunit-filter-passed-tests", "true" );
+                               } else {
+                                       sessionStorage.removeItem( "qunit-filter-passed-tests" );
+                               }
+                       }
+               });
+
+               if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) {
+                       filter.checked = true;
+                       // `ol` initialized at top of scope
+                       ol = document.getElementById( "qunit-tests" );
+                       ol.className = ol.className + " hidepass";
+               }
+               toolbar.appendChild( filter );
+
+               // `label` initialized at top of scope
+               label = document.createElement( "label" );
+               label.setAttribute( "for", "qunit-filter-pass" );
+               label.setAttribute( "title", "Only show tests and assertons that fail. Stored in sessionStorage." );
+               label.innerHTML = "Hide passed tests";
+               toolbar.appendChild( label );
+
+               urlConfigCheckboxesContainer = document.createElement("span");
+               urlConfigCheckboxesContainer.innerHTML = urlConfigHtml;
+               urlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName("input");
+               // For oldIE support:
+               // * Add handlers to the individual elements instead of the container
+               // * Use "click" instead of "change"
+               // * Fallback from event.target to event.srcElement
+               addEvents( urlConfigCheckboxes, "click", function( event ) {
+                       var params = {},
+                               target = event.target || event.srcElement;
+                       params[ target.name ] = target.checked ? true : undefined;
+                       window.location = QUnit.url( params );
+               });
+               toolbar.appendChild( urlConfigCheckboxesContainer );
+
+               if (numModules > 1) {
+                       moduleFilter = document.createElement( 'span' );
+                       moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
+                       moduleFilter.innerHTML = moduleFilterHtml;
+                       addEvent( moduleFilter.lastChild, "change", function() {
+                               var selectBox = moduleFilter.getElementsByTagName("select")[0],
+                                       selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
+
+                               window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
+                       });
+                       toolbar.appendChild(moduleFilter);
+               }
+       }
+
+       // `main` initialized at top of scope
+       main = id( "qunit-fixture" );
+       if ( main ) {
+               config.fixture = main.innerHTML;
+       }
+
+       if ( config.autostart ) {
+               QUnit.start();
+       }
+};
+
+addEvent( window, "load", QUnit.load );
+
+// `onErrorFnPrev` initialized at top of scope
+// Preserve other handlers
+onErrorFnPrev = window.onerror;
+
+// Cover uncaught exceptions
+// Returning true will surpress the default browser handler,
+// returning false will let it run.
+window.onerror = function ( error, filePath, linerNr ) {
+       var ret = false;
+       if ( onErrorFnPrev ) {
+               ret = onErrorFnPrev( error, filePath, linerNr );
+       }
+
+       // Treat return value as window.onerror itself does,
+       // Only do our handling if not surpressed.
+       if ( ret !== true ) {
+               if ( QUnit.config.current ) {
+                       if ( QUnit.config.current.ignoreGlobalErrors ) {
+                               return true;
+                       }
+                       QUnit.pushFailure( error, filePath + ":" + linerNr );
+               } else {
+                       QUnit.test( "global failure", extend( function() {
+                               QUnit.pushFailure( error, filePath + ":" + linerNr );
+                       }, { validTest: validTest } ) );
+               }
+               return false;
+       }
+
+       return ret;
+};
+
+function done() {
+       config.autorun = true;
+
+       // Log the last module results
+       if ( config.currentModule ) {
+               runLoggingCallbacks( "moduleDone", QUnit, {
+                       name: config.currentModule,
+                       failed: config.moduleStats.bad,
+                       passed: config.moduleStats.all - config.moduleStats.bad,
+                       total: config.moduleStats.all
+               });
+       }
+
+       var i, key,
+               banner = id( "qunit-banner" ),
+               tests = id( "qunit-tests" ),
+               runtime = +new Date() - config.started,
+               passed = config.stats.all - config.stats.bad,
+               html = [
+                       "Tests completed in ",
+                       runtime,
+                       " milliseconds.<br/>",
+                       "<span class='passed'>",
+                       passed,
+                       "</span> assertions of <span class='total'>",
+                       config.stats.all,
+                       "</span> passed, <span class='failed'>",
+                       config.stats.bad,
+                       "</span> failed."
+               ].join( "" );
+
+       if ( banner ) {
+               banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" );
+       }
+
+       if ( tests ) {
+               id( "qunit-testresult" ).innerHTML = html;
+       }
+
+       if ( config.altertitle && typeof document !== "undefined" && document.title ) {
+               // show ✖ for good, ✔ for bad suite result in title
+               // use escape sequences in case file gets loaded with non-utf-8-charset
+               document.title = [
+                       ( config.stats.bad ? "\u2716" : "\u2714" ),
+                       document.title.replace( /^[\u2714\u2716] /i, "" )
+               ].join( " " );
+       }
+
+       // clear own sessionStorage items if all tests passed
+       if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {
+               // `key` & `i` initialized at top of scope
+               for ( i = 0; i < sessionStorage.length; i++ ) {
+                       key = sessionStorage.key( i++ );
+                       if ( key.indexOf( "qunit-test-" ) === 0 ) {
+                               sessionStorage.removeItem( key );
+                       }
+               }
+       }
+
+       // scroll back to top to show results
+       if ( window.scrollTo ) {
+               window.scrollTo(0, 0);
+       }
+
+       runLoggingCallbacks( "done", QUnit, {
+               failed: config.stats.bad,
+               passed: passed,
+               total: config.stats.all,
+               runtime: runtime
+       });
+}
+
+/** @return Boolean: true if this test should be ran */
+function validTest( test ) {
+       var include,
+               filter = config.filter && config.filter.toLowerCase(),
+               module = config.module && config.module.toLowerCase(),
+               fullName = (test.module + ": " + test.testName).toLowerCase();
+
+       // Internally-generated tests are always valid
+       if ( test.callback && test.callback.validTest === validTest ) {
+               delete test.callback.validTest;
+               return true;
+       }
+
+       if ( config.testNumber ) {
+               return test.testNumber === config.testNumber;
+       }
+
+       if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
+               return false;
+       }
+
+       if ( !filter ) {
+               return true;
+       }
+
+       include = filter.charAt( 0 ) !== "!";
+       if ( !include ) {
+               filter = filter.slice( 1 );
+       }
+
+       // If the filter matches, we need to honour include
+       if ( fullName.indexOf( filter ) !== -1 ) {
+               return include;
+       }
+
+       // Otherwise, do the opposite
+       return !include;
+}
+
+// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)
+// Later Safari and IE10 are supposed to support error.stack as well
+// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
+function extractStacktrace( e, offset ) {
+       offset = offset === undefined ? 3 : offset;
+
+       var stack, include, i;
+
+       if ( e.stacktrace ) {
+               // Opera
+               return e.stacktrace.split( "\n" )[ offset + 3 ];
+       } else if ( e.stack ) {
+               // Firefox, Chrome
+               stack = e.stack.split( "\n" );
+               if (/^error$/i.test( stack[0] ) ) {
+                       stack.shift();
+               }
+               if ( fileName ) {
+                       include = [];
+                       for ( i = offset; i < stack.length; i++ ) {
+                               if ( stack[ i ].indexOf( fileName ) !== -1 ) {
+                                       break;
+                               }
+                               include.push( stack[ i ] );
+                       }
+                       if ( include.length ) {
+                               return include.join( "\n" );
+                       }
+               }
+               return stack[ offset ];
+       } else if ( e.sourceURL ) {
+               // Safari, PhantomJS
+               // hopefully one day Safari provides actual stacktraces
+               // exclude useless self-reference for generated Error objects
+               if ( /qunit.js$/.test( e.sourceURL ) ) {
+                       return;
+               }
+               // for actual exceptions, this is useful
+               return e.sourceURL + ":" + e.line;
+       }
+}
+function sourceFromStacktrace( offset ) {
+       try {
+               throw new Error();
+       } catch ( e ) {
+               return extractStacktrace( e, offset );
+       }
+}
+
+/**
+ * Escape text for attribute or text content.
+ */
+function escapeText( s ) {
+       if ( !s ) {
+               return "";
+       }
+       s = s + "";
+       // Both single quotes and double quotes (for attributes)
+       return s.replace( /['"<>&]/g, function( s ) {
+               switch( s ) {
+                       case '\'':
+                               return '&#039;';
+                       case '"':
+                               return '&quot;';
+                       case '<':
+                               return '&lt;';
+                       case '>':
+                               return '&gt;';
+                       case '&':
+                               return '&amp;';
+               }
+       });
+}
+
+function synchronize( callback, last ) {
+       config.queue.push( callback );
+
+       if ( config.autorun && !config.blocking ) {
+               process( last );
+       }
+}
+
+function process( last ) {
+       function next() {
+               process( last );
+       }
+       var start = new Date().getTime();
+       config.depth = config.depth ? config.depth + 1 : 1;
+
+       while ( config.queue.length && !config.blocking ) {
+               if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {
+                       config.queue.shift()();
+               } else {
+                       window.setTimeout( next, 13 );
+                       break;
+               }
+       }
+       config.depth--;
+       if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {
+               done();
+       }
+}
+
+function saveGlobal() {
+       config.pollution = [];
+
+       if ( config.noglobals ) {
+               for ( var key in window ) {
+                       // in Opera sometimes DOM element ids show up here, ignore them
+                       if ( !hasOwn.call( window, key ) || /^qunit-test-output/.test( key ) ) {
+                               continue;
+                       }
+                       config.pollution.push( key );
+               }
+       }
+}
+
+function checkPollution() {
+       var newGlobals,
+               deletedGlobals,
+               old = config.pollution;
+
+       saveGlobal();
+
+       newGlobals = diff( config.pollution, old );
+       if ( newGlobals.length > 0 ) {
+               QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") );
+       }
+
+       deletedGlobals = diff( old, config.pollution );
+       if ( deletedGlobals.length > 0 ) {
+               QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") );
+       }
+}
+
+// returns a new Array with the elements that are in a but not in b
+function diff( a, b ) {
+       var i, j,
+               result = a.slice();
+
+       for ( i = 0; i < result.length; i++ ) {
+               for ( j = 0; j < b.length; j++ ) {
+                       if ( result[i] === b[j] ) {
+                               result.splice( i, 1 );
+                               i--;
+                               break;
+                       }
+               }
+       }
+       return result;
+}
+
+function extend( a, b ) {
+       for ( var prop in b ) {
+               if ( b[ prop ] === undefined ) {
+                       delete a[ prop ];
+
+               // Avoid "Member not found" error in IE8 caused by setting window.constructor
+               } else if ( prop !== "constructor" || a !== window ) {
+                       a[ prop ] = b[ prop ];
+               }
+       }
+
+       return a;
+}
+
+/**
+ * @param {HTMLElement} elem
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvent( elem, type, fn ) {
+       // Standards-based browsers
+       if ( elem.addEventListener ) {
+               elem.addEventListener( type, fn, false );
+       // IE
+       } else {
+               elem.attachEvent( "on" + type, fn );
+       }
+}
+
+/**
+ * @param {Array|NodeList} elems
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvents( elems, type, fn ) {
+       var i = elems.length;
+       while ( i-- ) {
+               addEvent( elems[i], type, fn );
+       }
+}
+
+function hasClass( elem, name ) {
+       return (" " + elem.className + " ").indexOf(" " + name + " ") > -1;
+}
+
+function addClass( elem, name ) {
+       if ( !hasClass( elem, name ) ) {
+               elem.className += (elem.className ? " " : "") + name;
+       }
+}
+
+function removeClass( elem, name ) {
+       var set = " " + elem.className + " ";
+       // Class name may appear multiple times
+       while ( set.indexOf(" " + name + " ") > -1 ) {
+               set = set.replace(" " + name + " " , " ");
+       }
+       // If possible, trim it for prettiness, but not neccecarily
+       elem.className = window.jQuery ? jQuery.trim( set ) : ( set.trim ? set.trim() : set );
+}
+
+function id( name ) {
+       return !!( typeof document !== "undefined" && document && document.getElementById ) &&
+               document.getElementById( name );
+}
+
+function registerLoggingCallback( key ) {
+       return function( callback ) {
+               config[key].push( callback );
+       };
+}
+
+// Supports deprecated method of completely overwriting logging callbacks
+function runLoggingCallbacks( key, scope, args ) {
+       var i, callbacks;
+       if ( QUnit.hasOwnProperty( key ) ) {
+               QUnit[ key ].call(scope, args );
+       } else {
+               callbacks = config[ key ];
+               for ( i = 0; i < callbacks.length; i++ ) {
+                       callbacks[ i ].call( scope, args );
+               }
+       }
+}
+
+// Test for equality any JavaScript type.
+// Author: Philippe Rathé <prathe@gmail.com>
+QUnit.equiv = (function() {
+
+       // Call the o related callback with the given arguments.
+       function bindCallbacks( o, callbacks, args ) {
+               var prop = QUnit.objectType( o );
+               if ( prop ) {
+                       if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) {
+                               return callbacks[ prop ].apply( callbacks, args );
+                       } else {
+                               return callbacks[ prop ]; // or undefined
+                       }
+               }
+       }
+
+       // the real equiv function
+       var innerEquiv,
+               // stack to decide between skip/abort functions
+               callers = [],
+               // stack to avoiding loops from circular referencing
+               parents = [],
+
+               getProto = Object.getPrototypeOf || function ( obj ) {
+                       return obj.__proto__;
+               },
+               callbacks = (function () {
+
+                       // for string, boolean, number and null
+                       function useStrictEquality( b, a ) {
+                               /*jshint eqeqeq:false */
+                               if ( b instanceof a.constructor || a instanceof b.constructor ) {
+                                       // to catch short annotaion VS 'new' annotation of a
+                                       // declaration
+                                       // e.g. var i = 1;
+                                       // var j = new Number(1);
+                                       return a == b;
+                               } else {
+                                       return a === b;
+                               }
+                       }
+
+                       return {
+                               "string": useStrictEquality,
+                               "boolean": useStrictEquality,
+                               "number": useStrictEquality,
+                               "null": useStrictEquality,
+                               "undefined": useStrictEquality,
+
+                               "nan": function( b ) {
+                                       return isNaN( b );
+                               },
+
+                               "date": function( b, a ) {
+                                       return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf();
+                               },
+
+                               "regexp": function( b, a ) {
+                                       return QUnit.objectType( b ) === "regexp" &&
+                                               // the regex itself
+                                               a.source === b.source &&
+                                               // and its modifers
+                                               a.global === b.global &&
+                                               // (gmi) ...
+                                               a.ignoreCase === b.ignoreCase &&
+                                               a.multiline === b.multiline &&
+                                               a.sticky === b.sticky;
+                               },
+
+                               // - skip when the property is a method of an instance (OOP)
+                               // - abort otherwise,
+                               // initial === would have catch identical references anyway
+                               "function": function() {
+                                       var caller = callers[callers.length - 1];
+                                       return caller !== Object && typeof caller !== "undefined";
+                               },
+
+                               "array": function( b, a ) {
+                                       var i, j, len, loop;
+
+                                       // b could be an object literal here
+                                       if ( QUnit.objectType( b ) !== "array" ) {
+                                               return false;
+                                       }
+
+                                       len = a.length;
+                                       if ( len !== b.length ) {
+                                               // safe and faster
+                                               return false;
+                                       }
+
+                                       // track reference to avoid circular references
+                                       parents.push( a );
+                                       for ( i = 0; i < len; i++ ) {
+                                               loop = false;
+                                               for ( j = 0; j < parents.length; j++ ) {
+                                                       if ( parents[j] === a[i] ) {
+                                                               loop = true;// dont rewalk array
+                                                       }
+                                               }
+                                               if ( !loop && !innerEquiv(a[i], b[i]) ) {
+                                                       parents.pop();
+                                                       return false;
+                                               }
+                                       }
+                                       parents.pop();
+                                       return true;
+                               },
+
+                               "object": function( b, a ) {
+                                       var i, j, loop,
+                                               // Default to true
+                                               eq = true,
+                                               aProperties = [],
+                                               bProperties = [];
+
+                                       // comparing constructors is more strict than using
+                                       // instanceof
+                                       if ( a.constructor !== b.constructor ) {
+                                               // Allow objects with no prototype to be equivalent to
+                                               // objects with Object as their constructor.
+                                               if ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||
+                                                       ( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {
+                                                               return false;
+                                               }
+                                       }
+
+                                       // stack constructor before traversing properties
+                                       callers.push( a.constructor );
+                                       // track reference to avoid circular references
+                                       parents.push( a );
+
+                                       for ( i in a ) { // be strict: don't ensures hasOwnProperty
+                                                                       // and go deep
+                                               loop = false;
+                                               for ( j = 0; j < parents.length; j++ ) {
+                                                       if ( parents[j] === a[i] ) {
+                                                               // don't go down the same path twice
+                                                               loop = true;
+                                                       }
+                                               }
+                                               aProperties.push(i); // collect a's properties
+
+                                               if (!loop && !innerEquiv( a[i], b[i] ) ) {
+                                                       eq = false;
+                                                       break;
+                                               }
+                                       }
+
+                                       callers.pop(); // unstack, we are done
+                                       parents.pop();
+
+                                       for ( i in b ) {
+                                               bProperties.push( i ); // collect b's properties
+                                       }
+
+                                       // Ensures identical properties name
+                                       return eq && innerEquiv( aProperties.sort(), bProperties.sort() );
+                               }
+                       };
+               }());
+
+       innerEquiv = function() { // can take multiple arguments
+               var args = [].slice.apply( arguments );
+               if ( args.length < 2 ) {
+                       return true; // end transition
+               }
+
+               return (function( a, b ) {
+                       if ( a === b ) {
+                               return true; // catch the most you can
+                       } else if ( a === null || b === null || typeof a === "undefined" ||
+                                       typeof b === "undefined" ||
+                                       QUnit.objectType(a) !== QUnit.objectType(b) ) {
+                               return false; // don't lose time with error prone cases
+                       } else {
+                               return bindCallbacks(a, callbacks, [ b, a ]);
+                       }
+
+                       // apply transition with (1..n) arguments
+               }( args[0], args[1] ) && arguments.callee.apply( this, args.splice(1, args.length - 1 )) );
+       };
+
+       return innerEquiv;
+}());
+
+/**
+ * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
+ * http://flesler.blogspot.com Licensed under BSD
+ * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
+ *
+ * @projectDescription Advanced and extensible data dumping for Javascript.
+ * @version 1.0.0
+ * @author Ariel Flesler
+ * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
+ */
+QUnit.jsDump = (function() {
+       function quote( str ) {
+               return '"' + str.toString().replace( /"/g, '\\"' ) + '"';
+       }
+       function literal( o ) {
+               return o + "";
+       }
+       function join( pre, arr, post ) {
+               var s = jsDump.separator(),
+                       base = jsDump.indent(),
+                       inner = jsDump.indent(1);
+               if ( arr.join ) {
+                       arr = arr.join( "," + s + inner );
+               }
+               if ( !arr ) {
+                       return pre + post;
+               }
+               return [ pre, inner + arr, base + post ].join(s);
+       }
+       function array( arr, stack ) {
+               var i = arr.length, ret = new Array(i);
+               this.up();
+               while ( i-- ) {
+                       ret[i] = this.parse( arr[i] , undefined , stack);
+               }
+               this.down();
+               return join( "[", ret, "]" );
+       }
+
+       var reName = /^function (\w+)/,
+               jsDump = {
+                       // type is used mostly internally, you can fix a (custom)type in advance
+                       parse: function( obj, type, stack ) {
+                               stack = stack || [ ];
+                               var inStack, res,
+                                       parser = this.parsers[ type || this.typeOf(obj) ];
+
+                               type = typeof parser;
+                               inStack = inArray( obj, stack );
+
+                               if ( inStack !== -1 ) {
+                                       return "recursion(" + (inStack - stack.length) + ")";
+                               }
+                               if ( type === "function" )  {
+                                       stack.push( obj );
+                                       res = parser.call( this, obj, stack );
+                                       stack.pop();
+                                       return res;
+                               }
+                               return ( type === "string" ) ? parser : this.parsers.error;
+                       },
+                       typeOf: function( obj ) {
+                               var type;
+                               if ( obj === null ) {
+                                       type = "null";
+                               } else if ( typeof obj === "undefined" ) {
+                                       type = "undefined";
+                               } else if ( QUnit.is( "regexp", obj) ) {
+                                       type = "regexp";
+                               } else if ( QUnit.is( "date", obj) ) {
+                                       type = "date";
+                               } else if ( QUnit.is( "function", obj) ) {
+                                       type = "function";
+                               } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) {
+                                       type = "window";
+                               } else if ( obj.nodeType === 9 ) {
+                                       type = "document";
+                               } else if ( obj.nodeType ) {
+                                       type = "node";
+                               } else if (
+                                       // native arrays
+                                       toString.call( obj ) === "[object Array]" ||
+                                       // NodeList objects
+                                       ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
+                               ) {
+                                       type = "array";
+                               } else if ( obj.constructor === Error.prototype.constructor ) {
+                                       type = "error";
+                               } else {
+                                       type = typeof obj;
+                               }
+                               return type;
+                       },
+                       separator: function() {
+                               return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&nbsp;" : " ";
+                       },
+                       // extra can be a number, shortcut for increasing-calling-decreasing
+                       indent: function( extra ) {
+                               if ( !this.multiline ) {
+                                       return "";
+                               }
+                               var chr = this.indentChar;
+                               if ( this.HTML ) {
+                                       chr = chr.replace( /\t/g, "   " ).replace( / /g, "&nbsp;" );
+                               }
+                               return new Array( this._depth_ + (extra||0) ).join(chr);
+                       },
+                       up: function( a ) {
+                               this._depth_ += a || 1;
+                       },
+                       down: function( a ) {
+                               this._depth_ -= a || 1;
+                       },
+                       setParser: function( name, parser ) {
+                               this.parsers[name] = parser;
+                       },
+                       // The next 3 are exposed so you can use them
+                       quote: quote,
+                       literal: literal,
+                       join: join,
+                       //
+                       _depth_: 1,
+                       // This is the list of parsers, to modify them, use jsDump.setParser
+                       parsers: {
+                               window: "[Window]",
+                               document: "[Document]",
+                               error: function(error) {
+                                       return "Error(\"" + error.message + "\")";
+                               },
+                               unknown: "[Unknown]",
+                               "null": "null",
+                               "undefined": "undefined",
+                               "function": function( fn ) {
+                                       var ret = "function",
+                                               // functions never have name in IE
+                                               name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
+
+                                       if ( name ) {
+                                               ret += " " + name;
+                                       }
+                                       ret += "( ";
+
+                                       ret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" );
+                                       return join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" );
+                               },
+                               array: array,
+                               nodelist: array,
+                               "arguments": array,
+                               object: function( map, stack ) {
+                                       var ret = [ ], keys, key, val, i;
+                                       QUnit.jsDump.up();
+                                       keys = [];
+                                       for ( key in map ) {
+                                               keys.push( key );
+                                       }
+                                       keys.sort();
+                                       for ( i = 0; i < keys.length; i++ ) {
+                                               key = keys[ i ];
+                                               val = map[ key ];
+                                               ret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) );
+                                       }
+                                       QUnit.jsDump.down();
+                                       return join( "{", ret, "}" );
+                               },
+                               node: function( node ) {
+                                       var len, i, val,
+                                               open = QUnit.jsDump.HTML ? "&lt;" : "<",
+                                               close = QUnit.jsDump.HTML ? "&gt;" : ">",
+                                               tag = node.nodeName.toLowerCase(),
+                                               ret = open + tag,
+                                               attrs = node.attributes;
+
+                                       if ( attrs ) {
+                                               for ( i = 0, len = attrs.length; i < len; i++ ) {
+                                                       val = attrs[i].nodeValue;
+                                                       // IE6 includes all attributes in .attributes, even ones not explicitly set.
+                                                       // Those have values like undefined, null, 0, false, "" or "inherit".
+                                                       if ( val && val !== "inherit" ) {
+                                                               ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" );
+                                                       }
+                                               }
+                                       }
+                                       ret += close;
+
+                                       // Show content of TextNode or CDATASection
+                                       if ( node.nodeType === 3 || node.nodeType === 4 ) {
+                                               ret += node.nodeValue;
+                                       }
+
+                                       return ret + open + "/" + tag + close;
+                               },
+                               // function calls it internally, it's the arguments part of the function
+                               functionArgs: function( fn ) {
+                                       var args,
+                                               l = fn.length;
+
+                                       if ( !l ) {
+                                               return "";
+                                       }
+
+                                       args = new Array(l);
+                                       while ( l-- ) {
+                                               // 97 is 'a'
+                                               args[l] = String.fromCharCode(97+l);
+                                       }
+                                       return " " + args.join( ", " ) + " ";
+                               },
+                               // object calls it internally, the key part of an item in a map
+                               key: quote,
+                               // function calls it internally, it's the content of the function
+                               functionCode: "[code]",
+                               // node calls it internally, it's an html attribute value
+                               attribute: quote,
+                               string: quote,
+                               date: quote,
+                               regexp: literal,
+                               number: literal,
+                               "boolean": literal
+                       },
+                       // if true, entities are escaped ( <, >, \t, space and \n )
+                       HTML: false,
+                       // indentation unit
+                       indentChar: "  ",
+                       // if true, items in a collection, are separated by a \n, else just a space.
+                       multiline: true
+               };
+
+       return jsDump;
+}());
+
+// from jquery.js
+function inArray( elem, array ) {
+       if ( array.indexOf ) {
+               return array.indexOf( elem );
+       }
+
+       for ( var i = 0, length = array.length; i < length; i++ ) {
+               if ( array[ i ] === elem ) {
+                       return i;
+               }
+       }
+
+       return -1;
+}
+
+/*
+ * Javascript Diff Algorithm
+ *  By John Resig (http://ejohn.org/)
+ *  Modified by Chu Alan "sprite"
+ *
+ * Released under the MIT license.
+ *
+ * More Info:
+ *  http://ejohn.org/projects/javascript-diff-algorithm/
+ *
+ * Usage: QUnit.diff(expected, actual)
+ *
+ * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
+ */
+QUnit.diff = (function() {
+       /*jshint eqeqeq:false, eqnull:true */
+       function diff( o, n ) {
+               var i,
+                       ns = {},
+                       os = {};
+
+               for ( i = 0; i < n.length; i++ ) {
+                       if ( !hasOwn.call( ns, n[i] ) ) {
+                               ns[ n[i] ] = {
+                                       rows: [],
+                                       o: null
+                               };
+                       }
+                       ns[ n[i] ].rows.push( i );
+               }
+
+               for ( i = 0; i < o.length; i++ ) {
+                       if ( !hasOwn.call( os, o[i] ) ) {
+                               os[ o[i] ] = {
+                                       rows: [],
+                                       n: null
+                               };
+                       }
+                       os[ o[i] ].rows.push( i );
+               }
+
+               for ( i in ns ) {
+                       if ( !hasOwn.call( ns, i ) ) {
+                               continue;
+                       }
+                       if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {
+                               n[ ns[i].rows[0] ] = {
+                                       text: n[ ns[i].rows[0] ],
+                                       row: os[i].rows[0]
+                               };
+                               o[ os[i].rows[0] ] = {
+                                       text: o[ os[i].rows[0] ],
+                                       row: ns[i].rows[0]
+                               };
+                       }
+               }
+
+               for ( i = 0; i < n.length - 1; i++ ) {
+                       if ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
+                                               n[ i + 1 ] == o[ n[i].row + 1 ] ) {
+
+                               n[ i + 1 ] = {
+                                       text: n[ i + 1 ],
+                                       row: n[i].row + 1
+                               };
+                               o[ n[i].row + 1 ] = {
+                                       text: o[ n[i].row + 1 ],
+                                       row: i + 1
+                               };
+                       }
+               }
+
+               for ( i = n.length - 1; i > 0; i-- ) {
+                       if ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
+                                               n[ i - 1 ] == o[ n[i].row - 1 ]) {
+
+                               n[ i - 1 ] = {
+                                       text: n[ i - 1 ],
+                                       row: n[i].row - 1
+                               };
+                               o[ n[i].row - 1 ] = {
+                                       text: o[ n[i].row - 1 ],
+                                       row: i - 1
+                               };
+                       }
+               }
+
+               return {
+                       o: o,
+                       n: n
+               };
+       }
+
+       return function( o, n ) {
+               o = o.replace( /\s+$/, "" );
+               n = n.replace( /\s+$/, "" );
+
+               var i, pre,
+                       str = "",
+                       out = diff( o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/) ),
+                       oSpace = o.match(/\s+/g),
+                       nSpace = n.match(/\s+/g);
+
+               if ( oSpace == null ) {
+                       oSpace = [ " " ];
+               }
+               else {
+                       oSpace.push( " " );
+               }
+
+               if ( nSpace == null ) {
+                       nSpace = [ " " ];
+               }
+               else {
+                       nSpace.push( " " );
+               }
+
+               if ( out.n.length === 0 ) {
+                       for ( i = 0; i < out.o.length; i++ ) {
+                               str += "<del>" + out.o[i] + oSpace[i] + "</del>";
+                       }
+               }
+               else {
+                       if ( out.n[0].text == null ) {
+                               for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {
+                                       str += "<del>" + out.o[n] + oSpace[n] + "</del>";
+                               }
+                       }
+
+                       for ( i = 0; i < out.n.length; i++ ) {
+                               if (out.n[i].text == null) {
+                                       str += "<ins>" + out.n[i] + nSpace[i] + "</ins>";
+                               }
+                               else {
+                                       // `pre` initialized at top of scope
+                                       pre = "";
+
+                                       for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
+                                               pre += "<del>" + out.o[n] + oSpace[n] + "</del>";
+                                       }
+                                       str += " " + out.n[i].text + nSpace[i] + pre;
+                               }
+                       }
+               }
+
+               return str;
+       };
+}());
+
+// for CommonJS enviroments, export everything
+if ( typeof exports !== "undefined" ) {
+       extend( exports, QUnit );
+}
+
+// get at whatever the global object is, like window in browsers
+}( (function() {return this;}.call()) ));
diff --git a/resources/lib/jquery/jquery.validate.js b/resources/lib/jquery/jquery.validate.js
new file mode 100644 (file)
index 0000000..72296a6
--- /dev/null
@@ -0,0 +1,1166 @@
+/**
+ * jQuery Validation Plugin 1.8.1
+ *
+ * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
+ * http://docs.jquery.com/Plugins/Validation
+ *
+ * Copyright (c) 2006 - 2011 Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ */
+
+(function($) {
+
+$.extend($.fn, {
+       // http://docs.jquery.com/Plugins/Validation/validate
+       validate: function( options ) {
+
+               // if nothing is selected, return nothing; can't chain anyway
+               if (!this.length) {
+                       options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
+                       return;
+               }
+
+               // check if a validator for this form was already created
+               var validator = $.data(this[0], 'validator');
+               if ( validator ) {
+                       return validator;
+               }
+
+               validator = new $.validator( options, this[0] );
+               $.data(this[0], 'validator', validator);
+
+               if ( validator.settings.onsubmit ) {
+
+                       // allow suppresing validation by adding a cancel class to the submit button
+                       this.find("input, button").filter(".cancel").click(function() {
+                               validator.cancelSubmit = true;
+                       });
+
+                       // when a submitHandler is used, capture the submitting button
+                       if (validator.settings.submitHandler) {
+                               this.find("input, button").filter(":submit").click(function() {
+                                       validator.submitButton = this;
+                               });
+                       }
+
+                       // validate the form on submit
+                       this.submit( function( event ) {
+                               if ( validator.settings.debug )
+                                       // prevent form submit to be able to see console output
+                                       event.preventDefault();
+
+                               function handle() {
+                                       if ( validator.settings.submitHandler ) {
+                                               if (validator.submitButton) {
+                                                       // insert a hidden input as a replacement for the missing submit button
+                                                       var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
+                                               }
+                                               validator.settings.submitHandler.call( validator, validator.currentForm );
+                                               if (validator.submitButton) {
+                                                       // and clean up afterwards; thanks to no-block-scope, hidden can be referenced
+                                                       hidden.remove();
+                                               }
+                                               return false;
+                                       }
+                                       return true;
+                               }
+
+                               // prevent submit for invalid forms or custom submit handlers
+                               if ( validator.cancelSubmit ) {
+                                       validator.cancelSubmit = false;
+                                       return handle();
+                               }
+                               if ( validator.form() ) {
+                                       if ( validator.pendingRequest ) {
+                                               validator.formSubmitted = true;
+                                               return false;
+                                       }
+                                       return handle();
+                               } else {
+                                       validator.focusInvalid();
+                                       return false;
+                               }
+                       });
+               }
+
+               return validator;
+       },
+       // http://docs.jquery.com/Plugins/Validation/valid
+       valid: function() {
+        if ( $(this[0]).is('form')) {
+            return this.validate().form();
+        } else {
+            var valid = true;
+            var validator = $(this[0].form).validate();
+            this.each(function() {
+                               valid &= validator.element(this);
+            });
+            return valid;
+        }
+    },
+       // attributes: space seperated list of attributes to retrieve and remove
+       removeAttrs: function(attributes) {
+               var result = {},
+                       $element = this;
+               $.each(attributes.split(/\s/), function(index, value) {
+                       result[value] = $element.attr(value);
+                       $element.removeAttr(value);
+               });
+               return result;
+       },
+       // http://docs.jquery.com/Plugins/Validation/rules
+       rules: function(command, argument) {
+               var element = this[0];
+
+               if (command) {
+                       var settings = $.data(element.form, 'validator').settings;
+                       var staticRules = settings.rules;
+                       var existingRules = $.validator.staticRules(element);
+                       switch(command) {
+                       case "add":
+                               $.extend(existingRules, $.validator.normalizeRule(argument));
+                               staticRules[element.name] = existingRules;
+                               if (argument.messages)
+                                       settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
+                               break;
+                       case "remove":
+                               if (!argument) {
+                                       delete staticRules[element.name];
+                                       return existingRules;
+                               }
+                               var filtered = {};
+                               $.each(argument.split(/\s/), function(index, method) {
+                                       filtered[method] = existingRules[method];
+                                       delete existingRules[method];
+                               });
+                               return filtered;
+                       }
+               }
+
+               var data = $.validator.normalizeRules(
+               $.extend(
+                       {},
+                       $.validator.metadataRules(element),
+                       $.validator.classRules(element),
+                       $.validator.attributeRules(element),
+                       $.validator.staticRules(element)
+               ), element);
+
+               // make sure required is at front
+               if (data.required) {
+                       var param = data.required;
+                       delete data.required;
+                       data = $.extend({required: param}, data);
+               }
+
+               return data;
+       }
+});
+
+// Custom selectors
+$.extend($.expr[":"], {
+       // http://docs.jquery.com/Plugins/Validation/blank
+       blank: function(a) {return !$.trim("" + a.value);},
+       // http://docs.jquery.com/Plugins/Validation/filled
+       filled: function(a) {return !!$.trim("" + a.value);},
+       // http://docs.jquery.com/Plugins/Validation/unchecked
+       unchecked: function(a) {return !a.checked;}
+});
+
+// constructor for validator
+$.validator = function( options, form ) {
+       this.settings = $.extend( true, {}, $.validator.defaults, options );
+       this.currentForm = form;
+       this.init();
+};
+
+$.validator.format = function(source, params) {
+       if ( arguments.length == 1 )
+               return function() {
+                       var args = $.makeArray(arguments);
+                       args.unshift(source);
+                       return $.validator.format.apply( this, args );
+               };
+       if ( arguments.length > 2 && params.constructor != Array  ) {
+               params = $.makeArray(arguments).slice(1);
+       }
+       if ( params.constructor != Array ) {
+               params = [ params ];
+       }
+       $.each(params, function(i, n) {
+               source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
+       });
+       return source;
+};
+
+$.extend($.validator, {
+
+       defaults: {
+               messages: {},
+               groups: {},
+               rules: {},
+               errorClass: "error",
+               validClass: "valid",
+               errorElement: "label",
+               focusInvalid: true,
+               errorContainer: $( [] ),
+               errorLabelContainer: $( [] ),
+               onsubmit: true,
+               ignore: [],
+               ignoreTitle: false,
+               onfocusin: function(element) {
+                       this.lastActive = element;
+
+                       // hide error label and remove error class on focus if enabled
+                       if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
+                               this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
+                               this.addWrapper(this.errorsFor(element)).hide();
+                       }
+               },
+               onfocusout: function(element) {
+                       if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
+                               this.element(element);
+                       }
+               },
+               onkeyup: function(element) {
+                       if ( element.name in this.submitted || element == this.lastElement ) {
+                               this.element(element);
+                       }
+               },
+               onclick: function(element) {
+                       // click on selects, radiobuttons and checkboxes
+                       if ( element.name in this.submitted )
+                               this.element(element);
+                       // or option elements, check parent select in that case
+                       else if (element.parentNode.name in this.submitted)
+                               this.element(element.parentNode);
+               },
+               highlight: function(element, errorClass, validClass) {
+                       if (element.type === 'radio') {
+                               this.findByName(element.name).addClass(errorClass).removeClass(validClass);
+                       } else {
+                               $(element).addClass(errorClass).removeClass(validClass);
+                       }
+               },
+               unhighlight: function(element, errorClass, validClass) {
+                       if (element.type === 'radio') {
+                               this.findByName(element.name).removeClass(errorClass).addClass(validClass);
+                       } else {
+                               $(element).removeClass(errorClass).addClass(validClass);
+                       }
+               }
+       },
+
+       // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
+       setDefaults: function(settings) {
+               $.extend( $.validator.defaults, settings );
+       },
+
+       messages: {
+               required: "This field is required.",
+               remote: "Please fix this field.",
+               email: "Please enter a valid email address.",
+               url: "Please enter a valid URL.",
+               date: "Please enter a valid date.",
+               dateISO: "Please enter a valid date (ISO).",
+               number: "Please enter a valid number.",
+               digits: "Please enter only digits.",
+               creditcard: "Please enter a valid credit card number.",
+               equalTo: "Please enter the same value again.",
+               accept: "Please enter a value with a valid extension.",
+               maxlength: $.validator.format("Please enter no more than {0} characters."),
+               minlength: $.validator.format("Please enter at least {0} characters."),
+               rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
+               range: $.validator.format("Please enter a value between {0} and {1}."),
+               max: $.validator.format("Please enter a value less than or equal to {0}."),
+               min: $.validator.format("Please enter a value greater than or equal to {0}.")
+       },
+
+       autoCreateRanges: false,
+
+       prototype: {
+
+               init: function() {
+                       this.labelContainer = $(this.settings.errorLabelContainer);
+                       this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
+                       this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
+                       this.submitted = {};
+                       this.valueCache = {};
+                       this.pendingRequest = 0;
+                       this.pending = {};
+                       this.invalid = {};
+                       this.reset();
+
+                       var groups = (this.groups = {});
+                       $.each(this.settings.groups, function(key, value) {
+                               $.each(value.split(/\s/), function(index, name) {
+                                       groups[name] = key;
+                               });
+                       });
+                       var rules = this.settings.rules;
+                       $.each(rules, function(key, value) {
+                               rules[key] = $.validator.normalizeRule(value);
+                       });
+
+                       function delegate(event) {
+                               var validator = $.data(this[0].form, "validator"),
+                                       eventType = "on" + event.type.replace(/^validate/, "");
+                               validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
+                       }
+                       $(this.currentForm)
+                               .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
+                               .validateDelegate(":radio, :checkbox, select, option", "click", delegate);
+
+                       if (this.settings.invalidHandler)
+                               $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Validator/form
+               form: function() {
+                       this.checkForm();
+                       $.extend(this.submitted, this.errorMap);
+                       this.invalid = $.extend({}, this.errorMap);
+                       if (!this.valid())
+                               $(this.currentForm).triggerHandler("invalid-form", [this]);
+                       this.showErrors();
+                       return this.valid();
+               },
+
+               checkForm: function() {
+                       this.prepareForm();
+                       for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
+                               this.check( elements[i] );
+                       }
+                       return this.valid();
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Validator/element
+               element: function( element ) {
+                       element = this.clean( element );
+                       this.lastElement = element;
+                       this.prepareElement( element );
+                       this.currentElements = $(element);
+                       var result = this.check( element );
+                       if ( result ) {
+                               delete this.invalid[element.name];
+                       } else {
+                               this.invalid[element.name] = true;
+                       }
+                       if ( !this.numberOfInvalids() ) {
+                               // Hide error containers on last error
+                               this.toHide = this.toHide.add( this.containers );
+                       }
+                       this.showErrors();
+                       return result;
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
+               showErrors: function(errors) {
+                       if(errors) {
+                               // add items to error list and map
+                               $.extend( this.errorMap, errors );
+                               this.errorList = [];
+                               for ( var name in errors ) {
+                                       this.errorList.push({
+                                               message: errors[name],
+                                               element: this.findByName(name)[0]
+                                       });
+                               }
+                               // remove items from success list
+                               this.successList = $.grep( this.successList, function(element) {
+                                       return !(element.name in errors);
+                               });
+                       }
+                       this.settings.showErrors
+                               ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
+                               : this.defaultShowErrors();
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
+               resetForm: function() {
+                       if ( $.fn.resetForm )
+                               $( this.currentForm ).resetForm();
+                       this.submitted = {};
+                       this.prepareForm();
+                       this.hideErrors();
+                       this.elements().removeClass( this.settings.errorClass );
+               },
+
+               numberOfInvalids: function() {
+                       return this.objectLength(this.invalid);
+               },
+
+               objectLength: function( obj ) {
+                       var count = 0;
+                       for ( var i in obj )
+                               count++;
+                       return count;
+               },
+
+               hideErrors: function() {
+                       this.addWrapper( this.toHide ).hide();
+               },
+
+               valid: function() {
+                       return this.size() == 0;
+               },
+
+               size: function() {
+                       return this.errorList.length;
+               },
+
+               focusInvalid: function() {
+                       if( this.settings.focusInvalid ) {
+                               try {
+                                       $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
+                                       .filter(":visible")
+                                       .focus()
+                                       // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
+                                       .trigger("focusin");
+                               } catch(e) {
+                                       // ignore IE throwing errors when focusing hidden elements
+                               }
+                       }
+               },
+
+               findLastActive: function() {
+                       var lastActive = this.lastActive;
+                       return lastActive && $.grep(this.errorList, function(n) {
+                               return n.element.name == lastActive.name;
+                       }).length == 1 && lastActive;
+               },
+
+               elements: function() {
+                       var validator = this,
+                               rulesCache = {};
+
+                       // select all valid inputs inside the form (no submit or reset buttons)
+                       return $(this.currentForm)
+                       .find("input, select, textarea")
+                       .not(":submit, :reset, :image, [disabled]")
+                       .not( this.settings.ignore )
+                       .filter(function() {
+                               !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
+
+                               // select only the first element for each name, and only those with rules specified
+                               if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
+                                       return false;
+
+                               rulesCache[this.name] = true;
+                               return true;
+                       });
+               },
+
+               clean: function( selector ) {
+                       return $( selector )[0];
+               },
+
+               errors: function() {
+                       return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
+               },
+
+               reset: function() {
+                       this.successList = [];
+                       this.errorList = [];
+                       this.errorMap = {};
+                       this.toShow = $([]);
+                       this.toHide = $([]);
+                       this.currentElements = $([]);
+               },
+
+               prepareForm: function() {
+                       this.reset();
+                       this.toHide = this.errors().add( this.containers );
+               },
+
+               prepareElement: function( element ) {
+                       this.reset();
+                       this.toHide = this.errorsFor(element);
+               },
+
+               check: function( element ) {
+                       element = this.clean( element );
+
+                       // if radio/checkbox, validate first element in group instead
+                       if (this.checkable(element)) {
+                               element = this.findByName( element.name ).not(this.settings.ignore)[0];
+                       }
+
+                       var rules = $(element).rules();
+                       var dependencyMismatch = false;
+                       for (var method in rules ) {
+                               var rule = { method: method, parameters: rules[method] };
+                               try {
+                                       var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
+
+                                       // if a method indicates that the field is optional and therefore valid,
+                                       // don't mark it as valid when there are no other rules
+                                       if ( result == "dependency-mismatch" ) {
+                                               dependencyMismatch = true;
+                                               continue;
+                                       }
+                                       dependencyMismatch = false;
+
+                                       if ( result == "pending" ) {
+                                               this.toHide = this.toHide.not( this.errorsFor(element) );
+                                               return;
+                                       }
+
+                                       if( !result ) {
+                                               this.formatAndAdd( element, rule );
+                                               return false;
+                                       }
+                               } catch(e) {
+                                       this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
+                                                + ", check the '" + rule.method + "' method", e);
+                                       throw e;
+                               }
+                       }
+                       if (dependencyMismatch)
+                               return;
+                       if ( this.objectLength(rules) )
+                               this.successList.push(element);
+                       return true;
+               },
+
+               // return the custom message for the given element and validation method
+               // specified in the element's "messages" metadata
+               customMetaMessage: function(element, method) {
+                       if (!$.metadata)
+                               return;
+
+                       var meta = this.settings.meta
+                               ? $(element).metadata()[this.settings.meta]
+                               : $(element).metadata();
+
+                       return meta && meta.messages && meta.messages[method];
+               },
+
+               // return the custom message for the given element name and validation method
+               customMessage: function( name, method ) {
+                       var m = this.settings.messages[name];
+                       return m && (m.constructor == String
+                               ? m
+                               : m[method]);
+               },
+
+               // return the first defined argument, allowing empty strings
+               findDefined: function() {
+                       for(var i = 0; i < arguments.length; i++) {
+                               if (arguments[i] !== undefined)
+                                       return arguments[i];
+                       }
+                       return undefined;
+               },
+
+               defaultMessage: function( element, method) {
+                       return this.findDefined(
+                               this.customMessage( element.name, method ),
+                               this.customMetaMessage( element, method ),
+                               // title is never undefined, so handle empty string as undefined
+                               !this.settings.ignoreTitle && element.title || undefined,
+                               $.validator.messages[method],
+                               "<strong>Warning: No message defined for " + element.name + "</strong>"
+                       );
+               },
+
+               formatAndAdd: function( element, rule ) {
+                       var message = this.defaultMessage( element, rule.method ),
+                               theregex = /\$?\{(\d+)\}/g;
+                       if ( typeof message == "function" ) {
+                               message = message.call(this, rule.parameters, element);
+                       } else if (theregex.test(message)) {
+                               message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
+                       }
+                       this.errorList.push({
+                               message: message,
+                               element: element
+                       });
+
+                       this.errorMap[element.name] = message;
+                       this.submitted[element.name] = message;
+               },
+
+               addWrapper: function(toToggle) {
+                       if ( this.settings.wrapper )
+                               toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
+                       return toToggle;
+               },
+
+               defaultShowErrors: function() {
+                       for ( var i = 0; this.errorList[i]; i++ ) {
+                               var error = this.errorList[i];
+                               this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
+                               this.showLabel( error.element, error.message );
+                       }
+                       if( this.errorList.length ) {
+                               this.toShow = this.toShow.add( this.containers );
+                       }
+                       if (this.settings.success) {
+                               for ( var i = 0; this.successList[i]; i++ ) {
+                                       this.showLabel( this.successList[i] );
+                               }
+                       }
+                       if (this.settings.unhighlight) {
+                               for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
+                                       this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
+                               }
+                       }
+                       this.toHide = this.toHide.not( this.toShow );
+                       this.hideErrors();
+                       this.addWrapper( this.toShow ).show();
+               },
+
+               validElements: function() {
+                       return this.currentElements.not(this.invalidElements());
+               },
+
+               invalidElements: function() {
+                       return $(this.errorList).map(function() {
+                               return this.element;
+                       });
+               },
+
+               showLabel: function(element, message) {
+                       var label = this.errorsFor( element );
+                       if ( label.length ) {
+                               // refresh error/success class
+                               label.removeClass().addClass( this.settings.errorClass );
+
+                               // check if we have a generated label, replace the message then
+                               label.attr("generated") && label.html(message);
+                       } else {
+                               // create label
+                               label = $("<" + this.settings.errorElement + "/>")
+                                       .attr({"for":  this.idOrName(element), generated: true})
+                                       .addClass(this.settings.errorClass)
+                                       .html(message || "");
+                               if ( this.settings.wrapper ) {
+                                       // make sure the element is visible, even in IE
+                                       // actually showing the wrapped element is handled elsewhere
+                                       label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
+                               }
+                               if ( !this.labelContainer.append(label).length )
+                                       this.settings.errorPlacement
+                                               ? this.settings.errorPlacement(label, $(element) )
+                                               : label.insertAfter(element);
+                       }
+                       if ( !message && this.settings.success ) {
+                               label.text("");
+                               typeof this.settings.success == "string"
+                                       ? label.addClass( this.settings.success )
+                                       : this.settings.success( label );
+                       }
+                       this.toShow = this.toShow.add(label);
+               },
+
+               errorsFor: function(element) {
+                       var name = this.idOrName(element);
+               return this.errors().filter(function() {
+                               return $(this).attr('for') == name;
+                       });
+               },
+
+               idOrName: function(element) {
+                       return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
+               },
+
+               checkable: function( element ) {
+                       return /radio|checkbox/i.test(element.type);
+               },
+
+               findByName: function( name ) {
+                       // select by name and filter by form for performance over form.find("[name=...]")
+                       var form = this.currentForm;
+                       return $(document.getElementsByName(name)).map(function(index, element) {
+                               return element.form == form && element.name == name && element  || null;
+                       });
+               },
+
+               getLength: function(value, element) {
+                       switch( element.nodeName.toLowerCase() ) {
+                       case 'select':
+                               return $("option:selected", element).length;
+                       case 'input':
+                               if( this.checkable( element) )
+                                       return this.findByName(element.name).filter(':checked').length;
+                       }
+                       return value.length;
+               },
+
+               depend: function(param, element) {
+                       return this.dependTypes[typeof param]
+                               ? this.dependTypes[typeof param](param, element)
+                               : true;
+               },
+
+               dependTypes: {
+                       "boolean": function(param, element) {
+                               return param;
+                       },
+                       "string": function(param, element) {
+                               return !!$(param, element.form).length;
+                       },
+                       "function": function(param, element) {
+                               return param(element);
+                       }
+               },
+
+               optional: function(element) {
+                       return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
+               },
+
+               startRequest: function(element) {
+                       if (!this.pending[element.name]) {
+                               this.pendingRequest++;
+                               this.pending[element.name] = true;
+                       }
+               },
+
+               stopRequest: function(element, valid) {
+                       this.pendingRequest--;
+                       // sometimes synchronization fails, make sure pendingRequest is never < 0
+                       if (this.pendingRequest < 0)
+                               this.pendingRequest = 0;
+                       delete this.pending[element.name];
+                       if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
+                               $(this.currentForm).submit();
+                               this.formSubmitted = false;
+                       } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
+                               $(this.currentForm).triggerHandler("invalid-form", [this]);
+                               this.formSubmitted = false;
+                       }
+               },
+
+               previousValue: function(element) {
+                       return $.data(element, "previousValue") || $.data(element, "previousValue", {
+                               old: null,
+                               valid: true,
+                               message: this.defaultMessage( element, "remote" )
+                       });
+               }
+
+       },
+
+       classRuleSettings: {
+               required: {required: true},
+               email: {email: true},
+               url: {url: true},
+               date: {date: true},
+               dateISO: {dateISO: true},
+               dateDE: {dateDE: true},
+               number: {number: true},
+               numberDE: {numberDE: true},
+               digits: {digits: true},
+               creditcard: {creditcard: true}
+       },
+
+       addClassRules: function(className, rules) {
+               className.constructor == String ?
+                       this.classRuleSettings[className] = rules :
+                       $.extend(this.classRuleSettings, className);
+       },
+
+       classRules: function(element) {
+               var rules = {};
+               var classes = $(element).attr('class');
+               classes && $.each(classes.split(' '), function() {
+                       if (this in $.validator.classRuleSettings) {
+                               $.extend(rules, $.validator.classRuleSettings[this]);
+                       }
+               });
+               return rules;
+       },
+
+       attributeRules: function(element) {
+               var rules = {};
+               var $element = $(element);
+
+               for (var method in $.validator.methods) {
+                       var value = $element.attr(method);
+                       if (value) {
+                               rules[method] = value;
+                       }
+               }
+
+               // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
+               if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
+                       delete rules.maxlength;
+               }
+
+               return rules;
+       },
+
+       metadataRules: function(element) {
+               if (!$.metadata) return {};
+
+               var meta = $.data(element.form, 'validator').settings.meta;
+               return meta ?
+                       $(element).metadata()[meta] :
+                       $(element).metadata();
+       },
+
+       staticRules: function(element) {
+               var rules = {};
+               var validator = $.data(element.form, 'validator');
+               if (validator.settings.rules) {
+                       rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
+               }
+               return rules;
+       },
+
+       normalizeRules: function(rules, element) {
+               // handle dependency check
+               $.each(rules, function(prop, val) {
+                       // ignore rule when param is explicitly false, eg. required:false
+                       if (val === false) {
+                               delete rules[prop];
+                               return;
+                       }
+                       if (val.param || val.depends) {
+                               var keepRule = true;
+                               switch (typeof val.depends) {
+                                       case "string":
+                                               keepRule = !!$(val.depends, element.form).length;
+                                               break;
+                                       case "function":
+                                               keepRule = val.depends.call(element, element);
+                                               break;
+                               }
+                               if (keepRule) {
+                                       rules[prop] = val.param !== undefined ? val.param : true;
+                               } else {
+                                       delete rules[prop];
+                               }
+                       }
+               });
+
+               // evaluate parameters
+               $.each(rules, function(rule, parameter) {
+                       rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
+               });
+
+               // clean number parameters
+               $.each(['minlength', 'maxlength', 'min', 'max'], function() {
+                       if (rules[this]) {
+                               rules[this] = Number(rules[this]);
+                       }
+               });
+               $.each(['rangelength', 'range'], function() {
+                       if (rules[this]) {
+                               rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
+                       }
+               });
+
+               if ($.validator.autoCreateRanges) {
+                       // auto-create ranges
+                       if (rules.min && rules.max) {
+                               rules.range = [rules.min, rules.max];
+                               delete rules.min;
+                               delete rules.max;
+                       }
+                       if (rules.minlength && rules.maxlength) {
+                               rules.rangelength = [rules.minlength, rules.maxlength];
+                               delete rules.minlength;
+                               delete rules.maxlength;
+                       }
+               }
+
+               // To support custom messages in metadata ignore rule methods titled "messages"
+               if (rules.messages) {
+                       delete rules.messages;
+               }
+
+               return rules;
+       },
+
+       // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
+       normalizeRule: function(data) {
+               if( typeof data == "string" ) {
+                       var transformed = {};
+                       $.each(data.split(/\s/), function() {
+                               transformed[this] = true;
+                       });
+                       data = transformed;
+               }
+               return data;
+       },
+
+       // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
+       addMethod: function(name, method, message) {
+               $.validator.methods[name] = method;
+               $.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
+               if (method.length < 3) {
+                       $.validator.addClassRules(name, $.validator.normalizeRule(name));
+               }
+       },
+
+       methods: {
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/required
+               required: function(value, element, param) {
+                       // check if dependency is met
+                       if ( !this.depend(param, element) )
+                               return "dependency-mismatch";
+                       switch( element.nodeName.toLowerCase() ) {
+                       case 'select':
+                               // could be an array for select-multiple or a string, both are fine this way
+                               var val = $(element).val();
+                               return val && val.length > 0;
+                       case 'input':
+                               if ( this.checkable(element) )
+                                       return this.getLength(value, element) > 0;
+                       default:
+                               return $.trim(value).length > 0;
+                       }
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/remote
+               remote: function(value, element, param) {
+                       if ( this.optional(element) )
+                               return "dependency-mismatch";
+
+                       var previous = this.previousValue(element);
+                       if (!this.settings.messages[element.name] )
+                               this.settings.messages[element.name] = {};
+                       previous.originalMessage = this.settings.messages[element.name].remote;
+                       this.settings.messages[element.name].remote = previous.message;
+
+                       param = typeof param == "string" && {url:param} || param;
+
+                       if ( this.pending[element.name] ) {
+                               return "pending";
+                       }
+                       if ( previous.old === value ) {
+                               return previous.valid;
+                       }
+
+                       previous.old = value;
+                       var validator = this;
+                       this.startRequest(element);
+                       var data = {};
+                       data[element.name] = value;
+                       $.ajax($.extend(true, {
+                               url: param,
+                               mode: "abort",
+                               port: "validate" + element.name,
+                               dataType: "json",
+                               data: data,
+                               success: function(response) {
+                                       validator.settings.messages[element.name].remote = previous.originalMessage;
+                                       var valid = response === true;
+                                       if ( valid ) {
+                                               var submitted = validator.formSubmitted;
+                                               validator.prepareElement(element);
+                                               validator.formSubmitted = submitted;
+                                               validator.successList.push(element);
+                                               validator.showErrors();
+                                       } else {
+                                               var errors = {};
+                                               var message = response || validator.defaultMessage( element, "remote" );
+                                               errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
+                                               validator.showErrors(errors);
+                                       }
+                                       previous.valid = valid;
+                                       validator.stopRequest(element, valid);
+                               }
+                       }, param));
+                       return "pending";
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/minlength
+               minlength: function(value, element, param) {
+                       return this.optional(element) || this.getLength($.trim(value), element) >= param;
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
+               maxlength: function(value, element, param) {
+                       return this.optional(element) || this.getLength($.trim(value), element) <= param;
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
+               rangelength: function(value, element, param) {
+                       var length = this.getLength($.trim(value), element);
+                       return this.optional(element) || ( length >= param[0] && length <= param[1] );
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/min
+               min: function( value, element, param ) {
+                       return this.optional(element) || value >= param;
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/max
+               max: function( value, element, param ) {
+                       return this.optional(element) || value <= param;
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/range
+               range: function( value, element, param ) {
+                       return this.optional(element) || ( value >= param[0] && value <= param[1] );
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/email
+               email: function(value, element) {
+                       // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
+                       return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/url
+               url: function(value, element) {
+                       // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
+                       return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/date
+               date: function(value, element) {
+                       return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
+               dateISO: function(value, element) {
+                       return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/number
+               number: function(value, element) {
+                       return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/digits
+               digits: function(value, element) {
+                       return this.optional(element) || /^\d+$/.test(value);
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
+               // based on http://en.wikipedia.org/wiki/Luhn
+               creditcard: function(value, element) {
+                       if ( this.optional(element) )
+                               return "dependency-mismatch";
+                       // accept only digits and dashes
+                       if (/[^0-9-]+/.test(value))
+                               return false;
+                       var nCheck = 0,
+                               nDigit = 0,
+                               bEven = false;
+
+                       value = value.replace(/\D/g, "");
+
+                       for (var n = value.length - 1; n >= 0; n--) {
+                               var cDigit = value.charAt(n);
+                               var nDigit = parseInt(cDigit, 10);
+                               if (bEven) {
+                                       if ((nDigit *= 2) > 9)
+                                               nDigit -= 9;
+                               }
+                               nCheck += nDigit;
+                               bEven = !bEven;
+                       }
+
+                       return (nCheck % 10) == 0;
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/accept
+               accept: function(value, element, param) {
+                       param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
+                       return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
+               },
+
+               // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
+               equalTo: function(value, element, param) {
+                       // bind to the blur event of the target in order to revalidate whenever the target field is updated
+                       // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
+                       var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
+                               $(element).valid();
+                       });
+                       return value == target.val();
+               }
+
+       }
+
+});
+
+// deprecated, use $.validator.format instead
+$.format = $.validator.format;
+
+})(jQuery);
+
+// ajax mode: abort
+// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
+// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
+;(function($) {
+       var pendingRequests = {};
+       // Use a prefilter if available (1.5+)
+       if ( $.ajaxPrefilter ) {
+               $.ajaxPrefilter(function(settings, _, xhr) {
+                       var port = settings.port;
+                       if (settings.mode == "abort") {
+                               if ( pendingRequests[port] ) {
+                                       pendingRequests[port].abort();
+                               }
+                               pendingRequests[port] = xhr;
+                       }
+               });
+       } else {
+               // Proxy ajax
+               var ajax = $.ajax;
+               $.ajax = function(settings) {
+                       var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
+                               port = ( "port" in settings ? settings : $.ajaxSettings ).port;
+                       if (mode == "abort") {
+                               if ( pendingRequests[port] ) {
+                                       pendingRequests[port].abort();
+                               }
+                               return (pendingRequests[port] = ajax.apply(this, arguments));
+                       }
+                       return ajax.apply(this, arguments);
+               };
+       }
+})(jQuery);
+
+// provides cross-browser focusin and focusout events
+// IE has native support, in other browsers, use event caputuring (neither bubbles)
+
+// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
+// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
+;(function($) {
+       // only implement if not provided by jQuery core (since 1.4)
+       // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
+       if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
+               $.each({
+                       focus: 'focusin',
+                       blur: 'focusout'
+               }, function( original, fix ){
+                       $.event.special[fix] = {
+                               setup:function() {
+                                       this.addEventListener( original, handler, true );
+                               },
+                               teardown:function() {
+                                       this.removeEventListener( original, handler, true );
+                               },
+                               handler: function(e) {
+                                       arguments[0] = $.event.fix(e);
+                                       arguments[0].type = fix;
+                                       return $.event.handle.apply(this, arguments);
+                               }
+                       };
+                       function handler(e) {
+                               e = $.event.fix(e);
+                               e.type = fix;
+                               return $.event.handle.call(this, e);
+                       }
+               });
+       };
+       $.extend($.fn, {
+               validateDelegate: function(delegate, type, handler) {
+                       return this.bind(type, function(event) {
+                               var target = $(event.target);
+                               if (target.is(delegate)) {
+                                       return handler.apply(target, arguments);
+                               }
+                       });
+               }
+       });
+})(jQuery);
diff --git a/resources/lib/jquery/jquery.xmldom.js b/resources/lib/jquery/jquery.xmldom.js
new file mode 100644 (file)
index 0000000..85d0083
--- /dev/null
@@ -0,0 +1,46 @@
+/*!
+ * jQuery xmlDOM Plugin v1.0
+ * http://outwestmedia.com/jquery-plugins/xmldom/
+ *
+ * Released: 2009-04-06
+ * Version: 1.0
+ *
+ * Copyright (c) 2009 Jonathan Sharp, Out West Media LLC.
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ */
+(function($) {
+       // IE DOMParser wrapper
+       if ( window['DOMParser'] == undefined && window.ActiveXObject ) {
+               DOMParser = function() { };
+               DOMParser.prototype.parseFromString = function( xmlString ) {
+                       var doc = new ActiveXObject('Microsoft.XMLDOM');
+               doc.async = 'false';
+               doc.loadXML( xmlString );
+                       return doc;
+               };
+       }
+       
+       $.xmlDOM = function(xml, onErrorFn) {
+               try {
+                       var xmlDoc      = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
+                       if ( $.isXMLDoc( xmlDoc ) ) {
+                               var err = $('parsererror', xmlDoc);
+                               if ( err.length == 1 ) {
+                                       throw('Error: ' + $(xmlDoc).text() );
+                               }
+                       } else {
+                               throw('Unable to parse XML');
+                       }
+               } catch( e ) {
+                       var msg = ( e.name == undefined ? e : e.name + ': ' + e.message );
+                       if ( $.isFunction( onErrorFn ) ) {
+                               onErrorFn( msg );
+                       } else {
+                               $(document).trigger('xmlParseError', [ msg ]);
+                       }
+                       return $([]);
+               }
+               return $( xmlDoc );
+       };
+})(jQuery);
\ No newline at end of file
diff --git a/resources/lib/moment/LICENSE b/resources/lib/moment/LICENSE
new file mode 100644 (file)
index 0000000..b44e3a6
--- /dev/null
@@ -0,0 +1,22 @@
+Copyright (c) 2011-2013 Tim Wood, Iskren Chernev, Moment.js contributors
+
+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/resources/lib/moment/lang/ar-ma.js b/resources/lib/moment/lang/ar-ma.js
new file mode 100644 (file)
index 0000000..1c159f1
--- /dev/null
@@ -0,0 +1,56 @@
+// moment.js language configuration
+// language : Moroccan Arabic (ar-ma)
+// author : ElFadili Yassine : https://github.com/ElFadiliY
+// author : Abdel Said : https://github.com/abdelsaid
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('ar-ma', {
+        months : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),
+        monthsShort : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),
+        weekdays : "الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
+        weekdaysShort : "احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),
+        weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: "[اليوم على الساعة] LT",
+            nextDay: '[غدا على الساعة] LT',
+            nextWeek: 'dddd [على الساعة] LT',
+            lastDay: '[أمس على الساعة] LT',
+            lastWeek: 'dddd [على الساعة] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "في %s",
+            past : "منذ %s",
+            s : "ثوان",
+            m : "دقيقة",
+            mm : "%d دقائق",
+            h : "ساعة",
+            hh : "%d ساعات",
+            d : "يوم",
+            dd : "%d أيام",
+            M : "شهر",
+            MM : "%d أشهر",
+            y : "سنة",
+            yy : "%d سنوات"
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/ar.js b/resources/lib/moment/lang/ar.js
new file mode 100644 (file)
index 0000000..6e27d29
--- /dev/null
@@ -0,0 +1,56 @@
+// moment.js language configuration
+// language : Arabic (ar)
+// author : Abdel Said : https://github.com/abdelsaid
+// changes in months, weekdays : Ahmed Elkhatib
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('ar', {
+        months : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"),
+        monthsShort : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"),
+        weekdays : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
+        weekdaysShort : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
+        weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: "[اليوم على الساعة] LT",
+            nextDay: '[غدا على الساعة] LT',
+            nextWeek: 'dddd [على الساعة] LT',
+            lastDay: '[أمس على الساعة] LT',
+            lastWeek: 'dddd [على الساعة] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "في %s",
+            past : "منذ %s",
+            s : "ثوان",
+            m : "دقيقة",
+            mm : "%d دقائق",
+            h : "ساعة",
+            hh : "%d ساعات",
+            d : "يوم",
+            dd : "%d أيام",
+            M : "شهر",
+            MM : "%d أشهر",
+            y : "سنة",
+            yy : "%d سنوات"
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/bg.js b/resources/lib/moment/lang/bg.js
new file mode 100644 (file)
index 0000000..f47ed65
--- /dev/null
@@ -0,0 +1,86 @@
+// moment.js language configuration
+// language : bulgarian (bg)
+// author : Krasen Borisov : https://github.com/kraz
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('bg', {
+        months : "януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),
+        monthsShort : "янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),
+        weekdays : "неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),
+        weekdaysShort : "нед_пон_вто_сря_чет_пет_съб".split("_"),
+        weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "D.MM.YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd, D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay : '[Днес в] LT',
+            nextDay : '[Утре в] LT',
+            nextWeek : 'dddd [в] LT',
+            lastDay : '[Вчера в] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[В изминалата] dddd [в] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[В изминалия] dddd [в] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "след %s",
+            past : "преди %s",
+            s : "няколко секунди",
+            m : "минута",
+            mm : "%d минути",
+            h : "час",
+            hh : "%d часа",
+            d : "ден",
+            dd : "%d дни",
+            M : "месец",
+            MM : "%d месеца",
+            y : "година",
+            yy : "%d години"
+        },
+        ordinal : function (number) {
+            var lastDigit = number % 10,
+                last2Digits = number % 100;
+            if (number === 0) {
+                return number + '-ев';
+            } else if (last2Digits === 0) {
+                return number + '-ен';
+            } else if (last2Digits > 10 && last2Digits < 20) {
+                return number + '-ти';
+            } else if (lastDigit === 1) {
+                return number + '-ви';
+            } else if (lastDigit === 2) {
+                return number + '-ри';
+            } else if (lastDigit === 7 || lastDigit === 8) {
+                return number + '-ми';
+            } else {
+                return number + '-ти';
+            }
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/br.js b/resources/lib/moment/lang/br.js
new file mode 100644 (file)
index 0000000..39c60df
--- /dev/null
@@ -0,0 +1,107 @@
+// moment.js language configuration
+// language : breton (br)
+// author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function relativeTimeWithMutation(number, withoutSuffix, key) {
+        var format = {
+            'mm': "munutenn",
+            'MM': "miz",
+            'dd': "devezh"
+        };
+        return number + ' ' + mutation(format[key], number);
+    }
+
+    function specialMutationForYears(number) {
+        switch (lastNumber(number)) {
+        case 1:
+        case 3:
+        case 4:
+        case 5:
+        case 9:
+            return number + ' bloaz';
+        default:
+            return number + ' vloaz';
+        }
+    }
+
+    function lastNumber(number) {
+        if (number > 9) {
+            return lastNumber(number % 10);
+        }
+        return number;
+    }
+
+    function mutation(text, number) {
+        if (number === 2) {
+            return softMutation(text);
+        }
+        return text;
+    }
+
+    function softMutation(text) {
+        var mutationTable = {
+            'm': 'v',
+            'b': 'v',
+            'd': 'z'
+        };
+        if (mutationTable[text.charAt(0)] === undefined) {
+            return text;
+        }
+        return mutationTable[text.charAt(0)] + text.substring(1);
+    }
+
+    return moment.lang('br', {
+        months : "Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),
+        monthsShort : "Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),
+        weekdays : "Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"),
+        weekdaysShort : "Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),
+        weekdaysMin : "Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),
+        longDateFormat : {
+            LT : "h[e]mm A",
+            L : "DD/MM/YYYY",
+            LL : "D [a viz] MMMM YYYY",
+            LLL : "D [a viz] MMMM YYYY LT",
+            LLLL : "dddd, D [a viz] MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay : '[Hiziv da] LT',
+            nextDay : '[Warc\'hoazh da] LT',
+            nextWeek : 'dddd [da] LT',
+            lastDay : '[Dec\'h da] LT',
+            lastWeek : 'dddd [paset da] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "a-benn %s",
+            past : "%s 'zo",
+            s : "un nebeud segondennoù",
+            m : "ur vunutenn",
+            mm : relativeTimeWithMutation,
+            h : "un eur",
+            hh : "%d eur",
+            d : "un devezh",
+            dd : relativeTimeWithMutation,
+            M : "ur miz",
+            MM : relativeTimeWithMutation,
+            y : "ur bloaz",
+            yy : specialMutationForYears
+        },
+        ordinal : function (number) {
+            var output = (number === 1) ? 'añ' : 'vet';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/bs.js b/resources/lib/moment/lang/bs.js
new file mode 100644 (file)
index 0000000..83a9b4c
--- /dev/null
@@ -0,0 +1,139 @@
+// moment.js language configuration
+// language : bosnian (bs)
+// author : Nedim Cholich : https://github.com/frontyard
+// based on (hr) translation by Bojan Marković
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+
+    function translate(number, withoutSuffix, key) {
+        var result = number + " ";
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+        case 'mm':
+            if (number === 1) {
+                result += 'minuta';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'minute';
+            } else {
+                result += 'minuta';
+            }
+            return result;
+        case 'h':
+            return withoutSuffix ? 'jedan sat' : 'jednog sata';
+        case 'hh':
+            if (number === 1) {
+                result += 'sat';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'sata';
+            } else {
+                result += 'sati';
+            }
+            return result;
+        case 'dd':
+            if (number === 1) {
+                result += 'dan';
+            } else {
+                result += 'dana';
+            }
+            return result;
+        case 'MM':
+            if (number === 1) {
+                result += 'mjesec';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'mjeseca';
+            } else {
+                result += 'mjeseci';
+            }
+            return result;
+        case 'yy':
+            if (number === 1) {
+                result += 'godina';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'godine';
+            } else {
+                result += 'godina';
+            }
+            return result;
+        }
+    }
+
+    return moment.lang('bs', {
+               months : "januar_februar_mart_april_maj_juni_juli_avgust_septembar_oktobar_novembar_decembar".split("_"),
+               monthsShort : "jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),
+        weekdays : "nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),
+        weekdaysShort : "ned._pon._uto._sri._čet._pet._sub.".split("_"),
+        weekdaysMin : "ne_po_ut_sr_če_pe_su".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "DD. MM. YYYY",
+            LL : "D. MMMM YYYY",
+            LLL : "D. MMMM YYYY LT",
+            LLLL : "dddd, D. MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay  : '[danas u] LT',
+            nextDay  : '[sutra u] LT',
+
+            nextWeek : function () {
+                switch (this.day()) {
+                case 0:
+                    return '[u] [nedjelju] [u] LT';
+                case 3:
+                    return '[u] [srijedu] [u] LT';
+                case 6:
+                    return '[u] [subotu] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[u] dddd [u] LT';
+                }
+            },
+            lastDay  : '[jučer u] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                    return '[prošlu] dddd [u] LT';
+                case 6:
+                    return '[prošle] [subote] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[prošli] dddd [u] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "za %s",
+            past   : "prije %s",
+            s      : "par sekundi",
+            m      : translate,
+            mm     : translate,
+            h      : translate,
+            hh     : translate,
+            d      : "dan",
+            dd     : translate,
+            M      : "mjesec",
+            MM     : translate,
+            y      : "godinu",
+            yy     : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/ca.js b/resources/lib/moment/lang/ca.js
new file mode 100644 (file)
index 0000000..cf47113
--- /dev/null
@@ -0,0 +1,66 @@
+// moment.js language configuration
+// language : catalan (ca)
+// author : Juan G. Hurtado : https://github.com/juanghurtado
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('ca', {
+        months : "gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),
+        monthsShort : "gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.".split("_"),
+        weekdays : "diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),
+        weekdaysShort : "dg._dl._dt._dc._dj._dv._ds.".split("_"),
+        weekdaysMin : "Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay : function () {
+                return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            nextDay : function () {
+                return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            nextWeek : function () {
+                return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            lastDay : function () {
+                return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            lastWeek : function () {
+                return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "en %s",
+            past : "fa %s",
+            s : "uns segons",
+            m : "un minut",
+            mm : "%d minuts",
+            h : "una hora",
+            hh : "%d hores",
+            d : "un dia",
+            dd : "%d dies",
+            M : "un mes",
+            MM : "%d mesos",
+            y : "un any",
+            yy : "%d anys"
+        },
+        ordinal : '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/cs.js b/resources/lib/moment/lang/cs.js
new file mode 100644 (file)
index 0000000..c1396cf
--- /dev/null
@@ -0,0 +1,155 @@
+// moment.js language configuration
+// language : czech (cs)
+// author : petrbela : https://github.com/petrbela
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var months = "leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),
+        monthsShort = "led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_");
+
+    function plural(n) {
+        return (n > 1) && (n < 5) && (~~(n / 10) !== 1);
+    }
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var result = number + " ";
+        switch (key) {
+        case 's':  // a few seconds / in a few seconds / a few seconds ago
+            return (withoutSuffix || isFuture) ? 'pár vteřin' : 'pár vteřinami';
+        case 'm':  // a minute / in a minute / a minute ago
+            return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou');
+        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'minuty' : 'minut');
+            } else {
+                return result + 'minutami';
+            }
+            break;
+        case 'h':  // an hour / in an hour / an hour ago
+            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
+        case 'hh': // 9 hours / in 9 hours / 9 hours ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'hodiny' : 'hodin');
+            } else {
+                return result + 'hodinami';
+            }
+            break;
+        case 'd':  // a day / in a day / a day ago
+            return (withoutSuffix || isFuture) ? 'den' : 'dnem';
+        case 'dd': // 9 days / in 9 days / 9 days ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'dny' : 'dní');
+            } else {
+                return result + 'dny';
+            }
+            break;
+        case 'M':  // a month / in a month / a month ago
+            return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem';
+        case 'MM': // 9 months / in 9 months / 9 months ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'měsíce' : 'měsíců');
+            } else {
+                return result + 'měsíci';
+            }
+            break;
+        case 'y':  // a year / in a year / a year ago
+            return (withoutSuffix || isFuture) ? 'rok' : 'rokem';
+        case 'yy': // 9 years / in 9 years / 9 years ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'roky' : 'let');
+            } else {
+                return result + 'lety';
+            }
+            break;
+        }
+    }
+
+    return moment.lang('cs', {
+        months : months,
+        monthsShort : monthsShort,
+        monthsParse : (function (months, monthsShort) {
+            var i, _monthsParse = [];
+            for (i = 0; i < 12; i++) {
+                // use custom parser to solve problem with July (červenec)
+                _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
+            }
+            return _monthsParse;
+        }(months, monthsShort)),
+        weekdays : "neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),
+        weekdaysShort : "ne_po_út_st_čt_pá_so".split("_"),
+        weekdaysMin : "ne_po_út_st_čt_pá_so".split("_"),
+        longDateFormat : {
+            LT: "H:mm",
+            L : "DD.MM.YYYY",
+            LL : "D. MMMM YYYY",
+            LLL : "D. MMMM YYYY LT",
+            LLLL : "dddd D. MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: "[dnes v] LT",
+            nextDay: '[zítra v] LT',
+            nextWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[v neděli v] LT';
+                case 1:
+                case 2:
+                    return '[v] dddd [v] LT';
+                case 3:
+                    return '[ve středu v] LT';
+                case 4:
+                    return '[ve čtvrtek v] LT';
+                case 5:
+                    return '[v pátek v] LT';
+                case 6:
+                    return '[v sobotu v] LT';
+                }
+            },
+            lastDay: '[včera v] LT',
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[minulou neděli v] LT';
+                case 1:
+                case 2:
+                    return '[minulé] dddd [v] LT';
+                case 3:
+                    return '[minulou středu v] LT';
+                case 4:
+                case 5:
+                    return '[minulý] dddd [v] LT';
+                case 6:
+                    return '[minulou sobotu v] LT';
+                }
+            },
+            sameElse: "L"
+        },
+        relativeTime : {
+            future : "za %s",
+            past : "před %s",
+            s : translate,
+            m : translate,
+            mm : translate,
+            h : translate,
+            hh : translate,
+            d : translate,
+            dd : translate,
+            M : translate,
+            MM : translate,
+            y : translate,
+            yy : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/cv.js b/resources/lib/moment/lang/cv.js
new file mode 100644 (file)
index 0000000..a5812de
--- /dev/null
@@ -0,0 +1,59 @@
+// moment.js language configuration
+// language : chuvash (cv)
+// author : Anatoly Mironov : https://github.com/mirontoli
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('cv', {
+        months : "кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"),
+        monthsShort : "кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"),
+        weekdays : "вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"),
+        weekdaysShort : "выр_тун_ытл_юн_кĕç_эрн_шăм".split("_"),
+        weekdaysMin : "вр_тн_ыт_юн_кç_эр_шм".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD-MM-YYYY",
+            LL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ]",
+            LLL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT",
+            LLLL : "dddd, YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT"
+        },
+        calendar : {
+            sameDay: '[Паян] LT [сехетре]',
+            nextDay: '[Ыран] LT [сехетре]',
+            lastDay: '[Ĕнер] LT [сехетре]',
+            nextWeek: '[Çитес] dddd LT [сехетре]',
+            lastWeek: '[Иртнĕ] dddd LT [сехетре]',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : function (output) {
+                var affix = /сехет$/i.exec(output) ? "рен" : /çул$/i.exec(output) ? "тан" : "ран";
+                return output + affix;
+            },
+            past : "%s каялла",
+            s : "пĕр-ик çеккунт",
+            m : "пĕр минут",
+            mm : "%d минут",
+            h : "пĕр сехет",
+            hh : "%d сехет",
+            d : "пĕр кун",
+            dd : "%d кун",
+            M : "пĕр уйăх",
+            MM : "%d уйăх",
+            y : "пĕр çул",
+            yy : "%d çул"
+        },
+        ordinal : '%d-мĕш',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/cy.js b/resources/lib/moment/lang/cy.js
new file mode 100644 (file)
index 0000000..b47d7c2
--- /dev/null
@@ -0,0 +1,77 @@
+// moment.js language configuration
+// language : Welsh (cy)
+// author : Robert Allen
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang("cy", {
+        months: "Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),
+        monthsShort: "Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),
+        weekdays: "Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),
+        weekdaysShort: "Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),
+        weekdaysMin: "Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),
+        // time formats are the same as en-gb
+        longDateFormat: {
+            LT: "HH:mm",
+            L: "DD/MM/YYYY",
+            LL: "D MMMM YYYY",
+            LLL: "D MMMM YYYY LT",
+            LLLL: "dddd, D MMMM YYYY LT"
+        },
+        calendar: {
+            sameDay: '[Heddiw am] LT',
+            nextDay: '[Yfory am] LT',
+            nextWeek: 'dddd [am] LT',
+            lastDay: '[Ddoe am] LT',
+            lastWeek: 'dddd [diwethaf am] LT',
+            sameElse: 'L'
+        },
+        relativeTime: {
+            future: "mewn %s",
+            past: "%s yn àl",
+            s: "ychydig eiliadau",
+            m: "munud",
+            mm: "%d munud",
+            h: "awr",
+            hh: "%d awr",
+            d: "diwrnod",
+            dd: "%d diwrnod",
+            M: "mis",
+            MM: "%d mis",
+            y: "blwyddyn",
+            yy: "%d flynedd"
+        },
+        // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
+        ordinal: function (number) {
+            var b = number,
+                output = '',
+                lookup = [
+                    '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
+                    'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed
+                ];
+
+            if (b > 20) {
+                if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
+                    output = 'fed'; // not 30ain, 70ain or 90ain
+                } else {
+                    output = 'ain';
+                }
+            } else if (b > 0) {
+                output = lookup[b];
+            }
+
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/da.js b/resources/lib/moment/lang/da.js
new file mode 100644 (file)
index 0000000..2fa8244
--- /dev/null
@@ -0,0 +1,56 @@
+// moment.js language configuration
+// language : danish (da)
+// author : Ulrik Nielsen : https://github.com/mrbase
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('da', {
+        months : "januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),
+        monthsShort : "jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),
+        weekdays : "søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),
+        weekdaysShort : "søn_man_tir_ons_tor_fre_lør".split("_"),
+        weekdaysMin : "sø_ma_ti_on_to_fr_lø".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D. MMMM, YYYY LT"
+        },
+        calendar : {
+            sameDay : '[I dag kl.] LT',
+            nextDay : '[I morgen kl.] LT',
+            nextWeek : 'dddd [kl.] LT',
+            lastDay : '[I går kl.] LT',
+            lastWeek : '[sidste] dddd [kl] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "om %s",
+            past : "%s siden",
+            s : "få sekunder",
+            m : "et minut",
+            mm : "%d minutter",
+            h : "en time",
+            hh : "%d timer",
+            d : "en dag",
+            dd : "%d dage",
+            M : "en måned",
+            MM : "%d måneder",
+            y : "et år",
+            yy : "%d år"
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/de.js b/resources/lib/moment/lang/de.js
new file mode 100644 (file)
index 0000000..988f328
--- /dev/null
@@ -0,0 +1,71 @@
+// moment.js language configuration
+// language : german (de)
+// author : lluchs : https://github.com/lluchs
+// author: Menelion Elensúle: https://github.com/Oire
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            'm': ['eine Minute', 'einer Minute'],
+            'h': ['eine Stunde', 'einer Stunde'],
+            'd': ['ein Tag', 'einem Tag'],
+            'dd': [number + ' Tage', number + ' Tagen'],
+            'M': ['ein Monat', 'einem Monat'],
+            'MM': [number + ' Monate', number + ' Monaten'],
+            'y': ['ein Jahr', 'einem Jahr'],
+            'yy': [number + ' Jahre', number + ' Jahren']
+        };
+        return withoutSuffix ? format[key][0] : format[key][1];
+    }
+
+    return moment.lang('de', {
+        months : "Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),
+        monthsShort : "Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),
+        weekdays : "Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),
+        weekdaysShort : "So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),
+        weekdaysMin : "So_Mo_Di_Mi_Do_Fr_Sa".split("_"),
+        longDateFormat : {
+            LT: "H:mm [Uhr]",
+            L : "DD.MM.YYYY",
+            LL : "D. MMMM YYYY",
+            LLL : "D. MMMM YYYY LT",
+            LLLL : "dddd, D. MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: "[Heute um] LT",
+            sameElse: "L",
+            nextDay: '[Morgen um] LT',
+            nextWeek: 'dddd [um] LT',
+            lastDay: '[Gestern um] LT',
+            lastWeek: '[letzten] dddd [um] LT'
+        },
+        relativeTime : {
+            future : "in %s",
+            past : "vor %s",
+            s : "ein paar Sekunden",
+            m : processRelativeTime,
+            mm : "%d Minuten",
+            h : processRelativeTime,
+            hh : "%d Stunden",
+            d : processRelativeTime,
+            dd : processRelativeTime,
+            M : processRelativeTime,
+            MM : processRelativeTime,
+            y : processRelativeTime,
+            yy : processRelativeTime
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/el.js b/resources/lib/moment/lang/el.js
new file mode 100644 (file)
index 0000000..9dfea23
--- /dev/null
@@ -0,0 +1,79 @@
+// moment.js language configuration
+// language : modern greek (el)
+// author : Aggelos Karalias : https://github.com/mehiel
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('el', {
+        monthsNominativeEl : "Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),
+        monthsGenitiveEl : "Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),
+        months : function (momentToFormat, format) {
+            if (/D/.test(format.substring(0, format.indexOf("MMMM")))) { // if there is a day number before 'MMMM'
+                return this._monthsGenitiveEl[momentToFormat.month()];
+            } else {
+                return this._monthsNominativeEl[momentToFormat.month()];
+            }
+        },
+        monthsShort : "Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),
+        weekdays : "Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),
+        weekdaysShort : "Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),
+        weekdaysMin : "Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),
+        meridiem : function (hours, minutes, isLower) {
+            if (hours > 11) {
+                return isLower ? 'μμ' : 'ΜΜ';
+            } else {
+                return isLower ? 'πμ' : 'ΠΜ';
+            }
+        },
+        longDateFormat : {
+            LT : "h:mm A",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd, D MMMM YYYY LT"
+        },
+        calendarEl : {
+            sameDay : '[Σήμερα {}] LT',
+            nextDay : '[Αύριο {}] LT',
+            nextWeek : 'dddd [{}] LT',
+            lastDay : '[Χθες {}] LT',
+            lastWeek : '[την προηγούμενη] dddd [{}] LT',
+            sameElse : 'L'
+        },
+        calendar : function (key, mom) {
+            var output = this._calendarEl[key],
+                hours = mom && mom.hours();
+
+            return output.replace("{}", (hours % 12 === 1 ? "στη" : "στις"));
+        },
+        relativeTime : {
+            future : "σε %s",
+            past : "%s πριν",
+            s : "δευτερόλεπτα",
+            m : "ένα λεπτό",
+            mm : "%d λεπτά",
+            h : "μία ώρα",
+            hh : "%d ώρες",
+            d : "μία μέρα",
+            dd : "%d μέρες",
+            M : "ένας μήνας",
+            MM : "%d μήνες",
+            y : "ένας χρόνος",
+            yy : "%d χρόνια"
+        },
+        ordinal : function (number) {
+            return number + 'η';
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/en-au.js b/resources/lib/moment/lang/en-au.js
new file mode 100644 (file)
index 0000000..4d91e25
--- /dev/null
@@ -0,0 +1,62 @@
+// moment.js language configuration
+// language : australian english (en-au)
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('en-au', {
+        months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
+        monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
+        weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
+        weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
+        weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
+        longDateFormat : {
+            LT : "h:mm A",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd, D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "in %s",
+            past : "%s ago",
+            s : "a few seconds",
+            m : "a minute",
+            mm : "%d minutes",
+            h : "an hour",
+            hh : "%d hours",
+            d : "a day",
+            dd : "%d days",
+            M : "a month",
+            MM : "%d months",
+            y : "a year",
+            yy : "%d years"
+        },
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~ (number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/en-ca.js b/resources/lib/moment/lang/en-ca.js
new file mode 100644 (file)
index 0000000..a97e9f3
--- /dev/null
@@ -0,0 +1,59 @@
+// moment.js language configuration
+// language : canadian english (en-ca)
+// author : Jonathan Abourbih : https://github.com/jonbca
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('en-ca', {
+        months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
+        monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
+        weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
+        weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
+        weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
+        longDateFormat : {
+            LT : "h:mm A",
+            L : "YYYY-MM-DD",
+            LL : "D MMMM, YYYY",
+            LLL : "D MMMM, YYYY LT",
+            LLLL : "dddd, D MMMM, YYYY LT"
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "in %s",
+            past : "%s ago",
+            s : "a few seconds",
+            m : "a minute",
+            mm : "%d minutes",
+            h : "an hour",
+            hh : "%d hours",
+            d : "a day",
+            dd : "%d days",
+            M : "a month",
+            MM : "%d months",
+            y : "a year",
+            yy : "%d years"
+        },
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~ (number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/en-gb.js b/resources/lib/moment/lang/en-gb.js
new file mode 100644 (file)
index 0000000..3a7907b
--- /dev/null
@@ -0,0 +1,63 @@
+// moment.js language configuration
+// language : great britain english (en-gb)
+// author : Chris Gedrim : https://github.com/chrisgedrim
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('en-gb', {
+        months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
+        monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
+        weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
+        weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
+        weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd, D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "in %s",
+            past : "%s ago",
+            s : "a few seconds",
+            m : "a minute",
+            mm : "%d minutes",
+            h : "an hour",
+            hh : "%d hours",
+            d : "a day",
+            dd : "%d days",
+            M : "a month",
+            MM : "%d months",
+            y : "a year",
+            yy : "%d years"
+        },
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~ (number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/eo.js b/resources/lib/moment/lang/eo.js
new file mode 100644 (file)
index 0000000..03b1abf
--- /dev/null
@@ -0,0 +1,65 @@
+// moment.js language configuration
+// language : esperanto (eo)
+// author : Colin Dean : https://github.com/colindean
+// komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko.
+//          Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni!
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('eo', {
+        months : "januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro".split("_"),
+        monthsShort : "jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec".split("_"),
+        weekdays : "Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato".split("_"),
+        weekdaysShort : "Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab".split("_"),
+        weekdaysMin : "Di_Lu_Ma_Me_Ĵa_Ve_Sa".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "YYYY-MM-DD",
+            LL : "D[-an de] MMMM, YYYY",
+            LLL : "D[-an de] MMMM, YYYY LT",
+            LLLL : "dddd, [la] D[-an de] MMMM, YYYY LT"
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours > 11) {
+                return isLower ? 'p.t.m.' : 'P.T.M.';
+            } else {
+                return isLower ? 'a.t.m.' : 'A.T.M.';
+            }
+        },
+        calendar : {
+            sameDay : '[Hodiaŭ je] LT',
+            nextDay : '[Morgaŭ je] LT',
+            nextWeek : 'dddd [je] LT',
+            lastDay : '[Hieraŭ je] LT',
+            lastWeek : '[pasinta] dddd [je] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "je %s",
+            past : "antaŭ %s",
+            s : "sekundoj",
+            m : "minuto",
+            mm : "%d minutoj",
+            h : "horo",
+            hh : "%d horoj",
+            d : "tago",//ne 'diurno', ĉar estas uzita por proksimumo
+            dd : "%d tagoj",
+            M : "monato",
+            MM : "%d monatoj",
+            y : "jaro",
+            yy : "%d jaroj"
+        },
+        ordinal : "%da",
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/es.js b/resources/lib/moment/lang/es.js
new file mode 100644 (file)
index 0000000..0a38396
--- /dev/null
@@ -0,0 +1,66 @@
+// moment.js language configuration
+// language : spanish (es)
+// author : Julio Napurí : https://github.com/julionc
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('es', {
+        months : "enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),
+        monthsShort : "ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),
+        weekdays : "domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),
+        weekdaysShort : "dom._lun._mar._mié._jue._vie._sáb.".split("_"),
+        weekdaysMin : "Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "DD/MM/YYYY",
+            LL : "D [de] MMMM [de] YYYY",
+            LLL : "D [de] MMMM [de] YYYY LT",
+            LLLL : "dddd, D [de] MMMM [de] YYYY LT"
+        },
+        calendar : {
+            sameDay : function () {
+                return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            nextDay : function () {
+                return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            nextWeek : function () {
+                return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            lastDay : function () {
+                return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            lastWeek : function () {
+                return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "en %s",
+            past : "hace %s",
+            s : "unos segundos",
+            m : "un minuto",
+            mm : "%d minutos",
+            h : "una hora",
+            hh : "%d horas",
+            d : "un día",
+            dd : "%d días",
+            M : "un mes",
+            MM : "%d meses",
+            y : "un año",
+            yy : "%d años"
+        },
+        ordinal : '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/et.js b/resources/lib/moment/lang/et.js
new file mode 100644 (file)
index 0000000..fb410ef
--- /dev/null
@@ -0,0 +1,76 @@
+// moment.js language configuration
+// language : estonian (et)
+// author : Henry Kehlmann : https://github.com/madhenry
+// improvements : Illimar Tambek : https://github.com/ragulka
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'],
+            'm' : ['ühe minuti', 'üks minut'],
+            'mm': [number + ' minuti', number + ' minutit'],
+            'h' : ['ühe tunni', 'tund aega', 'üks tund'],
+            'hh': [number + ' tunni', number + ' tundi'],
+            'd' : ['ühe päeva', 'üks päev'],
+            'M' : ['kuu aja', 'kuu aega', 'üks kuu'],
+            'MM': [number + ' kuu', number + ' kuud'],
+            'y' : ['ühe aasta', 'aasta', 'üks aasta'],
+            'yy': [number + ' aasta', number + ' aastat']
+        };
+        if (withoutSuffix) {
+            return format[key][2] ? format[key][2] : format[key][1];
+        }
+        return isFuture ? format[key][0] : format[key][1];
+    }
+
+    return moment.lang('et', {
+        months        : "jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),
+        monthsShort   : "jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),
+        weekdays      : "pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"),
+        weekdaysShort : "P_E_T_K_N_R_L".split("_"),
+        weekdaysMin   : "P_E_T_K_N_R_L".split("_"),
+        longDateFormat : {
+            LT   : "H:mm",
+            L    : "DD.MM.YYYY",
+            LL   : "D. MMMM YYYY",
+            LLL  : "D. MMMM YYYY LT",
+            LLLL : "dddd, D. MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay  : '[Täna,] LT',
+            nextDay  : '[Homme,] LT',
+            nextWeek : '[Järgmine] dddd LT',
+            lastDay  : '[Eile,] LT',
+            lastWeek : '[Eelmine] dddd LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s pärast",
+            past   : "%s tagasi",
+            s      : processRelativeTime,
+            m      : processRelativeTime,
+            mm     : processRelativeTime,
+            h      : processRelativeTime,
+            hh     : processRelativeTime,
+            d      : processRelativeTime,
+            dd     : '%d päeva',
+            M      : processRelativeTime,
+            MM     : processRelativeTime,
+            y      : processRelativeTime,
+            yy     : processRelativeTime
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/eu.js b/resources/lib/moment/lang/eu.js
new file mode 100644 (file)
index 0000000..659b739
--- /dev/null
@@ -0,0 +1,60 @@
+// moment.js language configuration
+// language : euskara (eu)
+// author : Eneko Illarramendi : https://github.com/eillarra
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('eu', {
+        months : "urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),
+        monthsShort : "urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),
+        weekdays : "igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),
+        weekdaysShort : "ig._al._ar._az._og._ol._lr.".split("_"),
+        weekdaysMin : "ig_al_ar_az_og_ol_lr".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "YYYY-MM-DD",
+            LL : "YYYY[ko] MMMM[ren] D[a]",
+            LLL : "YYYY[ko] MMMM[ren] D[a] LT",
+            LLLL : "dddd, YYYY[ko] MMMM[ren] D[a] LT",
+            l : "YYYY-M-D",
+            ll : "YYYY[ko] MMM D[a]",
+            lll : "YYYY[ko] MMM D[a] LT",
+            llll : "ddd, YYYY[ko] MMM D[a] LT"
+        },
+        calendar : {
+            sameDay : '[gaur] LT[etan]',
+            nextDay : '[bihar] LT[etan]',
+            nextWeek : 'dddd LT[etan]',
+            lastDay : '[atzo] LT[etan]',
+            lastWeek : '[aurreko] dddd LT[etan]',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s barru",
+            past : "duela %s",
+            s : "segundo batzuk",
+            m : "minutu bat",
+            mm : "%d minutu",
+            h : "ordu bat",
+            hh : "%d ordu",
+            d : "egun bat",
+            dd : "%d egun",
+            M : "hilabete bat",
+            MM : "%d hilabete",
+            y : "urte bat",
+            yy : "%d urte"
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/fa.js b/resources/lib/moment/lang/fa.js
new file mode 100644 (file)
index 0000000..4a690c4
--- /dev/null
@@ -0,0 +1,97 @@
+// moment.js language configuration
+// language : Persian Language
+// author : Ebrahim Byagowi : https://github.com/ebraminio
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '۱',
+        '2': '۲',
+        '3': '۳',
+        '4': '۴',
+        '5': '۵',
+        '6': '۶',
+        '7': '۷',
+        '8': '۸',
+        '9': '۹',
+        '0': '۰'
+    }, numberMap = {
+        '۱': '1',
+        '۲': '2',
+        '۳': '3',
+        '۴': '4',
+        '۵': '5',
+        '۶': '6',
+        '۷': '7',
+        '۸': '8',
+        '۹': '9',
+        '۰': '0'
+    };
+
+    return moment.lang('fa', {
+        months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
+        monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
+        weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
+        weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
+        weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY LT',
+            LLLL : 'dddd, D MMMM YYYY LT'
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return "قبل از ظهر";
+            } else {
+                return "بعد از ظهر";
+            }
+        },
+        calendar : {
+            sameDay : '[امروز ساعت] LT',
+            nextDay : '[فردا ساعت] LT',
+            nextWeek : 'dddd [ساعت] LT',
+            lastDay : '[دیروز ساعت] LT',
+            lastWeek : 'dddd [پیش] [ساعت] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'در %s',
+            past : '%s پیش',
+            s : 'چندین ثانیه',
+            m : 'یک دقیقه',
+            mm : '%d دقیقه',
+            h : 'یک ساعت',
+            hh : '%d ساعت',
+            d : 'یک روز',
+            dd : '%d روز',
+            M : 'یک ماه',
+            MM : '%d ماه',
+            y : 'یک سال',
+            yy : '%d سال'
+        },
+        preparse: function (string) {
+            return string.replace(/[۰-۹]/g, function (match) {
+                return numberMap[match];
+            }).replace(/،/g, ',');
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            }).replace(/,/g, '،');
+        },
+        ordinal : '%dم',
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12 // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/fi.js b/resources/lib/moment/lang/fi.js
new file mode 100644 (file)
index 0000000..18529c1
--- /dev/null
@@ -0,0 +1,103 @@
+// moment.js language configuration
+// language : finnish (fi)
+// author : Tarmo Aidantausta : https://github.com/bleadof
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var numbers_past = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '),
+        numbers_future = ['nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden',
+                          numbers_past[7], numbers_past[8], numbers_past[9]];
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var result = "";
+        switch (key) {
+        case 's':
+            return isFuture ? 'muutaman sekunnin' : 'muutama sekunti';
+        case 'm':
+            return isFuture ? 'minuutin' : 'minuutti';
+        case 'mm':
+            result = isFuture ? 'minuutin' : 'minuuttia';
+            break;
+        case 'h':
+            return isFuture ? 'tunnin' : 'tunti';
+        case 'hh':
+            result = isFuture ? 'tunnin' : 'tuntia';
+            break;
+        case 'd':
+            return isFuture ? 'päivän' : 'päivä';
+        case 'dd':
+            result = isFuture ? 'päivän' : 'päivää';
+            break;
+        case 'M':
+            return isFuture ? 'kuukauden' : 'kuukausi';
+        case 'MM':
+            result = isFuture ? 'kuukauden' : 'kuukautta';
+            break;
+        case 'y':
+            return isFuture ? 'vuoden' : 'vuosi';
+        case 'yy':
+            result = isFuture ? 'vuoden' : 'vuotta';
+            break;
+        }
+        result = verbal_number(number, isFuture) + " " + result;
+        return result;
+    }
+
+    function verbal_number(number, isFuture) {
+        return number < 10 ? (isFuture ? numbers_future[number] : numbers_past[number]) : number;
+    }
+
+    return moment.lang('fi', {
+        months : "tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),
+        monthsShort : "tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),
+        weekdays : "sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),
+        weekdaysShort : "su_ma_ti_ke_to_pe_la".split("_"),
+        weekdaysMin : "su_ma_ti_ke_to_pe_la".split("_"),
+        longDateFormat : {
+            LT : "HH.mm",
+            L : "DD.MM.YYYY",
+            LL : "Do MMMM[ta] YYYY",
+            LLL : "Do MMMM[ta] YYYY, [klo] LT",
+            LLLL : "dddd, Do MMMM[ta] YYYY, [klo] LT",
+            l : "D.M.YYYY",
+            ll : "Do MMM YYYY",
+            lll : "Do MMM YYYY, [klo] LT",
+            llll : "ddd, Do MMM YYYY, [klo] LT"
+        },
+        calendar : {
+            sameDay : '[tänään] [klo] LT',
+            nextDay : '[huomenna] [klo] LT',
+            nextWeek : 'dddd [klo] LT',
+            lastDay : '[eilen] [klo] LT',
+            lastWeek : '[viime] dddd[na] [klo] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s päästä",
+            past : "%s sitten",
+            s : translate,
+            m : translate,
+            mm : translate,
+            h : translate,
+            hh : translate,
+            d : translate,
+            dd : translate,
+            M : translate,
+            MM : translate,
+            y : translate,
+            yy : translate
+        },
+        ordinal : "%d.",
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/fo.js b/resources/lib/moment/lang/fo.js
new file mode 100644 (file)
index 0000000..2f1cbb8
--- /dev/null
@@ -0,0 +1,56 @@
+// moment.js language configuration
+// language : faroese (fo)
+// author : Ragnar Johannesen : https://github.com/ragnar123
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('fo', {
+        months : "januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember".split("_"),
+        monthsShort : "jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),
+        weekdays : "sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur".split("_"),
+        weekdaysShort : "sun_mán_týs_mik_hós_frí_ley".split("_"),
+        weekdaysMin : "su_má_tý_mi_hó_fr_le".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D. MMMM, YYYY LT"
+        },
+        calendar : {
+            sameDay : '[Í dag kl.] LT',
+            nextDay : '[Í morgin kl.] LT',
+            nextWeek : 'dddd [kl.] LT',
+            lastDay : '[Í gjár kl.] LT',
+            lastWeek : '[síðstu] dddd [kl] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "um %s",
+            past : "%s síðani",
+            s : "fá sekund",
+            m : "ein minutt",
+            mm : "%d minuttir",
+            h : "ein tími",
+            hh : "%d tímar",
+            d : "ein dagur",
+            dd : "%d dagar",
+            M : "ein mánaði",
+            MM : "%d mánaðir",
+            y : "eitt ár",
+            yy : "%d ár"
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/fr-ca.js b/resources/lib/moment/lang/fr-ca.js
new file mode 100644 (file)
index 0000000..3280d79
--- /dev/null
@@ -0,0 +1,54 @@
+// moment.js language configuration
+// language : canadian french (fr-ca)
+// author : Jonathan Abourbih : https://github.com/jonbca
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('fr-ca', {
+        months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),
+        monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),
+        weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),
+        weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"),
+        weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "YYYY-MM-DD",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: "[Aujourd'hui à] LT",
+            nextDay: '[Demain à] LT',
+            nextWeek: 'dddd [à] LT',
+            lastDay: '[Hier à] LT',
+            lastWeek: 'dddd [dernier à] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "dans %s",
+            past : "il y a %s",
+            s : "quelques secondes",
+            m : "une minute",
+            mm : "%d minutes",
+            h : "une heure",
+            hh : "%d heures",
+            d : "un jour",
+            dd : "%d jours",
+            M : "un mois",
+            MM : "%d mois",
+            y : "un an",
+            yy : "%d ans"
+        },
+        ordinal : function (number) {
+            return number + (number === 1 ? 'er' : '');
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/fr.js b/resources/lib/moment/lang/fr.js
new file mode 100644 (file)
index 0000000..6b3dc52
--- /dev/null
@@ -0,0 +1,58 @@
+// moment.js language configuration
+// language : french (fr)
+// author : John Fischer : https://github.com/jfroffice
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('fr', {
+        months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),
+        monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),
+        weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),
+        weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"),
+        weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: "[Aujourd'hui à] LT",
+            nextDay: '[Demain à] LT',
+            nextWeek: 'dddd [à] LT',
+            lastDay: '[Hier à] LT',
+            lastWeek: 'dddd [dernier à] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "dans %s",
+            past : "il y a %s",
+            s : "quelques secondes",
+            m : "une minute",
+            mm : "%d minutes",
+            h : "une heure",
+            hh : "%d heures",
+            d : "un jour",
+            dd : "%d jours",
+            M : "un mois",
+            MM : "%d mois",
+            y : "un an",
+            yy : "%d ans"
+        },
+        ordinal : function (number) {
+            return number + (number === 1 ? 'er' : '');
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/gl.js b/resources/lib/moment/lang/gl.js
new file mode 100644 (file)
index 0000000..8b14127
--- /dev/null
@@ -0,0 +1,71 @@
+// moment.js language configuration
+// language : galician (gl)
+// author : Juan G. Hurtado : https://github.com/juanghurtado
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('gl', {
+        months : "Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"),
+        monthsShort : "Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),
+        weekdays : "Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),
+        weekdaysShort : "Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),
+        weekdaysMin : "Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay : function () {
+                return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
+            },
+            nextDay : function () {
+                return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
+            },
+            nextWeek : function () {
+                return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
+            },
+            lastDay : function () {
+                return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT';
+            },
+            lastWeek : function () {
+                return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : function (str) {
+                if (str === "uns segundos") {
+                    return "nuns segundos";
+                }
+                return "en " + str;
+            },
+            past : "hai %s",
+            s : "uns segundos",
+            m : "un minuto",
+            mm : "%d minutos",
+            h : "unha hora",
+            hh : "%d horas",
+            d : "un día",
+            dd : "%d días",
+            M : "un mes",
+            MM : "%d meses",
+            y : "un ano",
+            yy : "%d anos"
+        },
+        ordinal : '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/he.js b/resources/lib/moment/lang/he.js
new file mode 100644 (file)
index 0000000..b85dbe8
--- /dev/null
@@ -0,0 +1,77 @@
+// moment.js language configuration
+// language : Hebrew (he)
+// author : Tomer Cohen : https://github.com/tomer
+// author : Moshe Simantov : https://github.com/DevelopmentIL
+// author : Tal Ater : https://github.com/TalAter
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('he', {
+        months : "ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),
+        monthsShort : "ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),
+        weekdays : "ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),
+        weekdaysShort : "א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),
+        weekdaysMin : "א_ב_ג_ד_ה_ו_ש".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D [ב]MMMM YYYY",
+            LLL : "D [ב]MMMM YYYY LT",
+            LLLL : "dddd, D [ב]MMMM YYYY LT",
+            l : "D/M/YYYY",
+            ll : "D MMM YYYY",
+            lll : "D MMM YYYY LT",
+            llll : "ddd, D MMM YYYY LT"
+        },
+        calendar : {
+            sameDay : '[היום ב־]LT',
+            nextDay : '[מחר ב־]LT',
+            nextWeek : 'dddd [בשעה] LT',
+            lastDay : '[אתמול ב־]LT',
+            lastWeek : '[ביום] dddd [האחרון בשעה] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "בעוד %s",
+            past : "לפני %s",
+            s : "מספר שניות",
+            m : "דקה",
+            mm : "%d דקות",
+            h : "שעה",
+            hh : function (number) {
+                if (number === 2) {
+                    return "שעתיים";
+                }
+                return number + " שעות";
+            },
+            d : "יום",
+            dd : function (number) {
+                if (number === 2) {
+                    return "יומיים";
+                }
+                return number + " ימים";
+            },
+            M : "חודש",
+            MM : function (number) {
+                if (number === 2) {
+                    return "חודשיים";
+                }
+                return number + " חודשים";
+            },
+            y : "שנה",
+            yy : function (number) {
+                if (number === 2) {
+                    return "שנתיים";
+                }
+                return number + " שנים";
+            }
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/hi.js b/resources/lib/moment/lang/hi.js
new file mode 100644 (file)
index 0000000..8e6e99c
--- /dev/null
@@ -0,0 +1,105 @@
+// moment.js language configuration
+// language : hindi (hi)
+// author : Mayank Singhal : https://github.com/mayanksinghal
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '१',
+        '2': '२',
+        '3': '३',
+        '4': '४',
+        '5': '५',
+        '6': '६',
+        '7': '७',
+        '8': '८',
+        '9': '९',
+        '0': '०'
+    },
+    numberMap = {
+        '१': '1',
+        '२': '2',
+        '३': '3',
+        '४': '4',
+        '५': '5',
+        '६': '6',
+        '७': '7',
+        '८': '8',
+        '९': '9',
+        '०': '0'
+    };
+
+    return moment.lang('hi', {
+        months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split("_"),
+        monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split("_"),
+        weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split("_"),
+        weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split("_"),
+        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split("_"),
+        longDateFormat : {
+            LT : "A h:mm बजे",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY, LT",
+            LLLL : "dddd, D MMMM YYYY, LT"
+        },
+        calendar : {
+            sameDay : '[आज] LT',
+            nextDay : '[कल] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[कल] LT',
+            lastWeek : '[पिछले] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s में",
+            past : "%s पहले",
+            s : "कुछ ही क्षण",
+            m : "एक मिनट",
+            mm : "%d मिनट",
+            h : "एक घंटा",
+            hh : "%d घंटे",
+            d : "एक दिन",
+            dd : "%d दिन",
+            M : "एक महीने",
+            MM : "%d महीने",
+            y : "एक वर्ष",
+            yy : "%d वर्ष"
+        },
+        preparse: function (string) {
+            return string.replace(/[१२३४५६७८९०]/g, function (match) {
+                return numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            });
+        },
+        // Hindi notation for meridiems are quite fuzzy in practice. While there exists
+        // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi.
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return "रात";
+            } else if (hour < 10) {
+                return "सुबह";
+            } else if (hour < 17) {
+                return "दोपहर";
+            } else if (hour < 20) {
+                return "शाम";
+            } else {
+                return "रात";
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/hr.js b/resources/lib/moment/lang/hr.js
new file mode 100644 (file)
index 0000000..2e3bf11
--- /dev/null
@@ -0,0 +1,140 @@
+// moment.js language configuration
+// language : hrvatski (hr)
+// author : Bojan Marković : https://github.com/bmarkovic
+
+// based on (sl) translation by Robert Sedovšek
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+
+    function translate(number, withoutSuffix, key) {
+        var result = number + " ";
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+        case 'mm':
+            if (number === 1) {
+                result += 'minuta';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'minute';
+            } else {
+                result += 'minuta';
+            }
+            return result;
+        case 'h':
+            return withoutSuffix ? 'jedan sat' : 'jednog sata';
+        case 'hh':
+            if (number === 1) {
+                result += 'sat';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'sata';
+            } else {
+                result += 'sati';
+            }
+            return result;
+        case 'dd':
+            if (number === 1) {
+                result += 'dan';
+            } else {
+                result += 'dana';
+            }
+            return result;
+        case 'MM':
+            if (number === 1) {
+                result += 'mjesec';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'mjeseca';
+            } else {
+                result += 'mjeseci';
+            }
+            return result;
+        case 'yy':
+            if (number === 1) {
+                result += 'godina';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'godine';
+            } else {
+                result += 'godina';
+            }
+            return result;
+        }
+    }
+
+    return moment.lang('hr', {
+        months : "sječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_"),
+        monthsShort : "sje._vel._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),
+        weekdays : "nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),
+        weekdaysShort : "ned._pon._uto._sri._čet._pet._sub.".split("_"),
+        weekdaysMin : "ne_po_ut_sr_če_pe_su".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "DD. MM. YYYY",
+            LL : "D. MMMM YYYY",
+            LLL : "D. MMMM YYYY LT",
+            LLLL : "dddd, D. MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay  : '[danas u] LT',
+            nextDay  : '[sutra u] LT',
+
+            nextWeek : function () {
+                switch (this.day()) {
+                case 0:
+                    return '[u] [nedjelju] [u] LT';
+                case 3:
+                    return '[u] [srijedu] [u] LT';
+                case 6:
+                    return '[u] [subotu] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[u] dddd [u] LT';
+                }
+            },
+            lastDay  : '[jučer u] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                    return '[prošlu] dddd [u] LT';
+                case 6:
+                    return '[prošle] [subote] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[prošli] dddd [u] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "za %s",
+            past   : "prije %s",
+            s      : "par sekundi",
+            m      : translate,
+            mm     : translate,
+            h      : translate,
+            hh     : translate,
+            d      : "dan",
+            dd     : translate,
+            M      : "mjesec",
+            MM     : translate,
+            y      : "godinu",
+            yy     : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/hu.js b/resources/lib/moment/lang/hu.js
new file mode 100644 (file)
index 0000000..4d84ebd
--- /dev/null
@@ -0,0 +1,98 @@
+// moment.js language configuration
+// language : hungarian (hu)
+// author : Adam Brunner : https://github.com/adambrunner
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' ');
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var num = number,
+            suffix;
+
+        switch (key) {
+        case 's':
+            return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce';
+        case 'm':
+            return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce');
+        case 'mm':
+            return num + (isFuture || withoutSuffix ? ' perc' : ' perce');
+        case 'h':
+            return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája');
+        case 'hh':
+            return num + (isFuture || withoutSuffix ? ' óra' : ' órája');
+        case 'd':
+            return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja');
+        case 'dd':
+            return num + (isFuture || withoutSuffix ? ' nap' : ' napja');
+        case 'M':
+            return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
+        case 'MM':
+            return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
+        case 'y':
+            return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve');
+        case 'yy':
+            return num + (isFuture || withoutSuffix ? ' év' : ' éve');
+        }
+
+        return '';
+    }
+
+    function week(isFuture) {
+        return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]';
+    }
+
+    return moment.lang('hu', {
+        months : "január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),
+        monthsShort : "jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),
+        weekdays : "vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),
+        weekdaysShort : "vas_hét_kedd_sze_csüt_pén_szo".split("_"),
+        weekdaysMin : "v_h_k_sze_cs_p_szo".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "YYYY.MM.DD.",
+            LL : "YYYY. MMMM D.",
+            LLL : "YYYY. MMMM D., LT",
+            LLLL : "YYYY. MMMM D., dddd LT"
+        },
+        calendar : {
+            sameDay : '[ma] LT[-kor]',
+            nextDay : '[holnap] LT[-kor]',
+            nextWeek : function () {
+                return week.call(this, true);
+            },
+            lastDay : '[tegnap] LT[-kor]',
+            lastWeek : function () {
+                return week.call(this, false);
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s múlva",
+            past : "%s",
+            s : translate,
+            m : translate,
+            mm : translate,
+            h : translate,
+            hh : translate,
+            d : translate,
+            dd : translate,
+            M : translate,
+            MM : translate,
+            y : translate,
+            yy : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/hy-am.js b/resources/lib/moment/lang/hy-am.js
new file mode 100644 (file)
index 0000000..951655b
--- /dev/null
@@ -0,0 +1,113 @@
+// moment.js language configuration
+// language : Armenian (hy-am)
+// author : Armendarabyan : https://github.com/armendarabyan
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+
+    function monthsCaseReplace(m, format) {
+        var months = {
+            'nominative': 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_'),
+            'accusative': 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_')
+        },
+
+        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return months[nounCase][m.month()];
+    }
+
+    function monthsShortCaseReplace(m, format) {
+        var monthsShort = 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_');
+
+        return monthsShort[m.month()];
+    }
+
+    function weekdaysCaseReplace(m, format) {
+        var weekdays = 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_');
+
+        return weekdays[m.day()];
+    }
+
+    return moment.lang('hy-am', {
+        months : monthsCaseReplace,
+        monthsShort : monthsShortCaseReplace,
+        weekdays : weekdaysCaseReplace,
+        weekdaysShort : "կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),
+        weekdaysMin : "կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD.MM.YYYY",
+            LL : "D MMMM YYYY թ.",
+            LLL : "D MMMM YYYY թ., LT",
+            LLLL : "dddd, D MMMM YYYY թ., LT"
+        },
+        calendar : {
+            sameDay: '[այսօր] LT',
+            nextDay: '[վաղը] LT',
+            lastDay: '[երեկ] LT',
+            nextWeek: function () {
+                return 'dddd [օրը ժամը] LT';
+            },
+            lastWeek: function () {
+                return '[անցած] dddd [օրը ժամը] LT';
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "%s հետո",
+            past : "%s առաջ",
+            s : "մի քանի վայրկյան",
+            m : "րոպե",
+            mm : "%d րոպե",
+            h : "ժամ",
+            hh : "%d ժամ",
+            d : "օր",
+            dd : "%d օր",
+            M : "ամիս",
+            MM : "%d ամիս",
+            y : "տարի",
+            yy : "%d տարի"
+        },
+
+        meridiem : function (hour) {
+            if (hour < 4) {
+                return "գիշերվա";
+            } else if (hour < 12) {
+                return "առավոտվա";
+            } else if (hour < 17) {
+                return "ցերեկվա";
+            } else {
+                return "երեկոյան";
+            }
+        },
+
+        ordinal: function (number, period) {
+            switch (period) {
+            case 'DDD':
+            case 'w':
+            case 'W':
+            case 'DDDo':
+                if (number === 1) {
+                    return number + '-ին';
+                }
+                return number + '-րդ';
+            default:
+                return number;
+            }
+        },
+
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/id.js b/resources/lib/moment/lang/id.js
new file mode 100644 (file)
index 0000000..f186280
--- /dev/null
@@ -0,0 +1,67 @@
+// moment.js language configuration
+// language : Bahasa Indonesia (id)
+// author : Mohammad Satrio Utomo : https://github.com/tyok
+// reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('id', {
+        months : "Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),
+        monthsShort : "Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),
+        weekdays : "Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),
+        weekdaysShort : "Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),
+        weekdaysMin : "Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),
+        longDateFormat : {
+            LT : "HH.mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY [pukul] LT",
+            LLLL : "dddd, D MMMM YYYY [pukul] LT"
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 11) {
+                return 'pagi';
+            } else if (hours < 15) {
+                return 'siang';
+            } else if (hours < 19) {
+                return 'sore';
+            } else {
+                return 'malam';
+            }
+        },
+        calendar : {
+            sameDay : '[Hari ini pukul] LT',
+            nextDay : '[Besok pukul] LT',
+            nextWeek : 'dddd [pukul] LT',
+            lastDay : '[Kemarin pukul] LT',
+            lastWeek : 'dddd [lalu pukul] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "dalam %s",
+            past : "%s yang lalu",
+            s : "beberapa detik",
+            m : "semenit",
+            mm : "%d menit",
+            h : "sejam",
+            hh : "%d jam",
+            d : "sehari",
+            dd : "%d hari",
+            M : "sebulan",
+            MM : "%d bulan",
+            y : "setahun",
+            yy : "%d tahun"
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/is.js b/resources/lib/moment/lang/is.js
new file mode 100644 (file)
index 0000000..5b6b2a8
--- /dev/null
@@ -0,0 +1,124 @@
+// moment.js language configuration
+// language : icelandic (is)
+// author : Hinrik Örn Sigurðsson : https://github.com/hinrik
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function plural(n) {
+        if (n % 100 === 11) {
+            return true;
+        } else if (n % 10 === 1) {
+            return false;
+        }
+        return true;
+    }
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var result = number + " ";
+        switch (key) {
+        case 's':
+            return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum';
+        case 'm':
+            return withoutSuffix ? 'mínúta' : 'mínútu';
+        case 'mm':
+            if (plural(number)) {
+                return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum');
+            } else if (withoutSuffix) {
+                return result + 'mínúta';
+            }
+            return result + 'mínútu';
+        case 'hh':
+            if (plural(number)) {
+                return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum');
+            }
+            return result + 'klukkustund';
+        case 'd':
+            if (withoutSuffix) {
+                return 'dagur';
+            }
+            return isFuture ? 'dag' : 'degi';
+        case 'dd':
+            if (plural(number)) {
+                if (withoutSuffix) {
+                    return result + 'dagar';
+                }
+                return result + (isFuture ? 'daga' : 'dögum');
+            } else if (withoutSuffix) {
+                return result + 'dagur';
+            }
+            return result + (isFuture ? 'dag' : 'degi');
+        case 'M':
+            if (withoutSuffix) {
+                return 'mánuður';
+            }
+            return isFuture ? 'mánuð' : 'mánuði';
+        case 'MM':
+            if (plural(number)) {
+                if (withoutSuffix) {
+                    return result + 'mánuðir';
+                }
+                return result + (isFuture ? 'mánuði' : 'mánuðum');
+            } else if (withoutSuffix) {
+                return result + 'mánuður';
+            }
+            return result + (isFuture ? 'mánuð' : 'mánuði');
+        case 'y':
+            return withoutSuffix || isFuture ? 'ár' : 'ári';
+        case 'yy':
+            if (plural(number)) {
+                return result + (withoutSuffix || isFuture ? 'ár' : 'árum');
+            }
+            return result + (withoutSuffix || isFuture ? 'ár' : 'ári');
+        }
+    }
+
+    return moment.lang('is', {
+        months : "janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),
+        monthsShort : "jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),
+        weekdays : "sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),
+        weekdaysShort : "sun_mán_þri_mið_fim_fös_lau".split("_"),
+        weekdaysMin : "Su_Má_Þr_Mi_Fi_Fö_La".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "DD/MM/YYYY",
+            LL : "D. MMMM YYYY",
+            LLL : "D. MMMM YYYY [kl.] LT",
+            LLLL : "dddd, D. MMMM YYYY [kl.] LT"
+        },
+        calendar : {
+            sameDay : '[í dag kl.] LT',
+            nextDay : '[á morgun kl.] LT',
+            nextWeek : 'dddd [kl.] LT',
+            lastDay : '[í gær kl.] LT',
+            lastWeek : '[síðasta] dddd [kl.] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "eftir %s",
+            past : "fyrir %s síðan",
+            s : translate,
+            m : translate,
+            mm : translate,
+            h : "klukkustund",
+            hh : translate,
+            d : translate,
+            dd : translate,
+            M : translate,
+            MM : translate,
+            y : translate,
+            yy : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/it.js b/resources/lib/moment/lang/it.js
new file mode 100644 (file)
index 0000000..84b7698
--- /dev/null
@@ -0,0 +1,59 @@
+// moment.js language configuration
+// language : italian (it)
+// author : Lorenzo : https://github.com/aliem
+// author: Mattia Larentis: https://github.com/nostalgiaz
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('it', {
+        months : "Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settembre_Ottobre_Novembre_Dicembre".split("_"),
+        monthsShort : "Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"),
+        weekdays : "Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),
+        weekdaysShort : "Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),
+        weekdaysMin : "D_L_Ma_Me_G_V_S".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd, D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: '[Oggi alle] LT',
+            nextDay: '[Domani alle] LT',
+            nextWeek: 'dddd [alle] LT',
+            lastDay: '[Ieri alle] LT',
+            lastWeek: '[lo scorso] dddd [alle] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : function (s) {
+                return ((/^[0-9].+$/).test(s) ? "tra" : "in") + " " + s;
+            },
+            past : "%s fa",
+            s : "alcuni secondi",
+            m : "un minuto",
+            mm : "%d minuti",
+            h : "un'ora",
+            hh : "%d ore",
+            d : "un giorno",
+            dd : "%d giorni",
+            M : "un mese",
+            MM : "%d mesi",
+            y : "un anno",
+            yy : "%d anni"
+        },
+        ordinal: '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/ja.js b/resources/lib/moment/lang/ja.js
new file mode 100644 (file)
index 0000000..9cd7e9e
--- /dev/null
@@ -0,0 +1,58 @@
+// moment.js language configuration
+// language : japanese (ja)
+// author : LI Long : https://github.com/baryon
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('ja', {
+        months : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
+        monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
+        weekdays : "日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),
+        weekdaysShort : "日_月_火_水_木_金_土".split("_"),
+        weekdaysMin : "日_月_火_水_木_金_土".split("_"),
+        longDateFormat : {
+            LT : "Ah時m分",
+            L : "YYYY/MM/DD",
+            LL : "YYYY年M月D日",
+            LLL : "YYYY年M月D日LT",
+            LLLL : "YYYY年M月D日LT dddd"
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return "午前";
+            } else {
+                return "午後";
+            }
+        },
+        calendar : {
+            sameDay : '[今日] LT',
+            nextDay : '[明日] LT',
+            nextWeek : '[来週]dddd LT',
+            lastDay : '[昨日] LT',
+            lastWeek : '[前週]dddd LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s後",
+            past : "%s前",
+            s : "数秒",
+            m : "1分",
+            mm : "%d分",
+            h : "1時間",
+            hh : "%d時間",
+            d : "1日",
+            dd : "%d日",
+            M : "1ヶ月",
+            MM : "%dヶ月",
+            y : "1年",
+            yy : "%d年"
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/ka.js b/resources/lib/moment/lang/ka.js
new file mode 100644 (file)
index 0000000..0cebdaa
--- /dev/null
@@ -0,0 +1,108 @@
+// moment.js language configuration
+// language : Georgian (ka)
+// author : Irakli Janiashvili : https://github.com/irakli-janiashvili
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+
+    function monthsCaseReplace(m, format) {
+        var months = {
+            'nominative': 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'),
+            'accusative': 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_')
+        },
+
+        nounCase = (/D[oD] *MMMM?/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return months[nounCase][m.month()];
+    }
+
+    function weekdaysCaseReplace(m, format) {
+        var weekdays = {
+            'nominative': 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'),
+            'accusative': 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_')
+        },
+
+        nounCase = (/(წინა|შემდეგ)/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return weekdays[nounCase][m.day()];
+    }
+
+    return moment.lang('ka', {
+        months : monthsCaseReplace,
+        monthsShort : "იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ".split("_"),
+        weekdays : weekdaysCaseReplace,
+        weekdaysShort : "კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ".split("_"),
+        weekdaysMin : "კვ_ორ_სა_ოთ_ხუ_პა_შა".split("_"),
+        longDateFormat : {
+            LT : "h:mm A",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd, D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay : '[დღეს] LT[-ზე]',
+            nextDay : '[ხვალ] LT[-ზე]',
+            lastDay : '[გუშინ] LT[-ზე]',
+            nextWeek : '[შემდეგ] dddd LT[-ზე]',
+            lastWeek : '[წინა] dddd LT-ზე',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : function (s) {
+                return (/(წამი|წუთი|საათი|წელი)/).test(s) ?
+                    s.replace(/ი$/, "ში") :
+                    s + "ში";
+            },
+            past : function (s) {
+                if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) {
+                    return s.replace(/(ი|ე)$/, "ის წინ");
+                }
+                if ((/წელი/).test(s)) {
+                    return s.replace(/წელი$/, "წლის წინ");
+                }
+            },
+            s : "რამდენიმე წამი",
+            m : "წუთი",
+            mm : "%d წუთი",
+            h : "საათი",
+            hh : "%d საათი",
+            d : "დღე",
+            dd : "%d დღე",
+            M : "თვე",
+            MM : "%d თვე",
+            y : "წელი",
+            yy : "%d წელი"
+        },
+        ordinal : function (number) {
+            if (number === 0) {
+                return number;
+            }
+
+            if (number === 1) {
+                return number + "-ლი";
+            }
+
+            if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) {
+                return "მე-" + number;
+            }
+
+            return number + "-ე";
+        },
+        week : {
+            dow : 1,
+            doy : 7
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/ko.js b/resources/lib/moment/lang/ko.js
new file mode 100644 (file)
index 0000000..3b469df
--- /dev/null
@@ -0,0 +1,63 @@
+// moment.js language configuration
+// language : korean (ko)
+//
+// authors 
+//
+// - Kyungwook, Park : https://github.com/kyungw00k
+// - Jeeeyul Lee <jeeeyul@gmail.com>
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('ko', {
+        months : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),
+        monthsShort : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),
+        weekdays : "일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),
+        weekdaysShort : "일_월_화_수_목_금_토".split("_"),
+        weekdaysMin : "일_월_화_수_목_금_토".split("_"),
+        longDateFormat : {
+            LT : "A h시 mm분",
+            L : "YYYY.MM.DD",
+            LL : "YYYY년 MMMM D일",
+            LLL : "YYYY년 MMMM D일 LT",
+            LLLL : "YYYY년 MMMM D일 dddd LT"
+        },
+        meridiem : function (hour, minute, isUpper) {
+            return hour < 12 ? '오전' : '오후';
+        },
+        calendar : {
+            sameDay : '오늘 LT',
+            nextDay : '내일 LT',
+            nextWeek : 'dddd LT',
+            lastDay : '어제 LT',
+            lastWeek : '지난주 dddd LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s 후",
+            past : "%s 전",
+            s : "몇초",
+            ss : "%d초",
+            m : "일분",
+            mm : "%d분",
+            h : "한시간",
+            hh : "%d시간",
+            d : "하루",
+            dd : "%d일",
+            M : "한달",
+            MM : "%d달",
+            y : "일년",
+            yy : "%d년"
+        },
+        ordinal : '%d일',
+        meridiemParse : /(오전|오후)/,
+        isPM : function (token) {
+            return token === "오후";
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/lb.js b/resources/lib/moment/lang/lb.js
new file mode 100644 (file)
index 0000000..946ba13
--- /dev/null
@@ -0,0 +1,160 @@
+// moment.js language configuration
+// language : Luxembourgish (lb)
+// author : mweimerskirch : https://github.com/mweimerskirch
+
+// Note: Luxembourgish has a very particular phonological rule ("Eifeler Regel") that causes the
+// deletion of the final "n" in certain contexts. That's what the "eifelerRegelAppliesToWeekday"
+// and "eifelerRegelAppliesToNumber" methods are meant for
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            'm': ['eng Minutt', 'enger Minutt'],
+            'h': ['eng Stonn', 'enger Stonn'],
+            'd': ['een Dag', 'engem Dag'],
+            'dd': [number + ' Deeg', number + ' Deeg'],
+            'M': ['ee Mount', 'engem Mount'],
+            'MM': [number + ' Méint', number + ' Méint'],
+            'y': ['ee Joer', 'engem Joer'],
+            'yy': [number + ' Joer', number + ' Joer']
+        };
+        return withoutSuffix ? format[key][0] : format[key][1];
+    }
+
+    function processFutureTime(string) {
+        var number = string.substr(0, string.indexOf(' '));
+        if (eifelerRegelAppliesToNumber(number)) {
+            return "a " + string;
+        }
+        return "an " + string;
+    }
+
+    function processPastTime(string) {
+        var number = string.substr(0, string.indexOf(' '));
+        if (eifelerRegelAppliesToNumber(number)) {
+            return "viru " + string;
+        }
+        return "virun " + string;
+    }
+
+    function processLastWeek(string1) {
+        var weekday = this.format('d');
+        if (eifelerRegelAppliesToWeekday(weekday)) {
+            return '[Leschte] dddd [um] LT';
+        }
+        return '[Leschten] dddd [um] LT';
+    }
+
+    /**
+     * Returns true if the word before the given week day loses the "-n" ending.
+     * e.g. "Leschten Dënschdeg" but "Leschte Méindeg"
+     *
+     * @param weekday {integer}
+     * @returns {boolean}
+     */
+    function eifelerRegelAppliesToWeekday(weekday) {
+        weekday = parseInt(weekday, 10);
+        switch (weekday) {
+        case 0: // Sonndeg
+        case 1: // Méindeg
+        case 3: // Mëttwoch
+        case 5: // Freideg
+        case 6: // Samschdeg
+            return true;
+        default: // 2 Dënschdeg, 4 Donneschdeg
+            return false;
+        }
+    }
+
+    /**
+     * Returns true if the word before the given number loses the "-n" ending.
+     * e.g. "an 10 Deeg" but "a 5 Deeg"
+     *
+     * @param number {integer}
+     * @returns {boolean}
+     */
+    function eifelerRegelAppliesToNumber(number) {
+        number = parseInt(number, 10);
+        if (isNaN(number)) {
+            return false;
+        }
+        if (number < 0) {
+            // Negative Number --> always true
+            return true;
+        } else if (number < 10) {
+            // Only 1 digit
+            if (4 <= number && number <= 7) {
+                return true;
+            }
+            return false;
+        } else if (number < 100) {
+            // 2 digits
+            var lastDigit = number % 10, firstDigit = number / 10;
+            if (lastDigit === 0) {
+                return eifelerRegelAppliesToNumber(firstDigit);
+            }
+            return eifelerRegelAppliesToNumber(lastDigit);
+        } else if (number < 10000) {
+            // 3 or 4 digits --> recursively check first digit
+            while (number >= 10) {
+                number = number / 10;
+            }
+            return eifelerRegelAppliesToNumber(number);
+        } else {
+            // Anything larger than 4 digits: recursively check first n-3 digits
+            number = number / 1000;
+            return eifelerRegelAppliesToNumber(number);
+        }
+    }
+
+    return moment.lang('lb', {
+        months: "Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),
+        monthsShort: "Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),
+        weekdays: "Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),
+        weekdaysShort: "So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),
+        weekdaysMin: "So_Mé_Dë_Më_Do_Fr_Sa".split("_"),
+        longDateFormat: {
+            LT: "H:mm [Auer]",
+            L: "DD.MM.YYYY",
+            LL: "D. MMMM YYYY",
+            LLL: "D. MMMM YYYY LT",
+            LLLL: "dddd, D. MMMM YYYY LT"
+        },
+        calendar: {
+            sameDay: "[Haut um] LT",
+            sameElse: "L",
+            nextDay: '[Muer um] LT',
+            nextWeek: 'dddd [um] LT',
+            lastDay: '[Gëschter um] LT',
+            lastWeek: processLastWeek
+        },
+        relativeTime: {
+            future: processFutureTime,
+            past: processPastTime,
+            s: "e puer Sekonnen",
+            m: processRelativeTime,
+            mm: "%d Minutten",
+            h: processRelativeTime,
+            hh: "%d Stonnen",
+            d: processRelativeTime,
+            dd: processRelativeTime,
+            M: processRelativeTime,
+            MM: processRelativeTime,
+            y: processRelativeTime,
+            yy: processRelativeTime
+        },
+        ordinal: '%d.',
+        week: {
+            dow: 1, // Monday is the first day of the week.
+            doy: 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/lt.js b/resources/lib/moment/lang/lt.js
new file mode 100644 (file)
index 0000000..1cf6457
--- /dev/null
@@ -0,0 +1,118 @@
+// moment.js language configuration
+// language : Lithuanian (lt)
+// author : Mindaugas Mozūras : https://github.com/mmozuras
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var units = {
+        "m" : "minutė_minutės_minutę",
+        "mm": "minutės_minučių_minutes",
+        "h" : "valanda_valandos_valandą",
+        "hh": "valandos_valandų_valandas",
+        "d" : "diena_dienos_dieną",
+        "dd": "dienos_dienų_dienas",
+        "M" : "mėnuo_mėnesio_mėnesį",
+        "MM": "mėnesiai_mėnesių_mėnesius",
+        "y" : "metai_metų_metus",
+        "yy": "metai_metų_metus"
+    },
+    weekDays = "pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis_sekmadienis".split("_");
+
+    function translateSeconds(number, withoutSuffix, key, isFuture) {
+        if (withoutSuffix) {
+            return "kelios sekundės";
+        } else {
+            return isFuture ? "kelių sekundžių" : "kelias sekundes";
+        }
+    }
+
+    function translateSingular(number, withoutSuffix, key, isFuture) {
+        return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]);
+    }
+
+    function special(number) {
+        return number % 10 === 0 || (number > 10 && number < 20);
+    }
+
+    function forms(key) {
+        return units[key].split("_");
+    }
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var result = number + " ";
+        if (number === 1) {
+            return result + translateSingular(number, withoutSuffix, key[0], isFuture);
+        } else if (withoutSuffix) {
+            return result + (special(number) ? forms(key)[1] : forms(key)[0]);
+        } else {
+            if (isFuture) {
+                return result + forms(key)[1];
+            } else {
+                return result + (special(number) ? forms(key)[1] : forms(key)[2]);
+            }
+        }
+    }
+
+    function relativeWeekDay(moment, format) {
+        var nominative = format.indexOf('dddd LT') === -1,
+            weekDay = weekDays[moment.weekday()];
+
+        return nominative ? weekDay : weekDay.substring(0, weekDay.length - 2) + "į";
+    }
+
+    return moment.lang("lt", {
+        months : "sausio_vasario_kovo_balandžio_gegužės_biržėlio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),
+        monthsShort : "sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),
+        weekdays : relativeWeekDay,
+        weekdaysShort : "Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),
+        weekdaysMin : "S_P_A_T_K_Pn_Š".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "YYYY-MM-DD",
+            LL : "YYYY [m.] MMMM D [d.]",
+            LLL : "YYYY [m.] MMMM D [d.], LT [val.]",
+            LLLL : "YYYY [m.] MMMM D [d.], dddd, LT [val.]",
+            l : "YYYY-MM-DD",
+            ll : "YYYY [m.] MMMM D [d.]",
+            lll : "YYYY [m.] MMMM D [d.], LT [val.]",
+            llll : "YYYY [m.] MMMM D [d.], ddd, LT [val.]"
+        },
+        calendar : {
+            sameDay : "[Šiandien] LT",
+            nextDay : "[Rytoj] LT",
+            nextWeek : "dddd LT",
+            lastDay : "[Vakar] LT",
+            lastWeek : "[Praėjusį] dddd LT",
+            sameElse : "L"
+        },
+        relativeTime : {
+            future : "po %s",
+            past : "prieš %s",
+            s : translateSeconds,
+            m : translateSingular,
+            mm : translate,
+            h : translateSingular,
+            hh : translate,
+            d : translateSingular,
+            dd : translate,
+            M : translateSingular,
+            MM : translate,
+            y : translateSingular,
+            yy : translate
+        },
+        ordinal : function (number) {
+            return number + '-oji';
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/lv.js b/resources/lib/moment/lang/lv.js
new file mode 100644 (file)
index 0000000..ffe25cf
--- /dev/null
@@ -0,0 +1,77 @@
+// moment.js language configuration
+// language : latvian (lv)
+// author : Kristaps Karlsons : https://github.com/skakri
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var units = {
+        'mm': 'minūti_minūtes_minūte_minūtes',
+        'hh': 'stundu_stundas_stunda_stundas',
+        'dd': 'dienu_dienas_diena_dienas',
+        'MM': 'mēnesi_mēnešus_mēnesis_mēneši',
+        'yy': 'gadu_gadus_gads_gadi'
+    };
+
+    function format(word, number, withoutSuffix) {
+        var forms = word.split('_');
+        if (withoutSuffix) {
+            return number % 10 === 1 && number !== 11 ? forms[2] : forms[3];
+        } else {
+            return number % 10 === 1 && number !== 11 ? forms[0] : forms[1];
+        }
+    }
+
+    function relativeTimeWithPlural(number, withoutSuffix, key) {
+        return number + ' ' + format(units[key], number, withoutSuffix);
+    }
+
+    return moment.lang('lv', {
+        months : "janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),
+        monthsShort : "jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),
+        weekdays : "svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),
+        weekdaysShort : "Sv_P_O_T_C_Pk_S".split("_"),
+        weekdaysMin : "Sv_P_O_T_C_Pk_S".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD.MM.YYYY",
+            LL : "YYYY. [gada] D. MMMM",
+            LLL : "YYYY. [gada] D. MMMM, LT",
+            LLLL : "YYYY. [gada] D. MMMM, dddd, LT"
+        },
+        calendar : {
+            sameDay : '[Šodien pulksten] LT',
+            nextDay : '[Rīt pulksten] LT',
+            nextWeek : 'dddd [pulksten] LT',
+            lastDay : '[Vakar pulksten] LT',
+            lastWeek : '[Pagājušā] dddd [pulksten] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s vēlāk",
+            past : "%s agrāk",
+            s : "dažas sekundes",
+            m : "minūti",
+            mm : relativeTimeWithPlural,
+            h : "stundu",
+            hh : relativeTimeWithPlural,
+            d : "dienu",
+            dd : relativeTimeWithPlural,
+            M : "mēnesi",
+            MM : relativeTimeWithPlural,
+            y : "gadu",
+            yy : relativeTimeWithPlural
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/mk.js b/resources/lib/moment/lang/mk.js
new file mode 100644 (file)
index 0000000..5f272fa
--- /dev/null
@@ -0,0 +1,86 @@
+// moment.js language configuration
+// language : macedonian (mk)
+// author : Borislav Mickov : https://github.com/B0k0
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('mk', {
+        months : "јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември".split("_"),
+        monthsShort : "јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек".split("_"),
+        weekdays : "недела_понеделник_вторник_среда_четврток_петок_сабота".split("_"),
+        weekdaysShort : "нед_пон_вто_сре_чет_пет_саб".split("_"),
+        weekdaysMin : "нe_пo_вт_ср_че_пе_сa".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "D.MM.YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd, D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay : '[Денес во] LT',
+            nextDay : '[Утре во] LT',
+            nextWeek : 'dddd [во] LT',
+            lastDay : '[Вчера во] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[Во изминатата] dddd [во] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[Во изминатиот] dddd [во] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "после %s",
+            past : "пред %s",
+            s : "неколку секунди",
+            m : "минута",
+            mm : "%d минути",
+            h : "час",
+            hh : "%d часа",
+            d : "ден",
+            dd : "%d дена",
+            M : "месец",
+            MM : "%d месеци",
+            y : "година",
+            yy : "%d години"
+        },
+        ordinal : function (number) {
+            var lastDigit = number % 10,
+                last2Digits = number % 100;
+            if (number === 0) {
+                return number + '-ев';
+            } else if (last2Digits === 0) {
+                return number + '-ен';
+            } else if (last2Digits > 10 && last2Digits < 20) {
+                return number + '-ти';
+            } else if (lastDigit === 1) {
+                return number + '-ви';
+            } else if (lastDigit === 2) {
+                return number + '-ри';
+            } else if (lastDigit === 7 || lastDigit === 8) {
+                return number + '-ми';
+            } else {
+                return number + '-ти';
+            }
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/ml.js b/resources/lib/moment/lang/ml.js
new file mode 100644 (file)
index 0000000..cc7db9a
--- /dev/null
@@ -0,0 +1,64 @@
+// moment.js language configuration
+// language : malayalam (ml)
+// author : Floyd Pink : https://github.com/floydpink
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('ml', {
+        months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split("_"),
+        monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split("_"),
+        weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split("_"),
+        weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split("_"),
+        weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split("_"),
+        longDateFormat : {
+            LT : "A h:mm -നു",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY, LT",
+            LLLL : "dddd, D MMMM YYYY, LT"
+        },
+        calendar : {
+            sameDay : '[ഇന്ന്] LT',
+            nextDay : '[നാളെ] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[ഇന്നലെ] LT',
+            lastWeek : '[കഴിഞ്ഞ] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s കഴിഞ്ഞ്",
+            past : "%s മുൻപ്",
+            s : "അൽപ നിമിഷങ്ങൾ",
+            m : "ഒരു മിനിറ്റ്",
+            mm : "%d മിനിറ്റ്",
+            h : "ഒരു മണിക്കൂർ",
+            hh : "%d മണിക്കൂർ",
+            d : "ഒരു ദിവസം",
+            dd : "%d ദിവസം",
+            M : "ഒരു മാസം",
+            MM : "%d മാസം",
+            y : "ഒരു വർഷം",
+            yy : "%d വർഷം"
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return "രാത്രി";
+            } else if (hour < 12) {
+                return "രാവിലെ";
+            } else if (hour < 17) {
+                return "ഉച്ച കഴിഞ്ഞ്";
+            } else if (hour < 20) {
+                return "വൈകുന്നേരം";
+            } else {
+                return "രാത്രി";
+            }
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/mr.js b/resources/lib/moment/lang/mr.js
new file mode 100644 (file)
index 0000000..0d1adfd
--- /dev/null
@@ -0,0 +1,104 @@
+// moment.js language configuration
+// language : Marathi (mr)
+// author : Harshad Kale : https://github.com/kalehv
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '१',
+        '2': '२',
+        '3': '३',
+        '4': '४',
+        '5': '५',
+        '6': '६',
+        '7': '७',
+        '8': '८',
+        '9': '९',
+        '0': '०'
+    },
+    numberMap = {
+        '१': '1',
+        '२': '2',
+        '३': '3',
+        '४': '4',
+        '५': '5',
+        '६': '6',
+        '७': '7',
+        '८': '8',
+        '९': '9',
+        '०': '0'
+    };
+
+    return moment.lang('mr', {
+        months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split("_"),
+        monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split("_"),
+        weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split("_"),
+        weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split("_"),
+        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split("_"),
+        longDateFormat : {
+            LT : "A h:mm वाजता",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY, LT",
+            LLLL : "dddd, D MMMM YYYY, LT"
+        },
+        calendar : {
+            sameDay : '[आज] LT',
+            nextDay : '[उद्या] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[काल] LT',
+            lastWeek: '[मागील] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s नंतर",
+            past : "%s पूर्वी",
+            s : "सेकंद",
+            m: "एक मिनिट",
+            mm: "%d मिनिटे",
+            h : "एक तास",
+            hh : "%d तास",
+            d : "एक दिवस",
+            dd : "%d दिवस",
+            M : "एक महिना",
+            MM : "%d महिने",
+            y : "एक वर्ष",
+            yy : "%d वर्षे"
+        },
+        preparse: function (string) {
+            return string.replace(/[१२३४५६७८९०]/g, function (match) {
+                return numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            });
+        },
+        meridiem: function (hour, minute, isLower)
+        {
+            if (hour < 4) {
+                return "रात्री";
+            } else if (hour < 10) {
+                return "सकाळी";
+            } else if (hour < 17) {
+                return "दुपारी";
+            } else if (hour < 20) {
+                return "सायंकाळी";
+            } else {
+                return "रात्री";
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/ms-my.js b/resources/lib/moment/lang/ms-my.js
new file mode 100644 (file)
index 0000000..501d5aa
--- /dev/null
@@ -0,0 +1,66 @@
+// moment.js language configuration
+// language : Bahasa Malaysia (ms-MY)
+// author : Weldan Jamili : https://github.com/weldan
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('ms-my', {
+        months : "Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),
+        monthsShort : "Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),
+        weekdays : "Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),
+        weekdaysShort : "Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),
+        weekdaysMin : "Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),
+        longDateFormat : {
+            LT : "HH.mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY [pukul] LT",
+            LLLL : "dddd, D MMMM YYYY [pukul] LT"
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 11) {
+                return 'pagi';
+            } else if (hours < 15) {
+                return 'tengahari';
+            } else if (hours < 19) {
+                return 'petang';
+            } else {
+                return 'malam';
+            }
+        },
+        calendar : {
+            sameDay : '[Hari ini pukul] LT',
+            nextDay : '[Esok pukul] LT',
+            nextWeek : 'dddd [pukul] LT',
+            lastDay : '[Kelmarin pukul] LT',
+            lastWeek : 'dddd [lepas pukul] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "dalam %s",
+            past : "%s yang lepas",
+            s : "beberapa saat",
+            m : "seminit",
+            mm : "%d minit",
+            h : "sejam",
+            hh : "%d jam",
+            d : "sehari",
+            dd : "%d hari",
+            M : "sebulan",
+            MM : "%d bulan",
+            y : "setahun",
+            yy : "%d tahun"
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/nb.js b/resources/lib/moment/lang/nb.js
new file mode 100644 (file)
index 0000000..2f652ef
--- /dev/null
@@ -0,0 +1,57 @@
+// moment.js language configuration
+// language : norwegian bokmål (nb)
+// authors : Espen Hovlandsdal : https://github.com/rexxars
+//           Sigurd Gartmann : https://github.com/sigurdga
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('nb', {
+        months : "januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),
+        monthsShort : "jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.".split("_"),
+        weekdays : "søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),
+        weekdaysShort : "sø._ma._ti._on._to._fr._lø.".split("_"),
+        weekdaysMin : "sø_ma_ti_on_to_fr_lø".split("_"),
+        longDateFormat : {
+            LT : "H.mm",
+            L : "DD.MM.YYYY",
+            LL : "D. MMMM YYYY",
+            LLL : "D. MMMM YYYY [kl.] LT",
+            LLLL : "dddd D. MMMM YYYY [kl.] LT"
+        },
+        calendar : {
+            sameDay: '[i dag kl.] LT',
+            nextDay: '[i morgen kl.] LT',
+            nextWeek: 'dddd [kl.] LT',
+            lastDay: '[i går kl.] LT',
+            lastWeek: '[forrige] dddd [kl.] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "om %s",
+            past : "for %s siden",
+            s : "noen sekunder",
+            m : "ett minutt",
+            mm : "%d minutter",
+            h : "en time",
+            hh : "%d timer",
+            d : "en dag",
+            dd : "%d dager",
+            M : "en måned",
+            MM : "%d måneder",
+            y : "ett år",
+            yy : "%d år"
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/ne.js b/resources/lib/moment/lang/ne.js
new file mode 100644 (file)
index 0000000..1d57b8c
--- /dev/null
@@ -0,0 +1,105 @@
+// moment.js language configuration
+// language : nepali/nepalese
+// author : suvash : https://github.com/suvash
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var symbolMap = {
+        '1': '१',
+        '2': '२',
+        '3': '३',
+        '4': '४',
+        '5': '५',
+        '6': '६',
+        '7': '७',
+        '8': '८',
+        '9': '९',
+        '0': '०'
+    },
+    numberMap = {
+        '१': '1',
+        '२': '2',
+        '३': '3',
+        '४': '4',
+        '५': '5',
+        '६': '6',
+        '७': '7',
+        '८': '8',
+        '९': '9',
+        '०': '0'
+    };
+
+    return moment.lang('ne', {
+        months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split("_"),
+        monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split("_"),
+        weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split("_"),
+        weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split("_"),
+        weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split("_"),
+        longDateFormat : {
+            LT : "Aको h:mm बजे",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY, LT",
+            LLLL : "dddd, D MMMM YYYY, LT"
+        },
+        preparse: function (string) {
+            return string.replace(/[१२३४५६७८९०]/g, function (match) {
+                return numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            });
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 3) {
+                return "राती";
+            } else if (hour < 10) {
+                return "बिहान";
+            } else if (hour < 15) {
+                return "दिउँसो";
+            } else if (hour < 18) {
+                return "बेलुका";
+            } else if (hour < 20) {
+                return "साँझ";
+            } else {
+                return "राती";
+            }
+        },
+        calendar : {
+            sameDay : '[आज] LT',
+            nextDay : '[भोली] LT',
+            nextWeek : '[आउँदो] dddd[,] LT',
+            lastDay : '[हिजो] LT',
+            lastWeek : '[गएको] dddd[,] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%sमा",
+            past : "%s अगाडी",
+            s : "केही समय",
+            m : "एक मिनेट",
+            mm : "%d मिनेट",
+            h : "एक घण्टा",
+            hh : "%d घण्टा",
+            d : "एक दिन",
+            dd : "%d दिन",
+            M : "एक महिना",
+            MM : "%d महिना",
+            y : "एक बर्ष",
+            yy : "%d बर्ष"
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/nl.js b/resources/lib/moment/lang/nl.js
new file mode 100644 (file)
index 0000000..ffd454f
--- /dev/null
@@ -0,0 +1,67 @@
+// moment.js language configuration
+// language : dutch (nl)
+// author : Joris Röling : https://github.com/jjupiter
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var monthsShortWithDots = "jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),
+        monthsShortWithoutDots = "jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_");
+
+    return moment.lang('nl', {
+        months : "januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),
+        monthsShort : function (m, format) {
+            if (/-MMM-/.test(format)) {
+                return monthsShortWithoutDots[m.month()];
+            } else {
+                return monthsShortWithDots[m.month()];
+            }
+        },
+        weekdays : "zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),
+        weekdaysShort : "zo._ma._di._wo._do._vr._za.".split("_"),
+        weekdaysMin : "Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD-MM-YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: '[vandaag om] LT',
+            nextDay: '[morgen om] LT',
+            nextWeek: 'dddd [om] LT',
+            lastDay: '[gisteren om] LT',
+            lastWeek: '[afgelopen] dddd [om] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "over %s",
+            past : "%s geleden",
+            s : "een paar seconden",
+            m : "één minuut",
+            mm : "%d minuten",
+            h : "één uur",
+            hh : "%d uur",
+            d : "één dag",
+            dd : "%d dagen",
+            M : "één maand",
+            MM : "%d maanden",
+            y : "één jaar",
+            yy : "%d jaar"
+        },
+        ordinal : function (number) {
+            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/nn.js b/resources/lib/moment/lang/nn.js
new file mode 100644 (file)
index 0000000..f59c415
--- /dev/null
@@ -0,0 +1,56 @@
+// moment.js language configuration
+// language : norwegian nynorsk (nn)
+// author : https://github.com/mechuwind
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('nn', {
+        months : "januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),
+        monthsShort : "jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),
+        weekdays : "sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),
+        weekdaysShort : "sun_mån_tys_ons_tor_fre_lau".split("_"),
+        weekdaysMin : "su_må_ty_on_to_fr_lø".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD.MM.YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: '[I dag klokka] LT',
+            nextDay: '[I morgon klokka] LT',
+            nextWeek: 'dddd [klokka] LT',
+            lastDay: '[I går klokka] LT',
+            lastWeek: '[Føregående] dddd [klokka] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "om %s",
+            past : "for %s siden",
+            s : "noen sekund",
+            m : "ett minutt",
+            mm : "%d minutt",
+            h : "en time",
+            hh : "%d timar",
+            d : "en dag",
+            dd : "%d dagar",
+            M : "en månad",
+            MM : "%d månader",
+            y : "ett år",
+            yy : "%d år"
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/pl.js b/resources/lib/moment/lang/pl.js
new file mode 100644 (file)
index 0000000..97770d2
--- /dev/null
@@ -0,0 +1,98 @@
+// moment.js language configuration
+// language : polish (pl)
+// author : Rafal Hirsz : https://github.com/evoL
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var monthsNominative = "styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),
+        monthsSubjective = "stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_");
+
+    function plural(n) {
+        return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1);
+    }
+
+    function translate(number, withoutSuffix, key) {
+        var result = number + " ";
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'minuta' : 'minutę';
+        case 'mm':
+            return result + (plural(number) ? 'minuty' : 'minut');
+        case 'h':
+            return withoutSuffix  ? 'godzina'  : 'godzinę';
+        case 'hh':
+            return result + (plural(number) ? 'godziny' : 'godzin');
+        case 'MM':
+            return result + (plural(number) ? 'miesiące' : 'miesięcy');
+        case 'yy':
+            return result + (plural(number) ? 'lata' : 'lat');
+        }
+    }
+
+    return moment.lang('pl', {
+        months : function (momentToFormat, format) {
+            if (/D MMMM/.test(format)) {
+                return monthsSubjective[momentToFormat.month()];
+            } else {
+                return monthsNominative[momentToFormat.month()];
+            }
+        },
+        monthsShort : "sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),
+        weekdays : "niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),
+        weekdaysShort : "nie_pon_wt_śr_czw_pt_sb".split("_"),
+        weekdaysMin : "N_Pn_Wt_Śr_Cz_Pt_So".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD.MM.YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd, D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: '[Dziś o] LT',
+            nextDay: '[Jutro o] LT',
+            nextWeek: '[W] dddd [o] LT',
+            lastDay: '[Wczoraj o] LT',
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[W zeszłą niedzielę o] LT';
+                case 3:
+                    return '[W zeszłą środę o] LT';
+                case 6:
+                    return '[W zeszłą sobotę o] LT';
+                default:
+                    return '[W zeszły] dddd [o] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "za %s",
+            past : "%s temu",
+            s : "kilka sekund",
+            m : translate,
+            mm : translate,
+            h : translate,
+            hh : translate,
+            d : "1 dzień",
+            dd : '%d dni',
+            M : "miesiąc",
+            MM : translate,
+            y : "rok",
+            yy : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/pt-br.js b/resources/lib/moment/lang/pt-br.js
new file mode 100644 (file)
index 0000000..5cac19b
--- /dev/null
@@ -0,0 +1,56 @@
+// moment.js language configuration
+// language : brazilian portuguese (pt-br)
+// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('pt-br', {
+        months : "Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),
+        monthsShort : "Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),
+        weekdays : "Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),
+        weekdaysShort : "Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),
+        weekdaysMin : "Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D [de] MMMM [de] YYYY",
+            LLL : "D [de] MMMM [de] YYYY LT",
+            LLLL : "dddd, D [de] MMMM [de] YYYY LT"
+        },
+        calendar : {
+            sameDay: '[Hoje às] LT',
+            nextDay: '[Amanhã às] LT',
+            nextWeek: 'dddd [às] LT',
+            lastDay: '[Ontem às] LT',
+            lastWeek: function () {
+                return (this.day() === 0 || this.day() === 6) ?
+                    '[Último] dddd [às] LT' : // Saturday + Sunday
+                    '[Última] dddd [às] LT'; // Monday - Friday
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "em %s",
+            past : "%s atrás",
+            s : "segundos",
+            m : "um minuto",
+            mm : "%d minutos",
+            h : "uma hora",
+            hh : "%d horas",
+            d : "um dia",
+            dd : "%d dias",
+            M : "um mês",
+            MM : "%d meses",
+            y : "um ano",
+            yy : "%d anos"
+        },
+        ordinal : '%dº'
+    });
+}));
diff --git a/resources/lib/moment/lang/pt.js b/resources/lib/moment/lang/pt.js
new file mode 100644 (file)
index 0000000..7c1f2b5
--- /dev/null
@@ -0,0 +1,60 @@
+// moment.js language configuration
+// language : portuguese (pt)
+// author : Jefferson : https://github.com/jalex79
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('pt', {
+        months : "Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),
+        monthsShort : "Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),
+        weekdays : "Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),
+        weekdaysShort : "Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),
+        weekdaysMin : "Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D [de] MMMM [de] YYYY",
+            LLL : "D [de] MMMM [de] YYYY LT",
+            LLLL : "dddd, D [de] MMMM [de] YYYY LT"
+        },
+        calendar : {
+            sameDay: '[Hoje às] LT',
+            nextDay: '[Amanhã às] LT',
+            nextWeek: 'dddd [às] LT',
+            lastDay: '[Ontem às] LT',
+            lastWeek: function () {
+                return (this.day() === 0 || this.day() === 6) ?
+                    '[Último] dddd [às] LT' : // Saturday + Sunday
+                    '[Última] dddd [às] LT'; // Monday - Friday
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "em %s",
+            past : "%s atrás",
+            s : "segundos",
+            m : "um minuto",
+            mm : "%d minutos",
+            h : "uma hora",
+            hh : "%d horas",
+            d : "um dia",
+            dd : "%d dias",
+            M : "um mês",
+            MM : "%d meses",
+            y : "um ano",
+            yy : "%d anos"
+        },
+        ordinal : '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/ro.js b/resources/lib/moment/lang/ro.js
new file mode 100644 (file)
index 0000000..77d7355
--- /dev/null
@@ -0,0 +1,72 @@
+// moment.js language configuration
+// language : romanian (ro)
+// author : Vlad Gurdiga : https://github.com/gurdiga
+// author : Valentin Agachi : https://github.com/avaly
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function relativeTimeWithPlural(number, withoutSuffix, key) {
+        var format = {
+            'mm': 'minute',
+            'hh': 'ore',
+            'dd': 'zile',
+            'MM': 'luni',
+            'yy': 'ani'
+        },
+            separator = ' ';
+        if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) {
+            separator = ' de ';
+        }
+
+        return number + separator + format[key];
+    }
+
+    return moment.lang('ro', {
+        months : "ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),
+        monthsShort : "ian_feb_mar_apr_mai_iun_iul_aug_sep_oct_noi_dec".split("_"),
+        weekdays : "duminică_luni_marți_miercuri_joi_vineri_sâmbătă".split("_"),
+        weekdaysShort : "Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),
+        weekdaysMin : "Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "DD.MM.YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY H:mm",
+            LLLL : "dddd, D MMMM YYYY H:mm"
+        },
+        calendar : {
+            sameDay: "[azi la] LT",
+            nextDay: '[mâine la] LT',
+            nextWeek: 'dddd [la] LT',
+            lastDay: '[ieri la] LT',
+            lastWeek: '[fosta] dddd [la] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "peste %s",
+            past : "%s în urmă",
+            s : "câteva secunde",
+            m : "un minut",
+            mm : relativeTimeWithPlural,
+            h : "o oră",
+            hh : relativeTimeWithPlural,
+            d : "o zi",
+            dd : relativeTimeWithPlural,
+            M : "o lună",
+            MM : relativeTimeWithPlural,
+            y : "un an",
+            yy : relativeTimeWithPlural
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/rs.js b/resources/lib/moment/lang/rs.js
new file mode 100644 (file)
index 0000000..8627553
--- /dev/null
@@ -0,0 +1,139 @@
+// moment.js language configuration
+// language : serbian (rs)
+// author : Limon Monte : https://github.com/limonte
+// based on (bs) translation by Nedim Cholich
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+
+    function translate(number, withoutSuffix, key) {
+        var result = number + " ";
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+        case 'mm':
+            if (number === 1) {
+                result += 'minuta';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'minute';
+            } else {
+                result += 'minuta';
+            }
+            return result;
+        case 'h':
+            return withoutSuffix ? 'jedan sat' : 'jednog sata';
+        case 'hh':
+            if (number === 1) {
+                result += 'sat';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'sata';
+            } else {
+                result += 'sati';
+            }
+            return result;
+        case 'dd':
+            if (number === 1) {
+                result += 'dan';
+            } else {
+                result += 'dana';
+            }
+            return result;
+        case 'MM':
+            if (number === 1) {
+                result += 'mesec';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'meseca';
+            } else {
+                result += 'meseci';
+            }
+            return result;
+        case 'yy':
+            if (number === 1) {
+                result += 'godina';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'godine';
+            } else {
+                result += 'godina';
+            }
+            return result;
+        }
+    }
+
+    return moment.lang('rs', {
+        months : "januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),
+        monthsShort : "jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),
+        weekdays : "nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),
+        weekdaysShort : "ned._pon._uto._sre._čet._pet._sub.".split("_"),
+        weekdaysMin : "ne_po_ut_sr_če_pe_su".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "DD. MM. YYYY",
+            LL : "D. MMMM YYYY",
+            LLL : "D. MMMM YYYY LT",
+            LLLL : "dddd, D. MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay  : '[danas u] LT',
+            nextDay  : '[sutra u] LT',
+
+            nextWeek : function () {
+                switch (this.day()) {
+                case 0:
+                    return '[u] [nedelju] [u] LT';
+                case 3:
+                    return '[u] [sredu] [u] LT';
+                case 6:
+                    return '[u] [subotu] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[u] dddd [u] LT';
+                }
+            },
+            lastDay  : '[juče u] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                    return '[prošlu] dddd [u] LT';
+                case 6:
+                    return '[prošle] [subote] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[prošli] dddd [u] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "za %s",
+            past   : "pre %s",
+            s      : "par sekundi",
+            m      : translate,
+            mm     : translate,
+            h      : translate,
+            hh     : translate,
+            d      : "dan",
+            dd     : translate,
+            M      : "mesec",
+            MM     : translate,
+            y      : "godinu",
+            yy     : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/ru.js b/resources/lib/moment/lang/ru.js
new file mode 100644 (file)
index 0000000..1d1816c
--- /dev/null
@@ -0,0 +1,163 @@
+// moment.js language configuration
+// language : russian (ru)
+// author : Viktorminator : https://github.com/Viktorminator
+// Author : Menelion Elensúle : https://github.com/Oire
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function plural(word, num) {
+        var forms = word.split('_');
+        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+    }
+
+    function relativeTimeWithPlural(number, withoutSuffix, key) {
+        var format = {
+            'mm': 'минута_минуты_минут',
+            'hh': 'час_часа_часов',
+            'dd': 'день_дня_дней',
+            'MM': 'месяц_месяца_месяцев',
+            'yy': 'год_года_лет'
+        };
+        if (key === 'm') {
+            return withoutSuffix ? 'минута' : 'минуту';
+        }
+        else {
+            return number + ' ' + plural(format[key], +number);
+        }
+    }
+
+    function monthsCaseReplace(m, format) {
+        var months = {
+            'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'),
+            'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_')
+        },
+
+        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return months[nounCase][m.month()];
+    }
+
+    function monthsShortCaseReplace(m, format) {
+        var monthsShort = {
+            'nominative': 'янв_фев_мар_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'),
+            'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_')
+        },
+
+        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return monthsShort[nounCase][m.month()];
+    }
+
+    function weekdaysCaseReplace(m, format) {
+        var weekdays = {
+            'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
+            'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_')
+        },
+
+        nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую)? ?\] ?dddd/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return weekdays[nounCase][m.day()];
+    }
+
+    return moment.lang('ru', {
+        months : monthsCaseReplace,
+        monthsShort : monthsShortCaseReplace,
+        weekdays : weekdaysCaseReplace,
+        weekdaysShort : "вс_пн_вт_ср_чт_пт_сб".split("_"),
+        weekdaysMin : "вс_пн_вт_ср_чт_пт_сб".split("_"),
+        monthsParse : [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[й|я]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i],
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD.MM.YYYY",
+            LL : "D MMMM YYYY г.",
+            LLL : "D MMMM YYYY г., LT",
+            LLLL : "dddd, D MMMM YYYY г., LT"
+        },
+        calendar : {
+            sameDay: '[Сегодня в] LT',
+            nextDay: '[Завтра в] LT',
+            lastDay: '[Вчера в] LT',
+            nextWeek: function () {
+                return this.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT';
+            },
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[В прошлое] dddd [в] LT';
+                case 1:
+                case 2:
+                case 4:
+                    return '[В прошлый] dddd [в] LT';
+                case 3:
+                case 5:
+                case 6:
+                    return '[В прошлую] dddd [в] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "через %s",
+            past : "%s назад",
+            s : "несколько секунд",
+            m : relativeTimeWithPlural,
+            mm : relativeTimeWithPlural,
+            h : "час",
+            hh : relativeTimeWithPlural,
+            d : "день",
+            dd : relativeTimeWithPlural,
+            M : "месяц",
+            MM : relativeTimeWithPlural,
+            y : "год",
+            yy : relativeTimeWithPlural
+        },
+
+        // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
+
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return "ночи";
+            } else if (hour < 12) {
+                return "утра";
+            } else if (hour < 17) {
+                return "дня";
+            } else {
+                return "вечера";
+            }
+        },
+
+        ordinal: function (number, period) {
+            switch (period) {
+            case 'M':
+            case 'd':
+            case 'DDD':
+                return number + '-й';
+            case 'D':
+                return number + '-го';
+            case 'w':
+            case 'W':
+                return number + '-я';
+            default:
+                return number;
+            }
+        },
+
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/sk.js b/resources/lib/moment/lang/sk.js
new file mode 100644 (file)
index 0000000..ed8a41d
--- /dev/null
@@ -0,0 +1,156 @@
+// moment.js language configuration
+// language : slovak (sk)
+// author : Martin Minka : https://github.com/k2s
+// based on work of petrbela : https://github.com/petrbela
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    var months = "január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"),
+        monthsShort = "jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_");
+
+    function plural(n) {
+        return (n > 1) && (n < 5);
+    }
+
+    function translate(number, withoutSuffix, key, isFuture) {
+        var result = number + " ";
+        switch (key) {
+        case 's':  // a few seconds / in a few seconds / a few seconds ago
+            return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami';
+        case 'm':  // a minute / in a minute / a minute ago
+            return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou');
+        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'minúty' : 'minút');
+            } else {
+                return result + 'minútami';
+            }
+            break;
+        case 'h':  // an hour / in an hour / an hour ago
+            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
+        case 'hh': // 9 hours / in 9 hours / 9 hours ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'hodiny' : 'hodín');
+            } else {
+                return result + 'hodinami';
+            }
+            break;
+        case 'd':  // a day / in a day / a day ago
+            return (withoutSuffix || isFuture) ? 'deň' : 'dňom';
+        case 'dd': // 9 days / in 9 days / 9 days ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'dni' : 'dní');
+            } else {
+                return result + 'dňami';
+            }
+            break;
+        case 'M':  // a month / in a month / a month ago
+            return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom';
+        case 'MM': // 9 months / in 9 months / 9 months ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'mesiace' : 'mesiacov');
+            } else {
+                return result + 'mesiacmi';
+            }
+            break;
+        case 'y':  // a year / in a year / a year ago
+            return (withoutSuffix || isFuture) ? 'rok' : 'rokom';
+        case 'yy': // 9 years / in 9 years / 9 years ago
+            if (withoutSuffix || isFuture) {
+                return result + (plural(number) ? 'roky' : 'rokov');
+            } else {
+                return result + 'rokmi';
+            }
+            break;
+        }
+    }
+
+    return moment.lang('sk', {
+        months : months,
+        monthsShort : monthsShort,
+        monthsParse : (function (months, monthsShort) {
+            var i, _monthsParse = [];
+            for (i = 0; i < 12; i++) {
+                // use custom parser to solve problem with July (červenec)
+                _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
+            }
+            return _monthsParse;
+        }(months, monthsShort)),
+        weekdays : "nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"),
+        weekdaysShort : "ne_po_ut_st_št_pi_so".split("_"),
+        weekdaysMin : "ne_po_ut_st_št_pi_so".split("_"),
+        longDateFormat : {
+            LT: "H:mm",
+            L : "DD.MM.YYYY",
+            LL : "D. MMMM YYYY",
+            LLL : "D. MMMM YYYY LT",
+            LLLL : "dddd D. MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: "[dnes o] LT",
+            nextDay: '[zajtra o] LT',
+            nextWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[v nedeľu o] LT';
+                case 1:
+                case 2:
+                    return '[v] dddd [o] LT';
+                case 3:
+                    return '[v stredu o] LT';
+                case 4:
+                    return '[vo štvrtok o] LT';
+                case 5:
+                    return '[v piatok o] LT';
+                case 6:
+                    return '[v sobotu o] LT';
+                }
+            },
+            lastDay: '[včera o] LT',
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[minulú nedeľu o] LT';
+                case 1:
+                case 2:
+                    return '[minulý] dddd [o] LT';
+                case 3:
+                    return '[minulú stredu o] LT';
+                case 4:
+                case 5:
+                    return '[minulý] dddd [o] LT';
+                case 6:
+                    return '[minulú sobotu o] LT';
+                }
+            },
+            sameElse: "L"
+        },
+        relativeTime : {
+            future : "za %s",
+            past : "pred %s",
+            s : translate,
+            m : translate,
+            mm : translate,
+            h : translate,
+            hh : translate,
+            d : translate,
+            dd : translate,
+            M : translate,
+            MM : translate,
+            y : translate,
+            yy : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/sl.js b/resources/lib/moment/lang/sl.js
new file mode 100644 (file)
index 0000000..d260f80
--- /dev/null
@@ -0,0 +1,144 @@
+// moment.js language configuration
+// language : slovenian (sl)
+// author : Robert Sedovšek : https://github.com/sedovsek
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function translate(number, withoutSuffix, key) {
+        var result = number + " ";
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'ena minuta' : 'eno minuto';
+        case 'mm':
+            if (number === 1) {
+                result += 'minuta';
+            } else if (number === 2) {
+                result += 'minuti';
+            } else if (number === 3 || number === 4) {
+                result += 'minute';
+            } else {
+                result += 'minut';
+            }
+            return result;
+        case 'h':
+            return withoutSuffix ? 'ena ura' : 'eno uro';
+        case 'hh':
+            if (number === 1) {
+                result += 'ura';
+            } else if (number === 2) {
+                result += 'uri';
+            } else if (number === 3 || number === 4) {
+                result += 'ure';
+            } else {
+                result += 'ur';
+            }
+            return result;
+        case 'dd':
+            if (number === 1) {
+                result += 'dan';
+            } else {
+                result += 'dni';
+            }
+            return result;
+        case 'MM':
+            if (number === 1) {
+                result += 'mesec';
+            } else if (number === 2) {
+                result += 'meseca';
+            } else if (number === 3 || number === 4) {
+                result += 'mesece';
+            } else {
+                result += 'mesecev';
+            }
+            return result;
+        case 'yy':
+            if (number === 1) {
+                result += 'leto';
+            } else if (number === 2) {
+                result += 'leti';
+            } else if (number === 3 || number === 4) {
+                result += 'leta';
+            } else {
+                result += 'let';
+            }
+            return result;
+        }
+    }
+
+    return moment.lang('sl', {
+        months : "januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),
+        monthsShort : "jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),
+        weekdays : "nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),
+        weekdaysShort : "ned._pon._tor._sre._čet._pet._sob.".split("_"),
+        weekdaysMin : "ne_po_to_sr_če_pe_so".split("_"),
+        longDateFormat : {
+            LT : "H:mm",
+            L : "DD. MM. YYYY",
+            LL : "D. MMMM YYYY",
+            LLL : "D. MMMM YYYY LT",
+            LLLL : "dddd, D. MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay  : '[danes ob] LT',
+            nextDay  : '[jutri ob] LT',
+
+            nextWeek : function () {
+                switch (this.day()) {
+                case 0:
+                    return '[v] [nedeljo] [ob] LT';
+                case 3:
+                    return '[v] [sredo] [ob] LT';
+                case 6:
+                    return '[v] [soboto] [ob] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[v] dddd [ob] LT';
+                }
+            },
+            lastDay  : '[včeraj ob] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[prejšnja] dddd [ob] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[prejšnji] dddd [ob] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "čez %s",
+            past   : "%s nazaj",
+            s      : "nekaj sekund",
+            m      : translate,
+            mm     : translate,
+            h      : translate,
+            hh     : translate,
+            d      : "en dan",
+            dd     : translate,
+            M      : "en mesec",
+            MM     : translate,
+            y      : "eno leto",
+            yy     : translate
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/sq.js b/resources/lib/moment/lang/sq.js
new file mode 100644 (file)
index 0000000..a5e44b5
--- /dev/null
@@ -0,0 +1,57 @@
+// moment.js language configuration
+// language : Albanian (sq)
+// author : Flakërim Ismani : https://github.com/flakerimi
+// author: Menelion Elensúle: https://github.com/Oire (tests)
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('sq', {
+        months : "Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"),
+        monthsShort : "Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"),
+        weekdays : "E Diel_E Hënë_E Marte_E Mërkure_E Enjte_E Premte_E Shtunë".split("_"),
+        weekdaysShort : "Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"),
+        weekdaysMin : "D_H_Ma_Më_E_P_Sh".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd, D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay : '[Sot në] LT',
+            nextDay : '[Neser në] LT',
+            nextWeek : 'dddd [në] LT',
+            lastDay : '[Dje në] LT',
+            lastWeek : 'dddd [e kaluar në] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "në %s",
+            past : "%s me parë",
+            s : "disa sekonda",
+            m : "një minut",
+            mm : "%d minuta",
+            h : "një orë",
+            hh : "%d orë",
+            d : "një ditë",
+            dd : "%d ditë",
+            M : "një muaj",
+            MM : "%d muaj",
+            y : "një vit",
+            yy : "%d vite"
+        },
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/sv.js b/resources/lib/moment/lang/sv.js
new file mode 100644 (file)
index 0000000..0de8c40
--- /dev/null
@@ -0,0 +1,63 @@
+// moment.js language configuration
+// language : swedish (sv)
+// author : Jens Alm : https://github.com/ulmus
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('sv', {
+        months : "januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),
+        monthsShort : "jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),
+        weekdays : "söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),
+        weekdaysShort : "sön_mån_tis_ons_tor_fre_lör".split("_"),
+        weekdaysMin : "sö_må_ti_on_to_fr_lö".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "YYYY-MM-DD",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: '[Idag] LT',
+            nextDay: '[Imorgon] LT',
+            lastDay: '[Igår] LT',
+            nextWeek: 'dddd LT',
+            lastWeek: '[Förra] dddd[en] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "om %s",
+            past : "för %s sedan",
+            s : "några sekunder",
+            m : "en minut",
+            mm : "%d minuter",
+            h : "en timme",
+            hh : "%d timmar",
+            d : "en dag",
+            dd : "%d dagar",
+            M : "en månad",
+            MM : "%d månader",
+            y : "ett år",
+            yy : "%d år"
+        },
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~ (number % 100 / 10) === 1) ? 'e' :
+                (b === 1) ? 'a' :
+                (b === 2) ? 'a' :
+                (b === 3) ? 'e' : 'e';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/ta.js b/resources/lib/moment/lang/ta.js
new file mode 100644 (file)
index 0000000..cc742c9
--- /dev/null
@@ -0,0 +1,112 @@
+// moment.js language configuration
+// language : tamil (ta)
+// author : Arjunkumar Krishnamoorthy : https://github.com/tk120404
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    /*var symbolMap = {
+            '1': '௧',
+            '2': '௨',
+            '3': '௩',
+            '4': '௪',
+            '5': '௫',
+            '6': '௬',
+            '7': '௭',
+            '8': '௮',
+            '9': '௯',
+            '0': '௦'
+        },
+        numberMap = {
+            '௧': '1',
+            '௨': '2',
+            '௩': '3',
+            '௪': '4',
+            '௫': '5',
+            '௬': '6',
+            '௭': '7',
+            '௮': '8',
+            '௯': '9',
+            '௦': '0'
+        }; */
+
+    return moment.lang('ta', {
+        months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split("_"),
+        monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split("_"),
+        weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split("_"),
+        weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split("_"),
+        weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY, LT",
+            LLLL : "dddd, D MMMM YYYY, LT"
+        },
+        calendar : {
+            sameDay : '[இன்று] LT',
+            nextDay : '[நாளை] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[நேற்று] LT',
+            lastWeek : '[கடந்த வாரம்] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s இல்",
+            past : "%s முன்",
+            s : "ஒரு சில விநாடிகள்",
+            m : "ஒரு நிமிடம்",
+            mm : "%d நிமிடங்கள்",
+            h : "ஒரு மணி நேரம்",
+            hh : "%d மணி நேரம்",
+            d : "ஒரு நாள்",
+            dd : "%d நாட்கள்",
+            M : "ஒரு மாதம்",
+            MM : "%d மாதங்கள்",
+            y : "ஒரு வருடம்",
+            yy : "%d ஆண்டுகள்"
+        },
+/*        preparse: function (string) {
+            return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) {
+                return numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return symbolMap[match];
+            });
+        },*/
+        ordinal : function (number) {
+            return number + 'வது';
+        },
+
+
+// refer http://ta.wikipedia.org/s/1er1      
+
+        meridiem : function (hour, minute, isLower) {
+            if (hour >= 6 && hour <= 10) {
+                return " காலை";
+            } else   if (hour >= 10 && hour <= 14) {
+                return " நண்பகல்";
+            } else    if (hour >= 14 && hour <= 18) {
+                return " எற்பாடு";
+            } else   if (hour >= 18 && hour <= 20) {
+                return " மாலை";
+            } else  if (hour >= 20 && hour <= 24) {
+                return " இரவு";
+            } else  if (hour >= 0 && hour <= 6) {
+                return " வைகறை";
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/th.js b/resources/lib/moment/lang/th.js
new file mode 100644 (file)
index 0000000..70336c8
--- /dev/null
@@ -0,0 +1,58 @@
+// moment.js language configuration
+// language : thai (th)
+// author : Kridsada Thanabulpong : https://github.com/sirn
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('th', {
+        months : "มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),
+        monthsShort : "มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา".split("_"),
+        weekdays : "อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),
+        weekdaysShort : "อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"), // yes, three characters difference
+        weekdaysMin : "อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),
+        longDateFormat : {
+            LT : "H นาฬิกา m นาที",
+            L : "YYYY/MM/DD",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY เวลา LT",
+            LLLL : "วันddddที่ D MMMM YYYY เวลา LT"
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return "ก่อนเที่ยง";
+            } else {
+                return "หลังเที่ยง";
+            }
+        },
+        calendar : {
+            sameDay : '[วันนี้ เวลา] LT',
+            nextDay : '[พรุ่งนี้ เวลา] LT',
+            nextWeek : 'dddd[หน้า เวลา] LT',
+            lastDay : '[เมื่อวานนี้ เวลา] LT',
+            lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "อีก %s",
+            past : "%sที่แล้ว",
+            s : "ไม่กี่วินาที",
+            m : "1 นาที",
+            mm : "%d นาที",
+            h : "1 ชั่วโมง",
+            hh : "%d ชั่วโมง",
+            d : "1 วัน",
+            dd : "%d วัน",
+            M : "1 เดือน",
+            MM : "%d เดือน",
+            y : "1 ปี",
+            yy : "%d ปี"
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/tl-ph.js b/resources/lib/moment/lang/tl-ph.js
new file mode 100644 (file)
index 0000000..8044483
--- /dev/null
@@ -0,0 +1,58 @@
+// moment.js language configuration
+// language : Tagalog/Filipino (tl-ph)
+// author : Dan Hagman
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('tl-ph', {
+        months : "Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),
+        monthsShort : "Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),
+        weekdays : "Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),
+        weekdaysShort : "Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),
+        weekdaysMin : "Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "MM/D/YYYY",
+            LL : "MMMM D, YYYY",
+            LLL : "MMMM D, YYYY LT",
+            LLLL : "dddd, MMMM DD, YYYY LT"
+        },
+        calendar : {
+            sameDay: "[Ngayon sa] LT",
+            nextDay: '[Bukas sa] LT',
+            nextWeek: 'dddd [sa] LT',
+            lastDay: '[Kahapon sa] LT',
+            lastWeek: 'dddd [huling linggo] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "sa loob ng %s",
+            past : "%s ang nakalipas",
+            s : "ilang segundo",
+            m : "isang minuto",
+            mm : "%d minuto",
+            h : "isang oras",
+            hh : "%d oras",
+            d : "isang araw",
+            dd : "%d araw",
+            M : "isang buwan",
+            MM : "%d buwan",
+            y : "isang taon",
+            yy : "%d taon"
+        },
+        ordinal : function (number) {
+            return number;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/tr.js b/resources/lib/moment/lang/tr.js
new file mode 100644 (file)
index 0000000..e90f250
--- /dev/null
@@ -0,0 +1,93 @@
+// moment.js language configuration
+// language : turkish (tr)
+// authors : Erhan Gundogan : https://github.com/erhangundogan,
+//           Burak Yiğit Kaya: https://github.com/BYK
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+
+    var suffixes = {
+        1: "'inci",
+        5: "'inci",
+        8: "'inci",
+        70: "'inci",
+        80: "'inci",
+
+        2: "'nci",
+        7: "'nci",
+        20: "'nci",
+        50: "'nci",
+
+        3: "'üncü",
+        4: "'üncü",
+        100: "'üncü",
+
+        6: "'ncı",
+
+        9: "'uncu",
+        10: "'uncu",
+        30: "'uncu",
+
+        60: "'ıncı",
+        90: "'ıncı"
+    };
+
+    return moment.lang('tr', {
+        months : "Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),
+        monthsShort : "Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),
+        weekdays : "Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),
+        weekdaysShort : "Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),
+        weekdaysMin : "Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD.MM.YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd, D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay : '[bugün saat] LT',
+            nextDay : '[yarın saat] LT',
+            nextWeek : '[haftaya] dddd [saat] LT',
+            lastDay : '[dün] LT',
+            lastWeek : '[geçen hafta] dddd [saat] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "%s sonra",
+            past : "%s önce",
+            s : "birkaç saniye",
+            m : "bir dakika",
+            mm : "%d dakika",
+            h : "bir saat",
+            hh : "%d saat",
+            d : "bir gün",
+            dd : "%d gün",
+            M : "bir ay",
+            MM : "%d ay",
+            y : "bir yıl",
+            yy : "%d yıl"
+        },
+        ordinal : function (number) {
+            if (number === 0) {  // special case for zero
+                return number + "'ıncı";
+            }
+            var a = number % 10,
+                b = number % 100 - a,
+                c = number >= 100 ? 100 : null;
+
+            return number + (suffixes[a] || suffixes[b] || suffixes[c]);
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/tzm-la.js b/resources/lib/moment/lang/tzm-la.js
new file mode 100644 (file)
index 0000000..be1d878
--- /dev/null
@@ -0,0 +1,55 @@
+// moment.js language configuration
+// language : Morocco Central Atlas Tamaziɣt in Latin (tzm-la)
+// author : Abdel Said : https://github.com/abdelsaid
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('tzm-la', {
+        months : "innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),
+        monthsShort : "innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),
+        weekdays : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),
+        weekdaysShort : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),
+        weekdaysMin : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: "[asdkh g] LT",
+            nextDay: '[aska g] LT',
+            nextWeek: 'dddd [g] LT',
+            lastDay: '[assant g] LT',
+            lastWeek: 'dddd [g] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "dadkh s yan %s",
+            past : "yan %s",
+            s : "imik",
+            m : "minuḍ",
+            mm : "%d minuḍ",
+            h : "saɛa",
+            hh : "%d tassaɛin",
+            d : "ass",
+            dd : "%d ossan",
+            M : "ayowr",
+            MM : "%d iyyirn",
+            y : "asgas",
+            yy : "%d isgasn"
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/tzm.js b/resources/lib/moment/lang/tzm.js
new file mode 100644 (file)
index 0000000..c7c76bd
--- /dev/null
@@ -0,0 +1,55 @@
+// moment.js language configuration
+// language : Morocco Central Atlas Tamaziɣt (tzm)
+// author : Abdel Said : https://github.com/abdelsaid
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('tzm', {
+        months : "ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),
+        monthsShort : "ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),
+        weekdays : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),
+        weekdaysShort : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),
+        weekdaysMin : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "dddd D MMMM YYYY LT"
+        },
+        calendar : {
+            sameDay: "[ⴰⵙⴷⵅ ⴴ] LT",
+            nextDay: '[ⴰⵙⴽⴰ ⴴ] LT',
+            nextWeek: 'dddd [ⴴ] LT',
+            lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT',
+            lastWeek: 'dddd [ⴴ] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s",
+            past : "ⵢⴰⵏ %s",
+            s : "ⵉⵎⵉⴽ",
+            m : "ⵎⵉⵏⵓⴺ",
+            mm : "%d ⵎⵉⵏⵓⴺ",
+            h : "ⵙⴰⵄⴰ",
+            hh : "%d ⵜⴰⵙⵙⴰⵄⵉⵏ",
+            d : "ⴰⵙⵙ",
+            dd : "%d oⵙⵙⴰⵏ",
+            M : "ⴰⵢoⵓⵔ",
+            MM : "%d ⵉⵢⵢⵉⵔⵏ",
+            y : "ⴰⵙⴳⴰⵙ",
+            yy : "%d ⵉⵙⴳⴰⵙⵏ"
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/uk.js b/resources/lib/moment/lang/uk.js
new file mode 100644 (file)
index 0000000..47056cb
--- /dev/null
@@ -0,0 +1,157 @@
+// moment.js language configuration
+// language : ukrainian (uk)
+// author : zemlanin : https://github.com/zemlanin
+// Author : Menelion Elensúle : https://github.com/Oire
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    function plural(word, num) {
+        var forms = word.split('_');
+        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+    }
+
+    function relativeTimeWithPlural(number, withoutSuffix, key) {
+        var format = {
+            'mm': 'хвилина_хвилини_хвилин',
+            'hh': 'година_години_годин',
+            'dd': 'день_дні_днів',
+            'MM': 'місяць_місяці_місяців',
+            'yy': 'рік_роки_років'
+        };
+        if (key === 'm') {
+            return withoutSuffix ? 'хвилина' : 'хвилину';
+        }
+        else if (key === 'h') {
+            return withoutSuffix ? 'година' : 'годину';
+        }
+        else {
+            return number + ' ' + plural(format[key], +number);
+        }
+    }
+
+    function monthsCaseReplace(m, format) {
+        var months = {
+            'nominative': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_'),
+            'accusative': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_')
+        },
+
+        nounCase = (/D[oD]? *MMMM?/).test(format) ?
+            'accusative' :
+            'nominative';
+
+        return months[nounCase][m.month()];
+    }
+
+    function weekdaysCaseReplace(m, format) {
+        var weekdays = {
+            'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'),
+            'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'),
+            'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_')
+        },
+
+        nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ?
+            'accusative' :
+            ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ?
+                'genitive' :
+                'nominative');
+
+        return weekdays[nounCase][m.day()];
+    }
+
+    function processHoursFunction(str) {
+        return function () {
+            return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT';
+        };
+    }
+
+    return moment.lang('uk', {
+        months : monthsCaseReplace,
+        monthsShort : "січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),
+        weekdays : weekdaysCaseReplace,
+        weekdaysShort : "нд_пн_вт_ср_чт_пт_сб".split("_"),
+        weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD.MM.YYYY",
+            LL : "D MMMM YYYY р.",
+            LLL : "D MMMM YYYY р., LT",
+            LLLL : "dddd, D MMMM YYYY р., LT"
+        },
+        calendar : {
+            sameDay: processHoursFunction('[Сьогодні '),
+            nextDay: processHoursFunction('[Завтра '),
+            lastDay: processHoursFunction('[Вчора '),
+            nextWeek: processHoursFunction('[У] dddd ['),
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 5:
+                case 6:
+                    return processHoursFunction('[Минулої] dddd [').call(this);
+                case 1:
+                case 2:
+                case 4:
+                    return processHoursFunction('[Минулого] dddd [').call(this);
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "за %s",
+            past : "%s тому",
+            s : "декілька секунд",
+            m : relativeTimeWithPlural,
+            mm : relativeTimeWithPlural,
+            h : "годину",
+            hh : relativeTimeWithPlural,
+            d : "день",
+            dd : relativeTimeWithPlural,
+            M : "місяць",
+            MM : relativeTimeWithPlural,
+            y : "рік",
+            yy : relativeTimeWithPlural
+        },
+
+        // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
+
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return "ночі";
+            } else if (hour < 12) {
+                return "ранку";
+            } else if (hour < 17) {
+                return "дня";
+            } else {
+                return "вечора";
+            }
+        },
+
+        ordinal: function (number, period) {
+            switch (period) {
+            case 'M':
+            case 'd':
+            case 'DDD':
+            case 'w':
+            case 'W':
+                return number + '-й';
+            case 'D':
+                return number + '-го';
+            default:
+                return number;
+            }
+        },
+
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/uz.js b/resources/lib/moment/lang/uz.js
new file mode 100644 (file)
index 0000000..a5b06fa
--- /dev/null
@@ -0,0 +1,55 @@
+// moment.js language configuration
+// language : uzbek
+// author : Sardor Muminov : https://github.com/muminoff
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('uz', {
+        months : "январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),
+        monthsShort : "янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"),
+        weekdays : "Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба".split("_"),
+        weekdaysShort : "Якш_Душ_Сеш_Чор_Пай_Жум_Шан".split("_"),
+        weekdaysMin : "Як_Ду_Се_Чо_Па_Жу_Ша".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM YYYY",
+            LLL : "D MMMM YYYY LT",
+            LLLL : "D MMMM YYYY, dddd LT"
+        },
+        calendar : {
+            sameDay : '[Бугун соат] LT [да]',
+            nextDay : '[Эртага] LT [да]',
+            nextWeek : 'dddd [куни соат] LT [да]',
+            lastDay : '[Кеча соат] LT [да]',
+            lastWeek : '[Утган] dddd [куни соат] LT [да]',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : "Якин %s ичида",
+            past : "Бир неча %s олдин",
+            s : "фурсат",
+            m : "бир дакика",
+            mm : "%d дакика",
+            h : "бир соат",
+            hh : "%d соат",
+            d : "бир кун",
+            dd : "%d кун",
+            M : "бир ой",
+            MM : "%d ой",
+            y : "бир йил",
+            yy : "%d йил"
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/vn.js b/resources/lib/moment/lang/vn.js
new file mode 100644 (file)
index 0000000..f28e7c3
--- /dev/null
@@ -0,0 +1,62 @@
+// moment.js language configuration
+// language : vietnamese (vn)
+// author : Bang Nguyen : https://github.com/bangnk
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('vn', {
+        months : "tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),
+        monthsShort : "Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12".split("_"),
+        weekdays : "chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy".split("_"),
+        weekdaysShort : "CN_T2_T3_T4_T5_T6_T7".split("_"),
+        weekdaysMin : "CN_T2_T3_T4_T5_T6_T7".split("_"),
+        longDateFormat : {
+            LT : "HH:mm",
+            L : "DD/MM/YYYY",
+            LL : "D MMMM [năm] YYYY",
+            LLL : "D MMMM [năm] YYYY LT",
+            LLLL : "dddd, D MMMM [năm] YYYY LT",
+            l : "DD/M/YYYY",
+            ll : "D MMM YYYY",
+            lll : "D MMM YYYY LT",
+            llll : "ddd, D MMM YYYY LT"
+        },
+        calendar : {
+            sameDay: "[Hôm nay lúc] LT",
+            nextDay: '[Ngày mai lúc] LT',
+            nextWeek: 'dddd [tuần tới lúc] LT',
+            lastDay: '[Hôm qua lúc] LT',
+            lastWeek: 'dddd [tuần rồi lúc] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : "%s tới",
+            past : "%s trước",
+            s : "vài giây",
+            m : "một phút",
+            mm : "%d phút",
+            h : "một giờ",
+            hh : "%d giờ",
+            d : "một ngày",
+            dd : "%d ngày",
+            M : "một tháng",
+            MM : "%d tháng",
+            y : "một năm",
+            yy : "%d năm"
+        },
+        ordinal : function (number) {
+            return number;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/zh-cn.js b/resources/lib/moment/lang/zh-cn.js
new file mode 100644 (file)
index 0000000..50a3ed9
--- /dev/null
@@ -0,0 +1,108 @@
+// moment.js language configuration
+// language : chinese
+// author : suupic : https://github.com/suupic
+// author : Zeno Zeng : https://github.com/zenozeng
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('zh-cn', {
+        months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
+        monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
+        weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),
+        weekdaysShort : "周日_周一_周二_周三_周四_周五_周六".split("_"),
+        weekdaysMin : "日_一_二_三_四_五_六".split("_"),
+        longDateFormat : {
+            LT : "Ah点mm",
+            L : "YYYY-MM-DD",
+            LL : "YYYY年MMMD日",
+            LLL : "YYYY年MMMD日LT",
+            LLLL : "YYYY年MMMD日ddddLT",
+            l : "YYYY-MM-DD",
+            ll : "YYYY年MMMD日",
+            lll : "YYYY年MMMD日LT",
+            llll : "YYYY年MMMD日ddddLT"
+        },
+        meridiem : function (hour, minute, isLower) {
+            var hm = hour * 100 + minute;
+            if (hm < 600) {
+                return "凌晨";
+            } else if (hm < 900) {
+                return "早上";
+            } else if (hm < 1130) {
+                return "上午";
+            } else if (hm < 1230) {
+                return "中午";
+            } else if (hm < 1800) {
+                return "下午";
+            } else {
+                return "晚上";
+            }
+        },
+        calendar : {
+            sameDay : function () {
+                return this.minutes() === 0 ? "[今天]Ah[点整]" : "[今天]LT";
+            },
+            nextDay : function () {
+                return this.minutes() === 0 ? "[明天]Ah[点整]" : "[明天]LT";
+            },
+            lastDay : function () {
+                return this.minutes() === 0 ? "[昨天]Ah[点整]" : "[昨天]LT";
+            },
+            nextWeek : function () {
+                var startOfWeek, prefix;
+                startOfWeek = moment().startOf('week');
+                prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]';
+                return this.minutes() === 0 ? prefix + "dddAh点整" : prefix + "dddAh点mm";
+            },
+            lastWeek : function () {
+                var startOfWeek, prefix;
+                startOfWeek = moment().startOf('week');
+                prefix = this.unix() < startOfWeek.unix()  ? '[上]' : '[本]';
+                return this.minutes() === 0 ? prefix + "dddAh点整" : prefix + "dddAh点mm";
+            },
+            sameElse : 'LL'
+        },
+        ordinal : function (number, period) {
+            switch (period) {
+            case "d":
+            case "D":
+            case "DDD":
+                return number + "日";
+            case "M":
+                return number + "月";
+            case "w":
+            case "W":
+                return number + "周";
+            default:
+                return number;
+            }
+        },
+        relativeTime : {
+            future : "%s内",
+            past : "%s前",
+            s : "几秒",
+            m : "1分钟",
+            mm : "%d分钟",
+            h : "1小时",
+            hh : "%d小时",
+            d : "1天",
+            dd : "%d天",
+            M : "1个月",
+            MM : "%d个月",
+            y : "1年",
+            yy : "%d年"
+        },
+        week : {
+            // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+}));
diff --git a/resources/lib/moment/lang/zh-tw.js b/resources/lib/moment/lang/zh-tw.js
new file mode 100644 (file)
index 0000000..bbb0737
--- /dev/null
@@ -0,0 +1,84 @@
+// moment.js language configuration
+// language : traditional chinese (zh-tw)
+// author : Ben : https://github.com/ben-lin
+
+(function (factory) {
+    if (typeof define === 'function' && define.amd) {
+        define(['moment'], factory); // AMD
+    } else if (typeof exports === 'object') {
+        module.exports = factory(require('../moment')); // Node
+    } else {
+        factory(window.moment); // Browser global
+    }
+}(function (moment) {
+    return moment.lang('zh-tw', {
+        months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
+        monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
+        weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),
+        weekdaysShort : "週日_週一_週二_週三_週四_週五_週六".split("_"),
+        weekdaysMin : "日_一_二_三_四_五_六".split("_"),
+        longDateFormat : {
+            LT : "Ah點mm",
+            L : "YYYY年MMMD日",
+            LL : "YYYY年MMMD日",
+            LLL : "YYYY年MMMD日LT",
+            LLLL : "YYYY年MMMD日ddddLT",
+            l : "YYYY年MMMD日",
+            ll : "YYYY年MMMD日",
+            lll : "YYYY年MMMD日LT",
+            llll : "YYYY年MMMD日ddddLT"
+        },
+        meridiem : function (hour, minute, isLower) {
+            var hm = hour * 100 + minute;
+            if (hm < 900) {
+                return "早上";
+            } else if (hm < 1130) {
+                return "上午";
+            } else if (hm < 1230) {
+                return "中午";
+            } else if (hm < 1800) {
+                return "下午";
+            } else {
+                return "晚上";
+            }
+        },
+        calendar : {
+            sameDay : '[今天]LT',
+            nextDay : '[明天]LT',
+            nextWeek : '[下]ddddLT',
+            lastDay : '[昨天]LT',
+            lastWeek : '[上]ddddLT',
+            sameElse : 'L'
+        },
+        ordinal : function (number, period) {
+            switch (period) {
+            case "d" :
+            case "D" :
+            case "DDD" :
+                return number + "日";
+            case "M" :
+                return number + "月";
+            case "w" :
+            case "W" :
+                return number + "週";
+            default :
+                return number;
+            }
+        },
+        relativeTime : {
+            future : "%s內",
+            past : "%s前",
+            s : "幾秒",
+            m : "一分鐘",
+            mm : "%d分鐘",
+            h : "一小時",
+            hh : "%d小時",
+            d : "一天",
+            dd : "%d天",
+            M : "一個月",
+            MM : "%d個月",
+            y : "一年",
+            yy : "%d年"
+        }
+    });
+}));
diff --git a/resources/lib/moment/moment.js b/resources/lib/moment/moment.js
new file mode 100644 (file)
index 0000000..b79da7f
--- /dev/null
@@ -0,0 +1,2400 @@
+//! moment.js
+//! version : 2.5.1
+//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
+//! license : MIT
+//! momentjs.com
+
+(function (undefined) {
+
+    /************************************
+        Constants
+    ************************************/
+
+    var moment,
+        VERSION = "2.5.1",
+        global = this,
+        round = Math.round,
+        i,
+
+        YEAR = 0,
+        MONTH = 1,
+        DATE = 2,
+        HOUR = 3,
+        MINUTE = 4,
+        SECOND = 5,
+        MILLISECOND = 6,
+
+        // internal storage for language config files
+        languages = {},
+
+        // moment internal properties
+        momentProperties = {
+            _isAMomentObject: null,
+            _i : null,
+            _f : null,
+            _l : null,
+            _strict : null,
+            _isUTC : null,
+            _offset : null,  // optional. Combine with _isUTC
+            _pf : null,
+            _lang : null  // optional
+        },
+
+        // check for nodeJS
+        hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'),
+
+        // ASP.NET json date format regex
+        aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
+        aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
+
+        // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
+        // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
+        isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
+
+        // format tokens
+        formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
+        localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
+
+        // parsing token regexes
+        parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
+        parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
+        parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
+        parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
+        parseTokenDigits = /\d+/, // nonzero number of digits
+        parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
+        parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
+        parseTokenT = /T/i, // T (ISO separator)
+        parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
+
+        //strict parsing regexes
+        parseTokenOneDigit = /\d/, // 0 - 9
+        parseTokenTwoDigits = /\d\d/, // 00 - 99
+        parseTokenThreeDigits = /\d{3}/, // 000 - 999
+        parseTokenFourDigits = /\d{4}/, // 0000 - 9999
+        parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999
+        parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf
+
+        // iso 8601 regex
+        // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
+        isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
+
+        isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
+
+        isoDates = [
+            ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/],
+            ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/],
+            ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/],
+            ['GGGG-[W]WW', /\d{4}-W\d{2}/],
+            ['YYYY-DDD', /\d{4}-\d{3}/]
+        ],
+
+        // iso time formats and regexes
+        isoTimes = [
+            ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
+            ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
+            ['HH:mm', /(T| )\d\d:\d\d/],
+            ['HH', /(T| )\d\d/]
+        ],
+
+        // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
+        parseTimezoneChunker = /([\+\-]|\d\d)/gi,
+
+        // getter and setter names
+        proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
+        unitMillisecondFactors = {
+            'Milliseconds' : 1,
+            'Seconds' : 1e3,
+            'Minutes' : 6e4,
+            'Hours' : 36e5,
+            'Days' : 864e5,
+            'Months' : 2592e6,
+            'Years' : 31536e6
+        },
+
+        unitAliases = {
+            ms : 'millisecond',
+            s : 'second',
+            m : 'minute',
+            h : 'hour',
+            d : 'day',
+            D : 'date',
+            w : 'week',
+            W : 'isoWeek',
+            M : 'month',
+            y : 'year',
+            DDD : 'dayOfYear',
+            e : 'weekday',
+            E : 'isoWeekday',
+            gg: 'weekYear',
+            GG: 'isoWeekYear'
+        },
+
+        camelFunctions = {
+            dayofyear : 'dayOfYear',
+            isoweekday : 'isoWeekday',
+            isoweek : 'isoWeek',
+            weekyear : 'weekYear',
+            isoweekyear : 'isoWeekYear'
+        },
+
+        // format function strings
+        formatFunctions = {},
+
+        // tokens to ordinalize and pad
+        ordinalizeTokens = 'DDD w W M D d'.split(' '),
+        paddedTokens = 'M D H h m s w W'.split(' '),
+
+        formatTokenFunctions = {
+            M    : function () {
+                return this.month() + 1;
+            },
+            MMM  : function (format) {
+                return this.lang().monthsShort(this, format);
+            },
+            MMMM : function (format) {
+                return this.lang().months(this, format);
+            },
+            D    : function () {
+                return this.date();
+            },
+            DDD  : function () {
+                return this.dayOfYear();
+            },
+            d    : function () {
+                return this.day();
+            },
+            dd   : function (format) {
+                return this.lang().weekdaysMin(this, format);
+            },
+            ddd  : function (format) {
+                return this.lang().weekdaysShort(this, format);
+            },
+            dddd : function (format) {
+                return this.lang().weekdays(this, format);
+            },
+            w    : function () {
+                return this.week();
+            },
+            W    : function () {
+                return this.isoWeek();
+            },
+            YY   : function () {
+                return leftZeroFill(this.year() % 100, 2);
+            },
+            YYYY : function () {
+                return leftZeroFill(this.year(), 4);
+            },
+            YYYYY : function () {
+                return leftZeroFill(this.year(), 5);
+            },
+            YYYYYY : function () {
+                var y = this.year(), sign = y >= 0 ? '+' : '-';
+                return sign + leftZeroFill(Math.abs(y), 6);
+            },
+            gg   : function () {
+                return leftZeroFill(this.weekYear() % 100, 2);
+            },
+            gggg : function () {
+                return leftZeroFill(this.weekYear(), 4);
+            },
+            ggggg : function () {
+                return leftZeroFill(this.weekYear(), 5);
+            },
+            GG   : function () {
+                return leftZeroFill(this.isoWeekYear() % 100, 2);
+            },
+            GGGG : function () {
+                return leftZeroFill(this.isoWeekYear(), 4);
+            },
+            GGGGG : function () {
+                return leftZeroFill(this.isoWeekYear(), 5);
+            },
+            e : function () {
+                return this.weekday();
+            },
+            E : function () {
+                return this.isoWeekday();
+            },
+            a    : function () {
+                return this.lang().meridiem(this.hours(), this.minutes(), true);
+            },
+            A    : function () {
+                return this.lang().meridiem(this.hours(), this.minutes(), false);
+            },
+            H    : function () {
+                return this.hours();
+            },
+            h    : function () {
+                return this.hours() % 12 || 12;
+            },
+            m    : function () {
+                return this.minutes();
+            },
+            s    : function () {
+                return this.seconds();
+            },
+            S    : function () {
+                return toInt(this.milliseconds() / 100);
+            },
+            SS   : function () {
+                return leftZeroFill(toInt(this.milliseconds() / 10), 2);
+            },
+            SSS  : function () {
+                return leftZeroFill(this.milliseconds(), 3);
+            },
+            SSSS : function () {
+                return leftZeroFill(this.milliseconds(), 3);
+            },
+            Z    : function () {
+                var a = -this.zone(),
+                    b = "+";
+                if (a < 0) {
+                    a = -a;
+                    b = "-";
+                }
+                return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
+            },
+            ZZ   : function () {
+                var a = -this.zone(),
+                    b = "+";
+                if (a < 0) {
+                    a = -a;
+                    b = "-";
+                }
+                return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
+            },
+            z : function () {
+                return this.zoneAbbr();
+            },
+            zz : function () {
+                return this.zoneName();
+            },
+            X    : function () {
+                return this.unix();
+            },
+            Q : function () {
+                return this.quarter();
+            }
+        },
+
+        lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
+
+    function defaultParsingFlags() {
+        // We need to deep clone this object, and es5 standard is not very
+        // helpful.
+        return {
+            empty : false,
+            unusedTokens : [],
+            unusedInput : [],
+            overflow : -2,
+            charsLeftOver : 0,
+            nullInput : false,
+            invalidMonth : null,
+            invalidFormat : false,
+            userInvalidated : false,
+            iso: false
+        };
+    }
+
+    function padToken(func, count) {
+        return function (a) {
+            return leftZeroFill(func.call(this, a), count);
+        };
+    }
+    function ordinalizeToken(func, period) {
+        return function (a) {
+            return this.lang().ordinal(func.call(this, a), period);
+        };
+    }
+
+    while (ordinalizeTokens.length) {
+        i = ordinalizeTokens.pop();
+        formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
+    }
+    while (paddedTokens.length) {
+        i = paddedTokens.pop();
+        formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
+    }
+    formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
+
+
+    /************************************
+        Constructors
+    ************************************/
+
+    function Language() {
+
+    }
+
+    // Moment prototype object
+    function Moment(config) {
+        checkOverflow(config);
+        extend(this, config);
+    }
+
+    // Duration Constructor
+    function Duration(duration) {
+        var normalizedInput = normalizeObjectUnits(duration),
+            years = normalizedInput.year || 0,
+            months = normalizedInput.month || 0,
+            weeks = normalizedInput.week || 0,
+            days = normalizedInput.day || 0,
+            hours = normalizedInput.hour || 0,
+            minutes = normalizedInput.minute || 0,
+            seconds = normalizedInput.second || 0,
+            milliseconds = normalizedInput.millisecond || 0;
+
+        // representation for dateAddRemove
+        this._milliseconds = +milliseconds +
+            seconds * 1e3 + // 1000
+            minutes * 6e4 + // 1000 * 60
+            hours * 36e5; // 1000 * 60 * 60
+        // Because of dateAddRemove treats 24 hours as different from a
+        // day when working around DST, we need to store them separately
+        this._days = +days +
+            weeks * 7;
+        // It is impossible translate months into days without knowing
+        // which months you are are talking about, so we have to store
+        // it separately.
+        this._months = +months +
+            years * 12;
+
+        this._data = {};
+
+        this._bubble();
+    }
+
+    /************************************
+        Helpers
+    ************************************/
+
+
+    function extend(a, b) {
+        for (var i in b) {
+            if (b.hasOwnProperty(i)) {
+                a[i] = b[i];
+            }
+        }
+
+        if (b.hasOwnProperty("toString")) {
+            a.toString = b.toString;
+        }
+
+        if (b.hasOwnProperty("valueOf")) {
+            a.valueOf = b.valueOf;
+        }
+
+        return a;
+    }
+
+    function cloneMoment(m) {
+        var result = {}, i;
+        for (i in m) {
+            if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) {
+                result[i] = m[i];
+            }
+        }
+
+        return result;
+    }
+
+    function absRound(number) {
+        if (number < 0) {
+            return Math.ceil(number);
+        } else {
+            return Math.floor(number);
+        }
+    }
+
+    // left zero fill a number
+    // see http://jsperf.com/left-zero-filling for performance comparison
+    function leftZeroFill(number, targetLength, forceSign) {
+        var output = '' + Math.abs(number),
+            sign = number >= 0;
+
+        while (output.length < targetLength) {
+            output = '0' + output;
+        }
+        return (sign ? (forceSign ? '+' : '') : '-') + output;
+    }
+
+    // helper function for _.addTime and _.subtractTime
+    function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
+        var milliseconds = duration._milliseconds,
+            days = duration._days,
+            months = duration._months,
+            minutes,
+            hours;
+
+        if (milliseconds) {
+            mom._d.setTime(+mom._d + milliseconds * isAdding);
+        }
+        // store the minutes and hours so we can restore them
+        if (days || months) {
+            minutes = mom.minute();
+            hours = mom.hour();
+        }
+        if (days) {
+            mom.date(mom.date() + days * isAdding);
+        }
+        if (months) {
+            mom.month(mom.month() + months * isAdding);
+        }
+        if (milliseconds && !ignoreUpdateOffset) {
+            moment.updateOffset(mom);
+        }
+        // restore the minutes and hours after possibly changing dst
+        if (days || months) {
+            mom.minute(minutes);
+            mom.hour(hours);
+        }
+    }
+
+    // check if is an array
+    function isArray(input) {
+        return Object.prototype.toString.call(input) === '[object Array]';
+    }
+
+    function isDate(input) {
+        return  Object.prototype.toString.call(input) === '[object Date]' ||
+                input instanceof Date;
+    }
+
+    // compare two arrays, return the number of differences
+    function compareArrays(array1, array2, dontConvert) {
+        var len = Math.min(array1.length, array2.length),
+            lengthDiff = Math.abs(array1.length - array2.length),
+            diffs = 0,
+            i;
+        for (i = 0; i < len; i++) {
+            if ((dontConvert && array1[i] !== array2[i]) ||
+                (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
+                diffs++;
+            }
+        }
+        return diffs + lengthDiff;
+    }
+
+    function normalizeUnits(units) {
+        if (units) {
+            var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
+            units = unitAliases[units] || camelFunctions[lowered] || lowered;
+        }
+        return units;
+    }
+
+    function normalizeObjectUnits(inputObject) {
+        var normalizedInput = {},
+            normalizedProp,
+            prop;
+
+        for (prop in inputObject) {
+            if (inputObject.hasOwnProperty(prop)) {
+                normalizedProp = normalizeUnits(prop);
+                if (normalizedProp) {
+                    normalizedInput[normalizedProp] = inputObject[prop];
+                }
+            }
+        }
+
+        return normalizedInput;
+    }
+
+    function makeList(field) {
+        var count, setter;
+
+        if (field.indexOf('week') === 0) {
+            count = 7;
+            setter = 'day';
+        }
+        else if (field.indexOf('month') === 0) {
+            count = 12;
+            setter = 'month';
+        }
+        else {
+            return;
+        }
+
+        moment[field] = function (format, index) {
+            var i, getter,
+                method = moment.fn._lang[field],
+                results = [];
+
+            if (typeof format === 'number') {
+                index = format;
+                format = undefined;
+            }
+
+            getter = function (i) {
+                var m = moment().utc().set(setter, i);
+                return method.call(moment.fn._lang, m, format || '');
+            };
+
+            if (index != null) {
+                return getter(index);
+            }
+            else {
+                for (i = 0; i < count; i++) {
+                    results.push(getter(i));
+                }
+                return results;
+            }
+        };
+    }
+
+    function toInt(argumentForCoercion) {
+        var coercedNumber = +argumentForCoercion,
+            value = 0;
+
+        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
+            if (coercedNumber >= 0) {
+                value = Math.floor(coercedNumber);
+            } else {
+                value = Math.ceil(coercedNumber);
+            }
+        }
+
+        return value;
+    }
+
+    function daysInMonth(year, month) {
+        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
+    }
+
+    function daysInYear(year) {
+        return isLeapYear(year) ? 366 : 365;
+    }
+
+    function isLeapYear(year) {
+        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+    }
+
+    function checkOverflow(m) {
+        var overflow;
+        if (m._a && m._pf.overflow === -2) {
+            overflow =
+                m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
+                m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
+                m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
+                m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
+                m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
+                m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
+                -1;
+
+            if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
+                overflow = DATE;
+            }
+
+            m._pf.overflow = overflow;
+        }
+    }
+
+    function isValid(m) {
+        if (m._isValid == null) {
+            m._isValid = !isNaN(m._d.getTime()) &&
+                m._pf.overflow < 0 &&
+                !m._pf.empty &&
+                !m._pf.invalidMonth &&
+                !m._pf.nullInput &&
+                !m._pf.invalidFormat &&
+                !m._pf.userInvalidated;
+
+            if (m._strict) {
+                m._isValid = m._isValid &&
+                    m._pf.charsLeftOver === 0 &&
+                    m._pf.unusedTokens.length === 0;
+            }
+        }
+        return m._isValid;
+    }
+
+    function normalizeLanguage(key) {
+        return key ? key.toLowerCase().replace('_', '-') : key;
+    }
+
+    // Return a moment from input, that is local/utc/zone equivalent to model.
+    function makeAs(input, model) {
+        return model._isUTC ? moment(input).zone(model._offset || 0) :
+            moment(input).local();
+    }
+
+    /************************************
+        Languages
+    ************************************/
+
+
+    extend(Language.prototype, {
+
+        set : function (config) {
+            var prop, i;
+            for (i in config) {
+                prop = config[i];
+                if (typeof prop === 'function') {
+                    this[i] = prop;
+                } else {
+                    this['_' + i] = prop;
+                }
+            }
+        },
+
+        _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
+        months : function (m) {
+            return this._months[m.month()];
+        },
+
+        _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
+        monthsShort : function (m) {
+            return this._monthsShort[m.month()];
+        },
+
+        monthsParse : function (monthName) {
+            var i, mom, regex;
+
+            if (!this._monthsParse) {
+                this._monthsParse = [];
+            }
+
+            for (i = 0; i < 12; i++) {
+                // make the regex if we don't have it already
+                if (!this._monthsParse[i]) {
+                    mom = moment.utc([2000, i]);
+                    regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
+                    this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
+                }
+                // test the regex
+                if (this._monthsParse[i].test(monthName)) {
+                    return i;
+                }
+            }
+        },
+
+        _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
+        weekdays : function (m) {
+            return this._weekdays[m.day()];
+        },
+
+        _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
+        weekdaysShort : function (m) {
+            return this._weekdaysShort[m.day()];
+        },
+
+        _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
+        weekdaysMin : function (m) {
+            return this._weekdaysMin[m.day()];
+        },
+
+        weekdaysParse : function (weekdayName) {
+            var i, mom, regex;
+
+            if (!this._weekdaysParse) {
+                this._weekdaysParse = [];
+            }
+
+            for (i = 0; i < 7; i++) {
+                // make the regex if we don't have it already
+                if (!this._weekdaysParse[i]) {
+                    mom = moment([2000, 1]).day(i);
+                    regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
+                    this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
+                }
+                // test the regex
+                if (this._weekdaysParse[i].test(weekdayName)) {
+                    return i;
+                }
+            }
+        },
+
+        _longDateFormat : {
+            LT : "h:mm A",
+            L : "MM/DD/YYYY",
+            LL : "MMMM D YYYY",
+            LLL : "MMMM D YYYY LT",
+            LLLL : "dddd, MMMM D YYYY LT"
+        },
+        longDateFormat : function (key) {
+            var output = this._longDateFormat[key];
+            if (!output && this._longDateFormat[key.toUpperCase()]) {
+                output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
+                    return val.slice(1);
+                });
+                this._longDateFormat[key] = output;
+            }
+            return output;
+        },
+
+        isPM : function (input) {
+            // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
+            // Using charAt should be more compatible.
+            return ((input + '').toLowerCase().charAt(0) === 'p');
+        },
+
+        _meridiemParse : /[ap]\.?m?\.?/i,
+        meridiem : function (hours, minutes, isLower) {
+            if (hours > 11) {
+                return isLower ? 'pm' : 'PM';
+            } else {
+                return isLower ? 'am' : 'AM';
+            }
+        },
+
+        _calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        calendar : function (key, mom) {
+            var output = this._calendar[key];
+            return typeof output === 'function' ? output.apply(mom) : output;
+        },
+
+        _relativeTime : {
+            future : "in %s",
+            past : "%s ago",
+            s : "a few seconds",
+            m : "a minute",
+            mm : "%d minutes",
+            h : "an hour",
+            hh : "%d hours",
+            d : "a day",
+            dd : "%d days",
+            M : "a month",
+            MM : "%d months",
+            y : "a year",
+            yy : "%d years"
+        },
+        relativeTime : function (number, withoutSuffix, string, isFuture) {
+            var output = this._relativeTime[string];
+            return (typeof output === 'function') ?
+                output(number, withoutSuffix, string, isFuture) :
+                output.replace(/%d/i, number);
+        },
+        pastFuture : function (diff, output) {
+            var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
+            return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
+        },
+
+        ordinal : function (number) {
+            return this._ordinal.replace("%d", number);
+        },
+        _ordinal : "%d",
+
+        preparse : function (string) {
+            return string;
+        },
+
+        postformat : function (string) {
+            return string;
+        },
+
+        week : function (mom) {
+            return weekOfYear(mom, this._week.dow, this._week.doy).week;
+        },
+
+        _week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        },
+
+        _invalidDate: 'Invalid date',
+        invalidDate: function () {
+            return this._invalidDate;
+        }
+    });
+
+    // Loads a language definition into the `languages` cache.  The function
+    // takes a key and optionally values.  If not in the browser and no values
+    // are provided, it will load the language file module.  As a convenience,
+    // this function also returns the language values.
+    function loadLang(key, values) {
+        values.abbr = key;
+        if (!languages[key]) {
+            languages[key] = new Language();
+        }
+        languages[key].set(values);
+        return languages[key];
+    }
+
+    // Remove a language from the `languages` cache. Mostly useful in tests.
+    function unloadLang(key) {
+        delete languages[key];
+    }
+
+    // Determines which language definition to use and returns it.
+    //
+    // With no parameters, it will return the global language.  If you
+    // pass in a language key, such as 'en', it will return the
+    // definition for 'en', so long as 'en' has already been loaded using
+    // moment.lang.
+    function getLangDefinition(key) {
+        var i = 0, j, lang, next, split,
+            get = function (k) {
+                if (!languages[k] && hasModule) {
+                    try {
+                        require('./lang/' + k);
+                    } catch (e) { }
+                }
+                return languages[k];
+            };
+
+        if (!key) {
+            return moment.fn._lang;
+        }
+
+        if (!isArray(key)) {
+            //short-circuit everything else
+            lang = get(key);
+            if (lang) {
+                return lang;
+            }
+            key = [key];
+        }
+
+        //pick the language from the array
+        //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
+        //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
+        while (i < key.length) {
+            split = normalizeLanguage(key[i]).split('-');
+            j = split.length;
+            next = normalizeLanguage(key[i + 1]);
+            next = next ? next.split('-') : null;
+            while (j > 0) {
+                lang = get(split.slice(0, j).join('-'));
+                if (lang) {
+                    return lang;
+                }
+                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
+                    //the next array item is better than a shallower substring of this one
+                    break;
+                }
+                j--;
+            }
+            i++;
+        }
+        return moment.fn._lang;
+    }
+
+    /************************************
+        Formatting
+    ************************************/
+
+
+    function removeFormattingTokens(input) {
+        if (input.match(/\[[\s\S]/)) {
+            return input.replace(/^\[|\]$/g, "");
+        }
+        return input.replace(/\\/g, "");
+    }
+
+    function makeFormatFunction(format) {
+        var array = format.match(formattingTokens), i, length;
+
+        for (i = 0, length = array.length; i < length; i++) {
+            if (formatTokenFunctions[array[i]]) {
+                array[i] = formatTokenFunctions[array[i]];
+            } else {
+                array[i] = removeFormattingTokens(array[i]);
+            }
+        }
+
+        return function (mom) {
+            var output = "";
+            for (i = 0; i < length; i++) {
+                output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
+            }
+            return output;
+        };
+    }
+
+    // format date using native date object
+    function formatMoment(m, format) {
+
+        if (!m.isValid()) {
+            return m.lang().invalidDate();
+        }
+
+        format = expandFormat(format, m.lang());
+
+        if (!formatFunctions[format]) {
+            formatFunctions[format] = makeFormatFunction(format);
+        }
+
+        return formatFunctions[format](m);
+    }
+
+    function expandFormat(format, lang) {
+        var i = 5;
+
+        function replaceLongDateFormatTokens(input) {
+            return lang.longDateFormat(input) || input;
+        }
+
+        localFormattingTokens.lastIndex = 0;
+        while (i >= 0 && localFormattingTokens.test(format)) {
+            format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
+            localFormattingTokens.lastIndex = 0;
+            i -= 1;
+        }
+
+        return format;
+    }
+
+
+    /************************************
+        Parsing
+    ************************************/
+
+
+    // get the regex to find the next token
+    function getParseRegexForToken(token, config) {
+        var a, strict = config._strict;
+        switch (token) {
+        case 'DDDD':
+            return parseTokenThreeDigits;
+        case 'YYYY':
+        case 'GGGG':
+        case 'gggg':
+            return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
+        case 'Y':
+        case 'G':
+        case 'g':
+            return parseTokenSignedNumber;
+        case 'YYYYYY':
+        case 'YYYYY':
+        case 'GGGGG':
+        case 'ggggg':
+            return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
+        case 'S':
+            if (strict) { return parseTokenOneDigit; }
+            /* falls through */
+        case 'SS':
+            if (strict) { return parseTokenTwoDigits; }
+            /* falls through */
+        case 'SSS':
+            if (strict) { return parseTokenThreeDigits; }
+            /* falls through */
+        case 'DDD':
+            return parseTokenOneToThreeDigits;
+        case 'MMM':
+        case 'MMMM':
+        case 'dd':
+        case 'ddd':
+        case 'dddd':
+            return parseTokenWord;
+        case 'a':
+        case 'A':
+            return getLangDefinition(config._l)._meridiemParse;
+        case 'X':
+            return parseTokenTimestampMs;
+        case 'Z':
+        case 'ZZ':
+            return parseTokenTimezone;
+        case 'T':
+            return parseTokenT;
+        case 'SSSS':
+            return parseTokenDigits;
+        case 'MM':
+        case 'DD':
+        case 'YY':
+        case 'GG':
+        case 'gg':
+        case 'HH':
+        case 'hh':
+        case 'mm':
+        case 'ss':
+        case 'ww':
+        case 'WW':
+            return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
+        case 'M':
+        case 'D':
+        case 'd':
+        case 'H':
+        case 'h':
+        case 'm':
+        case 's':
+        case 'w':
+        case 'W':
+        case 'e':
+        case 'E':
+            return parseTokenOneOrTwoDigits;
+        default :
+            a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
+            return a;
+        }
+    }
+
+    function timezoneMinutesFromString(string) {
+        string = string || "";
+        var possibleTzMatches = (string.match(parseTokenTimezone) || []),
+            tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
+            parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
+            minutes = +(parts[1] * 60) + toInt(parts[2]);
+
+        return parts[0] === '+' ? -minutes : minutes;
+    }
+
+    // function to convert string input to date
+    function addTimeToArrayFromToken(token, input, config) {
+        var a, datePartArray = config._a;
+
+        switch (token) {
+        // MONTH
+        case 'M' : // fall through to MM
+        case 'MM' :
+            if (input != null) {
+                datePartArray[MONTH] = toInt(input) - 1;
+            }
+            break;
+        case 'MMM' : // fall through to MMMM
+        case 'MMMM' :
+            a = getLangDefinition(config._l).monthsParse(input);
+            // if we didn't find a month name, mark the date as invalid.
+            if (a != null) {
+                datePartArray[MONTH] = a;
+            } else {
+                config._pf.invalidMonth = input;
+            }
+            break;
+        // DAY OF MONTH
+        case 'D' : // fall through to DD
+        case 'DD' :
+            if (input != null) {
+                datePartArray[DATE] = toInt(input);
+            }
+            break;
+        // DAY OF YEAR
+        case 'DDD' : // fall through to DDDD
+        case 'DDDD' :
+            if (input != null) {
+                config._dayOfYear = toInt(input);
+            }
+
+            break;
+        // YEAR
+        case 'YY' :
+            datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
+            break;
+        case 'YYYY' :
+        case 'YYYYY' :
+        case 'YYYYYY' :
+            datePartArray[YEAR] = toInt(input);
+            break;
+        // AM / PM
+        case 'a' : // fall through to A
+        case 'A' :
+            config._isPm = getLangDefinition(config._l).isPM(input);
+            break;
+        // 24 HOUR
+        case 'H' : // fall through to hh
+        case 'HH' : // fall through to hh
+        case 'h' : // fall through to hh
+        case 'hh' :
+            datePartArray[HOUR] = toInt(input);
+            break;
+        // MINUTE
+        case 'm' : // fall through to mm
+        case 'mm' :
+            datePartArray[MINUTE] = toInt(input);
+            break;
+        // SECOND
+        case 's' : // fall through to ss
+        case 'ss' :
+            datePartArray[SECOND] = toInt(input);
+            break;
+        // MILLISECOND
+        case 'S' :
+        case 'SS' :
+        case 'SSS' :
+        case 'SSSS' :
+            datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
+            break;
+        // UNIX TIMESTAMP WITH MS
+        case 'X':
+            config._d = new Date(parseFloat(input) * 1000);
+            break;
+        // TIMEZONE
+        case 'Z' : // fall through to ZZ
+        case 'ZZ' :
+            config._useUTC = true;
+            config._tzm = timezoneMinutesFromString(input);
+            break;
+        case 'w':
+        case 'ww':
+        case 'W':
+        case 'WW':
+        case 'd':
+        case 'dd':
+        case 'ddd':
+        case 'dddd':
+        case 'e':
+        case 'E':
+            token = token.substr(0, 1);
+            /* falls through */
+        case 'gg':
+        case 'gggg':
+        case 'GG':
+        case 'GGGG':
+        case 'GGGGG':
+            token = token.substr(0, 2);
+            if (input) {
+                config._w = config._w || {};
+                config._w[token] = input;
+            }
+            break;
+        }
+    }
+
+    // convert an array to a date.
+    // the array should mirror the parameters below
+    // note: all values past the year are optional and will default to the lowest possible value.
+    // [year, month, day , hour, minute, second, millisecond]
+    function dateFromConfig(config) {
+        var i, date, input = [], currentDate,
+            yearToUse, fixYear, w, temp, lang, weekday, week;
+
+        if (config._d) {
+            return;
+        }
+
+        currentDate = currentDateArray(config);
+
+        //compute day of the year from weeks and weekdays
+        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
+            fixYear = function (val) {
+                var int_val = parseInt(val, 10);
+                return val ?
+                  (val.length < 3 ? (int_val > 68 ? 1900 + int_val : 2000 + int_val) : int_val) :
+                  (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]);
+            };
+
+            w = config._w;
+            if (w.GG != null || w.W != null || w.E != null) {
+                temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1);
+            }
+            else {
+                lang = getLangDefinition(config._l);
+                weekday = w.d != null ?  parseWeekday(w.d, lang) :
+                  (w.e != null ?  parseInt(w.e, 10) + lang._week.dow : 0);
+
+                week = parseInt(w.w, 10) || 1;
+
+                //if we're parsing 'd', then the low day numbers may be next week
+                if (w.d != null && weekday < lang._week.dow) {
+                    week++;
+                }
+
+                temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow);
+            }
+
+            config._a[YEAR] = temp.year;
+            config._dayOfYear = temp.dayOfYear;
+        }
+
+        //if the day of the year is set, figure out what it is
+        if (config._dayOfYear) {
+            yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
+
+            if (config._dayOfYear > daysInYear(yearToUse)) {
+                config._pf._overflowDayOfYear = true;
+            }
+
+            date = makeUTCDate(yearToUse, 0, config._dayOfYear);
+            config._a[MONTH] = date.getUTCMonth();
+            config._a[DATE] = date.getUTCDate();
+        }
+
+        // Default to current date.
+        // * if no year, month, day of month are given, default to today
+        // * if day of month is given, default month and year
+        // * if month is given, default only year
+        // * if year is given, don't default anything
+        for (i = 0; i < 3 && config._a[i] == null; ++i) {
+            config._a[i] = input[i] = currentDate[i];
+        }
+
+        // Zero out whatever was not defaulted, including time
+        for (; i < 7; i++) {
+            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
+        }
+
+        // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
+        input[HOUR] += toInt((config._tzm || 0) / 60);
+        input[MINUTE] += toInt((config._tzm || 0) % 60);
+
+        config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
+    }
+
+    function dateFromObject(config) {
+        var normalizedInput;
+
+        if (config._d) {
+            return;
+        }
+
+        normalizedInput = normalizeObjectUnits(config._i);
+        config._a = [
+            normalizedInput.year,
+            normalizedInput.month,
+            normalizedInput.day,
+            normalizedInput.hour,
+            normalizedInput.minute,
+            normalizedInput.second,
+            normalizedInput.millisecond
+        ];
+
+        dateFromConfig(config);
+    }
+
+    function currentDateArray(config) {
+        var now = new Date();
+        if (config._useUTC) {
+            return [
+                now.getUTCFullYear(),
+                now.getUTCMonth(),
+                now.getUTCDate()
+            ];
+        } else {
+            return [now.getFullYear(), now.getMonth(), now.getDate()];
+        }
+    }
+
+    // date from string and format string
+    function makeDateFromStringAndFormat(config) {
+
+        config._a = [];
+        config._pf.empty = true;
+
+        // This array is used to make a Date, either with `new Date` or `Date.UTC`
+        var lang = getLangDefinition(config._l),
+            string = '' + config._i,
+            i, parsedInput, tokens, token, skipped,
+            stringLength = string.length,
+            totalParsedInputLength = 0;
+
+        tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
+
+        for (i = 0; i < tokens.length; i++) {
+            token = tokens[i];
+            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
+            if (parsedInput) {
+                skipped = string.substr(0, string.indexOf(parsedInput));
+                if (skipped.length > 0) {
+                    config._pf.unusedInput.push(skipped);
+                }
+                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
+                totalParsedInputLength += parsedInput.length;
+            }
+            // don't parse if it's not a known token
+            if (formatTokenFunctions[token]) {
+                if (parsedInput) {
+                    config._pf.empty = false;
+                }
+                else {
+                    config._pf.unusedTokens.push(token);
+                }
+                addTimeToArrayFromToken(token, parsedInput, config);
+            }
+            else if (config._strict && !parsedInput) {
+                config._pf.unusedTokens.push(token);
+            }
+        }
+
+        // add remaining unparsed input length to the string
+        config._pf.charsLeftOver = stringLength - totalParsedInputLength;
+        if (string.length > 0) {
+            config._pf.unusedInput.push(string);
+        }
+
+        // handle am pm
+        if (config._isPm && config._a[HOUR] < 12) {
+            config._a[HOUR] += 12;
+        }
+        // if is 12 am, change hours to 0
+        if (config._isPm === false && config._a[HOUR] === 12) {
+            config._a[HOUR] = 0;
+        }
+
+        dateFromConfig(config);
+        checkOverflow(config);
+    }
+
+    function unescapeFormat(s) {
+        return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
+            return p1 || p2 || p3 || p4;
+        });
+    }
+
+    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+    function regexpEscape(s) {
+        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+    }
+
+    // date from string and array of format strings
+    function makeDateFromStringAndArray(config) {
+        var tempConfig,
+            bestMoment,
+
+            scoreToBeat,
+            i,
+            currentScore;
+
+        if (config._f.length === 0) {
+            config._pf.invalidFormat = true;
+            config._d = new Date(NaN);
+            return;
+        }
+
+        for (i = 0; i < config._f.length; i++) {
+            currentScore = 0;
+            tempConfig = extend({}, config);
+            tempConfig._pf = defaultParsingFlags();
+            tempConfig._f = config._f[i];
+            makeDateFromStringAndFormat(tempConfig);
+
+            if (!isValid(tempConfig)) {
+                continue;
+            }
+
+            // if there is any input that was not parsed add a penalty for that format
+            currentScore += tempConfig._pf.charsLeftOver;
+
+            //or tokens
+            currentScore += tempConfig._pf.unusedTokens.length * 10;
+
+            tempConfig._pf.score = currentScore;
+
+            if (scoreToBeat == null || currentScore < scoreToBeat) {
+                scoreToBeat = currentScore;
+                bestMoment = tempConfig;
+            }
+        }
+
+        extend(config, bestMoment || tempConfig);
+    }
+
+    // date from iso format
+    function makeDateFromString(config) {
+        var i, l,
+            string = config._i,
+            match = isoRegex.exec(string);
+
+        if (match) {
+            config._pf.iso = true;
+            for (i = 0, l = isoDates.length; i < l; i++) {
+                if (isoDates[i][1].exec(string)) {
+                    // match[5] should be "T" or undefined
+                    config._f = isoDates[i][0] + (match[6] || " ");
+                    break;
+                }
+            }
+            for (i = 0, l = isoTimes.length; i < l; i++) {
+                if (isoTimes[i][1].exec(string)) {
+                    config._f += isoTimes[i][0];
+                    break;
+                }
+            }
+            if (string.match(parseTokenTimezone)) {
+                config._f += "Z";
+            }
+            makeDateFromStringAndFormat(config);
+        }
+        else {
+            config._d = new Date(string);
+        }
+    }
+
+    function makeDateFromInput(config) {
+        var input = config._i,
+            matched = aspNetJsonRegex.exec(input);
+
+        if (input === undefined) {
+            config._d = new Date();
+        } else if (matched) {
+            config._d = new Date(+matched[1]);
+        } else if (typeof input === 'string') {
+            makeDateFromString(config);
+        } else if (isArray(input)) {
+            config._a = input.slice(0);
+            dateFromConfig(config);
+        } else if (isDate(input)) {
+            config._d = new Date(+input);
+        } else if (typeof(input) === 'object') {
+            dateFromObject(config);
+        } else {
+            config._d = new Date(input);
+        }
+    }
+
+    function makeDate(y, m, d, h, M, s, ms) {
+        //can't just apply() to create a date:
+        //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
+        var date = new Date(y, m, d, h, M, s, ms);
+
+        //the date constructor doesn't accept years < 1970
+        if (y < 1970) {
+            date.setFullYear(y);
+        }
+        return date;
+    }
+
+    function makeUTCDate(y) {
+        var date = new Date(Date.UTC.apply(null, arguments));
+        if (y < 1970) {
+            date.setUTCFullYear(y);
+        }
+        return date;
+    }
+
+    function parseWeekday(input, language) {
+        if (typeof input === 'string') {
+            if (!isNaN(input)) {
+                input = parseInt(input, 10);
+            }
+            else {
+                input = language.weekdaysParse(input);
+                if (typeof input !== 'number') {
+                    return null;
+                }
+            }
+        }
+        return input;
+    }
+
+    /************************************
+        Relative Time
+    ************************************/
+
+
+    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
+    function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
+        return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
+    }
+
+    function relativeTime(milliseconds, withoutSuffix, lang) {
+        var seconds = round(Math.abs(milliseconds) / 1000),
+            minutes = round(seconds / 60),
+            hours = round(minutes / 60),
+            days = round(hours / 24),
+            years = round(days / 365),
+            args = seconds < 45 && ['s', seconds] ||
+                minutes === 1 && ['m'] ||
+                minutes < 45 && ['mm', minutes] ||
+                hours === 1 && ['h'] ||
+                hours < 22 && ['hh', hours] ||
+                days === 1 && ['d'] ||
+                days <= 25 && ['dd', days] ||
+                days <= 45 && ['M'] ||
+                days < 345 && ['MM', round(days / 30)] ||
+                years === 1 && ['y'] || ['yy', years];
+        args[2] = withoutSuffix;
+        args[3] = milliseconds > 0;
+        args[4] = lang;
+        return substituteTimeAgo.apply({}, args);
+    }
+
+
+    /************************************
+        Week of Year
+    ************************************/
+
+
+    // firstDayOfWeek       0 = sun, 6 = sat
+    //                      the day of the week that starts the week
+    //                      (usually sunday or monday)
+    // firstDayOfWeekOfYear 0 = sun, 6 = sat
+    //                      the first week is the week that contains the first
+    //                      of this day of the week
+    //                      (eg. ISO weeks use thursday (4))
+    function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
+        var end = firstDayOfWeekOfYear - firstDayOfWeek,
+            daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
+            adjustedMoment;
+
+
+        if (daysToDayOfWeek > end) {
+            daysToDayOfWeek -= 7;
+        }
+
+        if (daysToDayOfWeek < end - 7) {
+            daysToDayOfWeek += 7;
+        }
+
+        adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
+        return {
+            week: Math.ceil(adjustedMoment.dayOfYear() / 7),
+            year: adjustedMoment.year()
+        };
+    }
+
+    //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
+    function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
+        var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
+
+        weekday = weekday != null ? weekday : firstDayOfWeek;
+        daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
+        dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
+
+        return {
+            year: dayOfYear > 0 ? year : year - 1,
+            dayOfYear: dayOfYear > 0 ?  dayOfYear : daysInYear(year - 1) + dayOfYear
+        };
+    }
+
+    /************************************
+        Top Level Functions
+    ************************************/
+
+    function makeMoment(config) {
+        var input = config._i,
+            format = config._f;
+
+        if (input === null) {
+            return moment.invalid({nullInput: true});
+        }
+
+        if (typeof input === 'string') {
+            config._i = input = getLangDefinition().preparse(input);
+        }
+
+        if (moment.isMoment(input)) {
+            config = cloneMoment(input);
+
+            config._d = new Date(+input._d);
+        } else if (format) {
+            if (isArray(format)) {
+                makeDateFromStringAndArray(config);
+            } else {
+                makeDateFromStringAndFormat(config);
+            }
+        } else {
+            makeDateFromInput(config);
+        }
+
+        return new Moment(config);
+    }
+
+    moment = function (input, format, lang, strict) {
+        var c;
+
+        if (typeof(lang) === "boolean") {
+            strict = lang;
+            lang = undefined;
+        }
+        // object construction must be done this way.
+        // https://github.com/moment/moment/issues/1423
+        c = {};
+        c._isAMomentObject = true;
+        c._i = input;
+        c._f = format;
+        c._l = lang;
+        c._strict = strict;
+        c._isUTC = false;
+        c._pf = defaultParsingFlags();
+
+        return makeMoment(c);
+    };
+
+    // creating with utc
+    moment.utc = function (input, format, lang, strict) {
+        var c;
+
+        if (typeof(lang) === "boolean") {
+            strict = lang;
+            lang = undefined;
+        }
+        // object construction must be done this way.
+        // https://github.com/moment/moment/issues/1423
+        c = {};
+        c._isAMomentObject = true;
+        c._useUTC = true;
+        c._isUTC = true;
+        c._l = lang;
+        c._i = input;
+        c._f = format;
+        c._strict = strict;
+        c._pf = defaultParsingFlags();
+
+        return makeMoment(c).utc();
+    };
+
+    // creating with unix timestamp (in seconds)
+    moment.unix = function (input) {
+        return moment(input * 1000);
+    };
+
+    // duration
+    moment.duration = function (input, key) {
+        var duration = input,
+            // matching against regexp is expensive, do it on demand
+            match = null,
+            sign,
+            ret,
+            parseIso;
+
+        if (moment.isDuration(input)) {
+            duration = {
+                ms: input._milliseconds,
+                d: input._days,
+                M: input._months
+            };
+        } else if (typeof input === 'number') {
+            duration = {};
+            if (key) {
+                duration[key] = input;
+            } else {
+                duration.milliseconds = input;
+            }
+        } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
+            sign = (match[1] === "-") ? -1 : 1;
+            duration = {
+                y: 0,
+                d: toInt(match[DATE]) * sign,
+                h: toInt(match[HOUR]) * sign,
+                m: toInt(match[MINUTE]) * sign,
+                s: toInt(match[SECOND]) * sign,
+                ms: toInt(match[MILLISECOND]) * sign
+            };
+        } else if (!!(match = isoDurationRegex.exec(input))) {
+            sign = (match[1] === "-") ? -1 : 1;
+            parseIso = function (inp) {
+                // We'd normally use ~~inp for this, but unfortunately it also
+                // converts floats to ints.
+                // inp may be undefined, so careful calling replace on it.
+                var res = inp && parseFloat(inp.replace(',', '.'));
+                // apply sign while we're at it
+                return (isNaN(res) ? 0 : res) * sign;
+            };
+            duration = {
+                y: parseIso(match[2]),
+                M: parseIso(match[3]),
+                d: parseIso(match[4]),
+                h: parseIso(match[5]),
+                m: parseIso(match[6]),
+                s: parseIso(match[7]),
+                w: parseIso(match[8])
+            };
+        }
+
+        ret = new Duration(duration);
+
+        if (moment.isDuration(input) && input.hasOwnProperty('_lang')) {
+            ret._lang = input._lang;
+        }
+
+        return ret;
+    };
+
+    // version number
+    moment.version = VERSION;
+
+    // default format
+    moment.defaultFormat = isoFormat;
+
+    // This function will be called whenever a moment is mutated.
+    // It is intended to keep the offset in sync with the timezone.
+    moment.updateOffset = function () {};
+
+    // This function will load languages and then set the global language.  If
+    // no arguments are passed in, it will simply return the current global
+    // language key.
+    moment.lang = function (key, values) {
+        var r;
+        if (!key) {
+            return moment.fn._lang._abbr;
+        }
+        if (values) {
+            loadLang(normalizeLanguage(key), values);
+        } else if (values === null) {
+            unloadLang(key);
+            key = 'en';
+        } else if (!languages[key]) {
+            getLangDefinition(key);
+        }
+        r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
+        return r._abbr;
+    };
+
+    // returns language data
+    moment.langData = function (key) {
+        if (key && key._lang && key._lang._abbr) {
+            key = key._lang._abbr;
+        }
+        return getLangDefinition(key);
+    };
+
+    // compare moment object
+    moment.isMoment = function (obj) {
+        return obj instanceof Moment ||
+            (obj != null &&  obj.hasOwnProperty('_isAMomentObject'));
+    };
+
+    // for typechecking Duration objects
+    moment.isDuration = function (obj) {
+        return obj instanceof Duration;
+    };
+
+    for (i = lists.length - 1; i >= 0; --i) {
+        makeList(lists[i]);
+    }
+
+    moment.normalizeUnits = function (units) {
+        return normalizeUnits(units);
+    };
+
+    moment.invalid = function (flags) {
+        var m = moment.utc(NaN);
+        if (flags != null) {
+            extend(m._pf, flags);
+        }
+        else {
+            m._pf.userInvalidated = true;
+        }
+
+        return m;
+    };
+
+    moment.parseZone = function (input) {
+        return moment(input).parseZone();
+    };
+
+    /************************************
+        Moment Prototype
+    ************************************/
+
+
+    extend(moment.fn = Moment.prototype, {
+
+        clone : function () {
+            return moment(this);
+        },
+
+        valueOf : function () {
+            return +this._d + ((this._offset || 0) * 60000);
+        },
+
+        unix : function () {
+            return Math.floor(+this / 1000);
+        },
+
+        toString : function () {
+            return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
+        },
+
+        toDate : function () {
+            return this._offset ? new Date(+this) : this._d;
+        },
+
+        toISOString : function () {
+            var m = moment(this).utc();
+            if (0 < m.year() && m.year() <= 9999) {
+                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+            } else {
+                return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+            }
+        },
+
+        toArray : function () {
+            var m = this;
+            return [
+                m.year(),
+                m.month(),
+                m.date(),
+                m.hours(),
+                m.minutes(),
+                m.seconds(),
+                m.milliseconds()
+            ];
+        },
+
+        isValid : function () {
+            return isValid(this);
+        },
+
+        isDSTShifted : function () {
+
+            if (this._a) {
+                return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
+            }
+
+            return false;
+        },
+
+        parsingFlags : function () {
+            return extend({}, this._pf);
+        },
+
+        invalidAt: function () {
+            return this._pf.overflow;
+        },
+
+        utc : function () {
+            return this.zone(0);
+        },
+
+        local : function () {
+            this.zone(0);
+            this._isUTC = false;
+            return this;
+        },
+
+        format : function (inputString) {
+            var output = formatMoment(this, inputString || moment.defaultFormat);
+            return this.lang().postformat(output);
+        },
+
+        add : function (input, val) {
+            var dur;
+            // switch args to support add('s', 1) and add(1, 's')
+            if (typeof input === 'string') {
+                dur = moment.duration(+val, input);
+            } else {
+                dur = moment.duration(input, val);
+            }
+            addOrSubtractDurationFromMoment(this, dur, 1);
+            return this;
+        },
+
+        subtract : function (input, val) {
+            var dur;
+            // switch args to support subtract('s', 1) and subtract(1, 's')
+            if (typeof input === 'string') {
+                dur = moment.duration(+val, input);
+            } else {
+                dur = moment.duration(input, val);
+            }
+            addOrSubtractDurationFromMoment(this, dur, -1);
+            return this;
+        },
+
+        diff : function (input, units, asFloat) {
+            var that = makeAs(input, this),
+                zoneDiff = (this.zone() - that.zone()) * 6e4,
+                diff, output;
+
+            units = normalizeUnits(units);
+
+            if (units === 'year' || units === 'month') {
+                // average number of days in the months in the given dates
+                diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
+                // difference in months
+                output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
+                // adjust by taking difference in days, average number of days
+                // and dst in the given months.
+                output += ((this - moment(this).startOf('month')) -
+                        (that - moment(that).startOf('month'))) / diff;
+                // same as above but with zones, to negate all dst
+                output -= ((this.zone() - moment(this).startOf('month').zone()) -
+                        (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff;
+                if (units === 'year') {
+                    output = output / 12;
+                }
+            } else {
+                diff = (this - that);
+                output = units === 'second' ? diff / 1e3 : // 1000
+                    units === 'minute' ? diff / 6e4 : // 1000 * 60
+                    units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
+                    units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
+                    units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
+                    diff;
+            }
+            return asFloat ? output : absRound(output);
+        },
+
+        from : function (time, withoutSuffix) {
+            return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
+        },
+
+        fromNow : function (withoutSuffix) {
+            return this.from(moment(), withoutSuffix);
+        },
+
+        calendar : function () {
+            // We want to compare the start of today, vs this.
+            // Getting start-of-today depends on whether we're zone'd or not.
+            var sod = makeAs(moment(), this).startOf('day'),
+                diff = this.diff(sod, 'days', true),
+                format = diff < -6 ? 'sameElse' :
+                    diff < -1 ? 'lastWeek' :
+                    diff < 0 ? 'lastDay' :
+                    diff < 1 ? 'sameDay' :
+                    diff < 2 ? 'nextDay' :
+                    diff < 7 ? 'nextWeek' : 'sameElse';
+            return this.format(this.lang().calendar(format, this));
+        },
+
+        isLeapYear : function () {
+            return isLeapYear(this.year());
+        },
+
+        isDST : function () {
+            return (this.zone() < this.clone().month(0).zone() ||
+                this.zone() < this.clone().month(5).zone());
+        },
+
+        day : function (input) {
+            var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
+            if (input != null) {
+                input = parseWeekday(input, this.lang());
+                return this.add({ d : input - day });
+            } else {
+                return day;
+            }
+        },
+
+        month : function (input) {
+            var utc = this._isUTC ? 'UTC' : '',
+                dayOfMonth;
+
+            if (input != null) {
+                if (typeof input === 'string') {
+                    input = this.lang().monthsParse(input);
+                    if (typeof input !== 'number') {
+                        return this;
+                    }
+                }
+
+                dayOfMonth = this.date();
+                this.date(1);
+                this._d['set' + utc + 'Month'](input);
+                this.date(Math.min(dayOfMonth, this.daysInMonth()));
+
+                moment.updateOffset(this);
+                return this;
+            } else {
+                return this._d['get' + utc + 'Month']();
+            }
+        },
+
+        startOf: function (units) {
+            units = normalizeUnits(units);
+            // the following switch intentionally omits break keywords
+            // to utilize falling through the cases.
+            switch (units) {
+            case 'year':
+                this.month(0);
+                /* falls through */
+            case 'month':
+                this.date(1);
+                /* falls through */
+            case 'week':
+            case 'isoWeek':
+            case 'day':
+                this.hours(0);
+                /* falls through */
+            case 'hour':
+                this.minutes(0);
+                /* falls through */
+            case 'minute':
+                this.seconds(0);
+                /* falls through */
+            case 'second':
+                this.milliseconds(0);
+                /* falls through */
+            }
+
+            // weeks are a special case
+            if (units === 'week') {
+                this.weekday(0);
+            } else if (units === 'isoWeek') {
+                this.isoWeekday(1);
+            }
+
+            return this;
+        },
+
+        endOf: function (units) {
+            units = normalizeUnits(units);
+            return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
+        },
+
+        isAfter: function (input, units) {
+            units = typeof units !== 'undefined' ? units : 'millisecond';
+            return +this.clone().startOf(units) > +moment(input).startOf(units);
+        },
+
+        isBefore: function (input, units) {
+            units = typeof units !== 'undefined' ? units : 'millisecond';
+            return +this.clone().startOf(units) < +moment(input).startOf(units);
+        },
+
+        isSame: function (input, units) {
+            units = units || 'ms';
+            return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
+        },
+
+        min: function (other) {
+            other = moment.apply(null, arguments);
+            return other < this ? this : other;
+        },
+
+        max: function (other) {
+            other = moment.apply(null, arguments);
+            return other > this ? this : other;
+        },
+
+        zone : function (input) {
+            var offset = this._offset || 0;
+            if (input != null) {
+                if (typeof input === "string") {
+                    input = timezoneMinutesFromString(input);
+                }
+                if (Math.abs(input) < 16) {
+                    input = input * 60;
+                }
+                this._offset = input;
+                this._isUTC = true;
+                if (offset !== input) {
+                    addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
+                }
+            } else {
+                return this._isUTC ? offset : this._d.getTimezoneOffset();
+            }
+            return this;
+        },
+
+        zoneAbbr : function () {
+            return this._isUTC ? "UTC" : "";
+        },
+
+        zoneName : function () {
+            return this._isUTC ? "Coordinated Universal Time" : "";
+        },
+
+        parseZone : function () {
+            if (this._tzm) {
+                this.zone(this._tzm);
+            } else if (typeof this._i === 'string') {
+                this.zone(this._i);
+            }
+            return this;
+        },
+
+        hasAlignedHourOffset : function (input) {
+            if (!input) {
+                input = 0;
+            }
+            else {
+                input = moment(input).zone();
+            }
+
+            return (this.zone() - input) % 60 === 0;
+        },
+
+        daysInMonth : function () {
+            return daysInMonth(this.year(), this.month());
+        },
+
+        dayOfYear : function (input) {
+            var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
+            return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
+        },
+
+        quarter : function () {
+            return Math.ceil((this.month() + 1.0) / 3.0);
+        },
+
+        weekYear : function (input) {
+            var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year;
+            return input == null ? year : this.add("y", (input - year));
+        },
+
+        isoWeekYear : function (input) {
+            var year = weekOfYear(this, 1, 4).year;
+            return input == null ? year : this.add("y", (input - year));
+        },
+
+        week : function (input) {
+            var week = this.lang().week(this);
+            return input == null ? week : this.add("d", (input - week) * 7);
+        },
+
+        isoWeek : function (input) {
+            var week = weekOfYear(this, 1, 4).week;
+            return input == null ? week : this.add("d", (input - week) * 7);
+        },
+
+        weekday : function (input) {
+            var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
+            return input == null ? weekday : this.add("d", input - weekday);
+        },
+
+        isoWeekday : function (input) {
+            // behaves the same as moment#day except
+            // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
+            // as a setter, sunday should belong to the previous week.
+            return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
+        },
+
+        get : function (units) {
+            units = normalizeUnits(units);
+            return this[units]();
+        },
+
+        set : function (units, value) {
+            units = normalizeUnits(units);
+            if (typeof this[units] === 'function') {
+                this[units](value);
+            }
+            return this;
+        },
+
+        // If passed a language key, it will set the language for this
+        // instance.  Otherwise, it will return the language configuration
+        // variables for this instance.
+        lang : function (key) {
+            if (key === undefined) {
+                return this._lang;
+            } else {
+                this._lang = getLangDefinition(key);
+                return this;
+            }
+        }
+    });
+
+    // helper for adding shortcuts
+    function makeGetterAndSetter(name, key) {
+        moment.fn[name] = moment.fn[name + 's'] = function (input) {
+            var utc = this._isUTC ? 'UTC' : '';
+            if (input != null) {
+                this._d['set' + utc + key](input);
+                moment.updateOffset(this);
+                return this;
+            } else {
+                return this._d['get' + utc + key]();
+            }
+        };
+    }
+
+    // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
+    for (i = 0; i < proxyGettersAndSetters.length; i ++) {
+        makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
+    }
+
+    // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
+    makeGetterAndSetter('year', 'FullYear');
+
+    // add plural methods
+    moment.fn.days = moment.fn.day;
+    moment.fn.months = moment.fn.month;
+    moment.fn.weeks = moment.fn.week;
+    moment.fn.isoWeeks = moment.fn.isoWeek;
+
+    // add aliased format methods
+    moment.fn.toJSON = moment.fn.toISOString;
+
+    /************************************
+        Duration Prototype
+    ************************************/
+
+
+    extend(moment.duration.fn = Duration.prototype, {
+
+        _bubble : function () {
+            var milliseconds = this._milliseconds,
+                days = this._days,
+                months = this._months,
+                data = this._data,
+                seconds, minutes, hours, years;
+
+            // The following code bubbles up values, see the tests for
+            // examples of what that means.
+            data.milliseconds = milliseconds % 1000;
+
+            seconds = absRound(milliseconds / 1000);
+            data.seconds = seconds % 60;
+
+            minutes = absRound(seconds / 60);
+            data.minutes = minutes % 60;
+
+            hours = absRound(minutes / 60);
+            data.hours = hours % 24;
+
+            days += absRound(hours / 24);
+            data.days = days % 30;
+
+            months += absRound(days / 30);
+            data.months = months % 12;
+
+            years = absRound(months / 12);
+            data.years = years;
+        },
+
+        weeks : function () {
+            return absRound(this.days() / 7);
+        },
+
+        valueOf : function () {
+            return this._milliseconds +
+              this._days * 864e5 +
+              (this._months % 12) * 2592e6 +
+              toInt(this._months / 12) * 31536e6;
+        },
+
+        humanize : function (withSuffix) {
+            var difference = +this,
+                output = relativeTime(difference, !withSuffix, this.lang());
+
+            if (withSuffix) {
+                output = this.lang().pastFuture(difference, output);
+            }
+
+            return this.lang().postformat(output);
+        },
+
+        add : function (input, val) {
+            // supports only 2.0-style add(1, 's') or add(moment)
+            var dur = moment.duration(input, val);
+
+            this._milliseconds += dur._milliseconds;
+            this._days += dur._days;
+            this._months += dur._months;
+
+            this._bubble();
+
+            return this;
+        },
+
+        subtract : function (input, val) {
+            var dur = moment.duration(input, val);
+
+            this._milliseconds -= dur._milliseconds;
+            this._days -= dur._days;
+            this._months -= dur._months;
+
+            this._bubble();
+
+            return this;
+        },
+
+        get : function (units) {
+            units = normalizeUnits(units);
+            return this[units.toLowerCase() + 's']();
+        },
+
+        as : function (units) {
+            units = normalizeUnits(units);
+            return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
+        },
+
+        lang : moment.fn.lang,
+
+        toIsoString : function () {
+            // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
+            var years = Math.abs(this.years()),
+                months = Math.abs(this.months()),
+                days = Math.abs(this.days()),
+                hours = Math.abs(this.hours()),
+                minutes = Math.abs(this.minutes()),
+                seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
+
+            if (!this.asSeconds()) {
+                // this is the same as C#'s (Noda) and python (isodate)...
+                // but not other JS (goog.date)
+                return 'P0D';
+            }
+
+            return (this.asSeconds() < 0 ? '-' : '') +
+                'P' +
+                (years ? years + 'Y' : '') +
+                (months ? months + 'M' : '') +
+                (days ? days + 'D' : '') +
+                ((hours || minutes || seconds) ? 'T' : '') +
+                (hours ? hours + 'H' : '') +
+                (minutes ? minutes + 'M' : '') +
+                (seconds ? seconds + 'S' : '');
+        }
+    });
+
+    function makeDurationGetter(name) {
+        moment.duration.fn[name] = function () {
+            return this._data[name];
+        };
+    }
+
+    function makeDurationAsGetter(name, factor) {
+        moment.duration.fn['as' + name] = function () {
+            return +this / factor;
+        };
+    }
+
+    for (i in unitMillisecondFactors) {
+        if (unitMillisecondFactors.hasOwnProperty(i)) {
+            makeDurationAsGetter(i, unitMillisecondFactors[i]);
+            makeDurationGetter(i.toLowerCase());
+        }
+    }
+
+    makeDurationAsGetter('Weeks', 6048e5);
+    moment.duration.fn.asMonths = function () {
+        return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
+    };
+
+
+    /************************************
+        Default Lang
+    ************************************/
+
+
+    // Set default language, other languages will inherit from English.
+    moment.lang('en', {
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (toInt(number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        }
+    });
+
+    /* EMBED_LANGUAGES */
+
+    /************************************
+        Exposing Moment
+    ************************************/
+
+    function makeGlobal(deprecate) {
+        var warned = false, local_moment = moment;
+        /*global ender:false */
+        if (typeof ender !== 'undefined') {
+            return;
+        }
+        // here, `this` means `window` in the browser, or `global` on the server
+        // add `moment` as a global object via a string identifier,
+        // for Closure Compiler "advanced" mode
+        if (deprecate) {
+            global.moment = function () {
+                if (!warned && console && console.warn) {
+                    warned = true;
+                    console.warn(
+                            "Accessing Moment through the global scope is " +
+                            "deprecated, and will be removed in an upcoming " +
+                            "release.");
+                }
+                return local_moment.apply(null, arguments);
+            };
+            extend(global.moment, local_moment);
+        } else {
+            global['moment'] = moment;
+        }
+    }
+
+    // CommonJS module is defined
+    if (hasModule) {
+        module.exports = moment;
+        makeGlobal(true);
+    } else if (typeof define === "function" && define.amd) {
+        define("moment", function (require, exports, module) {
+            if (module.config && module.config() && module.config().noGlobal !== true) {
+                // If user provided noGlobal, he is aware of global
+                makeGlobal(module.config().noGlobal === undefined);
+            }
+
+            return moment;
+        });
+    } else {
+        makeGlobal();
+    }
+}).call(this);
diff --git a/resources/lib/oojs-ui/i18n/ace.json b/resources/lib/oojs-ui/i18n/ace.json
new file mode 100644 (file)
index 0000000..554ae57
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Si Gam Acèh"
+        ]
+    },
+    "ooui-dialog-action-close": "Tôp",
+    "ooui-outline-control-move-down": "Pinah item u yup",
+    "ooui-outline-control-move-up": "Pinah item u ateuëh",
+    "ooui-toolbar-more": "Lom"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/af.json b/resources/lib/oojs-ui/i18n/af.json
new file mode 100644 (file)
index 0000000..a622f89
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Naudefj"
+        ]
+    },
+    "ooui-dialog-action-close": "Sluit",
+    "ooui-outline-control-move-down": "Skuif item af",
+    "ooui-outline-control-move-up": "Skuif item op"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/am.json b/resources/lib/oojs-ui/i18n/am.json
new file mode 100644 (file)
index 0000000..61e4ff6
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "Elfalem"
+        ]
+    },
+    "ooui-dialog-action-close": "ለመዝጋት"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ar.json b/resources/lib/oojs-ui/i18n/ar.json
new file mode 100644 (file)
index 0000000..65e1364
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ciphers",
+            "Claw eg",
+            "Elfalem",
+            "Jdforrester",
+            "Mido",
+            "OsamaK",
+            "زكريا",
+            "مشعل الحربي"
+        ]
+    },
+    "ooui-dialog-action-close": "أغلق",
+    "ooui-outline-control-move-down": "انقل العنصر للأسفل",
+    "ooui-outline-control-move-up": "انقل العنصر للأعلى",
+    "ooui-toolbar-more": "مزيد"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/arc.json b/resources/lib/oojs-ui/i18n/arc.json
new file mode 100644 (file)
index 0000000..0f9e75d
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "Basharh"
+        ]
+    },
+    "ooui-dialog-action-close": "ܣܟܘܪ"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ast.json b/resources/lib/oojs-ui/i18n/ast.json
new file mode 100644 (file)
index 0000000..fe6ea0a
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Basharh",
+            "Bishnu Saikia",
+            "Xuacu"
+        ]
+    },
+    "ooui-dialog-action-close": "Zarrar",
+    "ooui-outline-control-move-down": "Mover abaxo l'elementu",
+    "ooui-outline-control-move-up": "Mover arriba l'elementu",
+    "ooui-outline-control-remove": "Desaniciar elementu",
+    "ooui-toolbar-more": "Más"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/az.json b/resources/lib/oojs-ui/i18n/az.json
new file mode 100644 (file)
index 0000000..257680b
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cekli829",
+            "Interfase",
+            "Jduranboger"
+        ]
+    },
+    "ooui-dialog-action-close": "Bağla",
+    "ooui-outline-control-move-down": "Bəndi aşağı apar",
+    "ooui-outline-control-move-up": "Bəndi yuxarı apar",
+    "ooui-outline-control-remove": "Bəndi sil",
+    "ooui-toolbar-more": "Daha artıq"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ba.json b/resources/lib/oojs-ui/i18n/ba.json
new file mode 100644 (file)
index 0000000..4af0114
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "@metadata": {
+        "authors": [
+            "AiseluRB",
+            "Amire80",
+            "Assele",
+            "Haqmar",
+            "Sagan",
+            "Рустам Нурыев"
+        ]
+    },
+    "ooui-dialog-action-close": "Ябырға",
+    "ooui-outline-control-move-down": "Аҫҡа күсерергә",
+    "ooui-outline-control-move-up": "Өҫкә күсерергә"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/bcl.json b/resources/lib/oojs-ui/i18n/bcl.json
new file mode 100644 (file)
index 0000000..aff451e
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Geopoet",
+            "Sky Harbor"
+        ]
+    },
+    "ooui-dialog-action-close": "Seraduhon",
+    "ooui-outline-control-move-down": "Balyuhon an aytem paibaba",
+    "ooui-outline-control-move-up": "Balyuhon an aytem paitaas",
+    "ooui-toolbar-more": "Kadugangan"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/be-tarask.json b/resources/lib/oojs-ui/i18n/be-tarask.json
new file mode 100644 (file)
index 0000000..5922f61
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "EugeneZelenko",
+            "Wizardist",
+            "Чаховіч Уладзіслаў",
+            "Zedlik"
+        ]
+    },
+    "ooui-dialog-action-close": "Закрыць",
+    "ooui-outline-control-move-down": "Перасунуць ніжэй",
+    "ooui-outline-control-move-up": "Перасунуць вышэй",
+    "ooui-toolbar-more": "Болей"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/be.json b/resources/lib/oojs-ui/i18n/be.json
new file mode 100644 (file)
index 0000000..3058ab8
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "Чаховіч Уладзіслаў"
+        ]
+    },
+    "ooui-dialog-action-close": "Закрыць"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/bg.json b/resources/lib/oojs-ui/i18n/bg.json
new file mode 100644 (file)
index 0000000..6006244
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "DCLXVI",
+            "Hristofor.mirchev",
+            "පසිඳු කාවින්ද",
+            "Mitzev"
+        ]
+    },
+    "ooui-dialog-action-close": "Затваряне",
+    "ooui-outline-control-remove": "Премахване на обекта",
+    "ooui-toolbar-more": "Още"
+}
diff --git a/resources/lib/oojs-ui/i18n/bn.json b/resources/lib/oojs-ui/i18n/bn.json
new file mode 100644 (file)
index 0000000..c321ab1
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "@metadata": {
+        "authors": [
+            "Aftab1995",
+            "Bellayet",
+            "Jayantanth",
+            "Nasir8891",
+            "Runab",
+            "Sayak Sarkar"
+        ]
+    },
+    "ooui-dialog-action-close": "বন্ধ",
+    "ooui-outline-control-move-down": "আইটেম নিচে স্থানান্তর",
+    "ooui-outline-control-move-up": "আইটেম উপরে স্থানান্তর",
+    "ooui-toolbar-more": "আরও"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/br.json b/resources/lib/oojs-ui/i18n/br.json
new file mode 100644 (file)
index 0000000..38eb9e8
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Fohanno",
+            "Fulup",
+            "Y-M D"
+        ]
+    },
+    "ooui-dialog-action-close": "Serriñ",
+    "ooui-outline-control-move-down": "Lakaat an elfenn da ziskenn",
+    "ooui-outline-control-move-up": "Lakaat an elfenn da bignat"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/bs.json b/resources/lib/oojs-ui/i18n/bs.json
new file mode 100644 (file)
index 0000000..95ba48d
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "DzWiki"
+        ]
+    },
+    "ooui-dialog-action-close": "Zatvori",
+    "ooui-outline-control-move-down": "Premjesti stavku dole",
+    "ooui-outline-control-move-up": "Premjesti stavku gore",
+    "ooui-outline-control-remove": "Ukloni stavku",
+    "ooui-toolbar-more": "Više"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ca.json b/resources/lib/oojs-ui/i18n/ca.json
new file mode 100644 (file)
index 0000000..61bb1f6
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "@metadata": {
+        "authors": [
+            "Alvaro Vidal-Abarca",
+            "Amire80",
+            "Arnaugir",
+            "Pginer",
+            "QuimGil",
+            "SMP",
+            "Vriullop"
+        ]
+    },
+    "ooui-dialog-action-close": "Tanca",
+    "ooui-outline-control-move-down": "Baixa element",
+    "ooui-outline-control-move-up": "Puja element",
+    "ooui-toolbar-more": "Més"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ce.json b/resources/lib/oojs-ui/i18n/ce.json
new file mode 100644 (file)
index 0000000..ff14ff3
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Amire80",
+            "Умар"
+        ]
+    },
+    "ooui-dialog-action-close": "ДӀачӀагӀа",
+    "ooui-outline-control-move-down": "Лаха яккха элемент",
+    "ooui-outline-control-move-up": "Лаккха яккха элемент",
+    "ooui-outline-control-remove": "ДӀадаха меттиг",
+    "ooui-toolbar-more": "Кхин тӀе"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ckb.json b/resources/lib/oojs-ui/i18n/ckb.json
new file mode 100644 (file)
index 0000000..839f4a8
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Calak",
+            "Muhammed taha"
+        ]
+    },
+    "ooui-dialog-action-close": "دایخە"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/co.json b/resources/lib/oojs-ui/i18n/co.json
new file mode 100644 (file)
index 0000000..e5edb21
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Paulu"
+        ]
+    },
+    "ooui-dialog-action-close": "Chjude",
+    "ooui-outline-control-move-down": "Fà falà l'ogettu",
+    "ooui-outline-control-move-up": "Fà cullà l'ogettu"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/cs.json b/resources/lib/oojs-ui/i18n/cs.json
new file mode 100644 (file)
index 0000000..670073f
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    "@metadata": {
+        "authors": [
+            "Chmee2",
+            "Jkjk",
+            "Juandev",
+            "Koo6",
+            "Littledogboy",
+            "Michaelbrabec",
+            "Mormegil",
+            "Polda18",
+            "Tchoř",
+            "ශ්වෙත"
+        ]
+    },
+    "ooui-dialog-action-close": "Zavřít",
+    "ooui-outline-control-move-down": "Přesunout položku dolů",
+    "ooui-outline-control-move-up": "Přesunout položku nahoru",
+    "ooui-outline-control-remove": "Odstranit položku",
+    "ooui-toolbar-more": "Další"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/cu.json b/resources/lib/oojs-ui/i18n/cu.json
new file mode 100644 (file)
index 0000000..55594c1
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "ОйЛ"
+        ]
+    },
+    "ooui-dialog-action-close": "ꙁакрꙑи",
+    "ooui-toolbar-more": "вѧщє"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/cy.json b/resources/lib/oojs-ui/i18n/cy.json
new file mode 100644 (file)
index 0000000..d37912d
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Lloffiwr",
+            "Robin Owain",
+            "ОйЛ"
+        ]
+    },
+    "ooui-dialog-action-close": "Caeer",
+    "ooui-outline-control-move-down": "Symud yr eitem lawr",
+    "ooui-outline-control-move-up": "Symud yr eitem lan",
+    "ooui-toolbar-more": "Rhagor"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/da.json b/resources/lib/oojs-ui/i18n/da.json
new file mode 100644 (file)
index 0000000..bf47bcb
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cgtdk",
+            "Christian List",
+            "EileenSanda",
+            "Laketown",
+            "Palnatoke",
+            "Simeondahl",
+            "Tehnix"
+        ]
+    },
+    "ooui-dialog-action-close": "Luk",
+    "ooui-outline-control-move-down": "Flyt ned",
+    "ooui-outline-control-move-up": "Flyt op",
+    "ooui-toolbar-more": "Mere"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/de.json b/resources/lib/oojs-ui/i18n/de.json
new file mode 100644 (file)
index 0000000..bed2b2c
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    "@metadata": {
+        "authors": [
+            "APPER",
+            "G.Hagedorn",
+            "Inkowik",
+            "Jcornelius",
+            "Jdforrester",
+            "Kghbln",
+            "Metalhead64",
+            "Murma174",
+            "Se4598",
+            "Tomabrafix"
+        ]
+    },
+    "ooui-dialog-action-close": "Schließen",
+    "ooui-outline-control-move-down": "Element nach unten verschieben",
+    "ooui-outline-control-move-up": "Element nach oben verschieben",
+    "ooui-outline-control-remove": "Element entfernen",
+    "ooui-toolbar-more": "Mehr"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/diq.json b/resources/lib/oojs-ui/i18n/diq.json
new file mode 100644 (file)
index 0000000..bb0ac35
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "@metadata": {
+        "authors": [
+            "Erdemaslancan",
+            "Gorizon",
+            "Kghbln",
+            "Marmase",
+            "Mirzali",
+            "Se4598"
+        ]
+    },
+    "ooui-dialog-action-close": "Racnê",
+    "ooui-outline-control-move-down": "Bendi bere cêr",
+    "ooui-outline-control-move-up": "Bendi bere cor",
+    "ooui-toolbar-more": "Zewbi"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/dsb.json b/resources/lib/oojs-ui/i18n/dsb.json
new file mode 100644 (file)
index 0000000..ef60093
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Michawiki"
+        ]
+    },
+    "ooui-dialog-action-close": "Zacyniś",
+    "ooui-outline-control-move-down": "Element dołoj pśesunuś",
+    "ooui-outline-control-move-up": "Element górjej pśesunuś",
+    "ooui-outline-control-remove": "Zapisk wótpóraś",
+    "ooui-toolbar-more": "Wěcej"
+}
diff --git a/resources/lib/oojs-ui/i18n/el.json b/resources/lib/oojs-ui/i18n/el.json
new file mode 100644 (file)
index 0000000..d1ef8b2
--- /dev/null
@@ -0,0 +1,19 @@
+{
+    "@metadata": {
+        "authors": [
+            "Astralnet",
+            "Dipa1965",
+            "Evropi",
+            "FocalPoint",
+            "Geraki",
+            "Glavkos",
+            "Nikosguard",
+            "Tifa93"
+        ]
+    },
+    "ooui-dialog-action-close": "Κλείσιμο",
+    "ooui-outline-control-move-down": "Μετακίνηση στοιχείου προς τα κάτω",
+    "ooui-outline-control-move-up": "Μετακίνηση στοιχείου προς τα επάνω",
+    "ooui-outline-control-remove": "Αφαίρεση στοιχείου",
+    "ooui-toolbar-more": "Περισσότερα"
+}
diff --git a/resources/lib/oojs-ui/i18n/eml.json b/resources/lib/oojs-ui/i18n/eml.json
new file mode 100644 (file)
index 0000000..5dd09f5
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Gloria sah",
+            "Lévi"
+        ]
+    },
+    "ooui-dialog-action-close": "Sèra",
+    "ooui-outline-control-move-down": "Spôsta in bâs",
+    "ooui-outline-control-move-up": "Spôsta in êlt",
+    "ooui-toolbar-more": "Êter"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/en.json b/resources/lib/oojs-ui/i18n/en.json
new file mode 100644 (file)
index 0000000..5ff9915
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    "@metadata": {
+        "authors": [
+            "Trevor Parscal",
+            "Ed Sanders",
+            "James D. Forrester",
+            "Raimond Spekking",
+            "Erik Moeller",
+            "Moriel Schottlender",
+            "Yuki Shira",
+            "Siebrand Mazeland",
+            "Rob Moen",
+            "Timo Tijhof",
+            "Roan Kattouw",
+            "Christian Williams",
+            "Amir E. Aharoni"
+        ]
+    },
+    "ooui-dialog-action-close": "Close",
+    "ooui-outline-control-move-down": "Move item down",
+    "ooui-outline-control-move-up": "Move item up",
+    "ooui-outline-control-remove": "Remove item",
+    "ooui-toolbar-more": "More"
+}
diff --git a/resources/lib/oojs-ui/i18n/eo.json b/resources/lib/oojs-ui/i18n/eo.json
new file mode 100644 (file)
index 0000000..51f3261
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Happy5214",
+            "KuboF",
+            "Shirayuki",
+            "Yekrats"
+        ]
+    },
+    "ooui-dialog-action-close": "Fermi",
+    "ooui-outline-control-move-down": "Movi eron suben",
+    "ooui-outline-control-move-up": "Movi eron supren",
+    "ooui-toolbar-more": "Pli"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/es.json b/resources/lib/oojs-ui/i18n/es.json
new file mode 100644 (file)
index 0000000..a3be749
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    "@metadata": {
+        "authors": [
+            "Armando-Martin",
+            "Aruizdr",
+            "Benfutbol10",
+            "DJ Nietzsche",
+            "Erdemaslancan",
+            "Fitoschido",
+            "Imre",
+            "Invadinado",
+            "Jdforrester",
+            "Jduranboger",
+            "PoLuX124",
+            "Ralgis",
+            "Thehelpfulone"
+        ]
+    },
+    "ooui-dialog-action-close": "Cerrar",
+    "ooui-outline-control-move-down": "Mover abajo",
+    "ooui-outline-control-move-up": "Mover arriba",
+    "ooui-outline-control-remove": "Eliminar elemento",
+    "ooui-toolbar-more": "Más"
+}
diff --git a/resources/lib/oojs-ui/i18n/et.json b/resources/lib/oojs-ui/i18n/et.json
new file mode 100644 (file)
index 0000000..f0ddc39
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Avjoska",
+            "Pikne"
+        ]
+    },
+    "ooui-dialog-action-close": "Sule",
+    "ooui-outline-control-move-down": "Liiguta üksust allapoole",
+    "ooui-outline-control-move-up": "Liiguta üksust ülespoole",
+    "ooui-outline-control-remove": "Eemalda üksus",
+    "ooui-toolbar-more": "Veel"
+}
diff --git a/resources/lib/oojs-ui/i18n/eu.json b/resources/lib/oojs-ui/i18n/eu.json
new file mode 100644 (file)
index 0000000..5d3f08b
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "An13sa",
+            "Unai Fdz. de Betoño",
+            "Xabier Armendaritz"
+        ]
+    },
+    "ooui-dialog-action-close": "Itxi",
+    "ooui-outline-control-move-down": "Mugitu itema beherantz",
+    "ooui-outline-control-move-up": "Mugitu itema gorantz",
+    "ooui-toolbar-more": "Gehiago"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/fa.json b/resources/lib/oojs-ui/i18n/fa.json
new file mode 100644 (file)
index 0000000..3f1ad0c
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    "@metadata": {
+        "authors": [
+            "Dalba",
+            "Ebraminio",
+            "Jdforrester",
+            "Ladsgroup",
+            "Mjbmr",
+            "Nojan Madinehi",
+            "Reza1615",
+            "Taha",
+            "درفش کاویانی",
+            "Armin1392"
+        ]
+    },
+    "ooui-dialog-action-close": "بستن",
+    "ooui-outline-control-move-down": "انتقال مورد به پایین",
+    "ooui-outline-control-move-up": "انتقال مورد به بالا",
+    "ooui-outline-control-remove": "حذف مورد",
+    "ooui-toolbar-more": "بیشتر"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/fi.json b/resources/lib/oojs-ui/i18n/fi.json
new file mode 100644 (file)
index 0000000..ce2f6d0
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    "@metadata": {
+        "authors": [
+            "Beluga",
+            "Crt",
+            "Harriv",
+            "Linnea",
+            "Nedergard",
+            "Nike",
+            "Olli",
+            "Pxos",
+            "Samoasambia",
+            "Silvonen",
+            "Skalman",
+            "Stryn",
+            "VezonThunder"
+        ]
+    },
+    "ooui-dialog-action-close": "Sulje",
+    "ooui-outline-control-move-down": "Siirrä kohdetta alaspäin",
+    "ooui-outline-control-move-up": "Siirrä kohdetta ylöspäin",
+    "ooui-outline-control-remove": "Poista kohde",
+    "ooui-toolbar-more": "Lisää"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/fo.json b/resources/lib/oojs-ui/i18n/fo.json
new file mode 100644 (file)
index 0000000..00a48ff
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "EileenSanda"
+        ]
+    },
+    "ooui-dialog-action-close": "Lat aftur",
+    "ooui-outline-control-move-down": "Flyt lutin niður",
+    "ooui-outline-control-move-up": "Flyt lutin upp",
+    "ooui-toolbar-more": "Meira"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/fr.json b/resources/lib/oojs-ui/i18n/fr.json
new file mode 100644 (file)
index 0000000..7674d2f
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    "@metadata": {
+        "authors": [
+            "Automatik",
+            "Benoit Rochon",
+            "Boniface",
+            "Brunoperel",
+            "Crochet.david",
+            "DavidL",
+            "Dereckson",
+            "Gomoko",
+            "Guillom",
+            "Hello71",
+            "Jean-Frédéric",
+            "Linedwell",
+            "Ltrlg",
+            "Metroitendo",
+            "NemesisIII",
+            "Nicolas NALLET",
+            "Npettiaux",
+            "Rastus Vernon",
+            "Seb35",
+            "Sherbrooke",
+            "Tpt",
+            "Trizek",
+            "Urhixidur",
+            "Verdy p",
+            "Wyz"
+        ]
+    },
+    "ooui-dialog-action-close": "Fermer",
+    "ooui-outline-control-move-down": "Faire descendre l’élément",
+    "ooui-outline-control-move-up": "Faire monter l’élément",
+    "ooui-outline-control-remove": "Supprimer l’élément",
+    "ooui-toolbar-more": "Plus"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/frr.json b/resources/lib/oojs-ui/i18n/frr.json
new file mode 100644 (file)
index 0000000..adf8ce8
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "ChrisPtDe",
+            "Murma174"
+        ]
+    },
+    "ooui-dialog-action-close": "Slütj",
+    "ooui-outline-control-move-down": "Element efter onern sküüw",
+    "ooui-outline-control-move-up": "Element efter boowen sküüw",
+    "ooui-outline-control-remove": "Element wechnem",
+    "ooui-toolbar-more": "Muar"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/fur.json b/resources/lib/oojs-ui/i18n/fur.json
new file mode 100644 (file)
index 0000000..18ea383
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Klenje",
+            "Tocaibon"
+        ]
+    },
+    "ooui-dialog-action-close": "Siere",
+    "ooui-outline-control-move-down": "sposte sot",
+    "ooui-outline-control-move-up": "sposte in su",
+    "ooui-toolbar-more": "Altri"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/gl.json b/resources/lib/oojs-ui/i18n/gl.json
new file mode 100644 (file)
index 0000000..a029456
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Alison",
+            "Kscanne",
+            "Toliño"
+        ]
+    },
+    "ooui-dialog-action-close": "Pechar",
+    "ooui-outline-control-move-down": "Mover o elemento abaixo",
+    "ooui-outline-control-move-up": "Mover o elemento arriba",
+    "ooui-outline-control-remove": "Eliminar o elemento",
+    "ooui-toolbar-more": "Máis"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/gu.json b/resources/lib/oojs-ui/i18n/gu.json
new file mode 100644 (file)
index 0000000..ccabf8d
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ashok modhvadia",
+            "KartikMistry",
+            "The Discoverer"
+        ]
+    },
+    "ooui-dialog-action-close": "બંધ કરો",
+    "ooui-outline-control-move-down": "વસ્તુ નીચે ખસેડો",
+    "ooui-outline-control-move-up": "વસ્તુ ઉપર ખસેડો",
+    "ooui-outline-control-remove": "વસ્તુ હટાવો",
+    "ooui-toolbar-more": "વધુ"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/he.json b/resources/lib/oojs-ui/i18n/he.json
new file mode 100644 (file)
index 0000000..404dc82
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "@metadata": {
+        "authors": [
+            "Amire80",
+            "ExampleTomer",
+            "Guycn2",
+            "Matanya",
+            "Mooeypoo",
+            "Orsa",
+            "Shimmin Beg",
+            "אור שפירא",
+            "חיים",
+            "ערן",
+            "פוילישער",
+            "קיפודנחש"
+        ]
+    },
+    "ooui-dialog-action-close": "סגירה",
+    "ooui-outline-control-move-down": "להזיז את הפריט מטה",
+    "ooui-outline-control-move-up": "להזיז את הפריט מעלה",
+    "ooui-outline-control-remove": "הסרת פריט",
+    "ooui-toolbar-more": "עוד"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/hi.json b/resources/lib/oojs-ui/i18n/hi.json
new file mode 100644 (file)
index 0000000..ae895d1
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ansumang",
+            "Devayon",
+            "Rajesh",
+            "Siddhartha Ghai",
+            "Goelujjwal"
+        ]
+    },
+    "ooui-dialog-action-close": "बंद करें",
+    "ooui-outline-control-move-down": "प्रविष्टि नीचे ले जाएँ",
+    "ooui-outline-control-move-up": "प्रविष्टि ऊपर ले जाएँ",
+    "ooui-outline-control-remove": "आइटम हटाएँ",
+    "ooui-toolbar-more": "अधिक"
+}
diff --git a/resources/lib/oojs-ui/i18n/hr.json b/resources/lib/oojs-ui/i18n/hr.json
new file mode 100644 (file)
index 0000000..1c3f925
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "MaGa",
+            "Roberta F.",
+            "SpeedyGonsales"
+        ]
+    },
+    "ooui-dialog-action-close": "zatvori",
+    "ooui-outline-control-move-down": "Premjesti stavku dolje",
+    "ooui-outline-control-move-up": "Premjesti stavku gore",
+    "ooui-toolbar-more": "Više mogućnosti"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/hsb.json b/resources/lib/oojs-ui/i18n/hsb.json
new file mode 100644 (file)
index 0000000..f674cd2
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "J budissin",
+            "Michawiki"
+        ]
+    },
+    "ooui-dialog-action-close": "Začinić",
+    "ooui-outline-control-move-down": "Zapisk dele přesunyć",
+    "ooui-outline-control-move-up": "Zapisk horje přesunyć",
+    "ooui-outline-control-remove": "Zapisk wotstronić",
+    "ooui-toolbar-more": "Wjace"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/hu.json b/resources/lib/oojs-ui/i18n/hu.json
new file mode 100644 (file)
index 0000000..b2cf2c0
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "@metadata": {
+        "authors": [
+            "Dj",
+            "Einstein2",
+            "Misibacsi",
+            "ViDam",
+            "Tacsipacsi"
+        ]
+    },
+    "ooui-dialog-action-close": "Bezár",
+    "ooui-outline-control-move-down": "Elem mozgatása lefelé",
+    "ooui-outline-control-move-up": "Elem mozgatása felfelé",
+    "ooui-outline-control-remove": "Elem eltávolítása",
+    "ooui-toolbar-more": "Tovább..."
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/hy.json b/resources/lib/oojs-ui/i18n/hy.json
new file mode 100644 (file)
index 0000000..4cb8821
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Vacio",
+            "Xelgen"
+        ]
+    },
+    "ooui-dialog-action-close": "Փակել",
+    "ooui-outline-control-move-down": "Իջեցնել կետը",
+    "ooui-outline-control-move-up": "Բարձրացնել կետը",
+    "ooui-outline-control-remove": "Հեռացնել տարրը",
+    "ooui-toolbar-more": "Ավելին"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ia.json b/resources/lib/oojs-ui/i18n/ia.json
new file mode 100644 (file)
index 0000000..e335553
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "McDutchie"
+        ]
+    },
+    "ooui-dialog-action-close": "Clauder"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/id.json b/resources/lib/oojs-ui/i18n/id.json
new file mode 100644 (file)
index 0000000..6d3ba4d
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "@metadata": {
+        "authors": [
+            "Farras",
+            "Ilham151096",
+            "Iwan Novirion",
+            "Iyan",
+            "Kenrick95",
+            "McDutchie",
+            "Rv77ax",
+            "William Surya Permana"
+        ]
+    },
+    "ooui-dialog-action-close": "Tutup",
+    "ooui-outline-control-move-down": "Pindahkan butir ke bawah",
+    "ooui-outline-control-move-up": "Pindahkan butir ke atas",
+    "ooui-toolbar-more": "Lainnya"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ie.json b/resources/lib/oojs-ui/i18n/ie.json
new file mode 100644 (file)
index 0000000..84d002d
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Makuba"
+        ]
+    },
+    "ooui-dialog-action-close": "Terminar",
+    "ooui-outline-control-move-down": "Mover element a infra",
+    "ooui-outline-control-move-up": "Mover element a supra",
+    "ooui-toolbar-more": "Plu"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ilo.json b/resources/lib/oojs-ui/i18n/ilo.json
new file mode 100644 (file)
index 0000000..838face
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Lam-ang"
+        ]
+    },
+    "ooui-dialog-action-close": "Irekep",
+    "ooui-outline-control-move-down": "Ipababa ti banag",
+    "ooui-outline-control-move-up": "Ipangato ti banag",
+    "ooui-outline-control-remove": "Ikkaten ti banag",
+    "ooui-toolbar-more": "Adu pay"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/is.json b/resources/lib/oojs-ui/i18n/is.json
new file mode 100644 (file)
index 0000000..fbdb5d1
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Maxí",
+            "Snævar"
+        ]
+    },
+    "ooui-dialog-action-close": "Loka",
+    "ooui-outline-control-move-down": "Færa atriði niður",
+    "ooui-outline-control-move-up": "Færa atriði upp",
+    "ooui-toolbar-more": "Fleira"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/it.json b/resources/lib/oojs-ui/i18n/it.json
new file mode 100644 (file)
index 0000000..747ec79
--- /dev/null
@@ -0,0 +1,22 @@
+{
+    "@metadata": {
+        "authors": [
+            "Beta16",
+            "Darth Kule",
+            "Doc.mari",
+            "Eleonora negri",
+            "Elitre",
+            "F. Cosoleto",
+            "FRacco",
+            "Gianfranco",
+            "Minerva Titani",
+            "Raoli",
+            "Una giornata uggiosa '94"
+        ]
+    },
+    "ooui-dialog-action-close": "Chiudi",
+    "ooui-outline-control-move-down": "Sposta in basso",
+    "ooui-outline-control-move-up": "Sposta in alto",
+    "ooui-outline-control-remove": "Rimuovi elemento",
+    "ooui-toolbar-more": "Altro"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ja.json b/resources/lib/oojs-ui/i18n/ja.json
new file mode 100644 (file)
index 0000000..c7c0851
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "@metadata": {
+        "authors": [
+            "Fryed-peach",
+            "Miya",
+            "Penn Station",
+            "Shirayuki"
+        ]
+    },
+    "ooui-dialog-action-close": "閉じる",
+    "ooui-outline-control-move-down": "項目を下に移動させる",
+    "ooui-outline-control-move-up": "項目を上に移動させる",
+    "ooui-outline-control-remove": "項目を除去",
+    "ooui-toolbar-more": "その他"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/jv.json b/resources/lib/oojs-ui/i18n/jv.json
new file mode 100644 (file)
index 0000000..a362079
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Gleki",
+            "NoiX180",
+            "Pras"
+        ]
+    },
+    "ooui-dialog-action-close": "Tutup",
+    "ooui-outline-control-move-down": "Pindhahaken butir mangandhap"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ka.json b/resources/lib/oojs-ui/i18n/ka.json
new file mode 100644 (file)
index 0000000..c9d2774
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "@metadata": {
+        "authors": [
+            "BRUTE",
+            "David1010",
+            "Gleki",
+            "ITshnik",
+            "MIKHEIL",
+            "NoiX180",
+            "Pras",
+            "Tokoko"
+        ]
+    },
+    "ooui-dialog-action-close": "დახურვა",
+    "ooui-outline-control-move-down": "ელემენტის ქვემოთ გადატანა",
+    "ooui-outline-control-move-up": "ელემენტის ზემოთ გადატანა",
+    "ooui-toolbar-more": "მეტი"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/kk-cyrl.json b/resources/lib/oojs-ui/i18n/kk-cyrl.json
new file mode 100644 (file)
index 0000000..7213dad
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Arystanbek"
+        ]
+    },
+    "ooui-dialog-action-close": "Жабу",
+    "ooui-outline-control-move-down": "Элементті төмен жылжыту",
+    "ooui-outline-control-move-up": "Элементті жоғары жылжыту",
+    "ooui-outline-control-remove": "Элементті алып тастау",
+    "ooui-toolbar-more": "толығырақ"
+}
diff --git a/resources/lib/oojs-ui/i18n/km.json b/resources/lib/oojs-ui/i18n/km.json
new file mode 100644 (file)
index 0000000..2013ee3
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Sovichet"
+        ]
+    },
+    "ooui-dialog-action-close": "បិទ",
+    "ooui-outline-control-move-down": "រុញ​ទៅ​ក្រោម",
+    "ooui-outline-control-move-up": "រុញ​ទៅ​លើ",
+    "ooui-toolbar-more": "បន្ថែម"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/kn.json b/resources/lib/oojs-ui/i18n/kn.json
new file mode 100644 (file)
index 0000000..4932f6d
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Vikassy"
+        ]
+    },
+    "ooui-dialog-action-close": "ಮುಚ್ಚಿ",
+    "ooui-outline-control-remove": "ವಸ್ತು ತೆಗೆ",
+    "ooui-toolbar-more": "ಹೆಚ್ಚು"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ko.json b/resources/lib/oojs-ui/i18n/ko.json
new file mode 100644 (file)
index 0000000..25749ce
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "@metadata": {
+        "authors": [
+            "Freebiekr",
+            "Hym411",
+            "Kwj2772",
+            "LFM",
+            "아라"
+        ]
+    },
+    "ooui-dialog-action-close": "닫기",
+    "ooui-outline-control-move-down": "항목을 아래로 옮기기",
+    "ooui-outline-control-move-up": "항목을 위로 옮기기",
+    "ooui-outline-control-remove": "항목 지우기",
+    "ooui-toolbar-more": "더 보기"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/krc.json b/resources/lib/oojs-ui/i18n/krc.json
new file mode 100644 (file)
index 0000000..f629139
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Iltever"
+        ]
+    },
+    "ooui-dialog-action-close": "Джаб",
+    "ooui-outline-control-move-down": "Элементни тюбюне кёчюр",
+    "ooui-outline-control-move-up": "Элементни башына кёчюр"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/kw.json b/resources/lib/oojs-ui/i18n/kw.json
new file mode 100644 (file)
index 0000000..95a9b91
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "George Animal",
+            "Nrowe",
+            "Purodha"
+        ]
+    },
+    "ooui-dialog-action-close": "Degea"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ky.json b/resources/lib/oojs-ui/i18n/ky.json
new file mode 100644 (file)
index 0000000..2d62bda
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Chorobek",
+            "George Animal",
+            "Nrowe",
+            "Tynchtyk Chorotegin",
+            "Викиней"
+        ]
+    },
+    "ooui-dialog-action-close": "Жабуу"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/lb.json b/resources/lib/oojs-ui/i18n/lb.json
new file mode 100644 (file)
index 0000000..6359026
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "@metadata": {
+        "authors": [
+            "Autokrator",
+            "Chorobek",
+            "Robby",
+            "Soued031",
+            "Tynchtyk Chorotegin",
+            "UV",
+            "Викиней"
+        ]
+    },
+    "ooui-dialog-action-close": "Zoumaachen",
+    "ooui-outline-control-move-down": "Element erof réckelen",
+    "ooui-outline-control-move-up": "Element erop réckelen",
+    "ooui-outline-control-remove": "Element ewechhuelen",
+    "ooui-toolbar-more": "Méi"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/lmo.json b/resources/lib/oojs-ui/i18n/lmo.json
new file mode 100644 (file)
index 0000000..e506b7a
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ninonino"
+        ]
+    },
+    "ooui-dialog-action-close": "Sèra",
+    "ooui-outline-control-move-down": "Spòsta 'n zó",
+    "ooui-outline-control-move-up": "Spòsta 'n sö",
+    "ooui-toolbar-more": "Amò"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/lt.json b/resources/lib/oojs-ui/i18n/lt.json
new file mode 100644 (file)
index 0000000..db679bc
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Audriusa",
+            "Eitvys200",
+            "Mantak111"
+        ]
+    },
+    "ooui-dialog-action-close": "Uždaryti",
+    "ooui-outline-control-remove": "Šalinti elementus"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/lv.json b/resources/lib/oojs-ui/i18n/lv.json
new file mode 100644 (file)
index 0000000..c633339
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "@metadata": {
+        "authors": [
+            "Admresdeserv.",
+            "Audriusa",
+            "Eitvys200",
+            "Papuass",
+            "PeterisP"
+        ]
+    },
+    "ooui-dialog-action-close": "Aizvērt",
+    "ooui-outline-control-move-down": "Pārvietot vienumu uz leju",
+    "ooui-outline-control-move-up": "Pārvietot vienumu uz augšu",
+    "ooui-toolbar-more": "Vairāk"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/mg.json b/resources/lib/oojs-ui/i18n/mg.json
new file mode 100644 (file)
index 0000000..dcb5fd5
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "Jagwar"
+        ]
+    },
+    "ooui-dialog-action-close": "Hidiana"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/min.json b/resources/lib/oojs-ui/i18n/min.json
new file mode 100644 (file)
index 0000000..55174c0
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Iwan Novirion",
+            "Jagwar"
+        ]
+    },
+    "ooui-dialog-action-close": "Tutuik"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/mk.json b/resources/lib/oojs-ui/i18n/mk.json
new file mode 100644 (file)
index 0000000..22fd037
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Bjankuloski06",
+            "Brest",
+            "Iwan Novirion"
+        ]
+    },
+    "ooui-dialog-action-close": "Затвори",
+    "ooui-outline-control-move-down": "Помести надолу",
+    "ooui-outline-control-move-up": "Помести нагоре",
+    "ooui-outline-control-remove": "Отстрани ставка",
+    "ooui-toolbar-more": "Повеќе"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ml.json b/resources/lib/oojs-ui/i18n/ml.json
new file mode 100644 (file)
index 0000000..355e337
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Kavya Manohar",
+            "Praveenp",
+            "Santhosh.thottingal",
+            "Vssun"
+        ]
+    },
+    "ooui-dialog-action-close": "അടയ്ക്കുക",
+    "ooui-outline-control-move-down": "ഇനം താഴേയ്ക്ക് മാറ്റുക",
+    "ooui-outline-control-move-up": "ഇനം മുകളിലേയ്ക്ക് മാറ്റുക",
+    "ooui-toolbar-more": "കൂടുതൽ"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/mr.json b/resources/lib/oojs-ui/i18n/mr.json
new file mode 100644 (file)
index 0000000..d4db84f
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "@metadata": {
+        "authors": [
+            "Kaajawa",
+            "Mahitgar",
+            "Praju23",
+            "V.narsikar",
+            "Ydyashad",
+            "संतोष दहिवळ"
+        ]
+    },
+    "ooui-dialog-action-close": "बंद करा",
+    "ooui-outline-control-move-down": "घटक (आयटम) खाली सरकवा",
+    "ooui-outline-control-move-up": "घटक (आयटम) वर सरकवा",
+    "ooui-toolbar-more": "अधिक"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ms.json b/resources/lib/oojs-ui/i18n/ms.json
new file mode 100644 (file)
index 0000000..4f78aaa
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Anakmalaysia",
+            "Aurora"
+        ]
+    },
+    "ooui-dialog-action-close": "Tutup",
+    "ooui-outline-control-move-down": "Alihkan perkara ke bawah",
+    "ooui-outline-control-move-up": "Alihkan perkara ke atas",
+    "ooui-outline-control-remove": "Buang perkara",
+    "ooui-toolbar-more": "Selebihnya"
+}
diff --git a/resources/lib/oojs-ui/i18n/nap.json b/resources/lib/oojs-ui/i18n/nap.json
new file mode 100644 (file)
index 0000000..6b0b3ec
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Chelin",
+            "Chrisportelli",
+            "PiRSquared17"
+        ]
+    },
+    "ooui-dialog-action-close": "Chiure",
+    "ooui-toolbar-more": "Atro"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/nb.json b/resources/lib/oojs-ui/i18n/nb.json
new file mode 100644 (file)
index 0000000..7cdecaa
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "@metadata": {
+        "authors": [
+            "Danmichaelo",
+            "Event",
+            "Jeblad",
+            "Laaknor",
+            "Njardarlogar"
+        ]
+    },
+    "ooui-dialog-action-close": "Lukk",
+    "ooui-outline-control-move-down": "Flytt ned",
+    "ooui-outline-control-move-up": "Flytt opp",
+    "ooui-toolbar-more": "Mer"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/nds-nl.json b/resources/lib/oojs-ui/i18n/nds-nl.json
new file mode 100644 (file)
index 0000000..81f8a43
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Servien"
+        ]
+    },
+    "ooui-dialog-action-close": "Sluten",
+    "ooui-outline-control-move-down": "Onderwarp ummeneer zetten",
+    "ooui-outline-control-move-up": "Onderwarp umhoge zetten"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/nds.json b/resources/lib/oojs-ui/i18n/nds.json
new file mode 100644 (file)
index 0000000..d0806d0
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Zylbath"
+        ]
+    },
+    "ooui-dialog-action-close": "Dichtmaken",
+    "ooui-outline-control-move-down": "Element na ünnen schuven",
+    "ooui-outline-control-move-up": "Element na baven schuven",
+    "ooui-toolbar-more": "Mehr"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ne.json b/resources/lib/oojs-ui/i18n/ne.json
new file mode 100644 (file)
index 0000000..ae948c6
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "RajeshPandey",
+            "सरोज कुमार ढकाल"
+        ]
+    }
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/nl.json b/resources/lib/oojs-ui/i18n/nl.json
new file mode 100644 (file)
index 0000000..549fad2
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    "@metadata": {
+        "authors": [
+            "Bluyten",
+            "Breghtje",
+            "Catrope",
+            "Flightmare",
+            "Hansmuller",
+            "Jdforrester",
+            "Keegan",
+            "Konovalov",
+            "RajeshPandey",
+            "Romaine",
+            "SPQRobin",
+            "Saruman",
+            "Siebrand",
+            "Southparkfan",
+            "सरोज कुमार ढकाल",
+            "Sjoerddebruin"
+        ]
+    },
+    "ooui-dialog-action-close": "Sluiten",
+    "ooui-outline-control-move-down": "Item omlaag verplaatsen",
+    "ooui-outline-control-move-up": "Item omhoog verplaatsen",
+    "ooui-outline-control-remove": "Item verwijderen",
+    "ooui-toolbar-more": "Meer"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/nn.json b/resources/lib/oojs-ui/i18n/nn.json
new file mode 100644 (file)
index 0000000..dd86f5e
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Jeblad",
+            "Njardarlogar"
+        ]
+    },
+    "ooui-dialog-action-close": "Lat att",
+    "ooui-outline-control-move-down": "Flytt element ned",
+    "ooui-outline-control-move-up": "Flytt element opp",
+    "ooui-toolbar-more": "Fleire"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/om.json b/resources/lib/oojs-ui/i18n/om.json
new file mode 100644 (file)
index 0000000..cd22c40
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cedric31",
+            "Tumsaa"
+        ]
+    },
+    "ooui-dialog-action-close": "Cufi",
+    "ooui-outline-control-move-down": "Gad buusi",
+    "ooui-outline-control-move-up": "Ol baasi",
+    "ooui-outline-control-remove": "Balleessi",
+    "ooui-toolbar-more": "Dabalata"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/or.json b/resources/lib/oojs-ui/i18n/or.json
new file mode 100644 (file)
index 0000000..35721a1
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Odisha1",
+            "Psubhashish",
+            "ଶିତିକଣ୍ଠ ଦାଶ"
+        ]
+    },
+    "ooui-dialog-action-close": "ବନ୍ଦ କରିବେ"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/pa.json b/resources/lib/oojs-ui/i18n/pa.json
new file mode 100644 (file)
index 0000000..6c76d7f
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Amikeco",
+            "Babanwalia",
+            "Bouron",
+            "Nasir8891"
+        ]
+    },
+    "ooui-dialog-action-close": "বন্ধ"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/pfl.json b/resources/lib/oojs-ui/i18n/pfl.json
new file mode 100644 (file)
index 0000000..40cc15d
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Manuae"
+        ]
+    },
+    "ooui-dialog-action-close": "Schließe",
+    "ooui-outline-control-move-down": "Bweeschs nunna",
+    "ooui-outline-control-move-up": "Bweeschs nuff",
+    "ooui-outline-control-remove": "Leschs",
+    "ooui-toolbar-more": "Mea"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/pl.json b/resources/lib/oojs-ui/i18n/pl.json
new file mode 100644 (file)
index 0000000..2cb7330
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    "@metadata": {
+        "authors": [
+            "Babanwalia",
+            "Chrumps",
+            "Matma Rex",
+            "Mikołka",
+            "Nasir8891",
+            "Odie2",
+            "Rzuwig",
+            "Tar Lócesilion",
+            "Ty221",
+            "WTM",
+            "Woytecr",
+            "Wpedzich",
+            "Jacenty359"
+        ]
+    },
+    "ooui-dialog-action-close": "Zamknij",
+    "ooui-outline-control-move-down": "Przenieś niżej",
+    "ooui-outline-control-move-up": "Przenieś wyżej",
+    "ooui-outline-control-remove": "Usuń element",
+    "ooui-toolbar-more": "Więcej"
+}
diff --git a/resources/lib/oojs-ui/i18n/pms.json b/resources/lib/oojs-ui/i18n/pms.json
new file mode 100644 (file)
index 0000000..bb8f113
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Borichèt",
+            "Dragonòt",
+            "පසිඳු කාවින්ද"
+        ]
+    },
+    "ooui-dialog-action-close": "Saré",
+    "ooui-outline-control-move-down": "Fé calé giù l'element",
+    "ooui-outline-control-move-up": "Fé monté l'element",
+    "ooui-toolbar-more": "Ëd pi"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ps.json b/resources/lib/oojs-ui/i18n/ps.json
new file mode 100644 (file)
index 0000000..4f21707
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ahmed-Najib-Biabani-Ibrahimkhel"
+        ]
+    },
+    "ooui-dialog-action-close": "تړل",
+    "ooui-outline-control-move-down": "توکی ښکته راوړل",
+    "ooui-outline-control-move-up": "توکی پورته راوړل",
+    "ooui-toolbar-more": "نور"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/pt-br.json b/resources/lib/oojs-ui/i18n/pt-br.json
new file mode 100644 (file)
index 0000000..f758660
--- /dev/null
@@ -0,0 +1,19 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cainamarques",
+            "Dianakc",
+            "Fúlvio",
+            "Helder.wiki",
+            "HenriqueCrang",
+            "Jaideraf",
+            "Luckas",
+            "OTAVIO1981",
+            555
+        ]
+    },
+    "ooui-dialog-action-close": "Fechar",
+    "ooui-outline-control-move-down": "Mover item para baixo",
+    "ooui-outline-control-move-up": "Mover item para cima",
+    "ooui-toolbar-more": "Mais"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/pt.json b/resources/lib/oojs-ui/i18n/pt.json
new file mode 100644 (file)
index 0000000..53b5280
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cainamarques",
+            "Fúlvio",
+            "GoEThe",
+            "Hamilton Abreu",
+            "Helder.wiki",
+            "Jaideraf",
+            "Jdforrester",
+            "Luckas",
+            "Vitorvicentevalente",
+            "SandroHc"
+        ]
+    },
+    "ooui-dialog-action-close": "Fechar",
+    "ooui-outline-control-move-down": "Mover item para baixo",
+    "ooui-outline-control-move-up": "Mover item para cima",
+    "ooui-outline-control-remove": "Remover elemento",
+    "ooui-toolbar-more": "Mais"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/qqq.json b/resources/lib/oojs-ui/i18n/qqq.json
new file mode 100644 (file)
index 0000000..75bbec4
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    "@metadata": {
+        "authors": [
+            "Amire80",
+            "Beta16",
+            "Erik Moeller",
+            "Jdforrester",
+            "Lloffiwr",
+            "Mooeypoo",
+            "Mormegil",
+            "Nike",
+            "PoLuX124",
+            "Purodha",
+            "Raymond",
+            "Sagan",
+            "Sayak Sarkar",
+            "Shirayuki",
+            "Siebrand",
+            "Trevor Parscal"
+        ]
+    },
+    "ooui-dialog-action-close": "Label text for button to exit from dialog.\n\n{{Identical|Close}}",
+    "ooui-outline-control-move-down": "Tool tip for a button that moves items in a list down one place",
+    "ooui-outline-control-move-up": "Tool tip for a button that moves items in a list up one place",
+    "ooui-outline-control-remove": "Tool tip for a button that removes items from a list.\n{{Identical|Remove item}}",
+    "ooui-toolbar-more": "Label for the toolbar group that contains a list of all other available tools.\n{{Identical|More}}"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/qu.json b/resources/lib/oojs-ui/i18n/qu.json
new file mode 100644 (file)
index 0000000..4442528
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "AlimanRuna",
+            "Jduranboger"
+        ]
+    },
+    "ooui-dialog-action-close": "Wichq'ay",
+    "ooui-outline-control-move-down": "Qallawata uraykuchiy",
+    "ooui-outline-control-move-up": "Qallawata huqariy",
+    "ooui-outline-control-remove": "P'anqa sutikunata qichuy",
+    "ooui-toolbar-more": "Aswan"
+}
diff --git a/resources/lib/oojs-ui/i18n/ro.json b/resources/lib/oojs-ui/i18n/ro.json
new file mode 100644 (file)
index 0000000..4892975
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "@metadata": {
+        "authors": [
+            "AlimanRuna",
+            "Firilacroco",
+            "Minisarm",
+            "Stelistcristi"
+        ]
+    },
+    "ooui-dialog-action-close": "Închide",
+    "ooui-outline-control-move-down": "Mută elementul mai jos",
+    "ooui-outline-control-move-up": "Mută elementul mai sus",
+    "ooui-outline-control-remove": "Elimină elementul",
+    "ooui-toolbar-more": "Mai mult"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/roa-tara.json b/resources/lib/oojs-ui/i18n/roa-tara.json
new file mode 100644 (file)
index 0000000..c7699d6
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Joetaras"
+        ]
+    },
+    "ooui-dialog-action-close": "Achiude",
+    "ooui-outline-control-move-down": "Spuèste 'a vôsce sotte",
+    "ooui-outline-control-move-up": "Spuèste 'a vôsce sus",
+    "ooui-toolbar-more": "De cchiù"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ru.json b/resources/lib/oojs-ui/i18n/ru.json
new file mode 100644 (file)
index 0000000..f6e76a6
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    "@metadata": {
+        "authors": [
+            "Amire80",
+            "DR",
+            "Eugrus",
+            "Iluvatar",
+            "KPu3uC B Poccuu",
+            "Kalan",
+            "MaxBioHazard",
+            "NBS",
+            "Niklem",
+            "Okras",
+            "Ole Yves",
+            "Putnik",
+            "Sunpriat",
+            "Yury Katkov",
+            "Умар"
+        ]
+    },
+    "ooui-dialog-action-close": "Закрыть",
+    "ooui-outline-control-move-down": "Переместить элемент вниз",
+    "ooui-outline-control-move-up": "Переместить элемент вверх",
+    "ooui-outline-control-remove": "Удалить пункт",
+    "ooui-toolbar-more": "Ещё"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/sah.json b/resources/lib/oojs-ui/i18n/sah.json
new file mode 100644 (file)
index 0000000..9b3fcc8
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Gazeb",
+            "HalanTul"
+        ]
+    },
+    "ooui-dialog-action-close": "Сап"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/scn.json b/resources/lib/oojs-ui/i18n/scn.json
new file mode 100644 (file)
index 0000000..a699911
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Gazeb",
+            "Gmelfi",
+            "HalanTul"
+        ]
+    },
+    "ooui-dialog-action-close": "Chiùi",
+    "ooui-outline-control-move-down": "Sposta di sutta",
+    "ooui-outline-control-move-up": "Sposta di supra",
+    "ooui-toolbar-more": "Àutri cosi"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/sco.json b/resources/lib/oojs-ui/i18n/sco.json
new file mode 100644 (file)
index 0000000..f8dc77c
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "John Reid"
+        ]
+    },
+    "ooui-dialog-action-close": "Claise",
+    "ooui-outline-control-move-down": "Muiv eetem doon",
+    "ooui-outline-control-move-up": "Muiv eetem up",
+    "ooui-outline-control-remove": "Remuiv eitem",
+    "ooui-toolbar-more": "Mair"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/sh.json b/resources/lib/oojs-ui/i18n/sh.json
new file mode 100644 (file)
index 0000000..5e29980
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "OC Ripper"
+        ]
+    },
+    "ooui-dialog-action-close": "Zatvori",
+    "ooui-outline-control-move-down": "Pomakni stavku dolje",
+    "ooui-outline-control-move-up": "Pomakni stavku gore"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/si.json b/resources/lib/oojs-ui/i18n/si.json
new file mode 100644 (file)
index 0000000..cf7a9fd
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Singhalawap",
+            "පසිඳු කාවින්ද",
+            "ශ්වෙත"
+        ]
+    },
+    "ooui-dialog-action-close": "නිමවන්න",
+    "ooui-outline-control-move-down": "අයිතමය පහලටදමන්න",
+    "ooui-outline-control-move-up": "අයිතමය ඉහලටදමන්න"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/sk.json b/resources/lib/oojs-ui/i18n/sk.json
new file mode 100644 (file)
index 0000000..60b6f43
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Mimarik",
+            "Teslaton"
+        ]
+    },
+    "ooui-dialog-action-close": "Zatvoriť",
+    "ooui-outline-control-move-down": "Posunúť položku nadol",
+    "ooui-outline-control-move-up": "Posunúť položku nahor",
+    "ooui-toolbar-more": "Viac"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/sl.json b/resources/lib/oojs-ui/i18n/sl.json
new file mode 100644 (file)
index 0000000..b14d47b
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "@metadata": {
+        "authors": [
+            "Dbc334",
+            "Eleassar",
+            "Pinky sl",
+            "Yerpo"
+        ]
+    },
+    "ooui-dialog-action-close": "Zapri",
+    "ooui-outline-control-move-down": "Prestavi predmet nižje",
+    "ooui-outline-control-move-up": "Prestavi predmet višje",
+    "ooui-outline-control-remove": "Odstrani vnos",
+    "ooui-toolbar-more": "Več"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/sq.json b/resources/lib/oojs-ui/i18n/sq.json
new file mode 100644 (file)
index 0000000..24a5af2
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Euriditi",
+            "Kushtrim",
+            "Elioqoshi"
+        ]
+    },
+    "ooui-dialog-action-close": "Mbylle",
+    "ooui-outline-control-move-down": "Zhvendose artikullin më poshtë",
+    "ooui-outline-control-move-up": "Zhvendose artikullin më lart",
+    "ooui-outline-control-remove": "Hiq artikullin",
+    "ooui-toolbar-more": "Më tepër..."
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/sr-ec.json b/resources/lib/oojs-ui/i18n/sr-ec.json
new file mode 100644 (file)
index 0000000..7eaaacd
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Milicevic01",
+            "Nikola Smolenski",
+            "Милан Јелисавчић"
+        ]
+    },
+    "ooui-dialog-action-close": "Затвори",
+    "ooui-outline-control-move-down": "Премести ставку на доле",
+    "ooui-outline-control-move-up": "Премести ставку на горе",
+    "ooui-outline-control-remove": "Уклони ставку",
+    "ooui-toolbar-more": "Више"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/sv.json b/resources/lib/oojs-ui/i18n/sv.json
new file mode 100644 (file)
index 0000000..f7d6f04
--- /dev/null
@@ -0,0 +1,22 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ainali",
+            "Haxpett",
+            "Jopparn",
+            "Knuckles",
+            "Magol",
+            "Milicevic01",
+            "Per",
+            "Sendelbach",
+            "Skalman",
+            "WikiPhoenix",
+            "Lokal Profil"
+        ]
+    },
+    "ooui-dialog-action-close": "Stäng",
+    "ooui-outline-control-move-down": "Flytta ned objekt",
+    "ooui-outline-control-move-up": "Flytta upp objekt",
+    "ooui-outline-control-remove": "Ta bort objekt",
+    "ooui-toolbar-more": "Mer"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/sw.json b/resources/lib/oojs-ui/i18n/sw.json
new file mode 100644 (file)
index 0000000..1c61b06
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Lloffiwr",
+            "Muddyb Blast Producer"
+        ]
+    },
+    "ooui-dialog-action-close": "Funga",
+    "ooui-outline-control-move-down": "Sogeza kipengee chini",
+    "ooui-outline-control-move-up": "Sogeza kipengee juu",
+    "ooui-toolbar-more": "Zaidi"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ta.json b/resources/lib/oojs-ui/i18n/ta.json
new file mode 100644 (file)
index 0000000..a9795fd
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Jayarathina",
+            "Sank",
+            "Shanmugamp7",
+            "மதனாஹரன்"
+        ]
+    },
+    "ooui-dialog-action-close": "மூடுக"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/te.json b/resources/lib/oojs-ui/i18n/te.json
new file mode 100644 (file)
index 0000000..a1f1285
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Arjunaraoc",
+            "Jayarathina",
+            "Sank",
+            "Shanmugamp7",
+            "Veeven",
+            "Visdaviva",
+            "மதனாஹரன்"
+        ]
+    },
+    "ooui-dialog-action-close": "మూయి"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/th.json b/resources/lib/oojs-ui/i18n/th.json
new file mode 100644 (file)
index 0000000..b7ee05a
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Supasate",
+            "Taweetham"
+        ]
+    },
+    "ooui-dialog-action-close": "ปิด",
+    "ooui-outline-control-move-down": "เลื่อนรายการลง",
+    "ooui-outline-control-move-up": "ย้ายรายการขึ้น"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/tl.json b/resources/lib/oojs-ui/i18n/tl.json
new file mode 100644 (file)
index 0000000..a073882
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "AnakngAraw",
+            "Sky Harbor"
+        ]
+    },
+    "ooui-dialog-action-close": "Isara",
+    "ooui-outline-control-move-down": "Ilipat ang aytem pababa",
+    "ooui-outline-control-move-up": "Ilipat ang aytem pataas",
+    "ooui-toolbar-more": "Marami pa"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/tr.json b/resources/lib/oojs-ui/i18n/tr.json
new file mode 100644 (file)
index 0000000..94d34a2
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "@metadata": {
+        "authors": [
+            "Emperyan",
+            "Incelemeelemani",
+            "LuCKY",
+            "Maidis",
+            "Rapsar",
+            "Talha Samil Cakir",
+            "TurkishStyles"
+        ]
+    },
+    "ooui-dialog-action-close": "Kapat",
+    "ooui-outline-control-move-down": "Ögeyi aşağı taşı",
+    "ooui-outline-control-move-up": "Ögeyi yukarı taşı",
+    "ooui-toolbar-more": "Daha fazla"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/tt-cyrl.json b/resources/lib/oojs-ui/i18n/tt-cyrl.json
new file mode 100644 (file)
index 0000000..1c0bd90
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ajdar"
+        ]
+    },
+    "ooui-dialog-action-close": "Ябу",
+    "ooui-outline-control-move-down": "Элементны аска күчерү",
+    "ooui-outline-control-move-up": "Элементны өскә күчерү"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/ug-arab.json b/resources/lib/oojs-ui/i18n/ug-arab.json
new file mode 100644 (file)
index 0000000..efba086
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Sahran",
+            "Tel'et",
+            "Tifinaghes"
+        ]
+    }
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/uk.json b/resources/lib/oojs-ui/i18n/uk.json
new file mode 100644 (file)
index 0000000..42487c9
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    "@metadata": {
+        "authors": [
+            "AS",
+            "Aced",
+            "Ahonc",
+            "Andriykopanytsia",
+            "Base",
+            "Perohanych",
+            "RLuts",
+            "Sahran",
+            "Sergento",
+            "Steve.rusyn",
+            "SteveR",
+            "Tel'et",
+            "Tifinaghes",
+            "Ата"
+        ]
+    },
+    "ooui-dialog-action-close": "Закрити",
+    "ooui-outline-control-move-down": "Перемістити елемент униз",
+    "ooui-outline-control-move-up": "Перемістити елемент вгору",
+    "ooui-outline-control-remove": "Видалити елемент",
+    "ooui-toolbar-more": "Більше"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/uz.json b/resources/lib/oojs-ui/i18n/uz.json
new file mode 100644 (file)
index 0000000..473fc75
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "CoderSI",
+            "Noor2020",
+            "Sociologist",
+            "පසිඳු කාවින්ද"
+        ]
+    },
+    "ooui-dialog-action-close": "Yopish",
+    "ooui-outline-control-move-down": "Elementni pastga koʻchirish",
+    "ooui-outline-control-move-up": "Elementni yuqoriga koʻchirish",
+    "ooui-toolbar-more": "Yana"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/vec.json b/resources/lib/oojs-ui/i18n/vec.json
new file mode 100644 (file)
index 0000000..01833f7
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Candalua",
+            "GatoSelvadego"
+        ]
+    },
+    "ooui-dialog-action-close": "Sara",
+    "ooui-outline-control-move-down": "Sposta in baso",
+    "ooui-outline-control-move-up": "Sposta in sima",
+    "ooui-toolbar-more": "Altro"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/vi.json b/resources/lib/oojs-ui/i18n/vi.json
new file mode 100644 (file)
index 0000000..342ad6f
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cheers!",
+            "Jdforrester",
+            "Minh Nguyen"
+        ]
+    },
+    "ooui-dialog-action-close": "Đóng",
+    "ooui-outline-control-move-down": "Chuyển mục xuống",
+    "ooui-outline-control-move-up": "Chuyển mục lên",
+    "ooui-outline-control-remove": "Xóa khoản",
+    "ooui-toolbar-more": "Thêm"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/vo.json b/resources/lib/oojs-ui/i18n/vo.json
new file mode 100644 (file)
index 0000000..2ed7e2f
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Malafaya"
+        ]
+    },
+    "ooui-dialog-action-close": "Färmükön",
+    "ooui-toolbar-more": "Pluikos"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/wuu.json b/resources/lib/oojs-ui/i18n/wuu.json
new file mode 100644 (file)
index 0000000..72aa48b
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Malafaya",
+            "十弌"
+        ]
+    },
+    "ooui-toolbar-more": "還多"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/yi.json b/resources/lib/oojs-ui/i18n/yi.json
new file mode 100644 (file)
index 0000000..ab5c510
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Malafaya",
+            "פוילישער",
+            "十弌"
+        ]
+    },
+    "ooui-dialog-action-close": "שליסן",
+    "ooui-outline-control-move-down": "רוקן עלעמענט אראפ",
+    "ooui-outline-control-move-up": "רוקן עלעמענט ארויף",
+    "ooui-toolbar-more": "נאך"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/yo.json b/resources/lib/oojs-ui/i18n/yo.json
new file mode 100644 (file)
index 0000000..f71d3dd
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Demmy"
+        ]
+    },
+    "ooui-dialog-action-close": "Ìpadé",
+    "ooui-outline-control-move-down": "Sún onítòún sí sàlẹ̀",
+    "ooui-outline-control-move-up": "Sún onítòún s'ókè",
+    "ooui-toolbar-more": "Míràn"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/zh-hans.json b/resources/lib/oojs-ui/i18n/zh-hans.json
new file mode 100644 (file)
index 0000000..19d9c7e
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    "@metadata": {
+        "authors": [
+            "Anakmalaysia",
+            "Bencmq",
+            "Demmy",
+            "Hydra",
+            "Hzy980512",
+            "Liangent",
+            "Liuxinyu970226",
+            "Qiyue2001",
+            "Shirayuki",
+            "Shizhao",
+            "TianyinLee",
+            "Xiaomingyan",
+            "Yfdyh000",
+            "Zhangjintao",
+            "乌拉跨氪"
+        ]
+    },
+    "ooui-dialog-action-close": "关闭",
+    "ooui-outline-control-move-down": "下移项",
+    "ooui-outline-control-move-up": "上移项",
+    "ooui-outline-control-remove": "删除项",
+    "ooui-toolbar-more": "更多"
+}
diff --git a/resources/lib/oojs-ui/i18n/zh-hant.json b/resources/lib/oojs-ui/i18n/zh-hant.json
new file mode 100644 (file)
index 0000000..6e7b12e
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "@metadata": {
+        "authors": [
+            "Anakmalaysia",
+            "Ch.Andrew",
+            "Hydra",
+            "Justincheng12345",
+            "Liflon",
+            "Liuxinyu970226",
+            "Qiyue2001",
+            "Radish10cm",
+            "Shirayuki",
+            "Simon Shek",
+            "Spring Roll Conan",
+            "Waihorace"
+        ]
+    },
+    "ooui-dialog-action-close": "關閉",
+    "ooui-outline-control-move-down": "向下移項",
+    "ooui-outline-control-move-up": "向上移項",
+    "ooui-outline-control-remove": "移除項",
+    "ooui-toolbar-more": "更多"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/zh-hk.json b/resources/lib/oojs-ui/i18n/zh-hk.json
new file mode 100644 (file)
index 0000000..60e8fbd
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "@metadata": [],
+    "ooui-dialog-action-close": "關閉"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/i18n/zh-tw.json b/resources/lib/oojs-ui/i18n/zh-tw.json
new file mode 100644 (file)
index 0000000..f7987e5
--- /dev/null
@@ -0,0 +1,7 @@
+{
+    "@metadata": [],
+    "ooui-dialog-action-close": "關閉",
+    "ooui-outline-control-move-down": "向下移",
+    "ooui-outline-control-move-up": "向上移",
+    "ooui-toolbar-more": "更多"
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/images/fade-down.png b/resources/lib/oojs-ui/images/fade-down.png
new file mode 100644 (file)
index 0000000..50c7931
Binary files /dev/null and b/resources/lib/oojs-ui/images/fade-down.png differ
diff --git a/resources/lib/oojs-ui/images/fade-up.png b/resources/lib/oojs-ui/images/fade-up.png
new file mode 100644 (file)
index 0000000..7a0cb87
Binary files /dev/null and b/resources/lib/oojs-ui/images/fade-up.png differ
diff --git a/resources/lib/oojs-ui/images/icons/accept.png b/resources/lib/oojs-ui/images/icons/accept.png
new file mode 100644 (file)
index 0000000..1075110
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/accept.png differ
diff --git a/resources/lib/oojs-ui/images/icons/accept.svg b/resources/lib/oojs-ui/images/icons/accept.svg
new file mode 100644 (file)
index 0000000..df78186
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="apply" style="opacity:0.75;">
+       <polygon id="check" style="fill-rule:evenodd;clip-rule:evenodd;" points="19.062,5.139 17.418,4 8.867,16.357 5.413,12.903 4,14.316 9.021,19.338"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/add-item.png b/resources/lib/oojs-ui/images/icons/add-item.png
new file mode 100644 (file)
index 0000000..5cf353f
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/add-item.png differ
diff --git a/resources/lib/oojs-ui/images/icons/add-item.svg b/resources/lib/oojs-ui/images/icons/add-item.svg
new file mode 100644 (file)
index 0000000..2620e76
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="apply" style="opacity:0.75;">
+       <path d="M13,8 L11,8 L11,11 L8,11 L8,13 L11,13 L11,16 L13,16 L13,13 L16,13 L16,11 L13,11 z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/advanced.png b/resources/lib/oojs-ui/images/icons/advanced.png
new file mode 100644 (file)
index 0000000..7f5ada5
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/advanced.png differ
diff --git a/resources/lib/oojs-ui/images/icons/advanced.svg b/resources/lib/oojs-ui/images/icons/advanced.svg
new file mode 100644 (file)
index 0000000..3e87cab
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="settings" style="opacity:0.75;">
+       <path id="gear" style="fill-rule:evenodd;clip-rule:evenodd;" d="M20.869,13.476C20.948,12.994,21,12.504,21,12
+               s-0.052-0.994-0.131-1.476l-2.463-0.259c-0.149-0.556-0.367-1.082-0.648-1.57l1.558-1.924c-0.576-0.806-1.281-1.511-2.087-2.087
+               l-1.924,1.558c-0.488-0.281-1.015-0.499-1.57-0.648l-0.259-2.463C12.994,3.052,12.504,3,12,3s-0.994,0.052-1.476,0.131
+               l-0.259,2.463C9.71,5.743,9.184,5.961,8.695,6.242L6.771,4.685C5.966,5.261,5.261,5.966,4.685,6.771l1.558,1.924
+               c-0.281,0.488-0.499,1.015-0.648,1.57l-2.463,0.259C3.052,11.006,3,11.496,3,12s0.052,0.994,0.131,1.476l2.463,0.259
+               c0.149,0.556,0.367,1.082,0.648,1.57l-1.558,1.924c0.576,0.806,1.281,1.511,2.087,2.087l1.924-1.558
+               c0.488,0.281,1.015,0.499,1.57,0.648l0.259,2.463C11.006,20.948,11.496,21,12,21s0.994-0.052,1.476-0.131l0.259-2.463
+               c0.556-0.149,1.082-0.367,1.57-0.648l1.924,1.558c0.806-0.576,1.511-1.281,2.087-2.087l-1.558-1.924
+               c0.281-0.488,0.499-1.015,0.648-1.57L20.869,13.476z M12,15.998c-2.209,0-3.998-1.789-3.998-3.998S9.791,8.002,12,8.002
+               S15.998,9.791,15.998,12S14.209,15.998,12,15.998z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/alert.png b/resources/lib/oojs-ui/images/icons/alert.png
new file mode 100644 (file)
index 0000000..992ea2a
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/alert.png differ
diff --git a/resources/lib/oojs-ui/images/icons/alert.svg b/resources/lib/oojs-ui/images/icons/alert.svg
new file mode 100644 (file)
index 0000000..886a7c0
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="alert" style="opacity:0.75;">
+       <rect id="point" x="11" y="16" style="fill-rule:evenodd;clip-rule:evenodd;" width="2" height="2"/>
+       <polygon id="stroke" style="fill-rule:evenodd;clip-rule:evenodd;" points="13.516,10 10.516,10 11,15 13,15"/>
+       <path id="triangle" d="M12.017,5.974L19.536,19H4.496L12.017,5.974 M12.017,3.5c-0.544,0-1.088,0.357-1.5,1.071L2.532,18.402 C1.707,19.831,2.382,21,4.032,21H20c1.65,0,2.325-1.169,1.5-2.599L13.517,4.572C13.104,3.857,12.561,3.5,12.017,3.5L12.017,3.5z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/arched-arrow-ltr.png b/resources/lib/oojs-ui/images/icons/arched-arrow-ltr.png
new file mode 100644 (file)
index 0000000..5db1c4d
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/arched-arrow-ltr.png differ
diff --git a/resources/lib/oojs-ui/images/icons/arched-arrow-ltr.svg b/resources/lib/oojs-ui/images/icons/arched-arrow-ltr.svg
new file mode 100644 (file)
index 0000000..5b343a5
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="arched-arrow-ltr" style="opacity:0.75;">
+       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M19.925,14.937l-2.391-6.901l-1.48,2.329 c-0.964-0.845-2.699-1.85-5.513-1.823c-4.887,0.046-6.524,4.244-6.524,4.244s2.753-2.639,6.925-1.949 c1.729,0.286,3.007,1.206,3.675,1.791l-1.474,2.319L19.925,14.937z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/arched-arrow-rtl.png b/resources/lib/oojs-ui/images/icons/arched-arrow-rtl.png
new file mode 100644 (file)
index 0000000..7931971
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/arched-arrow-rtl.png differ
diff --git a/resources/lib/oojs-ui/images/icons/arched-arrow-rtl.svg b/resources/lib/oojs-ui/images/icons/arched-arrow-rtl.svg
new file mode 100644 (file)
index 0000000..bb5f10e
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="arched-arrow-rtl" style="opacity:0.75;">
+       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M13.401,8.542c-2.814-0.027-4.549,0.978-5.513,1.823 l-1.48-2.329l-2.391,6.901l6.782,0.009l-1.474-2.319c0.668-0.584,1.945-1.504,3.675-1.791c4.172-0.69,6.925,1.949,6.925,1.949 S18.288,8.588,13.401,8.542z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/check.png b/resources/lib/oojs-ui/images/icons/check.png
new file mode 100644 (file)
index 0000000..82c3cb4
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/check.png differ
diff --git a/resources/lib/oojs-ui/images/icons/check.svg b/resources/lib/oojs-ui/images/icons/check.svg
new file mode 100644 (file)
index 0000000..e67cd6c
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
+  <g id="check">
+    <path d="M7.105,13.473 L8.527,12.05 L10.428,13.952 L15.238,7 L16.895,8.148 L10.635,17 z" fill="#000000"/>
+  </g>
+  <defs/>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/clear.png b/resources/lib/oojs-ui/images/icons/clear.png
new file mode 100644 (file)
index 0000000..697dd62
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/clear.png differ
diff --git a/resources/lib/oojs-ui/images/icons/clear.svg b/resources/lib/oojs-ui/images/icons/clear.svg
new file mode 100644 (file)
index 0000000..d83eb02
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="clear" style="opacity:0.75;">
+       <path id="circle_with_strike" style="fill-rule:evenodd;clip-rule:evenodd;" d="M11.999,5.022c-3.853,0-6.977,3.124-6.977,6.978 c0,3.853,3.124,6.978,6.977,6.978c3.854,0,6.979-3.125,6.979-6.978C18.978,8.146,15.853,5.022,11.999,5.022z M6.886,12 c0-1.092,0.572-3.25,0.93-2.929l7.113,7.113c0.488,0.525-1.837,0.931-2.93,0.931C9.174,17.114,6.886,14.824,6.886,12z M16.184,14.929L9.07,7.816c-0.445-0.483,1.837-0.931,2.929-0.931c2.827,0,5.115,2.289,5.115,5.114 C17.114,13.092,16.75,15.542,16.184,14.929z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/close.png b/resources/lib/oojs-ui/images/icons/close.png
new file mode 100644 (file)
index 0000000..f7eed9f
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/close.png differ
diff --git a/resources/lib/oojs-ui/images/icons/close.svg b/resources/lib/oojs-ui/images/icons/close.svg
new file mode 100644 (file)
index 0000000..a0118c2
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="close" style="opacity:0.75;">
+       <polygon id="x" style="fill-rule:evenodd;clip-rule:evenodd;" points="18.717,6.697 17.303,5.283 12,10.586 6.697,5.283 5.283,6.697 10.586,12 5.283,17.303 6.697,18.717 12,13.414 17.303,18.717 18.717,17.303 13.414,12            "/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/code.png b/resources/lib/oojs-ui/images/icons/code.png
new file mode 100644 (file)
index 0000000..a5ebdbf
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/code.png differ
diff --git a/resources/lib/oojs-ui/images/icons/code.svg b/resources/lib/oojs-ui/images/icons/code.svg
new file mode 100644 (file)
index 0000000..6f1ed53
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+        width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
+<g id="code" opacity="0.75">
+       <path id="left-bracket" d="M4,12v-1h1c1,0,1,0,1-1V7.614C6,7.1,6.024,6.718,6.073,6.472C6.127,6.22,6.212,6.009,6.33,5.839
+               C6.534,5.56,6.803,5.364,7.138,5.255C7.473,5.14,8.01,5,8.973,5H10v1H9.248c-0.457,0-0.77,0.191-0.936,0.408
+               C8.145,6.623,8,6.853,8,7.476v1.857c0,0.729-0.041,1.18-0.244,1.493c-0.2,0.307-0.562,0.529-1.09,0.667
+               c0.535,0.155,0.9,0.385,1.096,0.688C7.961,12.484,8,12.938,8,13.665v1.862c0,0.619,0.145,0.848,0.312,1.062
+               c0.166,0.22,0.479,0.407,0.936,0.407L10,17l0,0v1H8.973c-0.963,0-1.5-0.133-1.835-0.248c-0.335-0.109-0.604-0.307-0.808-0.591
+               c-0.118-0.165-0.203-0.374-0.257-0.625C6.024,16.283,6,15.9,6,15.387V13c0-1,0-1-1-1H4z"/>
+       <use transform="matrix(-1,0,0,1,24,0)" id="right-bracket" x="0" y="0" width="24" height="24" xlink:href="#left-bracket" />
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/collapse.png b/resources/lib/oojs-ui/images/icons/collapse.png
new file mode 100644 (file)
index 0000000..38b796f
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/collapse.png differ
diff --git a/resources/lib/oojs-ui/images/icons/collapse.svg b/resources/lib/oojs-ui/images/icons/collapse.svg
new file mode 100644 (file)
index 0000000..a89cebf
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="collapse" style="opacity:0.75;">
+       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="6.697,15.714 12,10.412 17.303,15.714 18.717,14.3 12,7.583 5.283,14.3"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/comment.png b/resources/lib/oojs-ui/images/icons/comment.png
new file mode 100644 (file)
index 0000000..9546455
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/comment.png differ
diff --git a/resources/lib/oojs-ui/images/icons/comment.svg b/resources/lib/oojs-ui/images/icons/comment.svg
new file mode 100644 (file)
index 0000000..e052935
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="comment" style="opacity:0.75;">
+       <path id="speech_bubble" style="fill-rule:evenodd;clip-rule:evenodd;" d="M15,6H9C7.343,6,6,7.344,6,9v4c0,1.656,1.343,3,3,3v3 l3-3h3c1.657,0,3-1.344,3-3V9C18,7.344,16.657,6,15,6z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/expand.png b/resources/lib/oojs-ui/images/icons/expand.png
new file mode 100644 (file)
index 0000000..e90aca1
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/expand.png differ
diff --git a/resources/lib/oojs-ui/images/icons/expand.svg b/resources/lib/oojs-ui/images/icons/expand.svg
new file mode 100644 (file)
index 0000000..b542f5f
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="expand" style="opacity:0.75;">
+       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="17.303,8.283 12,13.586 6.697,8.283 5.283,9.697 12,16.414 18.717,9.697"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/help.png b/resources/lib/oojs-ui/images/icons/help.png
new file mode 100644 (file)
index 0000000..dca745b
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/help.png differ
diff --git a/resources/lib/oojs-ui/images/icons/help.svg b/resources/lib/oojs-ui/images/icons/help.svg
new file mode 100644 (file)
index 0000000..c68bdda
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="help" style="opacity:0.75;">
+       <path id="circle" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12.001,2.085c-5.478,0-9.916,4.438-9.916,9.916 c0,5.476,4.438,9.914,9.916,9.914c5.476,0,9.914-4.438,9.914-9.914C21.915,6.523,17.477,2.085,12.001,2.085z M12.002,20.085 c-4.465,0-8.084-3.619-8.084-8.083c0-4.465,3.619-8.084,8.084-8.084c4.464,0,8.083,3.619,8.083,8.084 C20.085,16.466,16.466,20.085,12.002,20.085z"/>
+       <g id="question_mark">
+               <path id="top" style="fill-rule:evenodd;clip-rule:evenodd;" d="M11.766,6.688c-2.5,0-3.219,2.188-3.219,2.188l1.411,0.854 c0,0,0.298-0.791,0.901-1.229c0.516-0.375,1.625-0.625,2.219,0.125c0.701,0.885-0.17,1.587-1.078,2.719 C11.047,12.531,11,15,11,15h1.969c0,0,0.135-2.318,1.041-3.381c0.603-0.707,1.443-1.338,1.443-2.494S14.266,6.688,11.766,6.688z"/>
+               <rect id="bottom" x="11" y="16" style="fill-rule:evenodd;clip-rule:evenodd;" width="2" height="2"/>
+       </g>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/history.png b/resources/lib/oojs-ui/images/icons/history.png
new file mode 100644 (file)
index 0000000..c049931
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/history.png differ
diff --git a/resources/lib/oojs-ui/images/icons/history.svg b/resources/lib/oojs-ui/images/icons/history.svg
new file mode 100644 (file)
index 0000000..40c0ae3
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="history" style="opacity:0.75;">
+       <path id="clock_hands" style="fill-rule:evenodd;clip-rule:evenodd;" d="M17.26,15.076c0,0-2.385-1.935-4.005-3.062 c0.72-2.397,1.702-6.559,1.702-6.559s-4.35,5.363-4.877,6.699c-0.463,1.168,1.459,2.209,2.346,1.678 C14.326,14.383,17.26,15.076,17.26,15.076z"/>
+       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12.086,2.085c-5.478,0-9.916,4.438-9.916,9.916 c0,1.783,0.476,3.454,1.301,4.898l-2.223,2.04h5.688v-5.219l-2.066,1.896c-0.55-1.088-0.866-2.312-0.866-3.615 c0-4.465,3.619-8.084,8.084-8.084c4.464,0,8.083,3.619,8.083,8.084c0,4.464-3.619,8.083-8.083,8.083 c-1.145,0-2.228-0.247-3.213-0.678l-0.833,1.634c1.235,0.557,2.602,0.874,4.045,0.874c5.476,0,9.914-4.438,9.914-9.914 C22,6.523,17.562,2.085,12.086,2.085z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/link.png b/resources/lib/oojs-ui/images/icons/link.png
new file mode 100644 (file)
index 0000000..7dfa268
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/link.png differ
diff --git a/resources/lib/oojs-ui/images/icons/link.svg b/resources/lib/oojs-ui/images/icons/link.svg
new file mode 100644 (file)
index 0000000..dadf69c
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="link" style="opacity:0.75;">
+       <path id="right" d="M19.188,12.001c0,1.1-0.891,2.015-1.988,2.015l-4.195-0.015C13.543,15.089,13.968,16,15.002,16h3
+               C19.658,16,21,13.657,21,12s-1.342-4-2.998-4h-3c-1.034,0-1.459,0.911-1.998,1.999l4.195-0.015
+               C18.297,9.984,19.188,10.901,19.188,12.001z"/>
+       <path id="center" d="M8,12c0,0.535,0.42,1,0.938,1h6.109c0.518,0,0.938-0.465,0.938-1c0-0.534-0.42-1-0.938-1H8.938
+               C8.42,11,8,11.466,8,12z"/>
+       <path id="left" d="M4.816,11.999c0-1.1,0.891-2.015,1.988-2.015L11,9.999C10.461,8.911,10.036,8,9.002,8h-3
+               c-1.656,0-2.998,2.343-2.998,4s1.342,4,2.998,4h3c1.034,0,1.459-0.911,1.998-1.999l-4.195,0.015
+               C5.707,14.016,4.816,13.099,4.816,11.999z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/menu.png b/resources/lib/oojs-ui/images/icons/menu.png
new file mode 100644 (file)
index 0000000..b5ac60f
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/menu.png differ
diff --git a/resources/lib/oojs-ui/images/icons/menu.svg b/resources/lib/oojs-ui/images/icons/menu.svg
new file mode 100644 (file)
index 0000000..657fab2
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="menu" style="opacity:0.75;">
+       <path id="lines" d="M6,15h12c0.553,0,1,0.447,1,1v1c0,0.553-0.447,1-1,1H6c-0.553,0-1-0.447-1-1v-1C5,15.447,5.447,15,6,15z M5,11v1
+               c0,0.553,0.447,1,1,1h12c0.553,0,1-0.447,1-1v-1c0-0.553-0.447-1-1-1H6C5.447,10,5,10.447,5,11z M5,6v1c0,0.553,0.447,1,1,1h12
+               c0.553,0,1-0.447,1-1V6c0-0.553-0.447-1-1-1H6C5.447,5,5,5.447,5,6z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/move-ltr.png b/resources/lib/oojs-ui/images/icons/move-ltr.png
new file mode 100644 (file)
index 0000000..ded5f05
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/move-ltr.png differ
diff --git a/resources/lib/oojs-ui/images/icons/move-ltr.svg b/resources/lib/oojs-ui/images/icons/move-ltr.svg
new file mode 100644 (file)
index 0000000..a378a5d
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="move-ltr" style="opacity:0.75;">
+       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="8.935,7.181 14.237,12.483 8.935,17.786
+               10.349,19.2 17.065,12.483 10.349,5.767"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/move-rtl.png b/resources/lib/oojs-ui/images/icons/move-rtl.png
new file mode 100644 (file)
index 0000000..fc6e62d
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/move-rtl.png differ
diff --git a/resources/lib/oojs-ui/images/icons/move-rtl.svg b/resources/lib/oojs-ui/images/icons/move-rtl.svg
new file mode 100644 (file)
index 0000000..c0b334b
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="move-rtl" style="opacity:0.75;">
+       <polygon id="arrow_9_" style="fill-rule:evenodd;clip-rule:evenodd;" points="15.065,17.786 9.763,12.483 15.065,7.181
+               13.651,5.767 6.935,12.483 13.651,19.2"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/picture.png b/resources/lib/oojs-ui/images/icons/picture.png
new file mode 100644 (file)
index 0000000..faf8af9
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/picture.png differ
diff --git a/resources/lib/oojs-ui/images/icons/picture.svg b/resources/lib/oojs-ui/images/icons/picture.svg
new file mode 100644 (file)
index 0000000..078ce10
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="picture" style="opacity:0.75;">
+       <path id="frame" style="fill-rule:evenodd;clip-rule:evenodd;" d="M18,4H6C4,3.993,3,4.993,3,6.993L3.014,16C3,18,4,18.988,6,19h12
+               c2-0.012,2.994-1,3-3.006V6.993C20.994,4.993,20,3.993,18,4z M19,17H5V6h14V17z"/>
+       <polygon id="mountains" style="fill-rule:evenodd;clip-rule:evenodd;" points="6,13.5 9.5,10 11.828,12.312 10.516,13.406
+               11.391,14.438 15.5,11 18,13 18,16 6,16"/>
+       <polygon id="sky" style="fill-rule:evenodd;clip-rule:evenodd;" points="6,12 9.516,7.844 12.562,11.016 15.5,9 18,11 18,7 6,7"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/remove-item.png b/resources/lib/oojs-ui/images/icons/remove-item.png
new file mode 100644 (file)
index 0000000..2f11db3
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/remove-item.png differ
diff --git a/resources/lib/oojs-ui/images/icons/remove-item.svg b/resources/lib/oojs-ui/images/icons/remove-item.svg
new file mode 100644 (file)
index 0000000..b95e7d3
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
+  <g id="remove-item">
+    <path d="M8,11 L16,11 L16,13 L8,13 z" fill="#000000"/>
+  </g>
+  <defs/>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/remove.png b/resources/lib/oojs-ui/images/icons/remove.png
new file mode 100644 (file)
index 0000000..d7e116c
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/remove.png differ
diff --git a/resources/lib/oojs-ui/images/icons/remove.svg b/resources/lib/oojs-ui/images/icons/remove.svg
new file mode 100644 (file)
index 0000000..17c8d39
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="remove" style="opacity:0.75;">
+       <path id="trash_can" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12,10h-1v6h1V10z M10,10H9v6h1V10z M14,10h-1v6h1V10z
+                M14,6V5H9v1H6v3h1v7.966l1,1.031v-0.074V18h6.984L15,17.982v0.015l1-1.031V9h1V6H14z M15,17H8V9h7V17z M16,8H7V7h9V8z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/search.png b/resources/lib/oojs-ui/images/icons/search.png
new file mode 100644 (file)
index 0000000..df29792
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/search.png differ
diff --git a/resources/lib/oojs-ui/images/icons/search.svg b/resources/lib/oojs-ui/images/icons/search.svg
new file mode 100644 (file)
index 0000000..37feda4
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="search" style="opacity:0.75;">
+       <path id="magnifying_glass" d="M16.021,15.96l-2.374-2.375c-0.048-0.047-0.105-0.079-0.169-0.099c0.403-0.566,0.643-1.26,0.643-2.009
+               C14.12,9.557,12.563,8,10.644,8c-1.921,0-3.478,1.557-3.478,3.478c0,1.92,1.557,3.477,3.478,3.477c0.749,0,1.442-0.239,2.01-0.643
+               c0.019,0.063,0.051,0.121,0.098,0.169l2.375,2.374c0.19,0.189,0.543,0.143,0.79-0.104S16.21,16.15,16.021,15.96z M10.644,13.69
+               c-1.221,0-2.213-0.991-2.213-2.213c0-1.221,0.992-2.213,2.213-2.213c1.222,0,2.213,0.992,2.213,2.213
+               C12.856,12.699,11.865,13.69,10.644,13.69z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/settings.png b/resources/lib/oojs-ui/images/icons/settings.png
new file mode 100644 (file)
index 0000000..b1b35e9
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/settings.png differ
diff --git a/resources/lib/oojs-ui/images/icons/settings.svg b/resources/lib/oojs-ui/images/icons/settings.svg
new file mode 100644 (file)
index 0000000..1464a79
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
+  <g id="settings" opacity="0.75">
+    <path d="M3,4 L6,4 L6,6 L3,6 z" fill="#000000"/>
+    <path d="M12,4 L21,4 L21,6 L12,6 z" fill="#000000"/>
+    <path d="M8,3 L10,3 C10.552,3 11,3.448 11,4 L11,6 C11,6.552 10.552,7 10,7 L8,7 C7.448,7 7,6.552 7,6 L7,4 C7,3.448 7.448,3 8,3 z" fill="#000000"/>
+    <path d="M3,11 L12,11 L12,13 L3,13 z" fill="#000000"/>
+    <path d="M18,11 L21,11 L21,13 L18,13 z" fill="#000000"/>
+    <path d="M14,10 L16,10 C16.552,10 17,10.448 17,11 L17,13 C17,13.552 16.552,14 16,14 L14,14 C13.448,14 13,13.552 13,13 L13,11 C13,10.448 13.448,10 14,10 z" fill="#000000"/>
+    <path d="M3,18 L9,18 L9,20 L3,20 z" fill="#000000"/>
+    <path d="M15,18 L21,18 L21,20 L15,20 z" fill="#000000"/>
+    <path d="M11,17 L13,17 C13.552,17 14,17.448 14,18 L14,20 C14,20.552 13.552,21 13,21 L11,21 C10.448,21 10,20.552 10,20 L10,18 C10,17.448 10.448,17 11,17 z" fill="#000000"/>
+  </g>
+  <defs/>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/tag.png b/resources/lib/oojs-ui/images/icons/tag.png
new file mode 100644 (file)
index 0000000..722f4d7
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/tag.png differ
diff --git a/resources/lib/oojs-ui/images/icons/tag.svg b/resources/lib/oojs-ui/images/icons/tag.svg
new file mode 100644 (file)
index 0000000..d21e5e3
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="tag" style="opacity:0.75;">
+       <path d="M18.748,11.717c0.389,0.389,0.389,1.025,0,1.414l-4.949,4.95c-0.389,0.389-1.025,0.389-1.414,0l-6.01-6.01
+               c-0.389-0.389-0.707-1.157-0.707-1.707L5.667,6c0-0.55,0.45-1,1-1h4.364c0.55,0,1.318,0.318,1.707,0.707L18.748,11.717z
+                M8.104,7.456C7.525,8.032,7.526,8.97,8.103,9.549c0.578,0.577,1.516,0.577,2.095,0.001c0.576-0.578,0.576-1.517,0-2.095
+               C9.617,6.879,8.68,6.878,8.104,7.456z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/icons/window.png b/resources/lib/oojs-ui/images/icons/window.png
new file mode 100644 (file)
index 0000000..3d48a3c
Binary files /dev/null and b/resources/lib/oojs-ui/images/icons/window.png differ
diff --git a/resources/lib/oojs-ui/images/icons/window.svg b/resources/lib/oojs-ui/images/icons/window.svg
new file mode 100644 (file)
index 0000000..621cf2c
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="window" style="opacity:0.75;">
+       <rect id="title" x="7" y="10" width="10" height="1"/>
+       <path id="window" d="M16,19H8c-2.206,0-4-1.794-4-4V9c0-2.206,1.794-4,4-4h8c2.206,0,4,1.794,4,4v6C20,17.206,18.206,19,16,19z
+                M8,7C6.897,7,6,7.897,6,9v6c0,1.103,0.897,2,2,2h8c1.103,0,2-0.897,2-2V9c0-1.103-0.897-2-2-2H8z"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/indicators/down.png b/resources/lib/oojs-ui/images/indicators/down.png
new file mode 100644 (file)
index 0000000..47ff54c
Binary files /dev/null and b/resources/lib/oojs-ui/images/indicators/down.png differ
diff --git a/resources/lib/oojs-ui/images/indicators/down.svg b/resources/lib/oojs-ui/images/indicators/down.svg
new file mode 100644 (file)
index 0000000..c871f60
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
+        height="12px" viewBox="0 0 12 12" style="enable-background:new 0 0 12 12;" xml:space="preserve">
+<g id="down" style="opacity:0.75;">
+       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="2.023,3 5.512,8.953 9,3"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/indicators/required.png b/resources/lib/oojs-ui/images/indicators/required.png
new file mode 100644 (file)
index 0000000..aeb35a3
Binary files /dev/null and b/resources/lib/oojs-ui/images/indicators/required.png differ
diff --git a/resources/lib/oojs-ui/images/indicators/required.svg b/resources/lib/oojs-ui/images/indicators/required.svg
new file mode 100644 (file)
index 0000000..7c60ec0
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12" height="12" viewBox="0, 0, 12, 12">
+  <g id="required" opacity="0.75">
+    <path d="M7,0 L7,4.268 L10.696,2.134 L11.696,3.866 L8,6 L11.696,8.134 L10.696,9.866 L7,7.732 L7,12 L5,12 L5,7.732 L1.304,9.866 L0.304,8.134 L4,6 L0.304,3.866 L1.304,2.134 L5,4.268 L5,0 z" fill="#000000"/>
+  </g>
+  <defs/>
+</svg>
diff --git a/resources/lib/oojs-ui/images/indicators/up.png b/resources/lib/oojs-ui/images/indicators/up.png
new file mode 100644 (file)
index 0000000..b827f6d
Binary files /dev/null and b/resources/lib/oojs-ui/images/indicators/up.png differ
diff --git a/resources/lib/oojs-ui/images/indicators/up.svg b/resources/lib/oojs-ui/images/indicators/up.svg
new file mode 100644 (file)
index 0000000..a5d7f38
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
+        height="12px" viewBox="0 0 12 12" style="enable-background:new 0 0 12 12;" xml:space="preserve">
+<g id="up" style="opacity:0.75;">
+       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="5.512,2.006 2,8 9.024,8                "/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/tail.svg b/resources/lib/oojs-ui/images/tail.svg
new file mode 100644 (file)
index 0000000..4df8bb2
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+        width="15px" height="8px" viewBox="0 0 15 8" style="enable-background:new 0 0 15 8;" xml:space="preserve">
+<g id="tail">
+       <polygon id="outline" style="fill-rule:evenodd;clip-rule:evenodd;fill:#808080;" points="7.609,2.499 2.096,8 13.125,8"/>
+       <polygon id="fill" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;" points="7.609,3 2.598,8 12.622,8"/>
+</g>
+</svg>
diff --git a/resources/lib/oojs-ui/images/textures/pending.gif b/resources/lib/oojs-ui/images/textures/pending.gif
new file mode 100644 (file)
index 0000000..1194eed
Binary files /dev/null and b/resources/lib/oojs-ui/images/textures/pending.gif differ
diff --git a/resources/lib/oojs-ui/images/textures/transparency.png b/resources/lib/oojs-ui/images/textures/transparency.png
new file mode 100644 (file)
index 0000000..b8e36d3
Binary files /dev/null and b/resources/lib/oojs-ui/images/textures/transparency.png differ
diff --git a/resources/lib/oojs-ui/images/toolbar-shadow.png b/resources/lib/oojs-ui/images/toolbar-shadow.png
new file mode 100644 (file)
index 0000000..97e8d13
Binary files /dev/null and b/resources/lib/oojs-ui/images/toolbar-shadow.png differ
diff --git a/resources/lib/oojs-ui/oojs-ui-agora.css b/resources/lib/oojs-ui/oojs-ui-agora.css
new file mode 100644 (file)
index 0000000..8aedde5
--- /dev/null
@@ -0,0 +1,80 @@
+.oo-ui-window-head {
+  height: 3.35em;
+  border-bottom: 1px solid #dddddd;
+}
+
+.oo-ui-window-body {
+  padding: 2em 3.35em;
+}
+
+.oo-ui-window-icon {
+  width: 3.35em;
+  height: 3.35em;
+  background-size: 2em auto;
+  border-left: 1px solid #dddddd;
+}
+
+.oo-ui-window-title {
+  line-height: 3.35em;
+}
+
+.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
+.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  width: 3.35em;
+  height: 3.35em;
+  background-size: 2em auto;
+}
+
+.oo-ui-optionWidget {
+  padding: 0.8em 1em 0.8em 3.35em;
+  font-weight: bold;
+  border-bottom: 1px solid #dddddd;
+}
+
+.oo-ui-optionWidget.oo-ui-indicatedElement .oo-ui-labeledElement-label {
+  padding-right: 1.5em;
+}
+
+.oo-ui-optionWidget-level-0 {
+  padding-left: 3.5em;
+}
+
+.oo-ui-optionWidget-level-0 .oo-ui-iconedElement-icon {
+  left: 1em;
+}
+
+.oo-ui-optionWidget-level-1 {
+  padding-left: 5em;
+}
+
+.oo-ui-optionWidget-level-1 .oo-ui-iconedElement-icon {
+  left: 2.5em;
+}
+
+.oo-ui-optionWidget-level-2 {
+  padding-left: 6.5em;
+}
+
+.oo-ui-optionWidget-level-2 .oo-ui-iconedElement-icon {
+  left: 4em;
+}
+
+.oo-ui-buttonOptionWidget {
+  padding: 0;
+}
+
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+  color: #ffffff;
+  background: #347bff;
+}
+
+.oo-ui-menuSectionItemWidget {
+  font-weight: normal;
+  color: #777777;
+  border: none;
+}
+
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  padding: .8em 1em;
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/oojs-ui-apex.css b/resources/lib/oojs-ui/oojs-ui-apex.css
new file mode 100644 (file)
index 0000000..3ddb5b3
--- /dev/null
@@ -0,0 +1,787 @@
+.oo-ui-dialog {
+  background-color: #fff;
+  background-color: rgba(255, 255, 255, 0.5);
+  opacity: 0;
+  -webkit-transition: all 250ms ease-in-out;
+     -moz-transition: all 250ms ease-in-out;
+      -ms-transition: all 250ms ease-in-out;
+       -o-transition: all 250ms ease-in-out;
+          transition: all 250ms ease-in-out;
+}
+
+.oo-ui-dialog .oo-ui-window-frame {
+  background-color: #fff;
+  border: solid 1px #ccc;
+  border-radius: 0.5em;
+  -webkit-transform: scale(0.5);
+     -moz-transform: scale(0.5);
+      -ms-transform: scale(0.5);
+       -o-transform: scale(0.5);
+          transform: scale(0.5);
+  box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
+  -webkit-transition: all 250ms ease-in-out;
+     -moz-transition: all 250ms ease-in-out;
+      -ms-transition: all 250ms ease-in-out;
+       -o-transition: all 250ms ease-in-out;
+          transition: all 250ms ease-in-out;
+}
+
+.oo-ui-dialog-open {
+  opacity: 1;
+}
+
+.oo-ui-dialog-open .oo-ui-window-frame {
+  -webkit-transform: scale(1);
+     -moz-transform: scale(1);
+      -ms-transform: scale(1);
+       -o-transform: scale(1);
+          transform: scale(1);
+}
+
+.oo-ui-dialog-content .oo-ui-window-body {
+  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
+}
+
+.oo-ui-frame-content {
+  font-family: sans-serif;
+  font-size: 0.8em;
+}
+
+.oo-ui-toolbar-bar {
+  background: #f8fbfd;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #f1f7fb));
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -ms-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -o-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  border-bottom: solid 1px #ccc;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#f1f7fb');
+}
+
+.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
+  background: none;
+  border: none;
+}
+
+.oo-ui-toolbar-shadow {
+  bottom: -9px;
+  height: 9px;
+  background-image: /* @embed */ url(images/toolbar-shadow.png);
+  opacity: 0.125;
+  -webkit-transition: opacity 500ms ease-in-out;
+     -moz-transition: opacity 500ms ease-in-out;
+      -ms-transition: opacity 500ms ease-in-out;
+       -o-transition: opacity 500ms ease-in-out;
+          transition: opacity 500ms ease-in-out;
+}
+
+.oo-ui-toolGroup {
+  border: solid 1px transparent;
+  border-radius: 0.25em;
+  -webkit-transition: border-color 300ms ease-in-out;
+     -moz-transition: border-color 300ms ease-in-out;
+      -ms-transition: border-color 300ms ease-in-out;
+       -o-transition: border-color 300ms ease-in-out;
+          transition: border-color 300ms ease-in-out;
+}
+
+.oo-ui-toolGroup.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-toolGroup.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-tool-title {
+  color: #000;
+}
+
+.oo-ui-window-body {
+  padding: 0 0.75em;
+}
+
+.oo-ui-window-icon {
+  width: 2em;
+  height: 2em;
+  margin-right: 0.5em;
+  line-height: 2em;
+}
+
+.oo-ui-window-title {
+  line-height: 2em;
+  color: #333;
+}
+
+.oo-ui-window-overlay {
+  font-family: sans-serif;
+  font-size: 1em;
+  line-height: 1.5em;
+}
+
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button {
+  color: #333;
+}
+
+.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
+.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  width: 1.9em;
+  height: 1.9em;
+  opacity: 0.8;
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  /* Don't animate opacities for now, causes wiggling in Chrome (bug 63020) */
+
+  /*.oo-ui-transition(opacity 200ms);*/
+
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-iconedElement-icon,
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-iconedElement-icon {
+  opacity: 1;
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-labeledElement-label,
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-labeledElement-label {
+  color: #000;
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+  color: #333;
+}
+
+.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+  color: #ccc;
+}
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
+  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+  background: #eeeeee;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #dddddd));
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  border: 1px #c9c9c9 solid;
+  border-radius: 0.3em;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
+  -webkit-transition: border-color 100ms ease-in-out;
+     -moz-transition: border-color 100ms ease-in-out;
+      -ms-transition: border-color 100ms ease-in-out;
+       -o-transition: border-color 100ms ease-in-out;
+          transition: border-color 100ms ease-in-out;
+}
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:focus {
+  border-color: #aaa;
+}
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+  color: black;
+  background: #eeeeee;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #dddddd), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  border-color: #c9c9c9;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
+  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button {
+  background: #cde7f4;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #eaf4fa), color-stop(100%, #b0d9ee));
+  background-image: -webkit-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: -moz-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: -ms-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: -o-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  border: solid 1px #a6cee1;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#eaf4fa', endColorstr='#b0d9ee');
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:focus {
+  border-color: #9dc2d4;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+  background: #cde7f4;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #b0d9ee), color-stop(100%, #eaf4fa));
+  background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  border: solid 1px #a6cee1;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button {
+  background: #daf0be;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f0fbe1), color-stop(100%, #c3e59a));
+  background-image: -webkit-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: -moz-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: -ms-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: -o-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  border: solid 1px #b8d892;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f0fbe1', endColorstr='#c3e59a');
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:focus {
+  border-color: #adcb89;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+  background: #daf0be;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #c3e59a), color-stop(100%, #f0fbe1));
+  background-image: -webkit-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: -moz-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: -ms-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: -o-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  border: solid 1px #b8d892;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#c3e59a', endColorstr='#f0fbe1');
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-destructive .oo-ui-buttonedElement-button {
+  color: #d45353;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+  color: #333;
+  background: #eee;
+  border-color: #ccc;
+  opacity: 0.5;
+  box-shadow: none;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active:hover,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed:hover,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:focus,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active:focus,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed:focus {
+  border-color: #ccc;
+  box-shadow: none;
+}
+
+.oo-ui-bookletLayout > .oo-ui-gridLayout > .oo-ui-panelLayout {
+  -webkit-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
+     -moz-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
+      -ms-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
+       -o-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
+          transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
+}
+
+.oo-ui-bookletLayout-outlinePanel {
+  border-right: solid 1px #ddd;
+}
+
+.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
+  box-shadow: 0 0 0.25em rgba(0, 0, 0, 0.25);
+}
+
+.oo-ui-fieldsetLayout {
+  border: none;
+}
+
+.oo-ui-fieldsetLayout > legend.oo-ui-labeledElement-label {
+  font-size: 1.5em;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool {
+  margin: -1px 0 -1px -1px;
+  border: solid 1px transparent;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool:first-child {
+  border-bottom-left-radius: 0.25em;
+  border-top-left-radius: 0.25em;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool:last-child {
+  margin-right: -1px;
+  border-top-right-radius: 0.25em;
+  border-bottom-right-radius: 0.25em;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.8;
+}
+
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-active.oo-ui-widget-enabled {
+  background: #f8fbfd;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  border-color: rgba(0, 0, 0, 0.2);
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
+  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+}
+
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
+  border-left-color: rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.8;
+}
+
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 1;
+}
+
+.oo-ui-barToolGroup.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool {
+  margin: -1px 0;
+  border: solid 1px transparent;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled {
+  background: #f8fbfd;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  border-color: rgba(0, 0, 0, 0.1);
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
+  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
+  border-top-color: rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.8;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 1;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
+  color: #ccc;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-indicatedElement-indicator,
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-menuToolGroup {
+  border-color: rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-menuToolGroup.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-menuToolGroup.oo-ui-popupToolGroup-active {
+  border-color: rgba(0, 0, 0, 0.25);
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+  background-color: #e1f3ff;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
+  color: #ccc;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-menuToolGroup.oo-ui-widget-disabled {
+  color: #ccc;
+  text-shadow: 0 1px 1px #fff;
+  background-color: #f3f3f3;
+  border-color: #ddd;
+}
+
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-indicatedElement-indicator,
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
+  opacity: 0.8;
+}
+
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+  background-color: white;
+  border: solid 1px #ccc;
+  box-shadow: 0 0.25em 1em rgba(0, 0, 0, 0.25);
+}
+
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled {
+  background: #f8fbfd;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
+  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+}
+
+.oo-ui-optionWidget {
+  padding: 0.5em 2em 0.5em 3em;
+}
+
+.oo-ui-optionWidget-highlighted {
+  background-color: #e1f3ff;
+}
+
+.oo-ui-selectWidget-depressed .oo-ui-optionWidget-selected {
+  background-color: #a7dcff;
+}
+
+.oo-ui-selectWidget-pressed .oo-ui-optionWidget-pressed {
+  background-color: #a7dcff;
+}
+
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+  color: #ccc;
+}
+
+.oo-ui-menuWidget {
+  margin-top: -1px;
+  background: #fff;
+  border: solid 1px #ccc;
+  border-radius: 0 0 0.25em 0.25em;
+  box-shadow: 0 0.15em 1em 0 rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-popupWidget-popup {
+  background-color: #fff;
+  border: solid 1px #ccc;
+  border-radius: 0.25em;
+  box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-popupWidget-tailed .oo-ui-popupWidget-tail {
+  width: 15px;
+  height: 8px;
+  margin-left: -7px;
+  background-image: /* @embed */ url(images/tail.svg);
+}
+
+.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
+  -webkit-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+     -moz-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+      -ms-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+       -o-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+          transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+}
+
+.oo-ui-popupWidget-body {
+  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
+}
+
+.oo-ui-buttonGroupWidget {
+  display: inline-block;
+  white-space: nowrap;
+}
+
+.oo-ui-buttonOptionWidget {
+  padding: 0;
+}
+
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected,
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-highlighted {
+  background-color: transparent;
+}
+
+.oo-ui-buttonSelectWidget {
+  border-radius: 0.3em;
+}
+
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
+  margin-left: -1px;
+  border-radius: 0;
+}
+
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonedElement-button {
+  margin-left: 0;
+  border-bottom-left-radius: 0.3em;
+  border-top-left-radius: 0.3em;
+}
+
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonedElement-button {
+  border-top-right-radius: 0.3em;
+  border-bottom-right-radius: 0.3em;
+}
+
+.oo-ui-inlineMenuWidget-handle {
+  border: solid 1px rgba(0, 0, 0, 0.1);
+  border-radius: 0.25em;
+}
+
+.oo-ui-inlineMenuWidget-handle:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator,
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
+  opacity: 0.8;
+}
+
+.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
+  color: #ccc;
+  text-shadow: 0 1px 1px #fff;
+  background-color: #f3f3f3;
+  border-color: #ddd;
+}
+
+.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-indicatedElement-indicator {
+  opacity: 0.2;
+}
+
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+  background-color: transparent;
+}
+
+.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted,
+.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted.oo-ui-optionWidget-selected {
+  background-color: #e1f3ff;
+}
+
+.oo-ui-menuSectionItemWidget {
+  padding: 0.33em 0.75em;
+  color: #888;
+}
+
+.oo-ui-outlineControlsWidget {
+  background-color: #fff;
+}
+
+.oo-ui-outlineControlsWidget > .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-outlineItemWidget {
+  font-size: 1.1em;
+}
+
+.oo-ui-outlineItemWidget.oo-ui-indicatedElement .oo-ui-labeledElement-label {
+  padding-right: 1.5em;
+}
+
+.oo-ui-outlineItemWidget-level-0 {
+  padding-left: 3.5em;
+}
+
+.oo-ui-outlineItemWidget-level-0 .oo-ui-iconedElement-icon {
+  left: 1em;
+}
+
+.oo-ui-outlineItemWidget-level-1 {
+  padding-left: 5em;
+}
+
+.oo-ui-outlineItemWidget-level-1 .oo-ui-iconedElement-icon {
+  left: 2.5em;
+}
+
+.oo-ui-outlineItemWidget-level-2 {
+  padding-left: 6.5em;
+}
+
+.oo-ui-outlineItemWidget-level-2 .oo-ui-iconedElement-icon {
+  left: 4em;
+}
+
+.oo-ui-selectWidget-depressed .oo-ui-outlineItemWidget.oo-ui-optionWidget-selected {
+  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+  background-color: #a7dcff;
+}
+
+.oo-ui-outlineItemWidget.oo-ui-flaggableElement-important {
+  font-weight: bold;
+}
+
+.oo-ui-outlineItemWidget.oo-ui-flaggableElement-placeholder {
+  font-style: italic;
+}
+
+.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-iconedElement-icon,
+.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-indicatedElement-indicator {
+  opacity: 0.5;
+}
+
+.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-labeledElement-label {
+  color: #777;
+}
+
+.oo-ui-searchWidget-query {
+  box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-textInputWidget {
+  width: 20em;
+}
+
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  padding: 0.5em;
+  font-family: sans-serif;
+  font-size: 1em;
+  background-color: #fff;
+  border: solid 1px #ccc;
+  border-radius: 0.25em;
+  box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
+  -webkit-transition: border-color 200ms, box-shadow 200ms;
+     -moz-transition: border-color 200ms, box-shadow 200ms;
+      -ms-transition: border-color 200ms, box-shadow 200ms;
+       -o-transition: border-color 200ms, box-shadow 200ms;
+          transition: border-color 200ms, box-shadow 200ms;
+}
+
+.oo-ui-textInputWidget-decorated input,
+.oo-ui-textInputWidget-decorated textarea {
+  padding-left: 2em;
+}
+
+.oo-ui-textInputWidget-icon {
+  width: 2em;
+}
+
+.oo-ui-textInputWidget.oo-ui-widget-enabled input:focus,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea:focus {
+  border-color: #a7dcff;
+  outline: none;
+  box-shadow: 0 0 0.3em #a7dcff, 0 0 0 white;
+}
+
+.oo-ui-textInputWidget input[readonly],
+.oo-ui-textInputWidget textarea[readonly] {
+  color: #777;
+  text-shadow: 0 1px 1px #fff;
+}
+
+.oo-ui-textInputWidget-pending input,
+.oo-ui-textInputWidget-pending textarea {
+  background-color: transparent;
+}
+
+.oo-ui-textInputWidget.oo-ui-widget-disabled input,
+.oo-ui-textInputWidget.oo-ui-widget-disabled input:focus,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea:focus {
+  color: #ccc;
+  text-shadow: 0 1px 1px #fff;
+  background-color: #f3f3f3;
+  border-color: #ddd;
+}
+
+.oo-ui-toggleSwitchWidget {
+  background: #eeeeee;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #dddddd), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  border: solid 1px #ccc;
+  border-radius: 1em;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
+  box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
+}
+
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+  opacity: 0.5;
+}
+
+.oo-ui-toggleSwitchWidget-grip {
+  background: #eeeeee;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #dddddd));
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  border: 1px #c9c9c9 solid;
+  border-radius: 1em;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
+  box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover .oo-ui-toggleSwitchWidget-grip {
+  border-color: #aaa;
+}
+
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  background: #cde7f4;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #b0d9ee), color-stop(100%, #eaf4fa));
+  background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  border-radius: 1em;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
+  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+}
+
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-glow {
+  opacity: 1;
+}
+
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+  display: block;
+  opacity: 0;
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/oojs-ui.js b/resources/lib/oojs-ui/oojs-ui.js
new file mode 100644 (file)
index 0000000..cf838b9
--- /dev/null
@@ -0,0 +1,8185 @@
+/*!
+ * OOjs UI v0.1.0-pre (4975b8db90)
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2014 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: Mon Apr 07 2014 15:17:10 GMT-0700 (PDT)
+ */
+( function ( OO ) {
+
+'use strict';
+/**
+ * Namespace for all classes, static methods and static properties.
+ *
+ * @class
+ * @singleton
+ */
+OO.ui = {};
+
+OO.ui.bind = $.proxy;
+
+/**
+ * @property {Object}
+ */
+OO.ui.Keys = {
+       'UNDEFINED': 0,
+       'BACKSPACE': 8,
+       'DELETE': 46,
+       'LEFT': 37,
+       'RIGHT': 39,
+       'UP': 38,
+       'DOWN': 40,
+       'ENTER': 13,
+       'END': 35,
+       'HOME': 36,
+       'TAB': 9,
+       'PAGEUP': 33,
+       'PAGEDOWN': 34,
+       'ESCAPE': 27,
+       'SHIFT': 16,
+       'SPACE': 32
+};
+
+/**
+ * Get the user's language and any fallback languages.
+ *
+ * These language codes are used to localize user interface elements in the user's language.
+ *
+ * In environments that provide a localization system, this function should be overridden to
+ * return the user's language(s). The default implementation returns English (en) only.
+ *
+ * @return {string[]} Language codes, in descending order of priority
+ */
+OO.ui.getUserLanguages = function () {
+       return [ 'en' ];
+};
+
+/**
+ * Get a value in an object keyed by language code.
+ *
+ * @param {Object.<string,Mixed>} obj Object keyed by language code
+ * @param {string|null} [lang] Language code, if omitted or null defaults to any user language
+ * @param {string} [fallback] Fallback code, used if no matching language can be found
+ * @return {Mixed} Local value
+ */
+OO.ui.getLocalValue = function ( obj, lang, fallback ) {
+       var i, len, langs;
+
+       // Requested language
+       if ( obj[lang] ) {
+               return obj[lang];
+       }
+       // Known user language
+       langs = OO.ui.getUserLanguages();
+       for ( i = 0, len = langs.length; i < len; i++ ) {
+               lang = langs[i];
+               if ( obj[lang] ) {
+                       return obj[lang];
+               }
+       }
+       // Fallback language
+       if ( obj[fallback] ) {
+               return obj[fallback];
+       }
+       // First existing language
+       for ( lang in obj ) {
+               return obj[lang];
+       }
+
+       return undefined;
+};
+
+( function () {
+
+/**
+ * Message store for the default implementation of OO.ui.msg
+ *
+ * Environments that provide a localization system should not use this, but should override
+ * OO.ui.msg altogether.
+ *
+ * @private
+ */
+var messages = {
+       // Label text for button to exit from dialog
+       'ooui-dialog-action-close': 'Close',
+       // Tool tip for a button that moves items in a list down one place
+       'ooui-outline-control-move-down': 'Move item down',
+       // Tool tip for a button that moves items in a list up one place
+       'ooui-outline-control-move-up': 'Move item up',
+       // Tool tip for a button that removes items from a list
+       'ooui-outline-control-remove': 'Remove item',
+       // Label for the toolbar group that contains a list of all other available tools
+       'ooui-toolbar-more': 'More'
+};
+
+/**
+ * Get a localized message.
+ *
+ * In environments that provide a localization system, this function should be overridden to
+ * return the message translated in the user's language. The default implementation always returns
+ * English messages.
+ *
+ * After the message key, message parameters may optionally be passed. In the default implementation,
+ * any occurrences of $1 are replaced with the first parameter, $2 with the second parameter, etc.
+ * Alternative implementations of OO.ui.msg may use any substitution system they like, as long as
+ * they support unnamed, ordered message parameters.
+ *
+ * @abstract
+ * @param {string} key Message key
+ * @param {Mixed...} [params] Message parameters
+ * @return {string} Translated message with parameters substituted
+ */
+OO.ui.msg = function ( key ) {
+       var message = messages[key], params = Array.prototype.slice.call( arguments, 1 );
+       if ( typeof message === 'string' ) {
+               // Perform $1 substitution
+               message = message.replace( /\$(\d+)/g, function ( unused, n ) {
+                       var i = parseInt( n, 10 );
+                       return params[i - 1] !== undefined ? params[i - 1] : '$' + n;
+               } );
+       } else {
+               // Return placeholder if message not found
+               message = '[' + key + ']';
+       }
+       return message;
+};
+
+/** */
+OO.ui.deferMsg = function ( key ) {
+       return function () {
+               return OO.ui.msg( key );
+       };
+};
+
+/** */
+OO.ui.resolveMsg = function ( msg ) {
+       if ( $.isFunction( msg ) ) {
+               return msg();
+       }
+       return msg;
+};
+
+} )();
+/**
+ * DOM element abstraction.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Function} [$] jQuery for the frame the widget is in
+ * @cfg {string[]} [classes] CSS class names
+ * @cfg {jQuery} [$content] Content elements to append
+ */
+OO.ui.Element = function OoUiElement( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Properties
+       this.$ = config.$ || OO.ui.Element.getJQuery( document );
+       this.$element = this.$( this.$.context.createElement( this.getTagName() ) );
+       this.elementGroup = null;
+
+       // Initialization
+       if ( $.isArray( config.classes ) ) {
+               this.$element.addClass( config.classes.join( ' ' ) );
+       }
+       if ( config.$content ) {
+               this.$element.append( config.$content );
+       }
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.Element );
+
+/* Static Properties */
+
+/**
+ * HTML tag name.
+ *
+ * This may be ignored if getTagName is overridden.
+ *
+ * @static
+ * @property {string}
+ * @inheritable
+ */
+OO.ui.Element.static.tagName = 'div';
+
+/* Static Methods */
+
+/**
+ * Get a jQuery function within a specific document.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} context Context to bind the function to
+ * @param {OO.ui.Frame} [frame] Frame of the document context
+ * @return {Function} Bound jQuery function
+ */
+OO.ui.Element.getJQuery = function ( context, frame ) {
+       function wrapper( selector ) {
+               return $( selector, wrapper.context );
+       }
+
+       wrapper.context = this.getDocument( context );
+
+       if ( frame ) {
+               wrapper.frame = frame;
+       }
+
+       return wrapper;
+};
+
+/**
+ * Get the document of an element.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Object to get the document for
+ * @return {HTMLDocument|null} Document object
+ */
+OO.ui.Element.getDocument = function ( obj ) {
+       // jQuery - selections created "offscreen" won't have a context, so .context isn't reliable
+       return ( obj[0] && obj[0].ownerDocument ) ||
+               // Empty jQuery selections might have a context
+               obj.context ||
+               // HTMLElement
+               obj.ownerDocument ||
+               // Window
+               obj.document ||
+               // HTMLDocument
+               ( obj.nodeType === 9 && obj ) ||
+               null;
+};
+
+/**
+ * Get the window of an element or document.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the window for
+ * @return {Window} Window object
+ */
+OO.ui.Element.getWindow = function ( obj ) {
+       var doc = this.getDocument( obj );
+       return doc.parentWindow || doc.defaultView;
+};
+
+/**
+ * Get the direction of an element or document.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the direction for
+ * @return {string} Text direction, either `ltr` or `rtl`
+ */
+OO.ui.Element.getDir = function ( obj ) {
+       var isDoc, isWin;
+
+       if ( obj instanceof jQuery ) {
+               obj = obj[0];
+       }
+       isDoc = obj.nodeType === 9;
+       isWin = obj.document !== undefined;
+       if ( isDoc || isWin ) {
+               if ( isWin ) {
+                       obj = obj.document;
+               }
+               obj = obj.body;
+       }
+       return $( obj ).css( 'direction' );
+};
+
+/**
+ * Get the offset between two frames.
+ *
+ * TODO: Make this function not use recursion.
+ *
+ * @static
+ * @param {Window} from Window of the child frame
+ * @param {Window} [to=window] Window of the parent frame
+ * @param {Object} [offset] Offset to start with, used internally
+ * @return {Object} Offset object, containing left and top properties
+ */
+OO.ui.Element.getFrameOffset = function ( from, to, offset ) {
+       var i, len, frames, frame, rect;
+
+       if ( !to ) {
+               to = window;
+       }
+       if ( !offset ) {
+               offset = { 'top': 0, 'left': 0 };
+       }
+       if ( from.parent === from ) {
+               return offset;
+       }
+
+       // Get iframe element
+       frames = from.parent.document.getElementsByTagName( 'iframe' );
+       for ( i = 0, len = frames.length; i < len; i++ ) {
+               if ( frames[i].contentWindow === from ) {
+                       frame = frames[i];
+                       break;
+               }
+       }
+
+       // Recursively accumulate offset values
+       if ( frame ) {
+               rect = frame.getBoundingClientRect();
+               offset.left += rect.left;
+               offset.top += rect.top;
+               if ( from !== to ) {
+                       this.getFrameOffset( from.parent, offset );
+               }
+       }
+       return offset;
+};
+
+/**
+ * Get the offset between two elements.
+ *
+ * @static
+ * @param {jQuery} $from
+ * @param {jQuery} $to
+ * @return {Object} Translated position coordinates, containing top and left properties
+ */
+OO.ui.Element.getRelativePosition = function ( $from, $to ) {
+       var from = $from.offset(),
+               to = $to.offset();
+       return { 'top': Math.round( from.top - to.top ), 'left': Math.round( from.left - to.left ) };
+};
+
+/**
+ * Get element border sizes.
+ *
+ * @static
+ * @param {HTMLElement} el Element to measure
+ * @return {Object} Dimensions object with `top`, `left`, `bottom` and `right` properties
+ */
+OO.ui.Element.getBorders = function ( el ) {
+       var doc = el.ownerDocument,
+               win = doc.parentWindow || doc.defaultView,
+               style = win && win.getComputedStyle ?
+                       win.getComputedStyle( el, null ) :
+                       el.currentStyle,
+               $el = $( el ),
+               top = parseFloat( style ? style.borderTopWidth : $el.css( 'borderTopWidth' ) ) || 0,
+               left = parseFloat( style ? style.borderLeftWidth : $el.css( 'borderLeftWidth' ) ) || 0,
+               bottom = parseFloat( style ? style.borderBottomWidth : $el.css( 'borderBottomWidth' ) ) || 0,
+               right = parseFloat( style ? style.borderRightWidth : $el.css( 'borderRightWidth' ) ) || 0;
+
+       return {
+               'top': Math.round( top ),
+               'left': Math.round( left ),
+               'bottom': Math.round( bottom ),
+               'right': Math.round( right )
+       };
+};
+
+/**
+ * Get dimensions of an element or window.
+ *
+ * @static
+ * @param {HTMLElement|Window} el Element to measure
+ * @return {Object} Dimensions object with `borders`, `scroll`, `scrollbar` and `rect` properties
+ */
+OO.ui.Element.getDimensions = function ( el ) {
+       var $el, $win,
+               doc = el.ownerDocument || el.document,
+               win = doc.parentWindow || doc.defaultView;
+
+       if ( win === el || el === doc.documentElement ) {
+               $win = $( win );
+               return {
+                       'borders': { 'top': 0, 'left': 0, 'bottom': 0, 'right': 0 },
+                       'scroll': {
+                               'top': $win.scrollTop(),
+                               'left': $win.scrollLeft()
+                       },
+                       'scrollbar': { 'right': 0, 'bottom': 0 },
+                       'rect': {
+                               'top': 0,
+                               'left': 0,
+                               'bottom': $win.innerHeight(),
+                               'right': $win.innerWidth()
+                       }
+               };
+       } else {
+               $el = $( el );
+               return {
+                       'borders': this.getBorders( el ),
+                       'scroll': {
+                               'top': $el.scrollTop(),
+                               'left': $el.scrollLeft()
+                       },
+                       'scrollbar': {
+                               'right': $el.innerWidth() - el.clientWidth,
+                               'bottom': $el.innerHeight() - el.clientHeight
+                       },
+                       'rect': el.getBoundingClientRect()
+               };
+       }
+};
+
+/**
+ * Get closest scrollable container.
+ *
+ * Traverses up until either a scrollable element or the root is reached, in which case the window
+ * will be returned.
+ *
+ * @static
+ * @param {HTMLElement} el Element to find scrollable container for
+ * @param {string} [dimension] Dimension of scrolling to look for; `x`, `y` or omit for either
+ * @return {HTMLElement|Window} Closest scrollable container
+ */
+OO.ui.Element.getClosestScrollableContainer = function ( el, dimension ) {
+       var i, val,
+               props = [ 'overflow' ],
+               $parent = $( el ).parent();
+
+       if ( dimension === 'x' || dimension === 'y' ) {
+               props.push( 'overflow-' + dimension );
+       }
+
+       while ( $parent.length ) {
+               if ( $parent[0] === el.ownerDocument.body ) {
+                       return $parent[0];
+               }
+               i = props.length;
+               while ( i-- ) {
+                       val = $parent.css( props[i] );
+                       if ( val === 'auto' || val === 'scroll' ) {
+                               return $parent[0];
+                       }
+               }
+               $parent = $parent.parent();
+       }
+       return this.getDocument( el ).body;
+};
+
+/**
+ * Scroll element into view.
+ *
+ * @static
+ * @param {HTMLElement} el Element to scroll into view
+ * @param {Object} [config={}] Configuration config
+ * @param {string} [config.duration] jQuery animation duration value
+ * @param {string} [config.direction] Scroll in only one direction, e.g. 'x' or 'y', omit
+ *  to scroll in both directions
+ * @param {Function} [config.complete] Function to call when scrolling completes
+ */
+OO.ui.Element.scrollIntoView = function ( el, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       var anim = {},
+               callback = typeof config.complete === 'function' && config.complete,
+               sc = this.getClosestScrollableContainer( el, config.direction ),
+               $sc = $( sc ),
+               eld = this.getDimensions( el ),
+               scd = this.getDimensions( sc ),
+               rel = {
+                       'top': eld.rect.top - ( scd.rect.top + scd.borders.top ),
+                       'bottom': scd.rect.bottom - scd.borders.bottom - scd.scrollbar.bottom - eld.rect.bottom,
+                       'left': eld.rect.left - ( scd.rect.left + scd.borders.left ),
+                       'right': scd.rect.right - scd.borders.right - scd.scrollbar.right - eld.rect.right
+               };
+
+       if ( !config.direction || config.direction === 'y' ) {
+               if ( rel.top < 0 ) {
+                       anim.scrollTop = scd.scroll.top + rel.top;
+               } else if ( rel.top > 0 && rel.bottom < 0 ) {
+                       anim.scrollTop = scd.scroll.top + Math.min( rel.top, -rel.bottom );
+               }
+       }
+       if ( !config.direction || config.direction === 'x' ) {
+               if ( rel.left < 0 ) {
+                       anim.scrollLeft = scd.scroll.left + rel.left;
+               } else if ( rel.left > 0 && rel.right < 0 ) {
+                       anim.scrollLeft = scd.scroll.left + Math.min( rel.left, -rel.right );
+               }
+       }
+       if ( !$.isEmptyObject( anim ) ) {
+               $sc.stop( true ).animate( anim, config.duration || 'fast' );
+               if ( callback ) {
+                       $sc.queue( function ( next ) {
+                               callback();
+                               next();
+                       } );
+               }
+       } else {
+               if ( callback ) {
+                       callback();
+               }
+       }
+};
+
+/* Methods */
+
+/**
+ * Get the HTML tag name.
+ *
+ * Override this method to base the result on instance information.
+ *
+ * @return {string} HTML tag name
+ */
+OO.ui.Element.prototype.getTagName = function () {
+       return this.constructor.static.tagName;
+};
+
+/**
+ * Check if the element is attached to the DOM
+ * @return {boolean} The element is attached to the DOM
+ */
+OO.ui.Element.prototype.isElementAttached = function () {
+       return $.contains( this.getElementDocument(), this.$element[0] );
+};
+
+/**
+ * Get the DOM document.
+ *
+ * @return {HTMLDocument} Document object
+ */
+OO.ui.Element.prototype.getElementDocument = function () {
+       return OO.ui.Element.getDocument( this.$element );
+};
+
+/**
+ * Get the DOM window.
+ *
+ * @return {Window} Window object
+ */
+OO.ui.Element.prototype.getElementWindow = function () {
+       return OO.ui.Element.getWindow( this.$element );
+};
+
+/**
+ * Get closest scrollable container.
+ *
+ * @see #static-method-getClosestScrollableContainer
+ */
+OO.ui.Element.prototype.getClosestScrollableElementContainer = function () {
+       return OO.ui.Element.getClosestScrollableContainer( this.$element[0] );
+};
+
+/**
+ * Get group element is in.
+ *
+ * @return {OO.ui.GroupElement|null} Group element, null if none
+ */
+OO.ui.Element.prototype.getElementGroup = function () {
+       return this.elementGroup;
+};
+
+/**
+ * Set group element is in.
+ *
+ * @param {OO.ui.GroupElement|null} group Group element, null if none
+ * @chainable
+ */
+OO.ui.Element.prototype.setElementGroup = function ( group ) {
+       this.elementGroup = group;
+       return this;
+};
+
+/**
+ * Scroll element into view.
+ *
+ * @see #static-method-scrollIntoView
+ * @param {Object} [config={}]
+ */
+OO.ui.Element.prototype.scrollElementIntoView = function ( config ) {
+       return OO.ui.Element.scrollIntoView( this.$element[0], config );
+};
+
+( function () {
+       // Static
+       var specialFocusin;
+
+       function handler( e ) {
+               jQuery.event.simulate( 'focusin', e.target, jQuery.event.fix( e ), /* bubble = */ true );
+       }
+
+       specialFocusin = {
+               setup: function () {
+                       var doc = this.ownerDocument || this,
+                               attaches = $.data( doc, 'ooui-focusin-attaches' );
+                       if ( !attaches ) {
+                               doc.addEventListener( 'focus', handler, true );
+                       }
+                       $.data( doc, 'ooui-focusin-attaches', ( attaches || 0 ) + 1 );
+               },
+               teardown: function () {
+                       var doc = this.ownerDocument || this,
+                               attaches = $.data( doc, 'ooui-focusin-attaches' ) - 1;
+                       if ( !attaches ) {
+                               doc.removeEventListener( 'focus', handler, true );
+                               $.removeData( doc, 'ooui-focusin-attaches' );
+                       } else {
+                               $.data( doc, 'ooui-focusin-attaches', attaches );
+                       }
+               }
+       };
+
+       /**
+        * Bind a handler for an event on the DOM element.
+        *
+        * Uses jQuery internally for everything except for events which are
+        * known to have issues in the browser or in jQuery. This method
+        * should become obsolete eventually.
+        *
+        * @param {string} event
+        * @param {Function} callback
+        */
+       OO.ui.Element.prototype.onDOMEvent = function ( event, callback ) {
+               var orig;
+
+               if ( event === 'focusin' ) {
+                       // jQuery 1.8.3 has a bug with handling focusin events inside iframes.
+                       // Firefox doesn't support focusin at all, so we listen for 'focus' on the
+                       // document, and simulate a 'focusin' event on the target element and make
+                       // it bubble from there.
+                       //
+                       // - http://jsfiddle.net/sw3hr/
+                       // - http://bugs.jquery.com/ticket/14180
+                       // - https://github.com/jquery/jquery/commit/1cecf64e5aa4153
+
+                       // Replace jQuery's override with our own
+                       orig = $.event.special.focusin;
+                       $.event.special.focusin = specialFocusin;
+
+                       this.$element.on( event, callback );
+
+                       // Restore
+                       $.event.special.focusin = orig;
+
+               } else {
+                       this.$element.on( event, callback );
+               }
+       };
+
+       /**
+        * @param {string} event
+        * @param {Function} callback
+        */
+       OO.ui.Element.prototype.offDOMEvent = function ( event, callback ) {
+               var orig;
+               if ( event === 'focusin' ) {
+                       orig = $.event.special.focusin;
+                       $.event.special.focusin = specialFocusin;
+                       this.$element.off( event, callback );
+                       $.event.special.focusin = orig;
+               } else {
+                       this.$element.off( event, callback );
+               }
+       };
+}() );
+/**
+ * Embedded iframe with the same styles as its parent.
+ *
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.Frame = function OoUiFrame( config ) {
+       // Parent constructor
+       OO.ui.Frame.super.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Properties
+       this.loading = false;
+       this.loaded = false;
+       this.config = config;
+
+       // Initialize
+       this.$element
+               .addClass( 'oo-ui-frame' )
+               .attr( { 'frameborder': 0, 'scrolling': 'no' } );
+
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Frame, OO.ui.Element );
+OO.mixinClass( OO.ui.Frame, OO.EventEmitter );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.Frame.static.tagName = 'iframe';
+
+/* Events */
+
+/**
+ * @event load
+ */
+
+/* Static Methods */
+
+/**
+ * Transplant the CSS styles from as parent document to a frame's document.
+ *
+ * This loops over the style sheets in the parent document, and copies their nodes to the
+ * frame's document. It then polls the document to see when all styles have loaded, and once they
+ * have, invokes the callback.
+ *
+ * If the styles still haven't loaded after a long time (5 seconds by default), we give up waiting
+ * and invoke the callback anyway. This protects against cases like a display: none; iframe in
+ * Firefox, where the styles won't load until the iframe becomes visible.
+ *
+ * For details of how we arrived at the strategy used in this function, see #load.
+ *
+ * @static
+ * @inheritable
+ * @param {HTMLDocument} parentDoc Document to transplant styles from
+ * @param {HTMLDocument} frameDoc Document to transplant styles to
+ * @param {Function} [callback] Callback to execute once styles have loaded
+ * @param {number} [timeout=5000] How long to wait before giving up (in ms). If 0, never give up.
+ */
+OO.ui.Frame.static.transplantStyles = function ( parentDoc, frameDoc, callback, timeout ) {
+       var i, numSheets, styleNode, newNode, timeoutID, pollNodeId, $pendingPollNodes,
+               $pollNodes = $( [] ),
+               // Fake font-family value
+               fontFamily = 'oo-ui-frame-transplantStyles-loaded';
+
+       for ( i = 0, numSheets = parentDoc.styleSheets.length; i < numSheets; i++ ) {
+               styleNode = parentDoc.styleSheets[i].ownerNode;
+               if ( callback && styleNode.nodeName.toLowerCase() === 'link' ) {
+                       // External stylesheet
+                       // Create a node with a unique ID that we're going to monitor to see when the CSS
+                       // has loaded
+                       pollNodeId = 'oo-ui-frame-transplantStyles-loaded-' + i;
+                       $pollNodes = $pollNodes.add( $( '<div>', frameDoc )
+                               .attr( 'id', pollNodeId )
+                               .appendTo( frameDoc.body )
+                       );
+
+                       // Add <style>@import url(...); #pollNodeId { font-family: ... }</style>
+                       // The font-family rule will only take effect once the @import finishes
+                       newNode = frameDoc.createElement( 'style' );
+                       newNode.textContent = '@import url(' + styleNode.href + ');\n' +
+                               '#' + pollNodeId + ' { font-family: ' + fontFamily + '; }';
+               } else {
+                       // Not an external stylesheet, or no polling required; just copy the node over
+                       newNode = frameDoc.importNode( styleNode, true );
+               }
+               frameDoc.head.appendChild( newNode );
+       }
+
+       if ( callback ) {
+               // Poll every 100ms until all external stylesheets have loaded
+               $pendingPollNodes = $pollNodes;
+               timeoutID = setTimeout( function pollExternalStylesheets() {
+                       while (
+                               $pendingPollNodes.length > 0 &&
+                               $pendingPollNodes.eq( 0 ).css( 'font-family' ) === fontFamily
+                       ) {
+                               $pendingPollNodes = $pendingPollNodes.slice( 1 );
+                       }
+
+                       if ( $pendingPollNodes.length === 0 ) {
+                               // We're done!
+                               if ( timeoutID !== null ) {
+                                       timeoutID = null;
+                                       $pollNodes.remove();
+                                       callback();
+                               }
+                       } else {
+                               timeoutID = setTimeout( pollExternalStylesheets, 100 );
+                       }
+               }, 100 );
+               // ...but give up after a while
+               if ( timeout !== 0 ) {
+                       setTimeout( function () {
+                               if ( timeoutID ) {
+                                       clearTimeout( timeoutID );
+                                       timeoutID = null;
+                                       $pollNodes.remove();
+                                       callback();
+                               }
+                       }, timeout || 5000 );
+               }
+       }
+};
+
+/* Methods */
+
+/**
+ * Load the frame contents.
+ *
+ * Once the iframe's stylesheets are loaded, the `initialize` event will be emitted.
+ *
+ * Sounds simple right? Read on...
+ *
+ * When you create a dynamic iframe using open/write/close, the window.load event for the
+ * iframe is triggered when you call close, and there's no further load event to indicate that
+ * everything is actually loaded.
+ *
+ * In Chrome, stylesheets don't show up in document.styleSheets until they have loaded, so we could
+ * just poll that array and wait for it to have the right length. However, in Firefox, stylesheets
+ * are added to document.styleSheets immediately, and the only way you can determine whether they've
+ * loaded is to attempt to access .cssRules and wait for that to stop throwing an exception. But
+ * cross-domain stylesheets never allow .cssRules to be accessed even after they have loaded.
+ *
+ * The workaround is to change all `<link href="...">` tags to `<style>@import url(...)</style>` tags.
+ * Because `@import` is blocking, Chrome won't add the stylesheet to document.styleSheets until
+ * the `@import` has finished, and Firefox won't allow .cssRules to be accessed until the `@import`
+ * has finished. And because the contents of the `<style>` tag are from the same origin, accessing
+ * .cssRules is allowed.
+ *
+ * However, now that we control the styles we're injecting, we might as well do away with
+ * browser-specific polling hacks like document.styleSheets and .cssRules, and instead inject
+ * `<style>@import url(...); #foo { font-family: someValue; }</style>`, then create `<div id="foo">`
+ * and wait for its font-family to change to someValue. Because `@import` is blocking, the font-family
+ * rule is not applied until after the `@import` finishes.
+ *
+ * All this stylesheet injection and polling magic is in #transplantStyles.
+ *
+ * @private
+ * @fires load
+ */
+OO.ui.Frame.prototype.load = function () {
+       var win = this.$element.prop( 'contentWindow' ),
+               doc = win.document,
+               frame = this;
+
+       this.loading = true;
+
+       // Figure out directionality:
+       this.dir = this.$element.closest( '[dir]' ).prop( 'dir' ) || 'ltr';
+
+       // Initialize contents
+       doc.open();
+       doc.write(
+               '<!doctype html>' +
+               '<html>' +
+                       '<body class="oo-ui-frame-body oo-ui-' + this.dir + '" style="direction:' + this.dir + ';" dir="' + this.dir + '">' +
+                               '<div class="oo-ui-frame-content"></div>' +
+                       '</body>' +
+               '</html>'
+       );
+       doc.close();
+
+       // Properties
+       this.$ = OO.ui.Element.getJQuery( doc, this );
+       this.$content = this.$( '.oo-ui-frame-content' );
+       this.$document = this.$( doc );
+
+       this.constructor.static.transplantStyles(
+               this.getElementDocument(),
+               this.$document[0],
+               function () {
+                       frame.loading = false;
+                       frame.loaded = true;
+                       frame.emit( 'load' );
+               }
+       );
+};
+
+/**
+ * Run a callback as soon as the frame has been loaded.
+ *
+ *
+ * This will start loading if it hasn't already, and runs
+ * immediately if the frame is already loaded.
+ *
+ * Don't call this until the element is attached.
+ *
+ * @param {Function} callback
+ */
+OO.ui.Frame.prototype.run = function ( callback ) {
+       if ( this.loaded ) {
+               callback();
+       } else {
+               if ( !this.loading ) {
+                       this.load();
+               }
+               this.once( 'load', callback );
+       }
+};
+
+/**
+ * Sets the size of the frame.
+ *
+ * @param {number} width Frame width in pixels
+ * @param {number} height Frame height in pixels
+ * @chainable
+ */
+OO.ui.Frame.prototype.setSize = function ( width, height ) {
+       this.$element.css( { 'width': width, 'height': height } );
+       return this;
+};
+/**
+ * Container for elements in a child frame.
+ *
+ * There are two ways to specify a title: set the static `title` property or provide a `title`
+ * property in the configuration options. The latter will override the former.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string|Function} [title] Title string or function that returns a string
+ * @cfg {string} [icon] Symbolic name of icon
+ * @fires initialize
+ */
+OO.ui.Window = function OoUiWindow( config ) {
+       // Parent constructor
+       OO.ui.Window.super.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Properties
+       this.visible = false;
+       this.opening = false;
+       this.closing = false;
+       this.title = OO.ui.resolveMsg( config.title || this.constructor.static.title );
+       this.icon = config.icon || this.constructor.static.icon;
+       this.frame = new OO.ui.Frame( { '$': this.$ } );
+       this.$frame = this.$( '<div>' );
+       this.$ = function () {
+               throw new Error( 'this.$() cannot be used until the frame has been initialized.' );
+       };
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-window' )
+               // Hide the window using visibility: hidden; while the iframe is still loading
+               // Can't use display: none; because that prevents the iframe from loading in Firefox
+               .css( 'visibility', 'hidden' )
+               .append( this.$frame );
+       this.$frame
+               .addClass( 'oo-ui-window-frame' )
+               .append( this.frame.$element );
+
+       // Events
+       this.frame.connect( this, { 'load': 'initialize' } );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Window, OO.ui.Element );
+OO.mixinClass( OO.ui.Window, OO.EventEmitter );
+
+/* Events */
+
+/**
+ * Initialize contents.
+ *
+ * Fired asynchronously after construction when iframe is ready.
+ *
+ * @event initialize
+ */
+
+/**
+ * Open window.
+ *
+ * Fired after window has been opened.
+ *
+ * @event open
+ * @param {Object} data Window opening data
+ */
+
+/**
+ * Close window.
+ *
+ * Fired after window has been closed.
+ *
+ * @event close
+ * @param {Object} data Window closing data
+ */
+
+/* Static Properties */
+
+/**
+ * Symbolic name of icon.
+ *
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.Window.static.icon = 'window';
+
+/**
+ * Window title.
+ *
+ * Subclasses must implement this property before instantiating the window.
+ * Alternatively, override #getTitle with an alternative implementation.
+ *
+ * @static
+ * @abstract
+ * @inheritable
+ * @property {string|Function} Title string or function that returns a string
+ */
+OO.ui.Window.static.title = null;
+
+/* Methods */
+
+/**
+ * Check if window is visible.
+ *
+ * @return {boolean} Window is visible
+ */
+OO.ui.Window.prototype.isVisible = function () {
+       return this.visible;
+};
+
+/**
+ * Check if window is opening.
+ *
+ * @return {boolean} Window is opening
+ */
+OO.ui.Window.prototype.isOpening = function () {
+       return this.opening;
+};
+
+/**
+ * Check if window is closing.
+ *
+ * @return {boolean} Window is closing
+ */
+OO.ui.Window.prototype.isClosing = function () {
+       return this.closing;
+};
+
+/**
+ * Get the window frame.
+ *
+ * @return {OO.ui.Frame} Frame of window
+ */
+OO.ui.Window.prototype.getFrame = function () {
+       return this.frame;
+};
+
+/**
+ * Get the title of the window.
+ *
+ * @return {string} Title text
+ */
+OO.ui.Window.prototype.getTitle = function () {
+       return this.title;
+};
+
+/**
+ * Get the window icon.
+ *
+ * @return {string} Symbolic name of icon
+ */
+OO.ui.Window.prototype.getIcon = function () {
+       return this.icon;
+};
+
+/**
+ * Set the size of window frame.
+ *
+ * @param {number} [width=auto] Custom width
+ * @param {number} [height=auto] Custom height
+ * @chainable
+ */
+OO.ui.Window.prototype.setSize = function ( width, height ) {
+       if ( !this.frame.$content ) {
+               return;
+       }
+
+       this.frame.$element.css( {
+               'width': width === undefined ? 'auto' : width,
+               'height': height === undefined ? 'auto' : height
+       } );
+
+       return this;
+};
+
+/**
+ * Set the title of the window.
+ *
+ * @param {string|Function} title Title text or a function that returns text
+ * @chainable
+ */
+OO.ui.Window.prototype.setTitle = function ( title ) {
+       this.title = OO.ui.resolveMsg( title );
+       if ( this.$title ) {
+               this.$title.text( title );
+       }
+       return this;
+};
+
+/**
+ * Set the icon of the window.
+ *
+ * @param {string} icon Symbolic name of icon
+ * @chainable
+ */
+OO.ui.Window.prototype.setIcon = function ( icon ) {
+       if ( this.$icon ) {
+               this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
+       }
+       this.icon = icon;
+       if ( this.$icon ) {
+               this.$icon.addClass( 'oo-ui-icon-' + this.icon );
+       }
+
+       return this;
+};
+
+/**
+ * Set the position of window to fit with contents.
+ *
+ * @param {string} left Left offset
+ * @param {string} top Top offset
+ * @chainable
+ */
+OO.ui.Window.prototype.setPosition = function ( left, top ) {
+       this.$element.css( { 'left': left, 'top': top } );
+       return this;
+};
+
+/**
+ * Set the height of window to fit with contents.
+ *
+ * @param {number} [min=0] Min height
+ * @param {number} [max] Max height (defaults to content's outer height)
+ * @chainable
+ */
+OO.ui.Window.prototype.fitHeightToContents = function ( min, max ) {
+       var height = this.frame.$content.outerHeight();
+
+       this.frame.$element.css(
+               'height', Math.max( min || 0, max === undefined ? height : Math.min( max, height ) )
+       );
+
+       return this;
+};
+
+/**
+ * Set the width of window to fit with contents.
+ *
+ * @param {number} [min=0] Min height
+ * @param {number} [max] Max height (defaults to content's outer width)
+ * @chainable
+ */
+OO.ui.Window.prototype.fitWidthToContents = function ( min, max ) {
+       var width = this.frame.$content.outerWidth();
+
+       this.frame.$element.css(
+               'width', Math.max( min || 0, max === undefined ? width : Math.min( max, width ) )
+       );
+
+       return this;
+};
+
+/**
+ * Initialize window contents.
+ *
+ * The first time the window is opened, #initialize is called when it's safe to begin populating
+ * its contents. See #setup for a way to make changes each time the window opens.
+ *
+ * Once this method is called, this.$$ can be used to create elements within the frame.
+ *
+ * @fires initialize
+ * @chainable
+ */
+OO.ui.Window.prototype.initialize = function () {
+       // Properties
+       this.$ = this.frame.$;
+       this.$title = this.$( '<div class="oo-ui-window-title"></div>' )
+               .text( this.title );
+       this.$icon = this.$( '<div class="oo-ui-window-icon"></div>' )
+               .addClass( 'oo-ui-icon-' + this.icon );
+       this.$head = this.$( '<div class="oo-ui-window-head"></div>' );
+       this.$body = this.$( '<div class="oo-ui-window-body"></div>' );
+       this.$foot = this.$( '<div class="oo-ui-window-foot"></div>' );
+       this.$overlay = this.$( '<div class="oo-ui-window-overlay"></div>' );
+
+       // Initialization
+       this.frame.$content.append(
+               this.$head.append( this.$icon, this.$title ),
+               this.$body,
+               this.$foot,
+               this.$overlay
+       );
+
+       // Undo the visibility: hidden; hack from the constructor and apply display: none;
+       // We can do this safely now that the iframe has initialized
+       this.$element.hide().css( 'visibility', '' );
+
+       this.emit( 'initialize' );
+
+       return this;
+};
+
+/**
+ * Setup window for use.
+ *
+ * Each time the window is opened, once it's ready to be interacted with, this will set it up for
+ * use in a particular context, based on the `data` argument.
+ *
+ * When you override this method, you must call the parent method at the very beginning.
+ *
+ * @abstract
+ * @param {Object} [data] Window opening data
+ */
+OO.ui.Window.prototype.setup = function () {
+       // Override to do something
+};
+
+/**
+ * Tear down window after use.
+ *
+ * Each time the window is closed, and it's done being interacted with, this will tear it down and
+ * do something with the user's interactions within the window, based on the `data` argument.
+ *
+ * When you override this method, you must call the parent method at the very end.
+ *
+ * @abstract
+ * @param {Object} [data] Window closing data
+ */
+OO.ui.Window.prototype.teardown = function () {
+       // Override to do something
+};
+
+/**
+ * Open window.
+ *
+ * Do not override this method. See #setup for a way to make changes each time the window opens.
+ *
+ * @param {Object} [data] Window opening data
+ * @fires open
+ * @chainable
+ */
+OO.ui.Window.prototype.open = function ( data ) {
+       if ( !this.opening && !this.closing && !this.visible ) {
+               this.opening = true;
+               this.frame.run( OO.ui.bind( function () {
+                       this.$element.show();
+                       this.visible = true;
+                       this.frame.$element.focus();
+                       this.emit( 'opening', data );
+                       this.setup( data );
+                       this.emit( 'open', data );
+                       this.opening = false;
+               }, this ) );
+       }
+
+       return this;
+};
+
+/**
+ * Close window.
+ *
+ * See #teardown for a way to do something each time the window closes.
+ *
+ * @param {Object} [data] Window closing data
+ * @fires close
+ * @chainable
+ */
+OO.ui.Window.prototype.close = function ( data ) {
+       if ( !this.opening && !this.closing && this.visible ) {
+               this.frame.$content.find( ':focus' ).blur();
+               this.closing = true;
+               this.$element.hide();
+               this.visible = false;
+               this.emit( 'closing', data );
+               this.teardown( data );
+               this.emit( 'close', data );
+               this.closing = false;
+       }
+
+       return this;
+};
+/**
+ * Set of mutually exclusive windows.
+ *
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {OO.Factory} factory Window factory
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.WindowSet = function OoUiWindowSet( factory, config ) {
+       // Parent constructor
+       OO.ui.WindowSet.super.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Properties
+       this.factory = factory;
+
+       /**
+        * List of all windows associated with this window set.
+        *
+        * @property {OO.ui.Window[]}
+        */
+       this.windowList = [];
+
+       /**
+        * Mapping of OO.ui.Window objects created by name from the #factory.
+        *
+        * @property {Object}
+        */
+       this.windows = {};
+       this.currentWindow = null;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-windowSet' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.WindowSet, OO.ui.Element );
+OO.mixinClass( OO.ui.WindowSet, OO.EventEmitter );
+
+/* Events */
+
+/**
+ * @event opening
+ * @param {OO.ui.Window} win Window that's being opened
+ * @param {Object} config Window opening information
+ */
+
+/**
+ * @event open
+ * @param {OO.ui.Window} win Window that's been opened
+ * @param {Object} config Window opening information
+ */
+
+/**
+ * @event closing
+ * @param {OO.ui.Window} win Window that's being closed
+ * @param {Object} config Window closing information
+ */
+
+/**
+ * @event close
+ * @param {OO.ui.Window} win Window that's been closed
+ * @param {Object} config Window closing information
+ */
+
+/* Methods */
+
+/**
+ * Handle a window that's being opened.
+ *
+ * @param {OO.ui.Window} win Window that's being opened
+ * @param {Object} [config] Window opening information
+ * @fires opening
+ */
+OO.ui.WindowSet.prototype.onWindowOpening = function ( win, config ) {
+       if ( this.currentWindow && this.currentWindow !== win ) {
+               this.currentWindow.close();
+       }
+       this.currentWindow = win;
+       this.emit( 'opening', win, config );
+};
+
+/**
+ * Handle a window that's been opened.
+ *
+ * @param {OO.ui.Window} win Window that's been opened
+ * @param {Object} [config] Window opening information
+ * @fires open
+ */
+OO.ui.WindowSet.prototype.onWindowOpen = function ( win, config ) {
+       this.emit( 'open', win, config );
+};
+
+/**
+ * Handle a window that's being closed.
+ *
+ * @param {OO.ui.Window} win Window that's being closed
+ * @param {Object} [config] Window closing information
+ * @fires closing
+ */
+OO.ui.WindowSet.prototype.onWindowClosing = function ( win, config ) {
+       this.currentWindow = null;
+       this.emit( 'closing', win, config );
+};
+
+/**
+ * Handle a window that's been closed.
+ *
+ * @param {OO.ui.Window} win Window that's been closed
+ * @param {Object} [config] Window closing information
+ * @fires close
+ */
+OO.ui.WindowSet.prototype.onWindowClose = function ( win, config ) {
+       this.emit( 'close', win, config );
+};
+
+/**
+ * Get the current window.
+ *
+ * @return {OO.ui.Window} Current window
+ */
+OO.ui.WindowSet.prototype.getCurrentWindow = function () {
+       return this.currentWindow;
+};
+
+/**
+ * Return a given window.
+ *
+ * @param {string} name Symbolic name of window
+ * @return {OO.ui.Window} Window with specified name
+ */
+OO.ui.WindowSet.prototype.getWindow = function ( name ) {
+       var win;
+
+       if ( !this.factory.lookup( name ) ) {
+               throw new Error( 'Unknown window: ' + name );
+       }
+       if ( !( name in this.windows ) ) {
+               win = this.windows[name] = this.createWindow( name );
+               this.addWindow( win );
+       }
+       return this.windows[name];
+};
+
+/**
+ * Create a window for use in this window set.
+ *
+ * @param {string} name Symbolic name of window
+ * @return {OO.ui.Window} Window with specified name
+ */
+OO.ui.WindowSet.prototype.createWindow = function ( name ) {
+       return this.factory.create( name, { '$': this.$ } );
+};
+
+/**
+ * Add a given window to this window set.
+ *
+ * Connects event handlers and attaches it to the DOM. Calling
+ * OO.ui.Window#open will not work until the window is added to the set.
+ *
+ * @param {OO.ui.Window} win
+ */
+OO.ui.WindowSet.prototype.addWindow = function ( win ) {
+       if ( this.windowList.indexOf( win ) !== -1 ) {
+               // Already set up
+               return;
+       }
+       this.windowList.push( win );
+
+       win.connect( this, {
+               'opening': [ 'onWindowOpening', win ],
+               'open': [ 'onWindowOpen', win ],
+               'closing': [ 'onWindowClosing', win ],
+               'close': [ 'onWindowClose', win ]
+       } );
+       this.$element.append( win.$element );
+};
+/**
+ * @abstract
+ * @class
+ * @extends OO.ui.Window
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [footless] Hide foot
+ * @cfg {string} [size='large'] Symbolic name of dialog size, `small`, `medium` or `large`
+ */
+OO.ui.Dialog = function OoUiDialog( config ) {
+       // Configuration initialization
+       config = $.extend( { 'size': 'large' }, config );
+
+       // Parent constructor
+       OO.ui.Dialog.super.call( this, config );
+
+       // Properties
+       this.visible = false;
+       this.footless = !!config.footless;
+       this.size = null;
+       this.onWindowMouseWheelHandler = OO.ui.bind( this.onWindowMouseWheel, this );
+       this.onDocumentKeyDownHandler = OO.ui.bind( this.onDocumentKeyDown, this );
+
+       // Events
+       this.$element.on( 'mousedown', false );
+       this.connect( this, { 'opening': 'onOpening' } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-dialog' );
+       this.setSize( config.size );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Dialog, OO.ui.Window );
+
+/* Static Properties */
+
+/**
+ * Symbolic name of dialog.
+ *
+ * @abstract
+ * @static
+ * @property {string}
+ * @inheritable
+ */
+OO.ui.Dialog.static.name = '';
+
+/**
+ * Map of symbolic size names and CSS classes.
+ *
+ * @static
+ * @property {Object}
+ * @inheritable
+ */
+OO.ui.Dialog.static.sizeCssClasses = {
+       'small': 'oo-ui-dialog-small',
+       'medium': 'oo-ui-dialog-medium',
+       'large': 'oo-ui-dialog-large'
+};
+
+/* Methods */
+
+/**
+ * Handle close button click events.
+ */
+OO.ui.Dialog.prototype.onCloseButtonClick = function () {
+       this.close( { 'action': 'cancel' } );
+};
+
+/**
+ * Handle window mouse wheel events.
+ *
+ * @param {jQuery.Event} e Mouse wheel event
+ */
+OO.ui.Dialog.prototype.onWindowMouseWheel = function () {
+       return false;
+};
+
+/**
+ * Handle document key down events.
+ *
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.Dialog.prototype.onDocumentKeyDown = function ( e ) {
+       switch ( e.which ) {
+               case OO.ui.Keys.PAGEUP:
+               case OO.ui.Keys.PAGEDOWN:
+               case OO.ui.Keys.END:
+               case OO.ui.Keys.HOME:
+               case OO.ui.Keys.LEFT:
+               case OO.ui.Keys.UP:
+               case OO.ui.Keys.RIGHT:
+               case OO.ui.Keys.DOWN:
+                       // Prevent any key events that might cause scrolling
+                       return false;
+       }
+};
+
+/**
+ * Handle frame document key down events.
+ *
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.Dialog.prototype.onFrameDocumentKeyDown = function ( e ) {
+       if ( e.which === OO.ui.Keys.ESCAPE ) {
+               this.close( { 'action': 'cancel' } );
+               return false;
+       }
+};
+
+/** */
+OO.ui.Dialog.prototype.onOpening = function () {
+       this.$element.addClass( 'oo-ui-dialog-open' );
+};
+
+/**
+ * Set dialog size.
+ *
+ * @param {string} [size='large'] Symbolic name of dialog size, `small`, `medium` or `large`
+ */
+OO.ui.Dialog.prototype.setSize = function ( size ) {
+       var name, state, cssClass,
+               sizeCssClasses = OO.ui.Dialog.static.sizeCssClasses;
+
+       if ( !sizeCssClasses[size] ) {
+               size = 'large';
+       }
+       this.size = size;
+       for ( name in sizeCssClasses ) {
+               state = name === size;
+               cssClass = sizeCssClasses[name];
+               this.$element.toggleClass( cssClass, state );
+               if ( this.frame.$content ) {
+                       this.frame.$content.toggleClass( cssClass, state );
+               }
+       }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.Dialog.prototype.initialize = function () {
+       // Parent method
+       OO.ui.Window.prototype.initialize.call( this );
+
+       // Properties
+       this.closeButton = new OO.ui.ButtonWidget( {
+               '$': this.$,
+               'frameless': true,
+               'icon': 'close',
+               'title': OO.ui.msg( 'ooui-dialog-action-close' )
+       } );
+
+       // Events
+       this.closeButton.connect( this, { 'click': 'onCloseButtonClick' } );
+       this.frame.$document.on( 'keydown', OO.ui.bind( this.onFrameDocumentKeyDown, this ) );
+
+       // Initialization
+       this.frame.$content.addClass( 'oo-ui-dialog-content' );
+       if ( this.footless ) {
+               this.frame.$content.addClass( 'oo-ui-dialog-content-footless' );
+       }
+       this.closeButton.$element.addClass( 'oo-ui-window-closeButton' );
+       this.$head.append( this.closeButton.$element );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.Dialog.prototype.setup = function ( data ) {
+       // Parent method
+       OO.ui.Window.prototype.setup.call( this, data );
+
+       // Prevent scrolling in top-level window
+       this.$( window ).on( 'mousewheel', this.onWindowMouseWheelHandler );
+       this.$( document ).on( 'keydown', this.onDocumentKeyDownHandler );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.Dialog.prototype.teardown = function ( data ) {
+       // Parent method
+       OO.ui.Window.prototype.teardown.call( this, data );
+
+       // Allow scrolling in top-level window
+       this.$( window ).off( 'mousewheel', this.onWindowMouseWheelHandler );
+       this.$( document ).off( 'keydown', this.onDocumentKeyDownHandler );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.Dialog.prototype.close = function ( data ) {
+       var dialog = this;
+       if ( !dialog.opening && !dialog.closing && dialog.visible ) {
+               // Trigger transition
+               dialog.$element.removeClass( 'oo-ui-dialog-open' );
+               // Allow transition to complete before actually closing
+               setTimeout( function () {
+                       // Parent method
+                       OO.ui.Window.prototype.close.call( dialog, data );
+               }, 250 );
+       }
+};
+/**
+ * Container for elements.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.Layout = function OoUiLayout( config ) {
+       // Initialize config
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Layout.super.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-layout' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Layout, OO.ui.Element );
+OO.mixinClass( OO.ui.Layout, OO.EventEmitter );
+/**
+ * User interface control.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [disabled=false] Disable
+ */
+OO.ui.Widget = function OoUiWidget( config ) {
+       // Initialize config
+       config = $.extend( { 'disabled': false }, config );
+
+       // Parent constructor
+       OO.ui.Widget.super.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Properties
+       this.disabled = null;
+       this.wasDisabled = null;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-widget' );
+       this.setDisabled( !!config.disabled );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Widget, OO.ui.Element );
+OO.mixinClass( OO.ui.Widget, OO.EventEmitter );
+
+/* Events */
+
+/**
+ * @event disable
+ * @param {boolean} disabled Widget is disabled
+ */
+
+/* Methods */
+
+/**
+ * Check if the widget is disabled.
+ *
+ * @param {boolean} Button is disabled
+ */
+OO.ui.Widget.prototype.isDisabled = function () {
+       return this.disabled;
+};
+
+/**
+ * Update the disabled state, in case of changes in parent widget.
+ *
+ * @chainable
+ */
+OO.ui.Widget.prototype.updateDisabled = function () {
+       this.setDisabled( this.disabled );
+       return this;
+};
+
+/**
+ * Set the disabled state of the widget.
+ *
+ * This should probably change the widgets' appearance and prevent it from being used.
+ *
+ * @param {boolean} disabled Disable widget
+ * @chainable
+ */
+OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
+       var isDisabled;
+
+       this.disabled = !!disabled;
+       isDisabled = this.isDisabled();
+       if ( isDisabled !== this.wasDisabled ) {
+               this.$element.toggleClass( 'oo-ui-widget-disabled', isDisabled );
+               this.$element.toggleClass( 'oo-ui-widget-enabled', !isDisabled );
+               this.emit( 'disable', isDisabled );
+       }
+       this.wasDisabled = isDisabled;
+       return this;
+};
+/**
+ * Element with a button.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $button Button node, assigned to #$button
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [frameless] Render button without a frame
+ * @cfg {number} [tabIndex=0] Button's tab index, use -1 to prevent tab focusing
+ */
+OO.ui.ButtonedElement = function OoUiButtonedElement( $button, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Properties
+       this.$button = $button;
+       this.tabIndex = null;
+       this.active = false;
+       this.onMouseUpHandler = OO.ui.bind( this.onMouseUp, this );
+
+       // Events
+       this.$button.on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-buttonedElement' );
+       this.$button
+               .addClass( 'oo-ui-buttonedElement-button' )
+               .attr( 'role', 'button' )
+               .prop( 'tabIndex', config.tabIndex || 0 );
+       if ( config.frameless ) {
+               this.$element.addClass( 'oo-ui-buttonedElement-frameless' );
+       } else {
+               this.$element.addClass( 'oo-ui-buttonedElement-framed' );
+       }
+};
+
+/* Methods */
+
+/**
+ * Handles mouse down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.ButtonedElement.prototype.onMouseDown = function () {
+       this.tabIndex = this.$button.attr( 'tabIndex' );
+       // Remove the tab-index while the button is down to prevent the button from stealing focus
+       this.$button
+               .removeAttr( 'tabIndex' )
+               .addClass( 'oo-ui-buttonedElement-pressed' );
+       this.getElementDocument().addEventListener( 'mouseup', this.onMouseUpHandler, true );
+};
+
+/**
+ * Handles mouse up events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse up event
+ */
+OO.ui.ButtonedElement.prototype.onMouseUp = function () {
+       // Restore the tab-index after the button is up to restore the button's accesssibility
+       this.$button
+               .attr( 'tabIndex', this.tabIndex )
+               .removeClass( 'oo-ui-buttonedElement-pressed' );
+       this.getElementDocument().removeEventListener( 'mouseup', this.onMouseUpHandler, true );
+};
+
+/**
+ * Set active state.
+ *
+ * @method
+ * @param {boolean} [value] Make button active
+ * @chainable
+ */
+OO.ui.ButtonedElement.prototype.setActive = function ( value ) {
+       this.$button.toggleClass( 'oo-ui-buttonedElement-active', !!value );
+       return this;
+};
+/**
+ * Element that can be automatically clipped to visible boundaies.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $clippable Nodes to clip, assigned to #$clippable
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ClippableElement = function OoUiClippableElement( $clippable, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Properties
+       this.$clippable = $clippable;
+       this.clipping = false;
+       this.clipped = false;
+       this.$clippableContainer = null;
+       this.$clippableScroller = null;
+       this.$clippableWindow = null;
+       this.idealWidth = null;
+       this.idealHeight = null;
+       this.onClippableContainerScrollHandler = OO.ui.bind( this.clip, this );
+       this.onClippableWindowResizeHandler = OO.ui.bind( this.clip, this );
+
+       // Initialization
+       this.$clippable.addClass( 'oo-ui-clippableElement-clippable' );
+};
+
+/* Methods */
+
+/**
+ * Set clipping.
+ *
+ * @method
+ * @param {boolean} value Enable clipping
+ * @chainable
+ */
+OO.ui.ClippableElement.prototype.setClipping = function ( value ) {
+       value = !!value;
+
+       if ( this.clipping !== value ) {
+               this.clipping = value;
+               if ( this.clipping ) {
+                       this.$clippableContainer = this.$( this.getClosestScrollableElementContainer() );
+                       // If the clippable container is the body, we have to listen to scroll events and check
+                       // jQuery.scrollTop on the window because of browser inconsistencies
+                       this.$clippableScroller = this.$clippableContainer.is( 'body' ) ?
+                               this.$( OO.ui.Element.getWindow( this.$clippableContainer ) ) :
+                               this.$clippableContainer;
+                       this.$clippableScroller.on( 'scroll', this.onClippableContainerScrollHandler );
+                       this.$clippableWindow = this.$( this.getElementWindow() )
+                               .on( 'resize', this.onClippableWindowResizeHandler );
+                       // Initial clip after visible
+                       setTimeout( OO.ui.bind( this.clip, this ) );
+               } else {
+                       this.$clippableContainer = null;
+                       this.$clippableScroller.off( 'scroll', this.onClippableContainerScrollHandler );
+                       this.$clippableScroller = null;
+                       this.$clippableWindow.off( 'resize', this.onClippableWindowResizeHandler );
+                       this.$clippableWindow = null;
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Check if the element will be clipped to fit the visible area of the nearest scrollable container.
+ *
+ * @method
+ * @return {boolean} Element will be clipped to the visible area
+ */
+OO.ui.ClippableElement.prototype.isClipping = function () {
+       return this.clipping;
+};
+
+/**
+ * Check if the bottom or right of the element is being clipped by the nearest scrollable container.
+ *
+ * @method
+ * @return {boolean} Part of the element is being clipped
+ */
+OO.ui.ClippableElement.prototype.isClipped = function () {
+       return this.clipped;
+};
+
+/**
+ * Set the ideal size.
+ *
+ * @method
+ * @param {number|string} [width] Width as a number of pixels or CSS string with unit suffix
+ * @param {number|string} [height] Height as a number of pixels or CSS string with unit suffix
+ */
+OO.ui.ClippableElement.prototype.setIdealSize = function ( width, height ) {
+       this.idealWidth = width;
+       this.idealHeight = height;
+};
+
+/**
+ * Clip element to visible boundaries and allow scrolling when needed.
+ *
+ * Element will be clipped the bottom or right of the element is within 10px of the edge of, or
+ * overlapped by, the visible area of the nearest scrollable container.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.ClippableElement.prototype.clip = function () {
+       if ( !this.clipping ) {
+               // this.$clippableContainer and this.$clippableWindow are null, so the below will fail
+               return this;
+       }
+
+       var buffer = 10,
+               cOffset = this.$clippable.offset(),
+               ccOffset = this.$clippableContainer.offset() || { 'top': 0, 'left': 0 },
+               ccHeight = this.$clippableContainer.innerHeight() - buffer,
+               ccWidth = this.$clippableContainer.innerWidth() - buffer,
+               scrollTop = this.$clippableScroller.scrollTop(),
+               scrollLeft = this.$clippableScroller.scrollLeft(),
+               desiredWidth = ( ccOffset.left + scrollLeft + ccWidth ) - cOffset.left,
+               desiredHeight = ( ccOffset.top + scrollTop + ccHeight ) - cOffset.top,
+               naturalWidth = this.$clippable.prop( 'scrollWidth' ),
+               naturalHeight = this.$clippable.prop( 'scrollHeight' ),
+               clipWidth = desiredWidth < naturalWidth,
+               clipHeight = desiredHeight < naturalHeight;
+
+       if ( clipWidth ) {
+               this.$clippable.css( { 'overflow-x': 'auto', 'width': desiredWidth } );
+       } else {
+               this.$clippable.css( { 'overflow-x': '', 'width': this.idealWidth || '' } );
+       }
+       if ( clipHeight ) {
+               this.$clippable.css( { 'overflow-y': 'auto', 'height': desiredHeight } );
+       } else {
+               this.$clippable.css( { 'overflow-y': '', 'height': this.idealHeight || '' } );
+       }
+
+       this.clipped = clipWidth || clipHeight;
+
+       return this;
+};
+/**
+ * Element with named flags, used for styling, that can be added, removed and listed and checked.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string[]} [flags=[]] Styling flags, e.g. 'primary', 'destructive' or 'constructive'
+ */
+OO.ui.FlaggableElement = function OoUiFlaggableElement( config ) {
+       // Config initialization
+       config = config || {};
+
+       // Properties
+       this.flags = {};
+
+       // Initialization
+       this.setFlags( config.flags );
+};
+
+/* Methods */
+
+/**
+ * Check if a flag is set.
+ *
+ * @method
+ * @param {string} flag Flag name to check
+ * @returns {boolean} Has flag
+ */
+OO.ui.FlaggableElement.prototype.hasFlag = function ( flag ) {
+       return flag in this.flags;
+};
+
+/**
+ * Get the names of all flags.
+ *
+ * @method
+ * @returns {string[]} flags Flag names
+ */
+OO.ui.FlaggableElement.prototype.getFlags = function () {
+       return Object.keys( this.flags );
+};
+
+/**
+ * Add one or more flags.
+ *
+ * @method
+ * @param {string[]|Object.<string, boolean>} flags List of flags to add, or list of set/remove
+ *  values, keyed by flag name
+ * @chainable
+ */
+OO.ui.FlaggableElement.prototype.setFlags = function ( flags ) {
+       var i, len, flag,
+               classPrefix = 'oo-ui-flaggableElement-';
+
+       if ( $.isArray( flags ) ) {
+               for ( i = 0, len = flags.length; i < len; i++ ) {
+                       flag = flags[i];
+                       // Set
+                       this.flags[flag] = true;
+                       this.$element.addClass( classPrefix + flag );
+               }
+       } else if ( OO.isPlainObject( flags ) ) {
+               for ( flag in flags ) {
+                       if ( flags[flag] ) {
+                               // Set
+                               this.flags[flag] = true;
+                               this.$element.addClass( classPrefix + flag );
+                       } else {
+                               // Remove
+                               delete this.flags[flag];
+                               this.$element.removeClass( classPrefix + flag );
+                       }
+               }
+       }
+       return this;
+};
+/**
+ * Element containing a sequence of child elements.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $group Container node, assigned to #$group
+ * @param {Object} [config] Configuration options
+ * @cfg {Object.<string,string>} [aggregations] Events to aggregate, keyed by item event name
+ */
+OO.ui.GroupElement = function OoUiGroupElement( $group, config ) {
+       // Configuration
+       config = config || {};
+
+       // Properties
+       this.$group = $group;
+       this.items = [];
+       this.$items = this.$( [] );
+       this.aggregate = !$.isEmptyObject( config.aggregations );
+       this.aggregations = config.aggregations || {};
+};
+
+/* Methods */
+
+/**
+ * Get items.
+ *
+ * @method
+ * @returns {OO.ui.Element[]} Items
+ */
+OO.ui.GroupElement.prototype.getItems = function () {
+       return this.items.slice( 0 );
+};
+
+/**
+ * Add items.
+ *
+ * @method
+ * @param {OO.ui.Element[]} items Item
+ * @param {number} [index] Index to insert items at
+ * @chainable
+ */
+OO.ui.GroupElement.prototype.addItems = function ( items, index ) {
+       var i, len, item, event, events, currentIndex,
+               $items = this.$( [] );
+
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+
+               // Check if item exists then remove it first, effectively "moving" it
+               currentIndex = $.inArray( item, this.items );
+               if ( currentIndex >= 0 ) {
+                       this.removeItems( [ item ] );
+                       // Adjust index to compensate for removal
+                       if ( currentIndex < index ) {
+                               index--;
+                       }
+               }
+               // Add the item
+               if ( this.aggregate ) {
+                       events = {};
+                       for ( event in this.aggregations ) {
+                               events[event] = [ 'emit', this.aggregations[event], item ];
+                       }
+                       item.connect( this, events );
+               }
+               item.setElementGroup( this );
+               $items = $items.add( item.$element );
+       }
+
+       if ( index === undefined || index < 0 || index >= this.items.length ) {
+               this.$group.append( $items );
+               this.items.push.apply( this.items, items );
+       } else if ( index === 0 ) {
+               this.$group.prepend( $items );
+               this.items.unshift.apply( this.items, items );
+       } else {
+               this.$items.eq( index ).before( $items );
+               this.items.splice.apply( this.items, [ index, 0 ].concat( items ) );
+       }
+
+       this.$items = this.$items.add( $items );
+
+       return this;
+};
+
+/**
+ * Remove items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @param {OO.ui.Element[]} items Items to remove
+ * @chainable
+ */
+OO.ui.GroupElement.prototype.removeItems = function ( items ) {
+       var i, len, item, index;
+
+       // Remove specific items
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+               index = $.inArray( item, this.items );
+               if ( index !== -1 ) {
+                       if ( this.aggregate ) {
+                               item.disconnect( this );
+                       }
+                       item.setElementGroup( null );
+                       this.items.splice( index, 1 );
+                       item.$element.detach();
+                       this.$items = this.$items.not( item.$element );
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Clear all items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.GroupElement.prototype.clearItems = function () {
+       var i, len, item;
+
+       // Remove all items
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               item = this.items[i];
+               if ( this.aggregate ) {
+                       item.disconnect( this );
+               }
+               item.setElementGroup( null );
+       }
+       this.items = [];
+       this.$items.detach();
+       this.$items = this.$( [] );
+};
+/**
+ * Element containing an icon.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $icon Icon node, assigned to #$icon
+ * @param {Object} [config] Configuration options
+ * @cfg {Object|string} [icon=''] Symbolic icon name, or map of icon names keyed by language ID;
+ *  use the 'default' key to specify the icon to be used when there is no icon in the user's
+ *  language
+ */
+OO.ui.IconedElement = function OoUiIconedElement( $icon, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.$icon = $icon;
+       this.icon = null;
+
+       // Initialization
+       this.$icon.addClass( 'oo-ui-iconedElement-icon' );
+       this.setIcon( config.icon || this.constructor.static.icon );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.IconedElement );
+
+/* Static Properties */
+
+/**
+ * Icon.
+ *
+ * Value should be the unique portion of an icon CSS class name, such as 'up' for 'oo-ui-icon-up'.
+ *
+ * For i18n purposes, this property can be an object containing a `default` icon name property and
+ * additional icon names keyed by language code.
+ *
+ * Example of i18n icon definition:
+ *     { 'default': 'bold-a', 'en': 'bold-b', 'de': 'bold-f' }
+ *
+ * @static
+ * @inheritable
+ * @property {Object|string} Symbolic icon name, or map of icon names keyed by language ID;
+ *  use the 'default' key to specify the icon to be used when there is no icon in the user's
+ *  language
+ */
+OO.ui.IconedElement.static.icon = null;
+
+/* Methods */
+
+/**
+ * Set icon.
+ *
+ * @method
+ * @param {Object|string} icon Symbolic icon name, or map of icon names keyed by language ID;
+ *  use the 'default' key to specify the icon to be used when there is no icon in the user's
+ *  language
+ * @chainable
+ */
+OO.ui.IconedElement.prototype.setIcon = function ( icon ) {
+       icon = OO.isPlainObject( icon ) ? OO.ui.getLocalValue( icon, null, 'default' ) : icon;
+
+       if ( this.icon ) {
+               this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
+       }
+       if ( typeof icon === 'string' ) {
+               icon = icon.trim();
+               if ( icon.length ) {
+                       this.$icon.addClass( 'oo-ui-icon-' + icon );
+                       this.icon = icon;
+               }
+       }
+       this.$element.toggleClass( 'oo-ui-iconedElement', !!this.icon );
+
+       return this;
+};
+
+/**
+ * Get icon.
+ *
+ * @method
+ * @returns {string} Icon
+ */
+OO.ui.IconedElement.prototype.getIcon = function () {
+       return this.icon;
+};
+/**
+ * Element containing an indicator.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $indicator Indicator node, assigned to #$indicator
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [indicator] Symbolic indicator name
+ * @cfg {string} [indicatorTitle] Indicator title text or a function that return text
+ */
+OO.ui.IndicatedElement = function OoUiIndicatedElement( $indicator, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.$indicator = $indicator;
+       this.indicator = null;
+       this.indicatorLabel = null;
+
+       // Initialization
+       this.$indicator.addClass( 'oo-ui-indicatedElement-indicator' );
+       this.setIndicator( config.indicator || this.constructor.static.indicator );
+       this.setIndicatorTitle( config.indicatorTitle  || this.constructor.static.indicatorTitle );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.IndicatedElement );
+
+/* Static Properties */
+
+/**
+ * indicator.
+ *
+ * @static
+ * @inheritable
+ * @property {string|null} Symbolic indicator name or null for no indicator
+ */
+OO.ui.IndicatedElement.static.indicator = null;
+
+/**
+ * Indicator title.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null} Indicator title text, a function that return text or null for no
+ *  indicator title
+ */
+OO.ui.IndicatedElement.static.indicatorTitle = null;
+
+/* Methods */
+
+/**
+ * Set indicator.
+ *
+ * @method
+ * @param {string|null} indicator Symbolic name of indicator to use or null for no indicator
+ * @chainable
+ */
+OO.ui.IndicatedElement.prototype.setIndicator = function ( indicator ) {
+       if ( this.indicator ) {
+               this.$indicator.removeClass( 'oo-ui-indicator-' + this.indicator );
+               this.indicator = null;
+       }
+       if ( typeof indicator === 'string' ) {
+               indicator = indicator.trim();
+               if ( indicator.length ) {
+                       this.$indicator.addClass( 'oo-ui-indicator-' + indicator );
+                       this.indicator = indicator;
+               }
+       }
+       this.$element.toggleClass( 'oo-ui-indicatedElement', !!this.indicator );
+
+       return this;
+};
+
+/**
+ * Set indicator label.
+ *
+ * @method
+ * @param {string|Function|null} indicator Indicator title text, a function that return text or null
+ *  for no indicator title
+ * @chainable
+ */
+OO.ui.IndicatedElement.prototype.setIndicatorTitle = function ( indicatorTitle ) {
+       this.indicatorTitle = indicatorTitle = OO.ui.resolveMsg( indicatorTitle );
+
+       if ( typeof indicatorTitle === 'string' && indicatorTitle.length ) {
+               this.$indicator.attr( 'title', indicatorTitle );
+       } else {
+               this.$indicator.removeAttr( 'title' );
+       }
+
+       return this;
+};
+
+/**
+ * Get indicator.
+ *
+ * @method
+ * @returns {string} title Symbolic name of indicator
+ */
+OO.ui.IndicatedElement.prototype.getIndicator = function () {
+       return this.indicator;
+};
+
+/**
+ * Get indicator title.
+ *
+ * @method
+ * @returns {string} Indicator title text
+ */
+OO.ui.IndicatedElement.prototype.getIndicatorTitle = function () {
+       return this.indicatorTitle;
+};
+/**
+ * Element containing a label.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $label Label node, assigned to #$label
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery|string|Function} [label] Label nodes, text or a function that returns nodes or text
+ * @cfg {boolean} [autoFitLabel=true] Whether to fit the label or not.
+ */
+OO.ui.LabeledElement = function OoUiLabeledElement( $label, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.$label = $label;
+       this.label = null;
+
+       // Initialization
+       this.$label.addClass( 'oo-ui-labeledElement-label' );
+       this.setLabel( config.label || this.constructor.static.label );
+       this.autoFitLabel = config.autoFitLabel === undefined || !!config.autoFitLabel;
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.LabeledElement );
+
+/* Static Properties */
+
+/**
+ * Label.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null} Label text; a function that returns a nodes or text; or null for
+ *  no label
+ */
+OO.ui.LabeledElement.static.label = null;
+
+/* Methods */
+
+/**
+ * Set the label.
+ *
+ * An empty string will result in the label being hidden. A string containing only whitespace will
+ * be converted to a single &nbsp;
+ *
+ * @method
+ * @param {jQuery|string|Function|null} label Label nodes; text; a function that retuns nodes or
+ *  text; or null for no label
+ * @chainable
+ */
+OO.ui.LabeledElement.prototype.setLabel = function ( label ) {
+       var empty = false;
+
+       this.label = label = OO.ui.resolveMsg( label ) || null;
+       if ( typeof label === 'string' && label.length ) {
+               if ( label.match( /^\s*$/ ) ) {
+                       // Convert whitespace only string to a single non-breaking space
+                       this.$label.html( '&nbsp;' );
+               } else {
+                       this.$label.text( label );
+               }
+       } else if ( label instanceof jQuery ) {
+               this.$label.empty().append( label );
+       } else {
+               this.$label.empty();
+               empty = true;
+       }
+       this.$element.toggleClass( 'oo-ui-labeledElement', !empty );
+       this.$label.css( 'display', empty ? 'none' : '' );
+
+       return this;
+};
+
+/**
+ * Get the label.
+ *
+ * @method
+ * @returns {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
+ *  text; or null for no label
+ */
+OO.ui.LabeledElement.prototype.getLabel = function () {
+       return this.label;
+};
+
+/**
+ * Fit the label.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.LabeledElement.prototype.fitLabel = function () {
+       if ( this.$label.autoEllipsis && this.autoFitLabel ) {
+               this.$label.autoEllipsis( { 'hasSpan': false, 'tooltip': true } );
+       }
+       return this;
+};
+/**
+ * Popuppable element.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [popupWidth=320] Width of popup
+ * @cfg {number} [popupHeight] Height of popup
+ * @cfg {Object} [popup] Configuration to pass to popup
+ */
+OO.ui.PopuppableElement = function OoUiPopuppableElement( config ) {
+       // Configuration initialization
+       config = $.extend( { 'popupWidth': 320 }, config );
+
+       // Properties
+       this.popup = new OO.ui.PopupWidget( $.extend(
+               { 'align': 'center', 'autoClose': true },
+               config.popup,
+               { '$': this.$, '$autoCloseIgnore': this.$element }
+       ) );
+       this.popupWidth = config.popupWidth;
+       this.popupHeight = config.popupHeight;
+};
+
+/* Methods */
+
+/**
+ * Get popup.
+ *
+ * @method
+ * @returns {OO.ui.PopupWidget} Popup widget
+ */
+OO.ui.PopuppableElement.prototype.getPopup = function () {
+       return this.popup;
+};
+
+/**
+ * Show popup.
+ *
+ * @method
+ */
+OO.ui.PopuppableElement.prototype.showPopup = function () {
+       this.popup.show().display( this.popupWidth, this.popupHeight );
+};
+
+/**
+ * Hide popup.
+ *
+ * @method
+ */
+OO.ui.PopuppableElement.prototype.hidePopup = function () {
+       this.popup.hide();
+};
+/**
+ * Element with a title.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $label Titled node, assigned to #$titled
+ * @param {Object} [config] Configuration options
+ * @cfg {string|Function} [title] Title text or a function that returns text
+ */
+OO.ui.TitledElement = function OoUiTitledElement( $titled, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.$titled = $titled;
+       this.title = null;
+
+       // Initialization
+       this.setTitle( config.title || this.constructor.static.title );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.TitledElement );
+
+/* Static Properties */
+
+/**
+ * Title.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function} Title text or a function that returns text
+ */
+OO.ui.TitledElement.static.title = null;
+
+/* Methods */
+
+/**
+ * Set title.
+ *
+ * @method
+ * @param {string|Function|null} title Title text, a function that returns text or null for no title
+ * @chainable
+ */
+OO.ui.TitledElement.prototype.setTitle = function ( title ) {
+       this.title = title = OO.ui.resolveMsg( title ) || null;
+
+       if ( typeof title === 'string' && title.length ) {
+               this.$titled.attr( 'title', title );
+       } else {
+               this.$titled.removeAttr( 'title' );
+       }
+
+       return this;
+};
+
+/**
+ * Get title.
+ *
+ * @method
+ * @returns {string} Title string
+ */
+OO.ui.TitledElement.prototype.getTitle = function () {
+       return this.title;
+};
+/**
+ * Generic toolbar tool.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.IconedElement
+ *
+ * @constructor
+ * @param {OO.ui.ToolGroup} toolGroup
+ * @param {Object} [config] Configuration options
+ * @cfg {string|Function} [title] Title text or a function that returns text
+ */
+OO.ui.Tool = function OoUiTool( toolGroup, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Tool.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
+
+       // Properties
+       this.toolGroup = toolGroup;
+       this.toolbar = this.toolGroup.getToolbar();
+       this.active = false;
+       this.$title = this.$( '<span>' );
+       this.$link = this.$( '<a>' );
+       this.title = null;
+
+       // Events
+       this.toolbar.connect( this, { 'updateState': 'onUpdateState' } );
+
+       // Initialization
+       this.$title.addClass( 'oo-ui-tool-title' );
+       this.$link
+               .addClass( 'oo-ui-tool-link' )
+               .append( this.$icon, this.$title );
+       this.$element
+               .data( 'oo-ui-tool', this )
+               .addClass(
+                       'oo-ui-tool ' + 'oo-ui-tool-name-' +
+                       this.constructor.static.name.replace( /^([^\/]+)\/([^\/]+).*$/, '$1-$2' )
+               )
+               .append( this.$link );
+       this.setTitle( config.title || this.constructor.static.title );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Tool, OO.ui.Widget );
+OO.mixinClass( OO.ui.Tool, OO.ui.IconedElement );
+
+/* Events */
+
+/**
+ * @event select
+ */
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.Tool.static.tagName = 'span';
+
+/**
+ * Symbolic name of tool.
+ *
+ * @abstract
+ * @static
+ * @property {string}
+ * @inheritable
+ */
+OO.ui.Tool.static.name = '';
+
+/**
+ * Tool group.
+ *
+ * @abstract
+ * @static
+ * @property {string}
+ * @inheritable
+ */
+OO.ui.Tool.static.group = '';
+
+/**
+ * Tool title.
+ *
+ * Title is used as a tooltip when the tool is part of a bar tool group, or a label when the tool
+ * is part of a list or menu tool group. If a trigger is associated with an action by the same name
+ * as the tool, a description of its keyboard shortcut for the appropriate platform will be
+ * appended to the title if the tool is part of a bar tool group.
+ *
+ * @abstract
+ * @static
+ * @property {string|Function} Title text or a function that returns text
+ * @inheritable
+ */
+OO.ui.Tool.static.title = '';
+
+/**
+ * Tool can be automatically added to catch-all groups.
+ *
+ * @static
+ * @property {boolean}
+ * @inheritable
+ */
+OO.ui.Tool.static.autoAddToCatchall = true;
+
+/**
+ * Tool can be automatically added to named groups.
+ *
+ * @static
+ * @property {boolean}
+ * @inheritable
+ */
+OO.ui.Tool.static.autoAddToGroup = true;
+
+/**
+ * Check if this tool is compatible with given data.
+ *
+ * @static
+ * @method
+ * @inheritable
+ * @param {Mixed} data Data to check
+ * @return {boolean} Tool can be used with data
+ */
+OO.ui.Tool.static.isCompatibleWith = function () {
+       return false;
+};
+
+/* Methods */
+
+/**
+ * Handle the toolbar state being updated.
+ *
+ * This is an abstract method that must be overridden in a concrete subclass.
+ *
+ * @abstract
+ */
+OO.ui.Tool.prototype.onUpdateState = function () {
+       throw new Error(
+               'OO.ui.Tool.onUpdateState not implemented in this subclass:' + this.constructor
+       );
+};
+
+/**
+ * Handle the tool being selected.
+ *
+ * This is an abstract method that must be overridden in a concrete subclass.
+ *
+ * @abstract
+ */
+OO.ui.Tool.prototype.onSelect = function () {
+       throw new Error(
+               'OO.ui.Tool.onSelect not implemented in this subclass:' + this.constructor
+       );
+};
+
+/**
+ * Check if the button is active.
+ *
+ * @param {boolean} Button is active
+ */
+OO.ui.Tool.prototype.isActive = function () {
+       return this.active;
+};
+
+/**
+ * Make the button appear active or inactive.
+ *
+ * @param {boolean} state Make button appear active
+ */
+OO.ui.Tool.prototype.setActive = function ( state ) {
+       this.active = !!state;
+       if ( this.active ) {
+               this.$element.addClass( 'oo-ui-tool-active' );
+       } else {
+               this.$element.removeClass( 'oo-ui-tool-active' );
+       }
+};
+
+/**
+ * Get the tool title.
+ *
+ * @param {string|Function} title Title text or a function that returns text
+ * @chainable
+ */
+OO.ui.Tool.prototype.setTitle = function ( title ) {
+       this.title = OO.ui.resolveMsg( title );
+       this.updateTitle();
+       return this;
+};
+
+/**
+ * Get the tool title.
+ *
+ * @return {string} Title text
+ */
+OO.ui.Tool.prototype.getTitle = function () {
+       return this.title;
+};
+
+/**
+ * Get the tool's symbolic name.
+ *
+ * @return {string} Symbolic name of tool
+ */
+OO.ui.Tool.prototype.getName = function () {
+       return this.constructor.static.name;
+};
+
+/**
+ * Update the title.
+ */
+OO.ui.Tool.prototype.updateTitle = function () {
+       var titleTooltips = this.toolGroup.constructor.static.titleTooltips,
+               accelTooltips = this.toolGroup.constructor.static.accelTooltips,
+               accel = this.toolbar.getToolAccelerator( this.constructor.static.name ),
+               tooltipParts = [];
+
+       this.$title.empty()
+               .text( this.title )
+               .append(
+                       this.$( '<span>' )
+                               .addClass( 'oo-ui-tool-accel' )
+                               .text( accel )
+               );
+
+       if ( titleTooltips && typeof this.title === 'string' && this.title.length ) {
+               tooltipParts.push( this.title );
+       }
+       if ( accelTooltips && typeof accel === 'string' && accel.length ) {
+               tooltipParts.push( accel );
+       }
+       if ( tooltipParts.length ) {
+               this.$link.attr( 'title', tooltipParts.join( ' ' ) );
+       } else {
+               this.$link.removeAttr( 'title' );
+       }
+};
+
+/**
+ * Destroy tool.
+ */
+OO.ui.Tool.prototype.destroy = function () {
+       this.toolbar.disconnect( this );
+       this.$element.remove();
+};
+/**
+ * Collection of tool groups.
+ *
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ * @mixins OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {OO.ui.ToolFactory} toolFactory Factory for creating tools
+ * @param {OO.ui.ToolGroupFactory} toolGroupFactory Factory for creating tool groups
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [actions] Add an actions section opposite to the tools
+ * @cfg {boolean} [shadow] Add a shadow below the toolbar
+ */
+OO.ui.Toolbar = function OoUiToolbar( toolFactory, toolGroupFactory, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Toolbar.super.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
+
+       // Properties
+       this.toolFactory = toolFactory;
+       this.toolGroupFactory = toolGroupFactory;
+       this.groups = [];
+       this.tools = {};
+       this.$bar = this.$( '<div>' );
+       this.$actions = this.$( '<div>' );
+       this.initialized = false;
+
+       // Events
+       this.$element
+               .add( this.$bar ).add( this.$group ).add( this.$actions )
+               .on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
+
+       // Initialization
+       this.$group.addClass( 'oo-ui-toolbar-tools' );
+       this.$bar.addClass( 'oo-ui-toolbar-bar' ).append( this.$group );
+       if ( config.actions ) {
+               this.$actions.addClass( 'oo-ui-toolbar-actions' );
+               this.$bar.append( this.$actions );
+       }
+       this.$bar.append( '<div style="clear:both"></div>' );
+       if ( config.shadow ) {
+               this.$bar.append( '<div class="oo-ui-toolbar-shadow"></div>' );
+       }
+       this.$element.addClass( 'oo-ui-toolbar' ).append( this.$bar );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Toolbar, OO.ui.Element );
+OO.mixinClass( OO.ui.Toolbar, OO.EventEmitter );
+OO.mixinClass( OO.ui.Toolbar, OO.ui.GroupElement );
+
+/* Methods */
+
+/**
+ * Get the tool factory.
+ *
+ * @return {OO.ui.ToolFactory} Tool factory
+ */
+OO.ui.Toolbar.prototype.getToolFactory = function () {
+       return this.toolFactory;
+};
+
+/**
+ * Get the tool group factory.
+ *
+ * @return {OO.Factory} Tool group factory
+ */
+OO.ui.Toolbar.prototype.getToolGroupFactory = function () {
+       return this.toolGroupFactory;
+};
+
+/**
+ * Handles mouse down events.
+ *
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.Toolbar.prototype.onMouseDown = function ( e ) {
+       var $closestWidgetToEvent = this.$( e.target ).closest( '.oo-ui-widget' ),
+               $closestWidgetToToolbar = this.$element.closest( '.oo-ui-widget' );
+       if ( !$closestWidgetToEvent.length || $closestWidgetToEvent[0] === $closestWidgetToToolbar[0] ) {
+               return false;
+       }
+};
+
+/**
+ * Sets up handles and preloads required information for the toolbar to work.
+ * This must be called immediately after it is attached to a visible document.
+ */
+OO.ui.Toolbar.prototype.initialize = function () {
+       this.initialized = true;
+};
+
+/**
+ * Setup toolbar.
+ *
+ * Tools can be specified in the following ways:
+ *
+ * - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
+ * - All tools in a group: `{ 'group': 'group-name' }`
+ * - All tools: `'*'` - Using this will make the group a list with a "More" label by default
+ *
+ * @param {Object.<string,Array>} groups List of tool group configurations
+ * @param {Array|string} [groups.include] Tools to include
+ * @param {Array|string} [groups.exclude] Tools to exclude
+ * @param {Array|string} [groups.promote] Tools to promote to the beginning
+ * @param {Array|string} [groups.demote] Tools to demote to the end
+ */
+OO.ui.Toolbar.prototype.setup = function ( groups ) {
+       var i, len, type, group,
+               items = [],
+               defaultType = 'bar';
+
+       // Cleanup previous groups
+       this.reset();
+
+       // Build out new groups
+       for ( i = 0, len = groups.length; i < len; i++ ) {
+               group = groups[i];
+               if ( group.include === '*' ) {
+                       // Apply defaults to catch-all groups
+                       if ( group.type === undefined ) {
+                               group.type = 'list';
+                       }
+                       if ( group.label === undefined ) {
+                               group.label = 'ooui-toolbar-more';
+                       }
+               }
+               // Check type has been registered
+               type = this.getToolGroupFactory().lookup( group.type ) ? group.type : defaultType;
+               items.push(
+                       this.getToolGroupFactory().create( type, this, $.extend( { '$': this.$ }, group ) )
+               );
+       }
+       this.addItems( items );
+};
+
+/**
+ * Remove all tools and groups from the toolbar.
+ */
+OO.ui.Toolbar.prototype.reset = function () {
+       var i, len;
+
+       this.groups = [];
+       this.tools = {};
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               this.items[i].destroy();
+       }
+       this.clearItems();
+};
+
+/**
+ * Destroys toolbar, removing event handlers and DOM elements.
+ *
+ * Call this whenever you are done using a toolbar.
+ */
+OO.ui.Toolbar.prototype.destroy = function () {
+       this.reset();
+       this.$element.remove();
+};
+
+/**
+ * Check if tool has not been used yet.
+ *
+ * @param {string} name Symbolic name of tool
+ * @return {boolean} Tool is available
+ */
+OO.ui.Toolbar.prototype.isToolAvailable = function ( name ) {
+       return !this.tools[name];
+};
+
+/**
+ * Prevent tool from being used again.
+ *
+ * @param {OO.ui.Tool} tool Tool to reserve
+ */
+OO.ui.Toolbar.prototype.reserveTool = function ( tool ) {
+       this.tools[tool.getName()] = tool;
+};
+
+/**
+ * Allow tool to be used again.
+ *
+ * @param {OO.ui.Tool} tool Tool to release
+ */
+OO.ui.Toolbar.prototype.releaseTool = function ( tool ) {
+       delete this.tools[tool.getName()];
+};
+
+/**
+ * Get accelerator label for tool.
+ *
+ * This is a stub that should be overridden to provide access to accelerator information.
+ *
+ * @param {string} name Symbolic name of tool
+ * @return {string|undefined} Tool accelerator label if available
+ */
+OO.ui.Toolbar.prototype.getToolAccelerator = function () {
+       return undefined;
+};
+/**
+ * Factory for tools.
+ *
+ * @class
+ * @extends OO.Factory
+ * @constructor
+ */
+OO.ui.ToolFactory = function OoUiToolFactory() {
+       // Parent constructor
+       OO.ui.ToolFactory.super.call( this );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToolFactory, OO.Factory );
+
+/* Methods */
+
+/** */
+OO.ui.ToolFactory.prototype.getTools = function ( include, exclude, promote, demote ) {
+       var i, len, included, promoted, demoted,
+               auto = [],
+               used = {};
+
+       // Collect included and not excluded tools
+       included = OO.simpleArrayDifference( this.extract( include ), this.extract( exclude ) );
+
+       // Promotion
+       promoted = this.extract( promote, used );
+       demoted = this.extract( demote, used );
+
+       // Auto
+       for ( i = 0, len = included.length; i < len; i++ ) {
+               if ( !used[included[i]] ) {
+                       auto.push( included[i] );
+               }
+       }
+
+       return promoted.concat( auto ).concat( demoted );
+};
+
+/**
+ * Get a flat list of names from a list of names or groups.
+ *
+ * Tools can be specified in the following ways:
+ *
+ * - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
+ * - All tools in a group: `{ 'group': 'group-name' }`
+ * - All tools: `'*'`
+ *
+ * @private
+ * @param {Array|string} collection List of tools
+ * @param {Object} [used] Object with names that should be skipped as properties; extracted
+ *  names will be added as properties
+ * @return {string[]} List of extracted names
+ */
+OO.ui.ToolFactory.prototype.extract = function ( collection, used ) {
+       var i, len, item, name, tool,
+               names = [];
+
+       if ( collection === '*' ) {
+               for ( name in this.registry ) {
+                       tool = this.registry[name];
+                       if (
+                               // Only add tools by group name when auto-add is enabled
+                               tool.static.autoAddToCatchall &&
+                               // Exclude already used tools
+                               ( !used || !used[name] )
+                       ) {
+                               names.push( name );
+                               if ( used ) {
+                                       used[name] = true;
+                               }
+                       }
+               }
+       } else if ( $.isArray( collection ) ) {
+               for ( i = 0, len = collection.length; i < len; i++ ) {
+                       item = collection[i];
+                       // Allow plain strings as shorthand for named tools
+                       if ( typeof item === 'string' ) {
+                               item = { 'name': item };
+                       }
+                       if ( OO.isPlainObject( item ) ) {
+                               if ( item.group ) {
+                                       for ( name in this.registry ) {
+                                               tool = this.registry[name];
+                                               if (
+                                                       // Include tools with matching group
+                                                       tool.static.group === item.group &&
+                                                       // Only add tools by group name when auto-add is enabled
+                                                       tool.static.autoAddToGroup &&
+                                                       // Exclude already used tools
+                                                       ( !used || !used[name] )
+                                               ) {
+                                                       names.push( name );
+                                                       if ( used ) {
+                                                               used[name] = true;
+                                                       }
+                                               }
+                                       }
+                               // Include tools with matching name and exclude already used tools
+                               } else if ( item.name && ( !used || !used[item.name] ) ) {
+                                       names.push( item.name );
+                                       if ( used ) {
+                                               used[item.name] = true;
+                                       }
+                               }
+                       }
+               }
+       }
+       return names;
+};
+/**
+ * Collection of tools.
+ *
+ * Tools can be specified in the following ways:
+ *
+ * - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
+ * - All tools in a group: `{ 'group': 'group-name' }`
+ * - All tools: `'*'`
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ * @cfg {Array|string} [include=[]] List of tools to include
+ * @cfg {Array|string} [exclude=[]] List of tools to exclude
+ * @cfg {Array|string} [promote=[]] List of tools to promote to the beginning
+ * @cfg {Array|string} [demote=[]] List of tools to demote to the end
+ */
+OO.ui.ToolGroup = function OoUiToolGroup( toolbar, config ) {
+       // Configuration initialization
+       config = $.extend( true, {
+               'aggregations': { 'disable': 'itemDisable' }
+       }, config );
+
+       // Parent constructor
+       OO.ui.ToolGroup.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
+
+       // Properties
+       this.toolbar = toolbar;
+       this.tools = {};
+       this.pressed = null;
+       this.autoDisabled = false;
+       this.include = config.include || [];
+       this.exclude = config.exclude || [];
+       this.promote = config.promote || [];
+       this.demote = config.demote || [];
+       this.onCapturedMouseUpHandler = OO.ui.bind( this.onCapturedMouseUp, this );
+
+       // Events
+       this.$element.on( {
+               'mousedown': OO.ui.bind( this.onMouseDown, this ),
+               'mouseup': OO.ui.bind( this.onMouseUp, this ),
+               'mouseover': OO.ui.bind( this.onMouseOver, this ),
+               'mouseout': OO.ui.bind( this.onMouseOut, this )
+       } );
+       this.toolbar.getToolFactory().connect( this, { 'register': 'onToolFactoryRegister' } );
+       this.connect( this, { 'itemDisable': 'updateDisabled' } );
+
+       // Initialization
+       this.$group.addClass( 'oo-ui-toolGroup-tools' );
+       this.$element
+               .addClass( 'oo-ui-toolGroup' )
+               .append( this.$group );
+       this.populate();
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToolGroup, OO.ui.Widget );
+OO.mixinClass( OO.ui.ToolGroup, OO.ui.GroupElement );
+
+/* Events */
+
+/**
+ * @event update
+ */
+
+/* Static Properties */
+
+/**
+ * Show labels in tooltips.
+ *
+ * @static
+ * @property {boolean}
+ * @inheritable
+ */
+OO.ui.ToolGroup.static.titleTooltips = false;
+
+/**
+ * Show acceleration labels in tooltips.
+ *
+ * @static
+ * @property {boolean}
+ * @inheritable
+ */
+OO.ui.ToolGroup.static.accelTooltips = false;
+
+/**
+ * Automatically disable the toolgroup when all tools are disabled
+ *
+ * @static
+ * @property {boolean}
+ * @inheritable
+ */
+OO.ui.ToolGroup.static.autoDisable = true;
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToolGroup.prototype.isDisabled = function () {
+       return this.autoDisabled || OO.ui.ToolGroup.super.prototype.isDisabled.apply( this, arguments );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToolGroup.prototype.updateDisabled = function () {
+       var i, item, allDisabled = true;
+
+       if ( this.constructor.static.autoDisable ) {
+               for ( i = this.items.length - 1; i >= 0; i-- ) {
+                       item = this.items[i];
+                       if ( !item.isDisabled() ) {
+                               allDisabled = false;
+                               break;
+                       }
+               }
+               this.autoDisabled = allDisabled;
+       }
+       OO.ui.ToolGroup.super.prototype.updateDisabled.apply( this, arguments );
+};
+
+/**
+ * Handle mouse down events.
+ *
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.ToolGroup.prototype.onMouseDown = function ( e ) {
+       if ( !this.disabled && e.which === 1 ) {
+               this.pressed = this.getTargetTool( e );
+               if ( this.pressed ) {
+                       this.pressed.setActive( true );
+                       this.getElementDocument().addEventListener(
+                               'mouseup', this.onCapturedMouseUpHandler, true
+                       );
+                       return false;
+               }
+       }
+};
+
+/**
+ * Handle captured mouse up events.
+ *
+ * @param {Event} e Mouse up event
+ */
+OO.ui.ToolGroup.prototype.onCapturedMouseUp = function ( e ) {
+       this.getElementDocument().removeEventListener( 'mouseup', this.onCapturedMouseUpHandler, true );
+       // onMouseUp may be called a second time, depending on where the mouse is when the button is
+       // released, but since `this.pressed` will no longer be true, the second call will be ignored.
+       this.onMouseUp( e );
+};
+
+/**
+ * Handle mouse up events.
+ *
+ * @param {jQuery.Event} e Mouse up event
+ */
+OO.ui.ToolGroup.prototype.onMouseUp = function ( e ) {
+       var tool = this.getTargetTool( e );
+
+       if ( !this.disabled && e.which === 1 && this.pressed && this.pressed === tool ) {
+               this.pressed.onSelect();
+       }
+
+       this.pressed = null;
+       return false;
+};
+
+/**
+ * Handle mouse over events.
+ *
+ * @param {jQuery.Event} e Mouse over event
+ */
+OO.ui.ToolGroup.prototype.onMouseOver = function ( e ) {
+       var tool = this.getTargetTool( e );
+
+       if ( this.pressed && this.pressed === tool ) {
+               this.pressed.setActive( true );
+       }
+};
+
+/**
+ * Handle mouse out events.
+ *
+ * @param {jQuery.Event} e Mouse out event
+ */
+OO.ui.ToolGroup.prototype.onMouseOut = function ( e ) {
+       var tool = this.getTargetTool( e );
+
+       if ( this.pressed && this.pressed === tool ) {
+               this.pressed.setActive( false );
+       }
+};
+
+/**
+ * Get the closest tool to a jQuery.Event.
+ *
+ * Only tool links are considered, which prevents other elements in the tool such as popups from
+ * triggering tool group interactions.
+ *
+ * @private
+ * @param {jQuery.Event} e
+ * @return {OO.ui.Tool|null} Tool, `null` if none was found
+ */
+OO.ui.ToolGroup.prototype.getTargetTool = function ( e ) {
+       var tool,
+               $item = this.$( e.target ).closest( '.oo-ui-tool-link' );
+
+       if ( $item.length ) {
+               tool = $item.parent().data( 'oo-ui-tool' );
+       }
+
+       return tool && !tool.isDisabled() ? tool : null;
+};
+
+/**
+ * Handle tool registry register events.
+ *
+ * If a tool is registered after the group is created, we must repopulate the list to account for:
+ *
+ * - a tool being added that may be included
+ * - a tool already included being overridden
+ *
+ * @param {string} name Symbolic name of tool
+ */
+OO.ui.ToolGroup.prototype.onToolFactoryRegister = function () {
+       this.populate();
+};
+
+/**
+ * Get the toolbar this group is in.
+ *
+ * @return {OO.ui.Toolbar} Toolbar of group
+ */
+OO.ui.ToolGroup.prototype.getToolbar = function () {
+       return this.toolbar;
+};
+
+/**
+ * Add and remove tools based on configuration.
+ */
+OO.ui.ToolGroup.prototype.populate = function () {
+       var i, len, name, tool,
+               toolFactory = this.toolbar.getToolFactory(),
+               names = {},
+               add = [],
+               remove = [],
+               list = this.toolbar.getToolFactory().getTools(
+                       this.include, this.exclude, this.promote, this.demote
+               );
+
+       // Build a list of needed tools
+       for ( i = 0, len = list.length; i < len; i++ ) {
+               name = list[i];
+               if (
+                       // Tool exists
+                       toolFactory.lookup( name ) &&
+                       // Tool is available or is already in this group
+                       ( this.toolbar.isToolAvailable( name ) || this.tools[name] )
+               ) {
+                       tool = this.tools[name];
+                       if ( !tool ) {
+                               // Auto-initialize tools on first use
+                               this.tools[name] = tool = toolFactory.create( name, this );
+                               tool.updateTitle();
+                       }
+                       this.toolbar.reserveTool( tool );
+                       add.push( tool );
+                       names[name] = true;
+               }
+       }
+       // Remove tools that are no longer needed
+       for ( name in this.tools ) {
+               if ( !names[name] ) {
+                       this.tools[name].destroy();
+                       this.toolbar.releaseTool( this.tools[name] );
+                       remove.push( this.tools[name] );
+                       delete this.tools[name];
+               }
+       }
+       if ( remove.length ) {
+               this.removeItems( remove );
+       }
+       // Update emptiness state
+       if ( add.length ) {
+               this.$element.removeClass( 'oo-ui-toolGroup-empty' );
+       } else {
+               this.$element.addClass( 'oo-ui-toolGroup-empty' );
+       }
+       // Re-add tools (moving existing ones to new locations)
+       this.addItems( add );
+       // Disabled state may depend on items
+       this.updateDisabled();
+};
+
+/**
+ * Destroy tool group.
+ */
+OO.ui.ToolGroup.prototype.destroy = function () {
+       var name;
+
+       this.clearItems();
+       this.toolbar.getToolFactory().disconnect( this );
+       for ( name in this.tools ) {
+               this.toolbar.releaseTool( this.tools[name] );
+               this.tools[name].disconnect( this ).destroy();
+               delete this.tools[name];
+       }
+       this.$element.remove();
+};
+/**
+ * Factory for tools.
+ *
+ * @class
+ * @extends OO.Factory
+ * @constructor
+ */
+OO.ui.ToolGroupFactory = function OoUiToolGroupFactory() {
+       // Parent constructor
+       OO.Factory.call( this );
+
+       var i, l,
+               defaultClasses = this.constructor.static.getDefaultClasses();
+
+       // Register default toolgroups
+       for ( i = 0, l = defaultClasses.length; i < l; i++ ) {
+               this.register( defaultClasses[i] );
+       }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToolGroupFactory, OO.Factory );
+
+/* Static Methods */
+
+/**
+ * Get a default set of classes to be registered on construction
+ * @return {Function[]} Default classes
+ */
+OO.ui.ToolGroupFactory.static.getDefaultClasses = function () {
+       return [
+               OO.ui.BarToolGroup,
+               OO.ui.ListToolGroup,
+               OO.ui.MenuToolGroup
+       ];
+};
+/**
+ * Layout made of a fieldset and optional legend.
+ *
+ * Just add OO.ui.FieldLayout items.
+ *
+ * @class
+ * @extends OO.ui.Layout
+ * @mixins OO.ui.LabeledElement
+ * @mixins OO.ui.IconedElement
+ * @mixins OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [icon] Symbolic icon name
+ * @cfg {OO.ui.FieldLayout[]} [items] Items to add
+ */
+OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) {
+       // Config initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.FieldsetLayout.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.IconedElement.call( this, this.$( '<div>' ), config );
+       OO.ui.LabeledElement.call( this, this.$( '<legend>' ), config );
+       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-fieldsetLayout' )
+               .append( this.$icon, this.$label, this.$group );
+       if ( $.isArray( config.items ) ) {
+               this.addItems( config.items );
+       }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.FieldsetLayout, OO.ui.Layout );
+OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.IconedElement );
+OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.LabeledElement );
+OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.GroupElement );
+
+/* Static Properties */
+
+OO.ui.FieldsetLayout.static.tagName = 'fieldset';
+/**
+ * Layout made of a field and optional label.
+ *
+ * @class
+ * @extends OO.ui.Layout
+ * @mixins OO.ui.LabeledElement
+ *
+ * Available label alignment modes include:
+ *  - 'left': Label is before the field and aligned away from it, best for when the user will be
+ *    scanning for a specific label in a form with many fields
+ *  - 'right': Label is before the field and aligned toward it, best for forms the user is very
+ *    familiar with and will tab through field checking quickly to verify which field they are in
+ *  - 'top': Label is before the field and above it, best for when the use will need to fill out all
+ *    fields from top to bottom in a form with few fields
+ *  - 'inline': Label is after the field and aligned toward it, best for small boolean fields like
+ *    checkboxes or radio buttons
+ *
+ * @constructor
+ * @param {OO.ui.Widget} field Field widget
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [align='left'] Alignment mode, either 'left', 'right', 'top' or 'inline'
+ */
+OO.ui.FieldLayout = function OoUiFieldLayout( field, config ) {
+       // Config initialization
+       config = $.extend( { 'align': 'left' }, config );
+
+       // Parent constructor
+       OO.ui.FieldLayout.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.LabeledElement.call( this, this.$( '<label>' ), config );
+
+       // Properties
+       this.$field = this.$( '<div>' );
+       this.field = field;
+       this.align = null;
+
+       // Events
+       if ( this.field instanceof OO.ui.InputWidget ) {
+               this.$label.on( 'click', OO.ui.bind( this.onLabelClick, this ) );
+       }
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-fieldLayout' );
+       this.$field
+               .addClass( 'oo-ui-fieldLayout-field' )
+               .append( this.field.$element );
+       this.setAlignment( config.align );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.FieldLayout, OO.ui.Layout );
+OO.mixinClass( OO.ui.FieldLayout, OO.ui.LabeledElement );
+
+/* Methods */
+
+/**
+ * Handles label mouse click events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse click event
+ */
+OO.ui.FieldLayout.prototype.onLabelClick = function () {
+       this.field.simulateLabelClick();
+       return false;
+};
+
+/**
+ * Get the field.
+ *
+ * @returns {OO.ui.Widget} Field widget
+ */
+OO.ui.FieldLayout.prototype.getField = function () {
+       return this.field;
+};
+
+/**
+ * Set the field alignment mode.
+ *
+ * @param {string} value Alignment mode, either 'left', 'right', 'top' or 'inline'
+ * @chainable
+ */
+OO.ui.FieldLayout.prototype.setAlignment = function ( value ) {
+       if ( value !== this.align ) {
+               // Default to 'left'
+               if ( [ 'left', 'right', 'top', 'inline' ].indexOf( value ) === -1 ) {
+                       value = 'left';
+               }
+               // Reorder elements
+               if ( value === 'inline' ) {
+                       this.$element.append( this.$field, this.$label );
+               } else {
+                       this.$element.append( this.$label, this.$field );
+               }
+               // Set classes
+               if ( this.align ) {
+                       this.$element.removeClass( 'oo-ui-fieldLayout-align-' + this.align );
+               }
+               this.align = value;
+               this.$element.addClass( 'oo-ui-fieldLayout-align-' + this.align );
+       }
+
+       return this;
+};
+/**
+ * Layout made of proportionally sized columns and rows.
+ *
+ * @class
+ * @extends OO.ui.Layout
+ *
+ * @constructor
+ * @param {OO.ui.PanelLayout[]} panels Panels in the grid
+ * @param {Object} [config] Configuration options
+ * @cfg {number[]} [widths] Widths of columns as ratios
+ * @cfg {number[]} [heights] Heights of columns as ratios
+ */
+OO.ui.GridLayout = function OoUiGridLayout( panels, config ) {
+       var i, len, widths;
+
+       // Config initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.GridLayout.super.call( this, config );
+
+       // Properties
+       this.panels = [];
+       this.widths = [];
+       this.heights = [];
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-gridLayout' );
+       for ( i = 0, len = panels.length; i < len; i++ ) {
+               this.panels.push( panels[i] );
+               this.$element.append( panels[i].$element );
+       }
+       if ( config.widths || config.heights ) {
+               this.layout( config.widths || [1], config.heights || [1] );
+       } else {
+               // Arrange in columns by default
+               widths = [];
+               for ( i = 0, len = this.panels.length; i < len; i++ ) {
+                       widths[i] = 1;
+               }
+               this.layout( widths, [1] );
+       }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.GridLayout, OO.ui.Layout );
+
+/* Events */
+
+/**
+ * @event layout
+ */
+
+/**
+ * @event update
+ */
+
+/* Static Properties */
+
+OO.ui.GridLayout.static.tagName = 'div';
+
+/* Methods */
+
+/**
+ * Set grid dimensions.
+ *
+ * @method
+ * @param {number[]} widths Widths of columns as ratios
+ * @param {number[]} heights Heights of rows as ratios
+ * @fires layout
+ * @throws {Error} If grid is not large enough to fit all panels
+ */
+OO.ui.GridLayout.prototype.layout = function ( widths, heights ) {
+       var x, y,
+               xd = 0,
+               yd = 0,
+               cols = widths.length,
+               rows = heights.length;
+
+       // Verify grid is big enough to fit panels
+       if ( cols * rows < this.panels.length ) {
+               throw new Error( 'Grid is not large enough to fit ' + this.panels.length + 'panels' );
+       }
+
+       // Sum up denominators
+       for ( x = 0; x < cols; x++ ) {
+               xd += widths[x];
+       }
+       for ( y = 0; y < rows; y++ ) {
+               yd += heights[y];
+       }
+       // Store factors
+       this.widths = [];
+       this.heights = [];
+       for ( x = 0; x < cols; x++ ) {
+               this.widths[x] = widths[x] / xd;
+       }
+       for ( y = 0; y < rows; y++ ) {
+               this.heights[y] = heights[y] / yd;
+       }
+       // Synchronize view
+       this.update();
+       this.emit( 'layout' );
+};
+
+/**
+ * Update panel positions and sizes.
+ *
+ * @method
+ * @fires update
+ */
+OO.ui.GridLayout.prototype.update = function () {
+       var x, y, panel,
+               i = 0,
+               left = 0,
+               top = 0,
+               dimensions,
+               width = 0,
+               height = 0,
+               cols = this.widths.length,
+               rows = this.heights.length;
+
+       for ( y = 0; y < rows; y++ ) {
+               for ( x = 0; x < cols; x++ ) {
+                       panel = this.panels[i];
+                       width = this.widths[x];
+                       height = this.heights[y];
+                       dimensions = {
+                               'width': Math.round( width * 100 ) + '%',
+                               'height': Math.round( height * 100 ) + '%',
+                               'top': Math.round( top * 100 ) + '%'
+                       };
+                       // If RTL, reverse:
+                       if ( OO.ui.Element.getDir( this.$.context ) === 'rtl' ) {
+                               dimensions.right = Math.round( left * 100 ) + '%';
+                       } else {
+                               dimensions.left = Math.round( left * 100 ) + '%';
+                       }
+                       panel.$element.css( dimensions );
+                       i++;
+                       left += width;
+               }
+               top += height;
+               left = 0;
+       }
+
+       this.emit( 'update' );
+};
+
+/**
+ * Get a panel at a given position.
+ *
+ * The x and y position is affected by the current grid layout.
+ *
+ * @method
+ * @param {number} x Horizontal position
+ * @param {number} y Vertical position
+ * @returns {OO.ui.PanelLayout} The panel at the given postion
+ */
+OO.ui.GridLayout.prototype.getPanel = function ( x, y ) {
+       return this.panels[( x * this.widths.length ) + y];
+};
+/**
+ * Layout containing a series of pages.
+ *
+ * @class
+ * @extends OO.ui.Layout
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [continuous=false] Show all pages, one after another
+ * @cfg {boolean} [autoFocus=false] Focus on the first focusable element when changing to a page
+ * @cfg {boolean} [outlined=false] Show an outline
+ * @cfg {boolean} [editable=false] Show controls for adding, removing and reordering pages
+ * @cfg {Object[]} [adders] List of adders for controls, each with name, icon and title properties
+ */
+OO.ui.BookletLayout = function OoUiBookletLayout( config ) {
+       // Initialize configuration
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.BookletLayout.super.call( this, config );
+
+       // Properties
+       this.currentPageName = null;
+       this.pages = {};
+       this.ignoreFocus = false;
+       this.stackLayout = new OO.ui.StackLayout( { '$': this.$, 'continuous': !!config.continuous } );
+       this.autoFocus = !!config.autoFocus;
+       this.outlineVisible = false;
+       this.outlined = !!config.outlined;
+       if ( this.outlined ) {
+               this.editable = !!config.editable;
+               this.adders = config.adders || null;
+               this.outlineControlsWidget = null;
+               this.outlineWidget = new OO.ui.OutlineWidget( { '$': this.$ } );
+               this.outlinePanel = new OO.ui.PanelLayout( { '$': this.$, 'scrollable': true } );
+               this.gridLayout = new OO.ui.GridLayout(
+                       [this.outlinePanel, this.stackLayout], { '$': this.$, 'widths': [1, 2] }
+               );
+               this.outlineVisible = true;
+               if ( this.editable ) {
+                       this.outlineControlsWidget = new OO.ui.OutlineControlsWidget(
+                               this.outlineWidget,
+                               { '$': this.$, 'adders': this.adders }
+                       );
+               }
+       }
+
+       // Events
+       this.stackLayout.connect( this, { 'set': 'onStackLayoutSet' } );
+       if ( this.outlined ) {
+               this.outlineWidget.connect( this, { 'select': 'onOutlineWidgetSelect' } );
+       }
+       if ( this.autoFocus ) {
+               // Event 'focus' does not bubble, but 'focusin' does
+               this.stackLayout.onDOMEvent( 'focusin', OO.ui.bind( this.onStackLayoutFocus, this ) );
+       }
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-bookletLayout' );
+       this.stackLayout.$element.addClass( 'oo-ui-bookletLayout-stackLayout' );
+       if ( this.outlined ) {
+               this.outlinePanel.$element
+                       .addClass( 'oo-ui-bookletLayout-outlinePanel' )
+                       .append( this.outlineWidget.$element );
+               if ( this.editable ) {
+                       this.outlinePanel.$element
+                               .addClass( 'oo-ui-bookletLayout-outlinePanel-editable' )
+                               .append( this.outlineControlsWidget.$element );
+               }
+               this.$element.append( this.gridLayout.$element );
+       } else {
+               this.$element.append( this.stackLayout.$element );
+       }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.BookletLayout, OO.ui.Layout );
+
+/* Events */
+
+/**
+ * @event set
+ * @param {OO.ui.PageLayout} page Current page
+ */
+
+/**
+ * @event add
+ * @param {OO.ui.PageLayout[]} page Added pages
+ * @param {number} index Index pages were added at
+ */
+
+/**
+ * @event remove
+ * @param {OO.ui.PageLayout[]} pages Removed pages
+ */
+
+/* Methods */
+
+/**
+ * Handle stack layout focus.
+ *
+ * @method
+ * @param {jQuery.Event} e Focusin event
+ */
+OO.ui.BookletLayout.prototype.onStackLayoutFocus = function ( e ) {
+       var name, $target;
+
+       if ( this.ignoreFocus ) {
+               // Avoid recursion from programmatic focus trigger in #onStackLayoutSet
+               return;
+       }
+
+       $target = $( e.target ).closest( '.oo-ui-pageLayout' );
+       for ( name in this.pages ) {
+               if ( this.pages[ name ].$element[0] === $target[0] ) {
+                       this.setPage( name );
+                       break;
+               }
+       }
+};
+
+/**
+ * Handle stack layout set events.
+ *
+ * @method
+ * @param {OO.ui.PanelLayout|null} page The page panel that is now the current panel
+ */
+OO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) {
+       if ( page ) {
+               this.stackLayout.$element.find( ':focus' ).blur();
+               page.scrollElementIntoView( { 'complete': OO.ui.bind( function () {
+                       this.ignoreFocus = true;
+                       if ( this.autoFocus ) {
+                               page.$element.find( ':input:first' ).focus();
+                       }
+                       this.ignoreFocus = false;
+               }, this ) } );
+       }
+};
+
+/**
+ * Handle outline widget select events.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget|null} item Selected item
+ */
+OO.ui.BookletLayout.prototype.onOutlineWidgetSelect = function ( item ) {
+       if ( item ) {
+               this.setPage( item.getData() );
+       }
+};
+
+/**
+ * Check if booklet has an outline.
+ *
+ * @method
+ * @returns {boolean} Booklet is outlined
+ */
+OO.ui.BookletLayout.prototype.isOutlined = function () {
+       return this.outlined;
+};
+
+/**
+ * Check if booklet has editing controls.
+ *
+ * @method
+ * @returns {boolean} Booklet is outlined
+ */
+OO.ui.BookletLayout.prototype.isEditable = function () {
+       return this.editable;
+};
+
+/**
+ * Check if booklet has editing controls.
+ *
+ * @method
+ * @returns {boolean} Booklet is outlined
+ */
+OO.ui.BookletLayout.prototype.isOutlineVisible = function () {
+       return this.outlined && this.outlineVisible;
+};
+
+/**
+ * Hide or show the outline.
+ *
+ * @param {boolean} [show] Show outline, omit to invert current state
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.toggleOutline = function ( show ) {
+       if ( this.outlined ) {
+               show = show === undefined ? !this.outlineVisible : !!show;
+               this.outlineVisible = show;
+               this.gridLayout.layout( show ? [ 1, 2 ] : [ 0, 1 ], [ 1 ] );
+       }
+
+       return this;
+};
+
+/**
+ * Get the outline widget.
+ *
+ * @method
+ * @param {OO.ui.PageLayout} page Page to be selected
+ * @returns {OO.ui.PageLayout|null} Closest page to another
+ */
+OO.ui.BookletLayout.prototype.getClosestPage = function ( page ) {
+       var next, prev, level,
+               pages = this.stackLayout.getItems(),
+               index = $.inArray( page, pages );
+
+       if ( index !== -1 ) {
+               next = pages[index + 1];
+               prev = pages[index - 1];
+               // Prefer adjacent pages at the same level
+               if ( this.outlined ) {
+                       level = this.outlineWidget.getItemFromData( page.getName() ).getLevel();
+                       if (
+                               prev &&
+                               level === this.outlineWidget.getItemFromData( prev.getName() ).getLevel()
+                       ) {
+                               return prev;
+                       }
+                       if (
+                               next &&
+                               level === this.outlineWidget.getItemFromData( next.getName() ).getLevel()
+                       ) {
+                               return next;
+                       }
+               }
+       }
+       return prev || next || null;
+};
+
+/**
+ * Get the outline widget.
+ *
+ * @method
+ * @returns {OO.ui.OutlineWidget|null} Outline widget, or null if boolet has no outline
+ */
+OO.ui.BookletLayout.prototype.getOutline = function () {
+       return this.outlineWidget;
+};
+
+/**
+ * Get the outline controls widget. If the outline is not editable, null is returned.
+ *
+ * @method
+ * @returns {OO.ui.OutlineControlsWidget|null} The outline controls widget.
+ */
+OO.ui.BookletLayout.prototype.getOutlineControls = function () {
+       return this.outlineControlsWidget;
+};
+
+/**
+ * Get a page by name.
+ *
+ * @method
+ * @param {string} name Symbolic name of page
+ * @returns {OO.ui.PageLayout|undefined} Page, if found
+ */
+OO.ui.BookletLayout.prototype.getPage = function ( name ) {
+       return this.pages[name];
+};
+
+/**
+ * Get the current page name.
+ *
+ * @method
+ * @returns {string|null} Current page name
+ */
+OO.ui.BookletLayout.prototype.getPageName = function () {
+       return this.currentPageName;
+};
+
+/**
+ * Add a page to the layout.
+ *
+ * When pages are added with the same names as existing pages, the existing pages will be
+ * automatically removed before the new pages are added.
+ *
+ * @method
+ * @param {OO.ui.PageLayout[]} pages Pages to add
+ * @param {number} index Index to insert pages after
+ * @fires add
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) {
+       var i, len, name, page, item, currentIndex,
+               stackLayoutPages = this.stackLayout.getItems(),
+               remove = [],
+               items = [];
+
+       // Remove pages with same names
+       for ( i = 0, len = pages.length; i < len; i++ ) {
+               page = pages[i];
+               name = page.getName();
+
+               if ( Object.prototype.hasOwnProperty.call( this.pages, name ) ) {
+                       // Correct the insertion index
+                       currentIndex = $.inArray( this.pages[name], stackLayoutPages );
+                       if ( currentIndex !== -1 && currentIndex + 1 < index ) {
+                               index--;
+                       }
+                       remove.push( this.pages[name] );
+               }
+       }
+       if ( remove.length ) {
+               this.removePages( remove );
+       }
+
+       // Add new pages
+       for ( i = 0, len = pages.length; i < len; i++ ) {
+               page = pages[i];
+               name = page.getName();
+               this.pages[page.getName()] = page;
+               if ( this.outlined ) {
+                       item = new OO.ui.OutlineItemWidget( name, page, { '$': this.$ } );
+                       page.setOutlineItem( item );
+                       items.push( item );
+               }
+       }
+
+       if ( this.outlined && items.length ) {
+               this.outlineWidget.addItems( items, index );
+               this.updateOutlineWidget();
+       }
+       this.stackLayout.addItems( pages, index );
+       this.emit( 'add', pages, index );
+
+       return this;
+};
+
+/**
+ * Remove a page from the layout.
+ *
+ * @method
+ * @fires remove
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.removePages = function ( pages ) {
+       var i, len, name, page,
+               items = [];
+
+       for ( i = 0, len = pages.length; i < len; i++ ) {
+               page = pages[i];
+               name = page.getName();
+               delete this.pages[name];
+               if ( this.outlined ) {
+                       items.push( this.outlineWidget.getItemFromData( name ) );
+                       page.setOutlineItem( null );
+               }
+       }
+       if ( this.outlined && items.length ) {
+               this.outlineWidget.removeItems( items );
+               this.updateOutlineWidget();
+       }
+       this.stackLayout.removeItems( pages );
+       this.emit( 'remove', pages );
+
+       return this;
+};
+
+/**
+ * Clear all pages from the layout.
+ *
+ * @method
+ * @fires remove
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.clearPages = function () {
+       var i, len,
+               pages = this.stackLayout.getItems();
+
+       this.pages = {};
+       this.currentPageName = null;
+       if ( this.outlined ) {
+               this.outlineWidget.clearItems();
+               for ( i = 0, len = pages.length; i < len; i++ ) {
+                       pages[i].setOutlineItem( null );
+               }
+       }
+       this.stackLayout.clearItems();
+
+       this.emit( 'remove', pages );
+
+       return this;
+};
+
+/**
+ * Set the current page by name.
+ *
+ * @method
+ * @fires set
+ * @param {string} name Symbolic name of page
+ */
+OO.ui.BookletLayout.prototype.setPage = function ( name ) {
+       var selectedItem,
+               page = this.pages[name];
+
+       if ( name !== this.currentPageName ) {
+               if ( this.outlined ) {
+                       selectedItem = this.outlineWidget.getSelectedItem();
+                       if ( selectedItem && selectedItem.getData() !== name ) {
+                               this.outlineWidget.selectItem( this.outlineWidget.getItemFromData( name ) );
+                       }
+               }
+               if ( page ) {
+                       if ( this.currentPageName && this.pages[this.currentPageName] ) {
+                               this.pages[this.currentPageName].setActive( false );
+                       }
+                       this.currentPageName = name;
+                       this.stackLayout.setItem( page );
+                       page.setActive( true );
+                       this.emit( 'set', page );
+               }
+       }
+};
+
+/**
+ * Call this after adding or removing items from the OutlineWidget.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.updateOutlineWidget = function () {
+       // Auto-select first item when nothing is selected anymore
+       if ( !this.outlineWidget.getSelectedItem() ) {
+               this.outlineWidget.selectItem( this.outlineWidget.getFirstSelectableItem() );
+       }
+
+       return this;
+};
+/**
+ * Layout that expands to cover the entire area of its parent, with optional scrolling and padding.
+ *
+ * @class
+ * @extends OO.ui.Layout
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [scrollable] Allow vertical scrolling
+ * @cfg {boolean} [padded] Pad the content from the edges
+ */
+OO.ui.PanelLayout = function OoUiPanelLayout( config ) {
+       // Config initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.PanelLayout.super.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-panelLayout' );
+       if ( config.scrollable ) {
+               this.$element.addClass( 'oo-ui-panelLayout-scrollable' );
+       }
+
+       if ( config.padded ) {
+               this.$element.addClass( 'oo-ui-panelLayout-padded' );
+       }
+
+       // Add directionality class:
+       this.$element.addClass( 'oo-ui-' + OO.ui.Element.getDir( this.$.context ) );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PanelLayout, OO.ui.Layout );
+/**
+ * Page within an OO.ui.BookletLayout.
+ *
+ * @class
+ * @extends OO.ui.PanelLayout
+ *
+ * @constructor
+ * @param {string} name Unique symbolic name of page
+ * @param {Object} [config] Configuration options
+ * @param {string} [outlineItem] Outline item widget
+ */
+OO.ui.PageLayout = function OoUiPageLayout( name, config ) {
+       // Configuration initialization
+       config = $.extend( { 'scrollable': true }, config );
+
+       // Parent constructor
+       OO.ui.PageLayout.super.call( this, config );
+
+       // Properties
+       this.name = name;
+       this.outlineItem = config.outlineItem || null;
+       this.active = false;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-pageLayout' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PageLayout, OO.ui.PanelLayout );
+
+/* Events */
+
+/**
+ * @event active
+ * @param {boolean} active Page is active
+ */
+
+/* Methods */
+
+/**
+ * Get page name.
+ *
+ * @returns {string} Symbolic name of page
+ */
+OO.ui.PageLayout.prototype.getName = function () {
+       return this.name;
+};
+
+/**
+ * Check if page is active.
+ *
+ * @returns {boolean} Page is active
+ */
+OO.ui.PageLayout.prototype.isActive = function () {
+       return this.active;
+};
+
+/**
+ * Get outline item.
+ *
+ * @returns {OO.ui.OutlineItemWidget|null} Outline item widget
+ */
+OO.ui.PageLayout.prototype.getOutlineItem = function () {
+       return this.outlineItem;
+};
+
+/**
+ * Get outline item.
+ *
+ * @param {OO.ui.OutlineItemWidget|null} outlineItem Outline item widget, null to clear
+ * @chainable
+ */
+OO.ui.PageLayout.prototype.setOutlineItem = function ( outlineItem ) {
+       this.outlineItem = outlineItem;
+       return this;
+};
+
+/**
+ * Set page active state.
+ *
+ * @param {boolean} Page is active
+ * @fires active
+ */
+OO.ui.PageLayout.prototype.setActive = function ( active ) {
+       active = !!active;
+
+       if ( active !== this.active ) {
+               this.active = active;
+               this.$element.toggleClass( 'oo-ui-pageLayout-active', active );
+               this.emit( 'active', this.active );
+       }
+};
+/**
+ * Layout containing a series of mutually exclusive pages.
+ *
+ * @class
+ * @extends OO.ui.PanelLayout
+ * @mixins OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [continuous=false] Show all pages, one after another
+ * @cfg {string} [icon=''] Symbolic icon name
+ * @cfg {OO.ui.Layout[]} [items] Layouts to add
+ */
+OO.ui.StackLayout = function OoUiStackLayout( config ) {
+       // Config initialization
+       config = $.extend( { 'scrollable': true }, config );
+
+       // Parent constructor
+       OO.ui.StackLayout.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.GroupElement.call( this, this.$element, config );
+
+       // Properties
+       this.currentItem = null;
+       this.continuous = !!config.continuous;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-stackLayout' );
+       if ( this.continuous ) {
+               this.$element.addClass( 'oo-ui-stackLayout-continuous' );
+       }
+       if ( $.isArray( config.items ) ) {
+               this.addItems( config.items );
+       }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.StackLayout, OO.ui.PanelLayout );
+OO.mixinClass( OO.ui.StackLayout, OO.ui.GroupElement );
+
+/* Events */
+
+/**
+ * @event set
+ * @param {OO.ui.PanelLayout|null} [item] Current item
+ */
+
+/* Methods */
+
+/**
+ * Add items.
+ *
+ * Adding an existing item (by value) will move it.
+ *
+ * @method
+ * @param {OO.ui.PanelLayout[]} items Items to add
+ * @param {number} [index] Index to insert items after
+ * @chainable
+ */
+OO.ui.StackLayout.prototype.addItems = function ( items, index ) {
+       OO.ui.GroupElement.prototype.addItems.call( this, items, index );
+
+       if ( !this.currentItem && items.length ) {
+               this.setItem( items[0] );
+       }
+
+       return this;
+};
+
+/**
+ * Remove items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @param {OO.ui.PanelLayout[]} items Items to remove
+ * @chainable
+ */
+OO.ui.StackLayout.prototype.removeItems = function ( items ) {
+       OO.ui.GroupElement.prototype.removeItems.call( this, items );
+       if ( $.inArray( this.currentItem, items  ) !== -1 ) {
+               this.currentItem = null;
+               if ( !this.currentItem && this.items.length ) {
+                       this.setItem( this.items[0] );
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Clear all items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.StackLayout.prototype.clearItems = function () {
+       this.currentItem = null;
+       OO.ui.GroupElement.prototype.clearItems.call( this );
+
+       return this;
+};
+
+/**
+ * Show item.
+ *
+ * Any currently shown item will be hidden.
+ *
+ * @method
+ * @param {OO.ui.PanelLayout} item Item to show
+ * @chainable
+ */
+OO.ui.StackLayout.prototype.setItem = function ( item ) {
+       if ( item !== this.currentItem ) {
+               if ( !this.continuous ) {
+                       this.$items.css( 'display', '' );
+               }
+               if ( $.inArray( item, this.items ) !== -1 ) {
+                       if ( !this.continuous ) {
+                               item.$element.css( 'display', 'block' );
+                       }
+               } else {
+                       item = null;
+               }
+               this.currentItem = item;
+               this.emit( 'set', item );
+       }
+
+       return this;
+};
+/**
+ * Horizontal bar layout of tools as icon buttons.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.ToolGroup
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.BarToolGroup = function OoUiBarToolGroup( toolbar, config ) {
+       // Parent constructor
+       OO.ui.BarToolGroup.super.call( this, toolbar, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-barToolGroup' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.BarToolGroup, OO.ui.ToolGroup );
+
+/* Static Properties */
+
+OO.ui.BarToolGroup.static.titleTooltips = true;
+
+OO.ui.BarToolGroup.static.accelTooltips = true;
+
+OO.ui.BarToolGroup.static.name = 'bar';
+/**
+ * Popup list of tools with an icon and optional label.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.ToolGroup
+ * @mixins OO.ui.IconedElement
+ * @mixins OO.ui.IndicatedElement
+ * @mixins OO.ui.LabeledElement
+ * @mixins OO.ui.TitledElement
+ * @mixins OO.ui.ClippableElement
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.PopupToolGroup.super.call( this, toolbar, config );
+
+       // Mixin constructors
+       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
+       OO.ui.TitledElement.call( this, this.$element, config );
+       OO.ui.ClippableElement.call( this, this.$group, config );
+
+       // Properties
+       this.active = false;
+       this.dragging = false;
+       this.onBlurHandler = OO.ui.bind( this.onBlur, this );
+       this.$handle = this.$( '<span>' );
+
+       // Events
+       this.$handle.on( {
+               'mousedown': OO.ui.bind( this.onHandleMouseDown, this ),
+               'mouseup': OO.ui.bind( this.onHandleMouseUp, this )
+       } );
+
+       // Initialization
+       this.$handle
+               .addClass( 'oo-ui-popupToolGroup-handle' )
+               .append( this.$icon, this.$label, this.$indicator );
+       this.$element
+               .addClass( 'oo-ui-popupToolGroup' )
+               .prepend( this.$handle );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PopupToolGroup, OO.ui.ToolGroup );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IconedElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IndicatedElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.LabeledElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.TitledElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.ClippableElement );
+
+/* Static Properties */
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.PopupToolGroup.prototype.setDisabled = function () {
+       // Parent method
+       OO.ui.PopupToolGroup.super.prototype.setDisabled.apply( this, arguments );
+
+       if ( this.isDisabled() && this.isElementAttached() ) {
+               this.setActive( false );
+       }
+};
+
+/**
+ * Handle focus being lost.
+ *
+ * The event is actually generated from a mouseup, so it is not a normal blur event object.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse up event
+ */
+OO.ui.PopupToolGroup.prototype.onBlur = function ( e ) {
+       // Only deactivate when clicking outside the dropdown element
+       if ( this.$( e.target ).closest( '.oo-ui-popupToolGroup' )[0] !== this.$element[0] ) {
+               this.setActive( false );
+       }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.PopupToolGroup.prototype.onMouseUp = function ( e ) {
+       if ( !this.disabled && e.which === 1 ) {
+               this.setActive( false );
+       }
+       return OO.ui.ToolGroup.prototype.onMouseUp.call( this, e );
+};
+
+/**
+ * Handle mouse up events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse up event
+ */
+OO.ui.PopupToolGroup.prototype.onHandleMouseUp = function () {
+       return false;
+};
+
+/**
+ * Handle mouse down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.PopupToolGroup.prototype.onHandleMouseDown = function ( e ) {
+       if ( !this.disabled && e.which === 1 ) {
+               this.setActive( !this.active );
+       }
+       return false;
+};
+
+/**
+ * Switch into active mode.
+ *
+ * When active, mouseup events anywhere in the document will trigger deactivation.
+ *
+ * @method
+ */
+OO.ui.PopupToolGroup.prototype.setActive = function ( value ) {
+       value = !!value;
+       if ( this.active !== value ) {
+               this.active = value;
+               if ( value ) {
+                       this.setClipping( true );
+                       this.$element.addClass( 'oo-ui-popupToolGroup-active' );
+                       this.getElementDocument().addEventListener( 'mouseup', this.onBlurHandler, true );
+               } else {
+                       this.setClipping( false );
+                       this.$element.removeClass( 'oo-ui-popupToolGroup-active' );
+                       this.getElementDocument().removeEventListener( 'mouseup', this.onBlurHandler, true );
+               }
+       }
+};
+/**
+ * Drop down list layout of tools as labeled icon buttons.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.PopupToolGroup
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ListToolGroup = function OoUiListToolGroup( toolbar, config ) {
+       // Parent constructor
+       OO.ui.ListToolGroup.super.call( this, toolbar, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-listToolGroup' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ListToolGroup, OO.ui.PopupToolGroup );
+
+/* Static Properties */
+
+OO.ui.ListToolGroup.static.accelTooltips = true;
+
+OO.ui.ListToolGroup.static.name = 'list';
+/**
+ * Drop down menu layout of tools as selectable menu items.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.PopupToolGroup
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.MenuToolGroup = function OoUiMenuToolGroup( toolbar, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.MenuToolGroup.super.call( this, toolbar, config );
+
+       // Events
+       this.toolbar.connect( this, { 'updateState': 'onUpdateState' } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-menuToolGroup' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MenuToolGroup, OO.ui.PopupToolGroup );
+
+/* Static Properties */
+
+OO.ui.MenuToolGroup.static.accelTooltips = true;
+
+OO.ui.MenuToolGroup.static.name = 'menu';
+
+/* Methods */
+
+/**
+ * Handle the toolbar state being updated.
+ *
+ * When the state changes, the title of each active item in the menu will be joined together and
+ * used as a label for the group. The label will be empty if none of the items are active.
+ *
+ * @method
+ */
+OO.ui.MenuToolGroup.prototype.onUpdateState = function () {
+       var name,
+               labelTexts = [];
+
+       for ( name in this.tools ) {
+               if ( this.tools[name].isActive() ) {
+                       labelTexts.push( this.tools[name].getTitle() );
+               }
+       }
+
+       this.setLabel( labelTexts.join( ', ' ) || ' ' );
+};
+/**
+ * UserInterface popup tool.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Tool
+ * @mixins OO.ui.PopuppableElement
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.PopupTool = function OoUiPopupTool( toolbar, config ) {
+       // Parent constructor
+       OO.ui.PopupTool.super.call( this, toolbar, config );
+
+       // Mixin constructors
+       OO.ui.PopuppableElement.call( this, config );
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-popupTool' )
+               .append( this.popup.$element );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PopupTool, OO.ui.Tool );
+OO.mixinClass( OO.ui.PopupTool, OO.ui.PopuppableElement );
+
+/* Methods */
+
+/**
+ * Handle the tool being selected.
+ *
+ * @inheritdoc
+ */
+OO.ui.PopupTool.prototype.onSelect = function () {
+       if ( !this.disabled ) {
+               if ( this.popup.isVisible() ) {
+                       this.hidePopup();
+               } else {
+                       this.showPopup();
+               }
+       }
+       this.setActive( false );
+       return false;
+};
+
+/**
+ * Handle the toolbar state being updated.
+ *
+ * @inheritdoc
+ */
+OO.ui.PopupTool.prototype.onUpdateState = function () {
+       this.setActive( false );
+};
+/**
+ * Group widget.
+ *
+ * Mixin for OO.ui.Widget subclasses.
+ *
+ * Use together with OO.ui.ItemWidget to make disabled state inheritable.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {jQuery} $group Container node, assigned to #$group
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.GroupWidget = function OoUiGroupWidget( $element, config ) {
+       // Parent constructor
+       OO.ui.GroupWidget.super.call( this, $element, config );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.GroupWidget, OO.ui.GroupElement );
+
+/* Methods */
+
+/**
+ * Set the disabled state of the widget.
+ *
+ * This will also update the disabled state of child widgets.
+ *
+ * @method
+ * @param {boolean} disabled Disable widget
+ * @chainable
+ */
+OO.ui.GroupWidget.prototype.setDisabled = function ( disabled ) {
+       var i, len;
+
+       // Parent method
+       // Note this is calling OO.ui.Widget; we're assuming the class this is mixed into
+       // is a subclass of OO.ui.Widget.
+       OO.ui.Widget.prototype.setDisabled.call( this, disabled );
+
+       // During construction, #setDisabled is called before the OO.ui.GroupElement constructor
+       if ( this.items ) {
+               for ( i = 0, len = this.items.length; i < len; i++ ) {
+                       this.items[i].updateDisabled();
+               }
+       }
+
+       return this;
+};
+/**
+ * Item widget.
+ *
+ * Use together with OO.ui.GroupWidget to make disabled state inheritable.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ */
+OO.ui.ItemWidget = function OoUiItemWidget() {
+       //
+};
+
+/* Methods */
+
+/**
+ * Check if widget is disabled.
+ *
+ * Checks parent if present, making disabled state inheritable.
+ *
+ * @returns {boolean} Widget is disabled
+ */
+OO.ui.ItemWidget.prototype.isDisabled = function () {
+       return this.disabled ||
+               ( this.elementGroup instanceof OO.ui.Widget && this.elementGroup.isDisabled() );
+};
+
+/**
+ * Set group element is in.
+ *
+ * @param {OO.ui.GroupElement|null} group Group element, null if none
+ * @chainable
+ */
+OO.ui.ItemWidget.prototype.setElementGroup = function ( group ) {
+       // Parent method
+       OO.ui.Element.prototype.setElementGroup.call( this, group );
+
+       // Initialize item disabled states
+       this.updateDisabled();
+
+       return this;
+};
+/**
+ * Creates an OO.ui.IconWidget object.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.IconedElement
+ * @mixins OO.ui.TitledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.IconWidget = function OoUiIconWidget( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.IconWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.IconedElement.call( this, this.$element, config );
+       OO.ui.TitledElement.call( this, this.$element, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-iconWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.IconWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.IconWidget, OO.ui.IconedElement );
+OO.mixinClass( OO.ui.IconWidget, OO.ui.TitledElement );
+
+/* Static Properties */
+
+OO.ui.IconWidget.static.tagName = 'span';
+/**
+ * Creates an OO.ui.IndicatorWidget object.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.IndicatedElement
+ * @mixins OO.ui.TitledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.IndicatorWidget = function OoUiIndicatorWidget( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.IndicatorWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.IndicatedElement.call( this, this.$element, config );
+       OO.ui.TitledElement.call( this, this.$element, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-indicatorWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.IndicatorWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.IndicatedElement );
+OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.TitledElement );
+
+/* Static Properties */
+
+OO.ui.IndicatorWidget.static.tagName = 'span';
+/**
+ * Container for multiple related buttons.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.ButtonWidget} [items] Buttons to add
+ */
+OO.ui.ButtonGroupWidget = function OoUiButtonGroupWidget( config ) {
+       // Parent constructor
+       OO.ui.ButtonGroupWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.GroupElement.call( this, this.$element, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-buttonGroupWidget' );
+       if ( $.isArray( config.items ) ) {
+               this.addItems( config.items );
+       }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ButtonGroupWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.ButtonGroupWidget, OO.ui.GroupElement );
+/**
+ * Creates an OO.ui.ButtonWidget object.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.ButtonedElement
+ * @mixins OO.ui.IconedElement
+ * @mixins OO.ui.IndicatedElement
+ * @mixins OO.ui.LabeledElement
+ * @mixins OO.ui.TitledElement
+ * @mixins OO.ui.FlaggableElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [title=''] Title text
+ * @cfg {string} [href] Hyperlink to visit when clicked
+ * @cfg {string} [target] Target to open hyperlink in
+ */
+OO.ui.ButtonWidget = function OoUiButtonWidget( config ) {
+       // Configuration initialization
+       config = $.extend( { 'target': '_blank' }, config );
+
+       // Parent constructor
+       OO.ui.ButtonWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.ButtonedElement.call( this, this.$( '<a>' ), config );
+       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
+       OO.ui.TitledElement.call( this, this.$button, config );
+       OO.ui.FlaggableElement.call( this, config );
+
+       // Properties
+       this.isHyperlink = typeof config.href === 'string';
+
+       // Events
+       this.$button.on( {
+               'click': OO.ui.bind( this.onClick, this ),
+               'keypress': OO.ui.bind( this.onKeyPress, this )
+       } );
+
+       // Initialization
+       this.$button
+               .append( this.$icon, this.$label, this.$indicator )
+               .attr( { 'href': config.href, 'target': config.target } );
+       this.$element
+               .addClass( 'oo-ui-buttonWidget' )
+               .append( this.$button );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ButtonWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.ButtonedElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IconedElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IndicatedElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.LabeledElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.TitledElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.FlaggableElement );
+
+/* Events */
+
+/**
+ * @event click
+ */
+
+/* Methods */
+
+/**
+ * Handles mouse click events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse click event
+ * @fires click
+ */
+OO.ui.ButtonWidget.prototype.onClick = function () {
+       if ( !this.disabled ) {
+               this.emit( 'click' );
+               if ( this.isHyperlink ) {
+                       return true;
+               }
+       }
+       return false;
+};
+
+/**
+ * Handles keypress events.
+ *
+ * @method
+ * @param {jQuery.Event} e Keypress event
+ * @fires click
+ */
+OO.ui.ButtonWidget.prototype.onKeyPress = function ( e ) {
+       if ( !this.disabled && e.which === OO.ui.Keys.SPACE ) {
+               if ( this.isHyperlink ) {
+                       this.onClick();
+                       return true;
+               }
+       }
+       return false;
+};
+/**
+ * Creates an OO.ui.InputWidget object.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [name=''] HTML input name
+ * @cfg {string} [value=''] Input value
+ * @cfg {boolean} [readOnly=false] Prevent changes
+ * @cfg {Function} [inputFilter] Filter function to apply to the input. Takes a string argument and returns a string.
+ */
+OO.ui.InputWidget = function OoUiInputWidget( config ) {
+       // Config intialization
+       config = $.extend( { 'readOnly': false }, config );
+
+       // Parent constructor
+       OO.ui.InputWidget.super.call( this, config );
+
+       // Properties
+       this.$input = this.getInputElement( config );
+       this.value = '';
+       this.readOnly = false;
+       this.inputFilter = config.inputFilter;
+
+       // Events
+       this.$input.on( 'keydown mouseup cut paste change input select', OO.ui.bind( this.onEdit, this ) );
+
+       // Initialization
+       this.$input
+               .attr( 'name', config.name )
+               .prop( 'disabled', this.disabled );
+       this.setReadOnly( config.readOnly );
+       this.$element.addClass( 'oo-ui-inputWidget' ).append( this.$input );
+       this.setValue( config.value );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.InputWidget, OO.ui.Widget );
+
+/* Events */
+
+/**
+ * @event change
+ * @param value
+ */
+
+/* Methods */
+
+/**
+ * Get input element.
+ *
+ * @method
+ * @param {Object} [config] Configuration options
+ * @returns {jQuery} Input element
+ */
+OO.ui.InputWidget.prototype.getInputElement = function () {
+       return this.$( '<input>' );
+};
+
+/**
+ * Handle potentially value-changing events.
+ *
+ * @method
+ * @param {jQuery.Event} e Key down, mouse up, cut, paste, change, input, or select event
+ */
+OO.ui.InputWidget.prototype.onEdit = function () {
+       if ( !this.disabled ) {
+               // Allow the stack to clear so the value will be updated
+               setTimeout( OO.ui.bind( function () {
+                       this.setValue( this.$input.val() );
+               }, this ) );
+       }
+};
+
+/**
+ * Get the value of the input.
+ *
+ * @method
+ * @returns {string} Input value
+ */
+OO.ui.InputWidget.prototype.getValue = function () {
+       return this.value;
+};
+
+/**
+ * Sets the direction of the current input, either RTL or LTR
+ *
+ * @method
+ * @param {boolean} isRTL
+ */
+OO.ui.InputWidget.prototype.setRTL = function ( isRTL ) {
+       if ( isRTL ) {
+               this.$input.removeClass( 'oo-ui-ltr' );
+               this.$input.addClass( 'oo-ui-rtl' );
+       } else {
+               this.$input.removeClass( 'oo-ui-rtl' );
+               this.$input.addClass( 'oo-ui-ltr' );
+       }
+};
+
+/**
+ * Set the value of the input.
+ *
+ * @method
+ * @param {string} value New value
+ * @fires change
+ * @chainable
+ */
+OO.ui.InputWidget.prototype.setValue = function ( value ) {
+       value = this.sanitizeValue( value );
+       if ( this.value !== value ) {
+               this.value = value;
+               this.emit( 'change', this.value );
+       }
+       // Update the DOM if it has changed. Note that with sanitizeValue, it
+       // is possible for the DOM value to change without this.value changing.
+       if ( this.$input.val() !== this.value ) {
+               this.$input.val( this.value );
+       }
+       return this;
+};
+
+/**
+ * Sanitize incoming value.
+ *
+ * Ensures value is a string, and converts undefined and null to empty strings.
+ *
+ * @method
+ * @param {string} value Original value
+ * @returns {string} Sanitized value
+ */
+OO.ui.InputWidget.prototype.sanitizeValue = function ( value ) {
+       if ( value === undefined || value === null ) {
+               return '';
+       } else if ( this.inputFilter ) {
+               return this.inputFilter( String( value ) );
+       } else {
+               return String( value );
+       }
+};
+
+/**
+ * Simulate the behavior of clicking on a label bound to this input.
+ *
+ * @method
+ */
+OO.ui.InputWidget.prototype.simulateLabelClick = function () {
+       if ( !this.isDisabled() ) {
+               if ( this.$input.is( ':checkbox,:radio' ) ) {
+                       this.$input.click();
+               } else if ( this.$input.is( ':input' ) ) {
+                       this.$input.focus();
+               }
+       }
+};
+
+/**
+ * Check if the widget is read-only.
+ *
+ * @method
+ * @param {boolean} Input is read-only
+ */
+OO.ui.InputWidget.prototype.isReadOnly = function () {
+       return this.readOnly;
+};
+
+/**
+ * Set the read-only state of the widget.
+ *
+ * This should probably change the widgets's appearance and prevent it from being used.
+ *
+ * @method
+ * @param {boolean} state Make input read-only
+ * @chainable
+ */
+OO.ui.InputWidget.prototype.setReadOnly = function ( state ) {
+       this.readOnly = !!state;
+       this.$input.prop( 'readonly', this.readOnly );
+       return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.InputWidget.prototype.setDisabled = function ( state ) {
+       OO.ui.Widget.prototype.setDisabled.call( this, state );
+       if ( this.$input ) {
+               this.$input.prop( 'disabled', this.disabled );
+       }
+       return this;
+};
+/**
+ * Creates an OO.ui.CheckboxInputWidget object.
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.CheckboxInputWidget = function OoUiCheckboxInputWidget( config ) {
+       // Parent constructor
+       OO.ui.CheckboxInputWidget.super.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-checkboxInputWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.CheckboxInputWidget, OO.ui.InputWidget );
+
+/* Events */
+
+/* Methods */
+
+/**
+ * Get input element.
+ *
+ * @returns {jQuery} Input element
+ */
+OO.ui.CheckboxInputWidget.prototype.getInputElement = function () {
+       return this.$( '<input type="checkbox" />' );
+};
+
+/**
+ * Get checked state of the checkbox
+ *
+ * @returns {boolean} If the checkbox is checked
+ */
+OO.ui.CheckboxInputWidget.prototype.getValue = function () {
+       return this.value;
+};
+
+/**
+ * Set value
+ */
+OO.ui.CheckboxInputWidget.prototype.setValue = function ( value ) {
+       value = !!value;
+       if ( this.value !== value ) {
+               this.value = value;
+               this.$input.prop( 'checked', this.value );
+               this.emit( 'change', this.value );
+       }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxInputWidget.prototype.onEdit = function () {
+       if ( !this.disabled ) {
+               // Allow the stack to clear so the value will be updated
+               setTimeout( OO.ui.bind( function () {
+                       this.setValue( this.$input.prop( 'checked' ) );
+               }, this ) );
+       }
+};
+/**
+ * Creates an OO.ui.LabelWidget object.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.LabeledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.LabelWidget = function OoUiLabelWidget( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.LabelWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.LabeledElement.call( this, this.$element, config );
+
+       // Properties
+       this.input = config.input;
+
+       // Events
+       if ( this.input instanceof OO.ui.InputWidget ) {
+               this.$element.on( 'click', OO.ui.bind( this.onClick, this ) );
+       }
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-labelWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.LabelWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.LabelWidget, OO.ui.LabeledElement );
+
+/* Static Properties */
+
+OO.ui.LabelWidget.static.tagName = 'label';
+
+/* Methods */
+
+/**
+ * Handles label mouse click events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse click event
+ */
+OO.ui.LabelWidget.prototype.onClick = function () {
+       this.input.simulateLabelClick();
+       return false;
+};
+/**
+ * Lookup input widget.
+ *
+ * Mixin that adds a menu showing suggested values to a text input. Subclasses must handle `select`
+ * and `choose` events on #lookupMenu to make use of selections.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {OO.ui.TextInputWidget} input Input widget
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$overlay=this.$( 'body' )] Overlay layer
+ */
+OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.lookupInput = input;
+       this.$overlay = config.$overlay || this.$( 'body,.oo-ui-window-overlay' ).last();
+       this.lookupMenu = new OO.ui.TextInputMenuWidget( this, {
+               '$': OO.ui.Element.getJQuery( this.$overlay ),
+               'input': this.lookupInput,
+               '$container': config.$container
+       } );
+       this.lookupCache = {};
+       this.lookupQuery = null;
+       this.lookupRequest = null;
+       this.populating = false;
+
+       // Events
+       this.$overlay.append( this.lookupMenu.$element );
+
+       this.lookupInput.$input.on( {
+               'focus': OO.ui.bind( this.onLookupInputFocus, this ),
+               'blur': OO.ui.bind( this.onLookupInputBlur, this ),
+               'mousedown': OO.ui.bind( this.onLookupInputMouseDown, this )
+       } );
+       this.lookupInput.connect( this, { 'change': 'onLookupInputChange' } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-lookupWidget' );
+       this.lookupMenu.$element.addClass( 'oo-ui-lookupWidget-menu' );
+};
+
+/* Methods */
+
+/**
+ * Handle input focus event.
+ *
+ * @method
+ * @param {jQuery.Event} e Input focus event
+ */
+OO.ui.LookupInputWidget.prototype.onLookupInputFocus = function () {
+       this.openLookupMenu();
+};
+
+/**
+ * Handle input blur event.
+ *
+ * @method
+ * @param {jQuery.Event} e Input blur event
+ */
+OO.ui.LookupInputWidget.prototype.onLookupInputBlur = function () {
+       this.lookupMenu.hide();
+};
+
+/**
+ * Handle input mouse down event.
+ *
+ * @method
+ * @param {jQuery.Event} e Input mouse down event
+ */
+OO.ui.LookupInputWidget.prototype.onLookupInputMouseDown = function () {
+       this.openLookupMenu();
+};
+
+/**
+ * Handle input change event.
+ *
+ * @method
+ * @param {string} value New input value
+ */
+OO.ui.LookupInputWidget.prototype.onLookupInputChange = function () {
+       this.openLookupMenu();
+};
+
+/**
+ * Open the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.LookupInputWidget.prototype.openLookupMenu = function () {
+       var value = this.lookupInput.getValue();
+
+       if ( this.lookupMenu.$input.is( ':focus' ) && $.trim( value ) !== '' ) {
+               this.populateLookupMenu();
+               if ( !this.lookupMenu.isVisible() ) {
+                       this.lookupMenu.show();
+               }
+       } else {
+               this.lookupMenu.clearItems();
+               this.lookupMenu.hide();
+       }
+
+       return this;
+};
+
+/**
+ * Populate lookup menu with current information.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.LookupInputWidget.prototype.populateLookupMenu = function () {
+       if ( !this.populating ) {
+               this.populating = true;
+               this.getLookupMenuItems()
+                       .done( OO.ui.bind( function ( items ) {
+                               this.lookupMenu.clearItems();
+                               if ( items.length ) {
+                                       this.lookupMenu.show();
+                                       this.lookupMenu.addItems( items );
+                                       this.initializeLookupMenuSelection();
+                                       this.openLookupMenu();
+                               } else {
+                                       this.lookupMenu.hide();
+                               }
+                               this.populating = false;
+                       }, this ) )
+                       .fail( OO.ui.bind( function () {
+                               this.lookupMenu.clearItems();
+                               this.populating = false;
+                       }, this ) );
+       }
+
+       return this;
+};
+
+/**
+ * Set selection in the lookup menu with current information.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.LookupInputWidget.prototype.initializeLookupMenuSelection = function () {
+       if ( !this.lookupMenu.getSelectedItem() ) {
+               this.lookupMenu.selectItem( this.lookupMenu.getFirstSelectableItem() );
+       }
+       this.lookupMenu.highlightItem( this.lookupMenu.getSelectedItem() );
+};
+
+/**
+ * Get lookup menu items for the current query.
+ *
+ * @method
+ * @returns {jQuery.Promise} Promise object which will be passed menu items as the first argument
+ * of the done event
+ */
+OO.ui.LookupInputWidget.prototype.getLookupMenuItems = function () {
+       var value = this.lookupInput.getValue(),
+               deferred = $.Deferred();
+
+       if ( value && value !== this.lookupQuery ) {
+               // Abort current request if query has changed
+               if ( this.lookupRequest ) {
+                       this.lookupRequest.abort();
+                       this.lookupQuery = null;
+                       this.lookupRequest = null;
+               }
+               if ( value in this.lookupCache ) {
+                       deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) );
+               } else {
+                       this.lookupQuery = value;
+                       this.lookupRequest = this.getLookupRequest()
+                               .always( OO.ui.bind( function () {
+                                       this.lookupQuery = null;
+                                       this.lookupRequest = null;
+                               }, this ) )
+                               .done( OO.ui.bind( function ( data ) {
+                                       this.lookupCache[value] = this.getLookupCacheItemFromData( data );
+                                       deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) );
+                               }, this ) )
+                               .fail( function () {
+                                       deferred.reject();
+                               } );
+                       this.pushPending();
+                       this.lookupRequest.always( OO.ui.bind( function () {
+                               this.popPending();
+                       }, this ) );
+               }
+       }
+       return deferred.promise();
+};
+
+/**
+ * Get a new request object of the current lookup query value.
+ *
+ * @method
+ * @abstract
+ * @returns {jqXHR} jQuery AJAX object, or promise object with an .abort() method
+ */
+OO.ui.LookupInputWidget.prototype.getLookupRequest = function () {
+       // Stub, implemented in subclass
+       return null;
+};
+
+/**
+ * Handle successful lookup request.
+ *
+ * Overriding methods should call #populateLookupMenu when results are available and cache results
+ * for future lookups in #lookupCache as an array of #OO.ui.MenuItemWidget objects.
+ *
+ * @method
+ * @abstract
+ * @param {Mixed} data Response from server
+ */
+OO.ui.LookupInputWidget.prototype.onLookupRequestDone = function () {
+       // Stub, implemented in subclass
+};
+
+/**
+ * Get a list of menu item widgets from the data stored by the lookup request's done handler.
+ *
+ * @method
+ * @abstract
+ * @param {Mixed} data Cached result data, usually an array
+ * @returns {OO.ui.MenuItemWidget[]} Menu items
+ */
+OO.ui.LookupInputWidget.prototype.getLookupMenuItemsFromData = function () {
+       // Stub, implemented in subclass
+       return [];
+};
+/**
+ * Creates an OO.ui.OptionWidget object.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.IconedElement
+ * @mixins OO.ui.LabeledElement
+ * @mixins OO.ui.IndicatedElement
+ * @mixins OO.ui.FlaggableElement
+ *
+ * @constructor
+ * @param {Mixed} data Option data
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [rel] Value for `rel` attribute in DOM, allowing per-option styling
+ */
+OO.ui.OptionWidget = function OoUiOptionWidget( data, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.OptionWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.ItemWidget.call( this );
+       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
+       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.FlaggableElement.call( this, config );
+
+       // Properties
+       this.data = data;
+       this.selected = false;
+       this.highlighted = false;
+       this.pressed = false;
+
+       // Initialization
+       this.$element
+               .data( 'oo-ui-optionWidget', this )
+               .attr( 'rel', config.rel )
+               .addClass( 'oo-ui-optionWidget' )
+               .append( this.$label );
+       this.$element
+               .prepend( this.$icon )
+               .append( this.$indicator );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.OptionWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.ItemWidget );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.IconedElement );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.LabeledElement );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.IndicatedElement );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.FlaggableElement );
+
+/* Static Properties */
+
+OO.ui.OptionWidget.static.tagName = 'li';
+
+OO.ui.OptionWidget.static.selectable = true;
+
+OO.ui.OptionWidget.static.highlightable = true;
+
+OO.ui.OptionWidget.static.pressable = true;
+
+OO.ui.OptionWidget.static.scrollIntoViewOnSelect = false;
+
+/* Methods */
+
+/**
+ * Check if option can be selected.
+ *
+ * @method
+ * @returns {boolean} Item is selectable
+ */
+OO.ui.OptionWidget.prototype.isSelectable = function () {
+       return this.constructor.static.selectable && !this.disabled;
+};
+
+/**
+ * Check if option can be highlighted.
+ *
+ * @method
+ * @returns {boolean} Item is highlightable
+ */
+OO.ui.OptionWidget.prototype.isHighlightable = function () {
+       return this.constructor.static.highlightable && !this.disabled;
+};
+
+/**
+ * Check if option can be pressed.
+ *
+ * @method
+ * @returns {boolean} Item is pressable
+ */
+OO.ui.OptionWidget.prototype.isPressable = function () {
+       return this.constructor.static.pressable && !this.disabled;
+};
+
+/**
+ * Check if option is selected.
+ *
+ * @method
+ * @returns {boolean} Item is selected
+ */
+OO.ui.OptionWidget.prototype.isSelected = function () {
+       return this.selected;
+};
+
+/**
+ * Check if option is highlighted.
+ *
+ * @method
+ * @returns {boolean} Item is highlighted
+ */
+OO.ui.OptionWidget.prototype.isHighlighted = function () {
+       return this.highlighted;
+};
+
+/**
+ * Check if option is pressed.
+ *
+ * @method
+ * @returns {boolean} Item is pressed
+ */
+OO.ui.OptionWidget.prototype.isPressed = function () {
+       return this.pressed;
+};
+
+/**
+ * Set selected state.
+ *
+ * @method
+ * @param {boolean} [state=false] Select option
+ * @chainable
+ */
+OO.ui.OptionWidget.prototype.setSelected = function ( state ) {
+       if ( !this.disabled && this.constructor.static.selectable ) {
+               this.selected = !!state;
+               if ( this.selected ) {
+                       this.$element.addClass( 'oo-ui-optionWidget-selected' );
+                       if ( this.constructor.static.scrollIntoViewOnSelect ) {
+                               this.scrollElementIntoView();
+                       }
+               } else {
+                       this.$element.removeClass( 'oo-ui-optionWidget-selected' );
+               }
+       }
+       return this;
+};
+
+/**
+ * Set highlighted state.
+ *
+ * @method
+ * @param {boolean} [state=false] Highlight option
+ * @chainable
+ */
+OO.ui.OptionWidget.prototype.setHighlighted = function ( state ) {
+       if ( !this.disabled && this.constructor.static.highlightable ) {
+               this.highlighted = !!state;
+               if ( this.highlighted ) {
+                       this.$element.addClass( 'oo-ui-optionWidget-highlighted' );
+               } else {
+                       this.$element.removeClass( 'oo-ui-optionWidget-highlighted' );
+               }
+       }
+       return this;
+};
+
+/**
+ * Set pressed state.
+ *
+ * @method
+ * @param {boolean} [state=false] Press option
+ * @chainable
+ */
+OO.ui.OptionWidget.prototype.setPressed = function ( state ) {
+       if ( !this.disabled && this.constructor.static.pressable ) {
+               this.pressed = !!state;
+               if ( this.pressed ) {
+                       this.$element.addClass( 'oo-ui-optionWidget-pressed' );
+               } else {
+                       this.$element.removeClass( 'oo-ui-optionWidget-pressed' );
+               }
+       }
+       return this;
+};
+
+/**
+ * Make the option's highlight flash.
+ *
+ * While flashing, the visual style of the pressed state is removed if present.
+ *
+ * @method
+ * @param {Function} [done] Callback to execute when flash effect is complete.
+ */
+OO.ui.OptionWidget.prototype.flash = function ( done ) {
+       var $this = this.$element;
+
+       if ( !this.disabled && this.constructor.static.pressable ) {
+               $this.removeClass( 'oo-ui-optionWidget-highlighted oo-ui-optionWidget-pressed' );
+               setTimeout( OO.ui.bind( function () {
+                       $this.addClass( 'oo-ui-optionWidget-highlighted' );
+                       if ( done ) {
+                               // Restore original classes
+                               $this
+                                       .toggleClass( 'oo-ui-optionWidget-highlighted', this.highlighted )
+                                       .toggleClass( 'oo-ui-optionWidget-pressed', this.pressed );
+                               setTimeout( done, 100 );
+                       }
+               }, this ), 100 );
+       }
+};
+
+/**
+ * Get option data.
+ *
+ * @method
+ * @returns {Mixed} Option data
+ */
+OO.ui.OptionWidget.prototype.getData = function () {
+       return this.data;
+};
+/**
+ * Create an OO.ui.SelectWidget object.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.OptionWidget[]} [items] Options to add
+ */
+OO.ui.SelectWidget = function OoUiSelectWidget( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.SelectWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.GroupWidget.call( this, this.$element, config );
+
+       // Properties
+       this.pressed = false;
+       this.selecting = null;
+       this.hashes = {};
+
+       // Events
+       this.$element.on( {
+               'mousedown': OO.ui.bind( this.onMouseDown, this ),
+               'mouseup': OO.ui.bind( this.onMouseUp, this ),
+               'mousemove': OO.ui.bind( this.onMouseMove, this ),
+               'mouseover': OO.ui.bind( this.onMouseOver, this ),
+               'mouseleave': OO.ui.bind( this.onMouseLeave, this )
+       } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-selectWidget oo-ui-selectWidget-depressed' );
+       if ( $.isArray( config.items ) ) {
+               this.addItems( config.items );
+       }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.SelectWidget, OO.ui.Widget );
+
+// Need to mixin base class as well
+OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupElement );
+OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupWidget );
+
+/* Events */
+
+/**
+ * @event highlight
+ * @param {OO.ui.OptionWidget|null} item Highlighted item
+ */
+
+/**
+ * @event press
+ * @param {OO.ui.OptionWidget|null} item Pressed item
+ */
+
+/**
+ * @event select
+ * @param {OO.ui.OptionWidget|null} item Selected item
+ */
+
+/**
+ * @event choose
+ * @param {OO.ui.OptionWidget|null} item Chosen item
+ */
+
+/**
+ * @event add
+ * @param {OO.ui.OptionWidget[]} items Added items
+ * @param {number} index Index items were added at
+ */
+
+/**
+ * @event remove
+ * @param {OO.ui.OptionWidget[]} items Removed items
+ */
+
+/* Static Properties */
+
+OO.ui.SelectWidget.static.tagName = 'ul';
+
+/* Methods */
+
+/**
+ * Handle mouse down events.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.SelectWidget.prototype.onMouseDown = function ( e ) {
+       var item;
+
+       if ( !this.disabled && e.which === 1 ) {
+               this.togglePressed( true );
+               item = this.getTargetItem( e );
+               if ( item && item.isSelectable() ) {
+                       this.pressItem( item );
+                       this.selecting = item;
+                       this.$( this.$.context ).one( 'mouseup', OO.ui.bind( this.onMouseUp, this ) );
+               }
+       }
+       return false;
+};
+
+/**
+ * Handle mouse up events.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e Mouse up event
+ */
+OO.ui.SelectWidget.prototype.onMouseUp = function ( e ) {
+       var item;
+
+       this.togglePressed( false );
+       if ( !this.selecting ) {
+               item = this.getTargetItem( e );
+               if ( item && item.isSelectable() ) {
+                       this.selecting = item;
+               }
+       }
+       if ( !this.disabled && e.which === 1 && this.selecting ) {
+               this.pressItem( null );
+               this.chooseItem( this.selecting );
+               this.selecting = null;
+       }
+
+       return false;
+};
+
+/**
+ * Handle mouse move events.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e Mouse move event
+ */
+OO.ui.SelectWidget.prototype.onMouseMove = function ( e ) {
+       var item;
+
+       if ( !this.disabled && this.pressed ) {
+               item = this.getTargetItem( e );
+               if ( item && item !== this.selecting && item.isSelectable() ) {
+                       this.pressItem( item );
+                       this.selecting = item;
+               }
+       }
+       return false;
+};
+
+/**
+ * Handle mouse over events.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e Mouse over event
+ */
+OO.ui.SelectWidget.prototype.onMouseOver = function ( e ) {
+       var item;
+
+       if ( !this.disabled ) {
+               item = this.getTargetItem( e );
+               this.highlightItem( item && item.isHighlightable() ? item : null );
+       }
+       return false;
+};
+
+/**
+ * Handle mouse leave events.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e Mouse over event
+ */
+OO.ui.SelectWidget.prototype.onMouseLeave = function () {
+       if ( !this.disabled ) {
+               this.highlightItem( null );
+       }
+       return false;
+};
+
+/**
+ * Get the closest item to a jQuery.Event.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e
+ * @returns {OO.ui.OptionWidget|null} Outline item widget, `null` if none was found
+ */
+OO.ui.SelectWidget.prototype.getTargetItem = function ( e ) {
+       var $item = this.$( e.target ).closest( '.oo-ui-optionWidget' );
+       if ( $item.length ) {
+               return $item.data( 'oo-ui-optionWidget' );
+       }
+       return null;
+};
+
+/**
+ * Get selected item.
+ *
+ * @method
+ * @returns {OO.ui.OptionWidget|null} Selected item, `null` if no item is selected
+ */
+OO.ui.SelectWidget.prototype.getSelectedItem = function () {
+       var i, len;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               if ( this.items[i].isSelected() ) {
+                       return this.items[i];
+               }
+       }
+       return null;
+};
+
+/**
+ * Get highlighted item.
+ *
+ * @method
+ * @returns {OO.ui.OptionWidget|null} Highlighted item, `null` if no item is highlighted
+ */
+OO.ui.SelectWidget.prototype.getHighlightedItem = function () {
+       var i, len;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               if ( this.items[i].isHighlighted() ) {
+                       return this.items[i];
+               }
+       }
+       return null;
+};
+
+/**
+ * Get an existing item with equivilant data.
+ *
+ * @method
+ * @param {Object} data Item data to search for
+ * @returns {OO.ui.OptionWidget|null} Item with equivilent value, `null` if none exists
+ */
+OO.ui.SelectWidget.prototype.getItemFromData = function ( data ) {
+       var hash = OO.getHash( data );
+
+       if ( hash in this.hashes ) {
+               return this.hashes[hash];
+       }
+
+       return null;
+};
+
+/**
+ * Toggle pressed state.
+ *
+ * @param {boolean} pressed An option is being pressed
+ */
+OO.ui.SelectWidget.prototype.togglePressed = function ( pressed ) {
+       if ( pressed === undefined ) {
+               pressed = !this.pressed;
+       }
+       if ( pressed !== this.pressed ) {
+               this.$element.toggleClass( 'oo-ui-selectWidget-pressed', pressed );
+               this.$element.toggleClass( 'oo-ui-selectWidget-depressed', !pressed );
+               this.pressed = pressed;
+       }
+};
+
+/**
+ * Highlight an item.
+ *
+ * Highlighting is mutually exclusive.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} [item] Item to highlight, omit to deselect all
+ * @fires highlight
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.highlightItem = function ( item ) {
+       var i, len, highlighted,
+               changed = false;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               highlighted = this.items[i] === item;
+               if ( this.items[i].isHighlighted() !== highlighted ) {
+                       this.items[i].setHighlighted( highlighted );
+                       changed = true;
+               }
+       }
+       if ( changed ) {
+               this.emit( 'highlight', item );
+       }
+
+       return this;
+};
+
+/**
+ * Select an item.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
+ * @fires select
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.selectItem = function ( item ) {
+       var i, len, selected,
+               changed = false;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               selected = this.items[i] === item;
+               if ( this.items[i].isSelected() !== selected ) {
+                       this.items[i].setSelected( selected );
+                       changed = true;
+               }
+       }
+       if ( changed ) {
+               this.emit( 'select', item );
+       }
+
+       return this;
+};
+
+/**
+ * Press an item.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} [item] Item to press, omit to depress all
+ * @fires press
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.pressItem = function ( item ) {
+       var i, len, pressed,
+               changed = false;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               pressed = this.items[i] === item;
+               if ( this.items[i].isPressed() !== pressed ) {
+                       this.items[i].setPressed( pressed );
+                       changed = true;
+               }
+       }
+       if ( changed ) {
+               this.emit( 'press', item );
+       }
+
+       return this;
+};
+
+/**
+ * Choose an item.
+ *
+ * Identical to #selectItem, but may vary in subclasses that want to take additional action when
+ * an item is selected using the keyboard or mouse.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} item Item to choose
+ * @fires choose
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.chooseItem = function ( item ) {
+       this.selectItem( item );
+       this.emit( 'choose', item );
+
+       return this;
+};
+
+/**
+ * Get an item relative to another one.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} item Item to start at
+ * @param {number} direction Direction to move in
+ * @returns {OO.ui.OptionWidget|null} Item at position, `null` if there are no items in the menu
+ */
+OO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direction ) {
+       var inc = direction > 0 ? 1 : -1,
+               len = this.items.length,
+               index = item instanceof OO.ui.OptionWidget ?
+                       $.inArray( item, this.items ) : ( inc > 0 ? -1 : 0 ),
+               stopAt = Math.max( Math.min( index, len - 1 ), 0 ),
+               i = inc > 0 ?
+                       // Default to 0 instead of -1, if nothing is selected let's start at the beginning
+                       Math.max( index, -1 ) :
+                       // Default to n-1 instead of -1, if nothing is selected let's start at the end
+                       Math.min( index, len );
+
+       while ( true ) {
+               i = ( i + inc + len ) % len;
+               item = this.items[i];
+               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
+                       return item;
+               }
+               // Stop iterating when we've looped all the way around
+               if ( i === stopAt ) {
+                       break;
+               }
+       }
+       return null;
+};
+
+/**
+ * Get the next selectable item.
+ *
+ * @method
+ * @returns {OO.ui.OptionWidget|null} Item, `null` if ther aren't any selectable items
+ */
+OO.ui.SelectWidget.prototype.getFirstSelectableItem = function () {
+       var i, len, item;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               item = this.items[i];
+               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
+                       return item;
+               }
+       }
+
+       return null;
+};
+
+/**
+ * Add items.
+ *
+ * When items are added with the same values as existing items, the existing items will be
+ * automatically removed before the new items are added.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget[]} items Items to add
+ * @param {number} [index] Index to insert items after
+ * @fires add
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.addItems = function ( items, index ) {
+       var i, len, item, hash,
+               remove = [];
+
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+               hash = OO.getHash( item.getData() );
+               if ( hash in this.hashes ) {
+                       // Remove item with same value
+                       remove.push( this.hashes[hash] );
+               }
+               this.hashes[hash] = item;
+       }
+       if ( remove.length ) {
+               this.removeItems( remove );
+       }
+
+       OO.ui.GroupElement.prototype.addItems.call( this, items, index );
+
+       // Always provide an index, even if it was omitted
+       this.emit( 'add', items, index === undefined ? this.items.length - items.length - 1 : index );
+
+       return this;
+};
+
+/**
+ * Remove items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget[]} items Items to remove
+ * @fires remove
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.removeItems = function ( items ) {
+       var i, len, item, hash;
+
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+               hash = OO.getHash( item.getData() );
+               if ( hash in this.hashes ) {
+                       // Remove existing item
+                       delete this.hashes[hash];
+               }
+               if ( item.isSelected() ) {
+                       this.selectItem( null );
+               }
+       }
+       OO.ui.GroupElement.prototype.removeItems.call( this, items );
+
+       this.emit( 'remove', items );
+
+       return this;
+};
+
+/**
+ * Clear all items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @fires remove
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.clearItems = function () {
+       var items = this.items.slice();
+
+       // Clear all items
+       this.hashes = {};
+       OO.ui.GroupElement.prototype.clearItems.call( this );
+       this.selectItem( null );
+
+       this.emit( 'remove', items );
+
+       return this;
+};
+/**
+ * Creates an OO.ui.MenuItemWidget object.
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ *
+ * @constructor
+ * @param {Mixed} data Item data
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.MenuItemWidget = function OoUiMenuItemWidget( data, config ) {
+       // Configuration initialization
+       config = $.extend( { 'icon': 'check' }, config );
+
+       // Parent constructor
+       OO.ui.MenuItemWidget.super.call( this, data, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-menuItemWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MenuItemWidget, OO.ui.OptionWidget );
+/**
+ * Create an OO.ui.MenuWidget object.
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ * @mixins OO.ui.ClippableElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.InputWidget} [input] Input to bind keyboard handlers to
+ */
+OO.ui.MenuWidget = function OoUiMenuWidget( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.MenuWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.ClippableElement.call( this, this.$group, config );
+
+       // Properties
+       this.newItems = null;
+       this.$input = config.input ? config.input.$input : null;
+       this.$previousFocus = null;
+       this.isolated = !config.input;
+       this.visible = false;
+       this.flashing = false;
+       this.onKeyDownHandler = OO.ui.bind( this.onKeyDown, this );
+
+       // Initialization
+       this.$element.hide().addClass( 'oo-ui-menuWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MenuWidget, OO.ui.SelectWidget );
+OO.mixinClass( OO.ui.MenuWidget, OO.ui.ClippableElement );
+
+/* Methods */
+
+/**
+ * Handles key down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.MenuWidget.prototype.onKeyDown = function ( e ) {
+       var nextItem,
+               handled = false,
+               highlightItem = this.getHighlightedItem();
+
+       if ( !this.disabled && this.visible ) {
+               if ( !highlightItem ) {
+                       highlightItem = this.getSelectedItem();
+               }
+               switch ( e.keyCode ) {
+                       case OO.ui.Keys.ENTER:
+                               this.chooseItem( highlightItem );
+                               handled = true;
+                               break;
+                       case OO.ui.Keys.UP:
+                               nextItem = this.getRelativeSelectableItem( highlightItem, -1 );
+                               handled = true;
+                               break;
+                       case OO.ui.Keys.DOWN:
+                               nextItem = this.getRelativeSelectableItem( highlightItem, 1 );
+                               handled = true;
+                               break;
+                       case OO.ui.Keys.ESCAPE:
+                               if ( highlightItem ) {
+                                       highlightItem.setHighlighted( false );
+                               }
+                               this.hide();
+                               handled = true;
+                               break;
+               }
+
+               if ( nextItem ) {
+                       this.highlightItem( nextItem );
+                       nextItem.scrollElementIntoView();
+               }
+
+               if ( handled ) {
+                       e.preventDefault();
+                       e.stopPropagation();
+                       return false;
+               }
+       }
+};
+
+/**
+ * Check if the menu is visible.
+ *
+ * @method
+ * @returns {boolean} Menu is visible
+ */
+OO.ui.MenuWidget.prototype.isVisible = function () {
+       return this.visible;
+};
+
+/**
+ * Bind key down listener
+ *
+ * @method
+ */
+OO.ui.MenuWidget.prototype.bindKeyDownListener = function () {
+       if ( this.$input ) {
+               this.$input.on( 'keydown', this.onKeyDownHandler );
+       } else {
+               // Capture menu navigation keys
+               this.getElementWindow().addEventListener( 'keydown', this.onKeyDownHandler, true );
+       }
+};
+
+/**
+ * Unbind key down listener
+ *
+ * @method
+ */
+OO.ui.MenuWidget.prototype.unbindKeyDownListener = function () {
+       if ( this.$input ) {
+               this.$input.off( 'keydown' );
+       } else {
+               this.getElementWindow().removeEventListener( 'keydown', this.onKeyDownHandler, true );
+       }
+};
+
+/**
+ * Choose an item.
+ *
+ * This will close the menu when done, unlike selectItem which only changes selection.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} item Item to choose
+ * @chainable
+ */
+OO.ui.MenuWidget.prototype.chooseItem = function ( item ) {
+       // Parent method
+       OO.ui.MenuWidget.super.prototype.chooseItem.call( this, item );
+
+       if ( item && !this.flashing ) {
+               this.flashing = true;
+               item.flash( OO.ui.bind( function () {
+                       this.hide();
+                       this.flashing = false;
+               }, this ) );
+       } else {
+               this.hide();
+       }
+
+       return this;
+};
+
+/**
+ * Add items.
+ *
+ * Adding an existing item (by value) will move it.
+ *
+ * @method
+ * @param {OO.ui.MenuItemWidget[]} items Items to add
+ * @param {number} [index] Index to insert items after
+ * @chainable
+ */
+OO.ui.MenuWidget.prototype.addItems = function ( items, index ) {
+       var i, len, item;
+
+       // Parent method
+       OO.ui.SelectWidget.prototype.addItems.call( this, items, index );
+
+       // Auto-initialize
+       if ( !this.newItems ) {
+               this.newItems = [];
+       }
+
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+               if ( this.visible ) {
+                       // Defer fitting label until
+                       item.fitLabel();
+               } else {
+                       this.newItems.push( item );
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Show the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.MenuWidget.prototype.show = function () {
+       var i, len;
+
+       if ( this.items.length ) {
+               this.$element.show();
+               this.visible = true;
+               this.bindKeyDownListener();
+
+               // Change focus to enable keyboard navigation
+               if ( this.isolated && this.$input && !this.$input.is( ':focus' ) ) {
+                       this.$previousFocus = this.$( ':focus' );
+                       this.$input.focus();
+               }
+               if ( this.newItems && this.newItems.length ) {
+                       for ( i = 0, len = this.newItems.length; i < len; i++ ) {
+                               this.newItems[i].fitLabel();
+                       }
+                       this.newItems = null;
+               }
+
+               this.setClipping( true );
+       }
+
+       return this;
+};
+
+/**
+ * Hide the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.MenuWidget.prototype.hide = function () {
+       this.$element.hide();
+       this.visible = false;
+       this.unbindKeyDownListener();
+
+       if ( this.isolated && this.$previousFocus ) {
+               this.$previousFocus.focus();
+               this.$previousFocus = null;
+       }
+
+       this.setClipping( false );
+
+       return this;
+};
+/**
+ * Inline menu of options.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.IconedElement
+ * @mixins OO.ui.IndicatedElement
+ * @mixins OO.ui.LabeledElement
+ * @mixins OO.ui.TitledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} [menu] Configuration options to pass to menu widget
+ */
+OO.ui.InlineMenuWidget = function OoUiInlineMenuWidget( config ) {
+       // Configuration initialization
+       config = $.extend( { 'indicator': 'down' }, config );
+
+       // Parent constructor
+       OO.ui.InlineMenuWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
+       OO.ui.TitledElement.call( this, this.$label, config );
+
+       // Properties
+       this.menu = new OO.ui.MenuWidget( $.extend( { '$': this.$ }, config.menu ) );
+       this.$handle = this.$( '<span>' );
+
+       // Events
+       this.$element.on( { 'click': OO.ui.bind( this.onClick, this ) } );
+       this.menu.connect( this, { 'select': 'onMenuSelect' } );
+
+       // Initialization
+       this.$handle
+               .addClass( 'oo-ui-inlineMenuWidget-handle' )
+               .append( this.$icon, this.$label, this.$indicator );
+       this.$element
+               .addClass( 'oo-ui-inlineMenuWidget' )
+               .append( this.$handle, this.menu.$element );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.InlineMenuWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.IconedElement );
+OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.IndicatedElement );
+OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.LabeledElement );
+OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.TitledElement );
+
+/* Methods */
+
+/**
+ * Get the menu.
+ *
+ * @return {OO.ui.MenuWidget} Menu of widget
+ */
+OO.ui.InlineMenuWidget.prototype.getMenu = function () {
+       return this.menu;
+};
+
+/**
+ * Handles menu select events.
+ *
+ * @method
+ * @param {OO.ui.MenuItemWidget} item Selected menu item
+ */
+OO.ui.InlineMenuWidget.prototype.onMenuSelect = function ( item ) {
+       var selectedLabel = item.getLabel();
+
+       // If the label is a DOM element, clone it, because setLabel will append() it
+       if ( selectedLabel instanceof jQuery ) {
+               selectedLabel = selectedLabel.clone();
+       }
+
+       this.setLabel( selectedLabel );
+};
+
+/**
+ * Handles mouse click events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse click event
+ */
+OO.ui.InlineMenuWidget.prototype.onClick = function ( e ) {
+       // Skip clicks within the menu
+       if ( $.contains( this.menu.$element[0], e.target ) ) {
+               return;
+       }
+
+       if ( !this.disabled ) {
+               if ( this.menu.isVisible() ) {
+                       this.menu.hide();
+               } else {
+                       this.menu.show();
+               }
+       }
+       return false;
+};
+/**
+ * Creates an OO.ui.MenuSectionItemWidget object.
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ *
+ * @constructor
+ * @param {Mixed} data Item data
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.MenuSectionItemWidget = function OoUiMenuSectionItemWidget( data, config ) {
+       // Parent constructor
+       OO.ui.MenuSectionItemWidget.super.call( this, data, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-menuSectionItemWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MenuSectionItemWidget, OO.ui.OptionWidget );
+
+/* Static Properties */
+
+OO.ui.MenuSectionItemWidget.static.selectable = false;
+
+OO.ui.MenuSectionItemWidget.static.highlightable = false;
+/**
+ * Create an OO.ui.OutlineWidget object.
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.OutlineWidget = function OoUiOutlineWidget( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.OutlineWidget.super.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-outlineWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.OutlineWidget, OO.ui.SelectWidget );
+/**
+ * Creates an OO.ui.OutlineControlsWidget object.
+ *
+ * @class
+ *
+ * @constructor
+ * @param {OO.ui.OutlineWidget} outline Outline to control
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) {
+       // Configuration initialization
+       config = $.extend( { 'icon': 'add-item' }, config );
+
+       // Parent constructor
+       OO.ui.OutlineControlsWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
+       OO.ui.IconedElement.call( this, this.$( '<div>' ), config );
+
+       // Properties
+       this.outline = outline;
+       this.$movers = this.$( '<div>' );
+       this.upButton = new OO.ui.ButtonWidget( {
+               '$': this.$,
+               'frameless': true,
+               'icon': 'collapse',
+               'title': OO.ui.msg( 'ooui-outline-control-move-up' )
+       } );
+       this.downButton = new OO.ui.ButtonWidget( {
+               '$': this.$,
+               'frameless': true,
+               'icon': 'expand',
+               'title': OO.ui.msg( 'ooui-outline-control-move-down' )
+       } );
+       this.removeButton = new OO.ui.ButtonWidget( {
+               '$': this.$,
+               'frameless': true,
+               'icon': 'remove',
+               'title': OO.ui.msg( 'ooui-outline-control-remove' )
+       } );
+
+       // Events
+       outline.connect( this, {
+               'select': 'onOutlineChange',
+               'add': 'onOutlineChange',
+               'remove': 'onOutlineChange'
+       } );
+       this.upButton.connect( this, { 'click': ['emit', 'move', -1] } );
+       this.downButton.connect( this, { 'click': ['emit', 'move', 1] } );
+       this.removeButton.connect( this, { 'click': ['emit', 'remove'] } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-outlineControlsWidget' );
+       this.$group.addClass( 'oo-ui-outlineControlsWidget-adders' );
+       this.$movers
+               .addClass( 'oo-ui-outlineControlsWidget-movers' )
+               .append( this.removeButton.$element, this.upButton.$element, this.downButton.$element );
+       this.$element.append( this.$icon, this.$group, this.$movers );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.GroupElement );
+OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.IconedElement );
+
+/* Events */
+
+/**
+ * @event move
+ * @param {number} places Number of places to move
+ */
+
+/**
+ * @event remove
+ */
+
+/* Methods */
+
+/**
+ * Handle outline change events.
+ *
+ * @method
+ */
+OO.ui.OutlineControlsWidget.prototype.onOutlineChange = function () {
+       var i, len, firstMovable, lastMovable,
+               items = this.outline.getItems(),
+               selectedItem = this.outline.getSelectedItem(),
+               movable = selectedItem && selectedItem.isMovable(),
+               removable = selectedItem && selectedItem.isRemovable();
+
+       if ( movable ) {
+               i = -1;
+               len = items.length;
+               while ( ++i < len ) {
+                       if ( items[i].isMovable() ) {
+                               firstMovable = items[i];
+                               break;
+                       }
+               }
+               i = len;
+               while ( i-- ) {
+                       if ( items[i].isMovable() ) {
+                               lastMovable = items[i];
+                               break;
+                       }
+               }
+       }
+       this.upButton.setDisabled( !movable || selectedItem === firstMovable );
+       this.downButton.setDisabled( !movable || selectedItem === lastMovable );
+       this.removeButton.setDisabled( !removable );
+};
+/**
+ * Creates an OO.ui.OutlineItemWidget object.
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ *
+ * @constructor
+ * @param {Mixed} data Item data
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [level] Indentation level
+ * @cfg {boolean} [movable] Allow modification from outline controls
+ */
+OO.ui.OutlineItemWidget = function OoUiOutlineItemWidget( data, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.OutlineItemWidget.super.call( this, data, config );
+
+       // Properties
+       this.level = 0;
+       this.movable = !!config.movable;
+       this.removable = !!config.removable;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-outlineItemWidget' );
+       this.setLevel( config.level );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.OutlineItemWidget, OO.ui.OptionWidget );
+
+/* Static Properties */
+
+OO.ui.OutlineItemWidget.static.highlightable = false;
+
+OO.ui.OutlineItemWidget.static.scrollIntoViewOnSelect = true;
+
+OO.ui.OutlineItemWidget.static.levelClass = 'oo-ui-outlineItemWidget-level-';
+
+OO.ui.OutlineItemWidget.static.levels = 3;
+
+/* Methods */
+
+/**
+ * Check if item is movable.
+ *
+ * Movablilty is used by outline controls.
+ *
+ * @returns {boolean} Item is movable
+ */
+OO.ui.OutlineItemWidget.prototype.isMovable = function () {
+       return this.movable;
+};
+
+/**
+ * Check if item is removable.
+ *
+ * Removablilty is used by outline controls.
+ *
+ * @returns {boolean} Item is removable
+ */
+OO.ui.OutlineItemWidget.prototype.isRemovable = function () {
+       return this.removable;
+};
+
+/**
+ * Get indentation level.
+ *
+ * @returns {number} Indentation level
+ */
+OO.ui.OutlineItemWidget.prototype.getLevel = function () {
+       return this.level;
+};
+
+/**
+ * Set movability.
+ *
+ * Movablilty is used by outline controls.
+ *
+ * @param {boolean} movable Item is movable
+ * @chainable
+ */
+OO.ui.OutlineItemWidget.prototype.setMovable = function ( movable ) {
+       this.movable = !!movable;
+       return this;
+};
+
+/**
+ * Set removability.
+ *
+ * Removablilty is used by outline controls.
+ *
+ * @param {boolean} movable Item is removable
+ * @chainable
+ */
+OO.ui.OutlineItemWidget.prototype.setRemovable = function ( removable ) {
+       this.removable = !!removable;
+       return this;
+};
+
+/**
+ * Set indentation level.
+ *
+ * @method
+ * @param {number} [level=0] Indentation level, in the range of [0,#maxLevel]
+ * @chainable
+ */
+OO.ui.OutlineItemWidget.prototype.setLevel = function ( level ) {
+       var levels = this.constructor.static.levels,
+               levelClass = this.constructor.static.levelClass,
+               i = levels;
+
+       this.level = level ? Math.max( 0, Math.min( levels - 1, level ) ) : 0;
+       while ( i-- ) {
+               if ( this.level === i ) {
+                       this.$element.addClass( levelClass + i );
+               } else {
+                       this.$element.removeClass( levelClass + i );
+               }
+       }
+
+       return this;
+};
+/**
+ * Create an OO.ui.ButtonOptionWidget object.
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ * @mixins OO.ui.ButtonedElement
+ * @mixins OO.ui.FlaggableElement
+ *
+ * @constructor
+ * @param {Mixed} data Option data
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ButtonOptionWidget = function OoUiButtonOptionWidget( data, config ) {
+       // Parent constructor
+       OO.ui.ButtonOptionWidget.super.call( this, data, config );
+
+       // Mixin constructors
+       OO.ui.ButtonedElement.call( this, this.$( '<a>' ), config );
+       OO.ui.FlaggableElement.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-buttonOptionWidget' );
+       this.$button.append( this.$element.contents() );
+       this.$element.append( this.$button );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ButtonOptionWidget, OO.ui.OptionWidget );
+OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.ButtonedElement );
+OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.FlaggableElement );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
+       OO.ui.OptionWidget.prototype.setSelected.call( this, state );
+
+       this.setActive( state );
+
+       return this;
+};
+/**
+ * Create an OO.ui.ButtonSelect object.
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ButtonSelectWidget = function OoUiButtonSelectWidget( config ) {
+       // Parent constructor
+       OO.ui.ButtonSelectWidget.super.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-buttonSelectWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ButtonSelectWidget, OO.ui.SelectWidget );
+/**
+ * Creates an OO.ui.PopupWidget object.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.LabeledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [tail=true] Show tail pointing to origin of popup
+ * @cfg {string} [align='center'] Alignment of popup to origin
+ * @cfg {jQuery} [$container] Container to prevent popup from rendering outside of
+ * @cfg {boolean} [autoClose=false] Popup auto-closes when it loses focus
+ * @cfg {jQuery} [$autoCloseIgnore] Elements to not auto close when clicked
+ * @cfg {boolean} [head] Show label and close button at the top
+ */
+OO.ui.PopupWidget = function OoUiPopupWidget( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.PopupWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.LabeledElement.call( this, this.$( '<div>' ), config );
+       OO.ui.ClippableElement.call( this, this.$( '<div>' ), config );
+
+       // Properties
+       this.visible = false;
+       this.$popup = this.$( '<div>' );
+       this.$head = this.$( '<div>' );
+       this.$body = this.$clippable;
+       this.$tail = this.$( '<div>' );
+       this.$container = config.$container || this.$( 'body' );
+       this.autoClose = !!config.autoClose;
+       this.$autoCloseIgnore = config.$autoCloseIgnore;
+       this.transitionTimeout = null;
+       this.tail = false;
+       this.align = config.align || 'center';
+       this.closeButton = new OO.ui.ButtonWidget( { '$': this.$, 'frameless': true, 'icon': 'close' } );
+       this.onMouseDownHandler = OO.ui.bind( this.onMouseDown, this );
+
+       // Events
+       this.closeButton.connect( this, { 'click': 'onCloseButtonClick' } );
+
+       // Initialization
+       this.useTail( config.tail !== undefined ? !!config.tail : true );
+       this.$body.addClass( 'oo-ui-popupWidget-body' );
+       this.$tail.addClass( 'oo-ui-popupWidget-tail' );
+       this.$head
+               .addClass( 'oo-ui-popupWidget-head' )
+               .append( this.$label, this.closeButton.$element );
+       if ( !config.head ) {
+               this.$head.hide();
+       }
+       this.$popup
+               .addClass( 'oo-ui-popupWidget-popup' )
+               .append( this.$head, this.$body );
+       this.$element.hide()
+               .addClass( 'oo-ui-popupWidget' )
+               .append( this.$popup, this.$tail );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PopupWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.PopupWidget, OO.ui.LabeledElement );
+OO.mixinClass( OO.ui.PopupWidget, OO.ui.ClippableElement );
+
+/* Events */
+
+/**
+ * @event hide
+ */
+
+/**
+ * @event show
+ */
+
+/* Methods */
+
+/**
+ * Handles mouse down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.PopupWidget.prototype.onMouseDown = function ( e ) {
+       if (
+               this.visible &&
+               !$.contains( this.$element[0], e.target ) &&
+               ( !this.$autoCloseIgnore || !this.$autoCloseIgnore.has( e.target ).length )
+       ) {
+               this.hide();
+       }
+};
+
+/**
+ * Bind mouse down listener
+ *
+ * @method
+ */
+OO.ui.PopupWidget.prototype.bindMouseDownListener = function () {
+       // Capture clicks outside popup
+       this.getElementWindow().addEventListener( 'mousedown', this.onMouseDownHandler, true );
+};
+
+/**
+ * Handles close button click events.
+ *
+ * @method
+ */
+OO.ui.PopupWidget.prototype.onCloseButtonClick = function () {
+       if ( this.visible ) {
+               this.hide();
+       }
+};
+
+/**
+ * Unbind mouse down listener
+ *
+ * @method
+ */
+OO.ui.PopupWidget.prototype.unbindMouseDownListener = function () {
+       this.getElementWindow().removeEventListener( 'mousedown', this.onMouseDownHandler, true );
+};
+
+/**
+ * Check if the popup is visible.
+ *
+ * @method
+ * @returns {boolean} Popup is visible
+ */
+OO.ui.PopupWidget.prototype.isVisible = function () {
+       return this.visible;
+};
+
+/**
+ * Set whether to show a tail.
+ *
+ * @method
+ * @returns {boolean} Make tail visible
+ */
+OO.ui.PopupWidget.prototype.useTail = function ( value ) {
+       value = !!value;
+       if ( this.tail !== value ) {
+               this.tail = value;
+               if ( value ) {
+                       this.$element.addClass( 'oo-ui-popupWidget-tailed' );
+               } else {
+                       this.$element.removeClass( 'oo-ui-popupWidget-tailed' );
+               }
+       }
+};
+
+/**
+ * Check if showing a tail.
+ *
+ * @method
+ * @returns {boolean} tail is visible
+ */
+OO.ui.PopupWidget.prototype.hasTail = function () {
+       return this.tail;
+};
+
+/**
+ * Show the context.
+ *
+ * @method
+ * @fires show
+ * @chainable
+ */
+OO.ui.PopupWidget.prototype.show = function () {
+       if ( !this.visible ) {
+               this.setClipping( true );
+               this.$element.show();
+               this.visible = true;
+               this.emit( 'show' );
+               if ( this.autoClose ) {
+                       this.bindMouseDownListener();
+               }
+       }
+       return this;
+};
+
+/**
+ * Hide the context.
+ *
+ * @method
+ * @fires hide
+ * @chainable
+ */
+OO.ui.PopupWidget.prototype.hide = function () {
+       if ( this.visible ) {
+               this.setClipping( false );
+               this.$element.hide();
+               this.visible = false;
+               this.emit( 'hide' );
+               if ( this.autoClose ) {
+                       this.unbindMouseDownListener();
+               }
+       }
+       return this;
+};
+
+/**
+ * Updates the position and size.
+ *
+ * @method
+ * @param {number} width Width
+ * @param {number} height Height
+ * @param {boolean} [transition=false] Use a smooth transition
+ * @chainable
+ */
+OO.ui.PopupWidget.prototype.display = function ( width, height, transition ) {
+       var padding = 10,
+               originOffset = Math.round( this.$element.offset().left ),
+               containerLeft = Math.round( this.$container.offset().left ),
+               containerWidth = this.$container.innerWidth(),
+               containerRight = containerLeft + containerWidth,
+               popupOffset = width * ( { 'left': 0, 'center': -0.5, 'right': -1 } )[this.align],
+               popupLeft = popupOffset - padding,
+               popupRight = popupOffset + padding + width + padding,
+               overlapLeft = ( originOffset + popupLeft ) - containerLeft,
+               overlapRight = containerRight - ( originOffset + popupRight );
+
+       // Prevent transition from being interrupted
+       clearTimeout( this.transitionTimeout );
+       if ( transition ) {
+               // Enable transition
+               this.$element.addClass( 'oo-ui-popupWidget-transitioning' );
+       }
+
+       if ( overlapRight < 0 ) {
+               popupOffset += overlapRight;
+       } else if ( overlapLeft < 0 ) {
+               popupOffset -= overlapLeft;
+       }
+
+       // Position body relative to anchor and resize
+       this.$popup.css( {
+               'left': popupOffset,
+               'width': width,
+               'height': height === undefined ? 'auto' : height
+       } );
+
+       if ( transition ) {
+               // Prevent transitioning after transition is complete
+               this.transitionTimeout = setTimeout( OO.ui.bind( function () {
+                       this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
+               }, this ), 200 );
+       } else {
+               // Prevent transitioning immediately
+               this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
+       }
+
+       return this;
+};
+/**
+ * Button that shows and hides a popup.
+ *
+ * @class
+ * @extends OO.ui.ButtonWidget
+ * @mixins OO.ui.PopuppableElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.PopupButtonWidget = function OoUiPopupButtonWidget( config ) {
+       // Parent constructor
+       OO.ui.PopupButtonWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.PopuppableElement.call( this, config );
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-popupButtonWidget' )
+               .append( this.popup.$element );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PopupButtonWidget, OO.ui.ButtonWidget );
+OO.mixinClass( OO.ui.PopupButtonWidget, OO.ui.PopuppableElement );
+
+/* Methods */
+
+/**
+ * Handles mouse click events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse click event
+ */
+OO.ui.PopupButtonWidget.prototype.onClick = function ( e ) {
+       // Skip clicks within the popup
+       if ( $.contains( this.popup.$element[0], e.target ) ) {
+               return;
+       }
+
+       if ( !this.disabled ) {
+               if ( this.popup.isVisible() ) {
+                       this.hidePopup();
+               } else {
+                       this.showPopup();
+               }
+               OO.ui.ButtonWidget.prototype.onClick.call( this );
+       }
+       return false;
+};
+/**
+ * Creates an OO.ui.SearchWidget object.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string|jQuery} [placeholder] Placeholder text for query input
+ * @cfg {string} [value] Initial query value
+ */
+OO.ui.SearchWidget = function OoUiSearchWidget( config ) {
+       // Configuration intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.SearchWidget.super.call( this, config );
+
+       // Properties
+       this.query = new OO.ui.TextInputWidget( {
+               '$': this.$,
+               'icon': 'search',
+               'placeholder': config.placeholder,
+               'value': config.value
+       } );
+       this.results = new OO.ui.SelectWidget( { '$': this.$ } );
+       this.$query = this.$( '<div>' );
+       this.$results = this.$( '<div>' );
+
+       // Events
+       this.query.connect( this, {
+               'change': 'onQueryChange',
+               'enter': 'onQueryEnter'
+       } );
+       this.results.connect( this, {
+               'highlight': 'onResultsHighlight',
+               'select': 'onResultsSelect'
+       } );
+       this.query.$input.on( 'keydown', OO.ui.bind( this.onQueryKeydown, this ) );
+
+       // Initialization
+       this.$query
+               .addClass( 'oo-ui-searchWidget-query' )
+               .append( this.query.$element );
+       this.$results
+               .addClass( 'oo-ui-searchWidget-results' )
+               .append( this.results.$element );
+       this.$element
+               .addClass( 'oo-ui-searchWidget' )
+               .append( this.$results, this.$query );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.SearchWidget, OO.ui.Widget );
+
+/* Events */
+
+/**
+ * @event highlight
+ * @param {Object|null} item Item data or null if no item is highlighted
+ */
+
+/**
+ * @event select
+ * @param {Object|null} item Item data or null if no item is selected
+ */
+
+/* Methods */
+
+/**
+ * Handle query key down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.SearchWidget.prototype.onQueryKeydown = function ( e ) {
+       var highlightedItem, nextItem,
+               dir = e.which === OO.ui.Keys.DOWN ? 1 : ( e.which === OO.ui.Keys.UP ? -1 : 0 );
+
+       if ( dir ) {
+               highlightedItem = this.results.getHighlightedItem();
+               if ( !highlightedItem ) {
+                       highlightedItem = this.results.getSelectedItem();
+               }
+               nextItem = this.results.getRelativeSelectableItem( highlightedItem, dir );
+               this.results.highlightItem( nextItem );
+               nextItem.scrollElementIntoView();
+       }
+};
+
+/**
+ * Handle select widget select events.
+ *
+ * Clears existing results. Subclasses should repopulate items according to new query.
+ *
+ * @method
+ * @param {string} value New value
+ */
+OO.ui.SearchWidget.prototype.onQueryChange = function () {
+       // Reset
+       this.results.clearItems();
+};
+
+/**
+ * Handle select widget enter key events.
+ *
+ * Selects highlighted item.
+ *
+ * @method
+ * @param {string} value New value
+ */
+OO.ui.SearchWidget.prototype.onQueryEnter = function () {
+       // Reset
+       this.results.selectItem( this.results.getHighlightedItem() );
+};
+
+/**
+ * Handle select widget highlight events.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} item Highlighted item
+ * @fires highlight
+ */
+OO.ui.SearchWidget.prototype.onResultsHighlight = function ( item ) {
+       this.emit( 'highlight', item ? item.getData() : null );
+};
+
+/**
+ * Handle select widget select events.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} item Selected item
+ * @fires select
+ */
+OO.ui.SearchWidget.prototype.onResultsSelect = function ( item ) {
+       this.emit( 'select', item ? item.getData() : null );
+};
+
+/**
+ * Get the query input.
+ *
+ * @method
+ * @returns {OO.ui.TextInputWidget} Query input
+ */
+OO.ui.SearchWidget.prototype.getQuery = function () {
+       return this.query;
+};
+
+/**
+ * Reset the widget to initial value.
+ */
+OO.ui.SearchWidget.prototype.clear = function () {
+       this.query.setValue( '' );
+};
+
+/**
+ * Get the results list.
+ *
+ * @method
+ * @returns {OO.ui.SelectWidget} Select list
+ */
+OO.ui.SearchWidget.prototype.getResults = function () {
+       return this.results;
+};
+/**
+ * Creates an OO.ui.TextInputWidget object.
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [placeholder] Placeholder text
+ * @cfg {string} [icon] Symbolic name of icon
+ * @cfg {boolean} [multiline=false] Allow multiple lines of text
+ * @cfg {boolean} [autosize=false] Automatically resize to fit content
+ * @cfg {boolean} [maxRows=10] Maximum number of rows to make visible when autosizing
+ */
+OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
+       config = $.extend( { 'maxRows': 10 }, config );
+
+       // Parent constructor
+       OO.ui.TextInputWidget.super.call( this, config );
+
+       // Properties
+       this.pending = 0;
+       this.multiline = !!config.multiline;
+       this.autosize = !!config.autosize;
+       this.maxRows = config.maxRows;
+
+       // Events
+       this.$input.on( 'keypress', OO.ui.bind( this.onKeyPress, this ) );
+       this.$element.on( 'DOMNodeInsertedIntoDocument', OO.ui.bind( this.onElementAttach, this ) );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-textInputWidget' );
+       if ( config.icon ) {
+               this.$element.addClass( 'oo-ui-textInputWidget-decorated' );
+               this.$element.append(
+                       this.$( '<span>' )
+                               .addClass( 'oo-ui-textInputWidget-icon oo-ui-icon-' + config.icon )
+                               .mousedown( OO.ui.bind( function () {
+                                       this.$input.focus();
+                                       return false;
+                               }, this ) )
+               );
+       }
+       if ( config.placeholder ) {
+               this.$input.attr( 'placeholder', config.placeholder );
+       }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.TextInputWidget, OO.ui.InputWidget );
+
+/* Events */
+
+/**
+ * User presses enter inside the text box.
+ *
+ * Not called if input is multiline.
+ *
+ * @event enter
+ */
+
+/* Methods */
+
+/**
+ * Handles key press events.
+ *
+ * @param {jQuery.Event} e Key press event
+ * @fires enter If enter key is pressed and input is not multiline
+ */
+OO.ui.TextInputWidget.prototype.onKeyPress = function ( e ) {
+       if ( e.which === OO.ui.Keys.ENTER && !this.multiline ) {
+               this.emit( 'enter' );
+       }
+};
+
+/**
+ * Handles element attach events.
+ *
+ * @param {jQuery.Event} e Element attach event
+ */
+OO.ui.TextInputWidget.prototype.onElementAttach = function () {
+       this.adjustSize();
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.TextInputWidget.prototype.onEdit = function () {
+       this.adjustSize();
+
+       // Parent method
+       return OO.ui.InputWidget.prototype.onEdit.call( this );
+};
+
+/**
+ * Automatically adjust the size of the text input.
+ *
+ * This only affects multi-line inputs that are auto-sized.
+ *
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.adjustSize = function () {
+       var $clone, scrollHeight, innerHeight, outerHeight, maxInnerHeight, idealHeight;
+
+       if ( this.multiline && this.autosize ) {
+               $clone = this.$input.clone()
+                       .val( this.$input.val() )
+                       .css( { 'height': 0 } )
+                       .insertAfter( this.$input );
+               // Set inline height property to 0 to measure scroll height
+               scrollHeight = $clone[0].scrollHeight;
+               // Remove inline height property to measure natural heights
+               $clone.css( 'height', '' );
+               innerHeight = $clone.innerHeight();
+               outerHeight = $clone.outerHeight();
+               // Measure max rows height
+               $clone.attr( 'rows', this.maxRows ).css( 'height', 'auto' );
+               maxInnerHeight = $clone.innerHeight();
+               $clone.removeAttr( 'rows' ).css( 'height', '' );
+               $clone.remove();
+               idealHeight = Math.min( maxInnerHeight, scrollHeight );
+               // Only apply inline height when expansion beyond natural height is needed
+               this.$input.css(
+                       'height',
+                       // Use the difference between the inner and outer height as a buffer
+                       idealHeight > outerHeight ? idealHeight + ( outerHeight - innerHeight ) : ''
+               );
+       }
+       return this;
+};
+
+/**
+ * Get input element.
+ *
+ * @method
+ * @param {Object} [config] Configuration options
+ * @returns {jQuery} Input element
+ */
+OO.ui.TextInputWidget.prototype.getInputElement = function ( config ) {
+       return config.multiline ? this.$( '<textarea>' ) : this.$( '<input type="text" />' );
+};
+
+/* Methods */
+
+/**
+ * Checks if input supports multiple lines.
+ *
+ * @method
+ * @returns {boolean} Input supports multiple lines
+ */
+OO.ui.TextInputWidget.prototype.isMultiline = function () {
+       return !!this.multiline;
+};
+
+/**
+ * Checks if input automatically adjusts its size.
+ *
+ * @method
+ * @returns {boolean} Input automatically adjusts its size
+ */
+OO.ui.TextInputWidget.prototype.isAutosizing = function () {
+       return !!this.autosize;
+};
+
+/**
+ * Checks if input is pending.
+ *
+ * @method
+ * @returns {boolean} Input is pending
+ */
+OO.ui.TextInputWidget.prototype.isPending = function () {
+       return !!this.pending;
+};
+
+/**
+ * Increases the pending stack.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.pushPending = function () {
+       this.pending++;
+       this.$element.addClass( 'oo-ui-textInputWidget-pending' );
+       this.$input.addClass( 'oo-ui-texture-pending' );
+       return this;
+};
+
+/**
+ * Reduces the pending stack.
+ *
+ * Clamped at zero.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.popPending = function () {
+       this.pending = Math.max( 0, this.pending - 1 );
+       if ( !this.pending ) {
+               this.$element.removeClass( 'oo-ui-textInputWidget-pending' );
+               this.$input.removeClass( 'oo-ui-texture-pending' );
+       }
+       return this;
+};
+/**
+ * Creates an OO.ui.TextInputMenuWidget object.
+ *
+ * @class
+ * @extends OO.ui.MenuWidget
+ *
+ * @constructor
+ * @param {OO.ui.TextInputWidget} input Text input widget to provide menu for
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$container=input.$element] Element to render menu under
+ */
+OO.ui.TextInputMenuWidget = function OoUiTextInputMenuWidget( input, config ) {
+       // Parent constructor
+       OO.ui.TextInputMenuWidget.super.call( this, config );
+
+       // Properties
+       this.input = input;
+       this.$container = config.$container || this.input.$element;
+       this.onWindowResizeHandler = OO.ui.bind( this.onWindowResize, this );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-textInputMenuWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.TextInputMenuWidget, OO.ui.MenuWidget );
+
+/* Methods */
+
+/**
+ * Handle window resize event.
+ *
+ * @method
+ * @param {jQuery.Event} e Window resize event
+ */
+OO.ui.TextInputMenuWidget.prototype.onWindowResize = function () {
+       this.position();
+};
+
+/**
+ * Shows the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.TextInputMenuWidget.prototype.show = function () {
+       // Parent method
+       OO.ui.MenuWidget.prototype.show.call( this );
+
+       this.position();
+       this.$( this.getElementWindow() ).on( 'resize', this.onWindowResizeHandler );
+       return this;
+};
+
+/**
+ * Hides the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.TextInputMenuWidget.prototype.hide = function () {
+       // Parent method
+       OO.ui.MenuWidget.prototype.hide.call( this );
+
+       this.$( this.getElementWindow() ).off( 'resize', this.onWindowResizeHandler );
+       return this;
+};
+
+/**
+ * Positions the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.TextInputMenuWidget.prototype.position = function () {
+       var frameOffset,
+               $container = this.$container,
+               dimensions = $container.offset();
+
+       // Position under input
+       dimensions.top += $container.height();
+
+       // Compensate for frame position if in a differnt frame
+       if ( this.input.$.frame && this.input.$.context !== this.$element[0].ownerDocument ) {
+               frameOffset = OO.ui.Element.getRelativePosition(
+                       this.input.$.frame.$element, this.$element.offsetParent()
+               );
+               dimensions.left += frameOffset.left;
+               dimensions.top += frameOffset.top;
+       } else {
+               // Fix for RTL (for some reason, no need to fix if the frameoffset is set)
+               if ( this.$element.css( 'direction' ) === 'rtl' ) {
+                       dimensions.right = this.$element.parent().position().left -
+                               dimensions.width - dimensions.left;
+                       // Erase the value for 'left':
+                       delete dimensions.left;
+               }
+       }
+
+       this.$element.css( dimensions );
+       this.setIdealSize( $container.width() );
+       return this;
+};
+/**
+ * Mixin for widgets with a boolean state.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [value=false] Initial value
+ */
+OO.ui.ToggleWidget = function OoUiToggleWidget( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Properties
+       this.value = null;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-toggleWidget' );
+       this.setValue( !!config.value );
+};
+
+/* Events */
+
+/**
+ * @event change
+ * @param {boolean} value Changed value
+ */
+
+/* Methods */
+
+/**
+ * Get the value of the toggle.
+ *
+ * @method
+ * @returns {boolean} Toggle value
+ */
+OO.ui.ToggleWidget.prototype.getValue = function () {
+       return this.value;
+};
+
+/**
+ * Set the value of the toggle.
+ *
+ * @method
+ * @param {boolean} value New value
+ * @fires change
+ * @chainable
+ */
+OO.ui.ToggleWidget.prototype.setValue = function ( value ) {
+       value = !!value;
+       if ( this.value !== value ) {
+               this.value = value;
+               this.emit( 'change', value );
+               this.$element.toggleClass( 'oo-ui-toggleWidget-on', value );
+               this.$element.toggleClass( 'oo-ui-toggleWidget-off', !value );
+       }
+       return this;
+};
+/**
+ * @class
+ * @extends OO.ui.ButtonWidget
+ * @mixins OO.ui.ToggleWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [value=false] Initial value
+ */
+OO.ui.ToggleButtonWidget = function OoUiToggleButtonWidget( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.ToggleButtonWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.ToggleWidget.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-toggleButtonWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToggleButtonWidget, OO.ui.ButtonWidget );
+OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.ToggleWidget );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToggleButtonWidget.prototype.onClick = function () {
+       if ( !this.disabled ) {
+               this.setValue( !this.value );
+       }
+
+       // Parent method
+       return OO.ui.ButtonWidget.prototype.onClick.call( this );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToggleButtonWidget.prototype.setValue = function ( value ) {
+       value = !!value;
+       if ( value !== this.value ) {
+               this.setActive( value );
+       }
+
+       // Parent method
+       OO.ui.ToggleWidget.prototype.setValue.call( this, value );
+
+       return this;
+};
+/**
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.ToggleWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [value=false] Initial value
+ */
+OO.ui.ToggleSwitchWidget = function OoUiToggleSwitchWidget( config ) {
+       // Parent constructor
+       OO.ui.ToggleSwitchWidget.super.call( this, config );
+
+       // Mixin constructors
+       OO.ui.ToggleWidget.call( this, config );
+
+       // Properties
+       this.dragging = false;
+       this.dragStart = null;
+       this.sliding = false;
+       this.$glow = this.$( '<span>' );
+       this.$grip = this.$( '<span>' );
+
+       // Events
+       this.$element.on( 'click', OO.ui.bind( this.onClick, this ) );
+
+       // Initialization
+       this.$glow.addClass( 'oo-ui-toggleSwitchWidget-glow' );
+       this.$grip.addClass( 'oo-ui-toggleSwitchWidget-grip' );
+       this.$element
+               .addClass( 'oo-ui-toggleSwitchWidget' )
+               .append( this.$glow, this.$grip );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToggleSwitchWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.ToggleSwitchWidget, OO.ui.ToggleWidget );
+
+/* Methods */
+
+/**
+ * Handles mouse down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.ToggleSwitchWidget.prototype.onClick = function ( e ) {
+       if ( !this.disabled && e.which === 1 ) {
+               this.setValue( !this.value );
+       }
+};
+}( OO ) );
diff --git a/resources/lib/oojs-ui/oojs-ui.svg.css b/resources/lib/oojs-ui/oojs-ui.svg.css
new file mode 100644 (file)
index 0000000..873fd19
--- /dev/null
@@ -0,0 +1,1230 @@
+/*!
+ * OOjs UI v0.1.0-pre (4975b8db90)
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2014 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: Mon Apr 07 2014 15:17:10 GMT-0700 (PDT)
+ */
+
+/* Textures */
+
+.oo-ui-texture-pending {
+  background-image: /* @embed */ url(images/textures/pending.gif);
+}
+
+.oo-ui-texture-transparency {
+  background-image: /* @embed */ url(images/textures/transparency.png);
+}
+
+/* RTL Definitions */
+
+/* @noflip */
+
+.oo-ui-rtl {
+  direction: rtl;
+}
+
+/* @noflip */
+
+.oo-ui-ltr {
+  direction: ltr;
+}
+
+.oo-ui-dialog {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1em;
+  line-height: 1em;
+  /* Fix for strange opacity-related rendering issues.
+          CAUTION: -webkit-backface-visibility: hidden; is EXTREMELY DANGEROUS.
+          If applied to a VE surface directly, it will break selection of
+          FocusableNodes, and in the past it's caused transparent PNGs to
+          render as opaque black images. For some reason applying it to the dialog
+          wrapper in the main document fixes opacity-related behavior in the iframe
+          document, but doesn't break the surface inside the iframe. */
+
+  -webkit-backface-visibility: hidden;
+          backface-visibility: hidden;
+}
+
+.oo-ui-dialog .oo-ui-window-frame {
+  position: fixed;
+  top: 1em;
+  right: 0;
+  bottom: 1em;
+  left: 0;
+  min-height: 12em;
+  margin: auto;
+  overflow: hidden;
+}
+
+.oo-ui-dialog-small .oo-ui-window-frame {
+  width: 400px;
+  max-height: 230px;
+}
+
+.oo-ui-dialog-medium .oo-ui-window-frame {
+  width: 600px;
+  max-height: 460px;
+}
+
+.oo-ui-dialog-large .oo-ui-window-frame {
+  width: 800px;
+  max-height: 690px;
+}
+
+.oo-ui-dialog .oo-ui-frame {
+  width: 100%;
+  height: 100%;
+}
+
+.oo-ui-dialog-content .oo-ui-window-head,
+.oo-ui-dialog-content .oo-ui-window-body,
+.oo-ui-dialog-content .oo-ui-window-foot {
+  position: absolute;
+  right: 0;
+  left: 0;
+  overflow: hidden;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.oo-ui-dialog-content .oo-ui-window-head {
+  top: 0;
+  height: 3.8em;
+  padding: 0.5em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-title {
+  line-height: 2.8em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-icon {
+  width: 2.4em;
+  height: 2.8em;
+  line-height: 2.8em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-closeButton {
+  float: right;
+  margin: 0.25em 0.25em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-body {
+  top: 3.8em;
+  bottom: 4.8em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-foot {
+  bottom: 0;
+  height: 4.8em;
+  padding: 1em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed {
+  float: left;
+  margin: 0.125em 0.25em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-primary,
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-constructive,
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-destructive {
+  float: right;
+}
+
+.oo-ui-dialog-content-footless .oo-ui-window-body {
+  bottom: 0;
+}
+
+.oo-ui-dialog-content-footless .oo-ui-window-foot {
+  display: none;
+}
+
+.oo-ui-frame {
+  padding: 0;
+  margin: 0;
+}
+
+.oo-ui-frame-body {
+  padding: 0;
+  margin: 0;
+  background: none;
+}
+
+.oo-ui-toolbar {
+  clear: both;
+}
+
+.oo-ui-toolbar-bar {
+  line-height: 1em;
+}
+
+.oo-ui-toolbar-bottom .oo-ui-toolbar-bar {
+  position: absolute;
+}
+
+.oo-ui-toolbar-actions {
+  float: right;
+}
+
+.oo-ui-toolbar-tools {
+  float: left;
+}
+
+.oo-ui-toolbar-tools,
+.oo-ui-toolbar-actions,
+.oo-ui-toolbar-shadow {
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
+}
+
+.oo-ui-toolbar-actions .oo-ui-popupWidget {
+  -webkit-user-select: all;
+     -moz-user-select: all;
+      -ms-user-select: all;
+          user-select: all;
+  -webkit-touch-callout: default;
+}
+
+.oo-ui-toolbar-shadow {
+  position: absolute;
+  width: 100%;
+  pointer-events: none;
+  background-position: left top;
+  background-repeat: repeat-x;
+}
+
+.oo-ui-toolGroup {
+  display: inline-block;
+  margin: 0.3em;
+  vertical-align: middle;
+}
+
+.oo-ui-toolGroup-empty {
+  display: none;
+}
+
+.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+
+.oo-ui-window-head {
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
+}
+
+.oo-ui-window-icon {
+  float: left;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+
+.oo-ui-window-title {
+  float: left;
+  white-space: nowrap;
+  cursor: default;
+}
+
+.oo-ui-window-overlay {
+  position: absolute;
+  top: 0;
+  left: 0;
+}
+
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button {
+  display: inline-block;
+  vertical-align: middle;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
+}
+
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  display: none;
+  margin-left: 0;
+}
+
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator {
+  display: none;
+  margin-right: -0.75em;
+}
+
+.oo-ui-buttonedElement.oo-ui-widget-disabled .oo-ui-buttonedElement-button {
+  cursor: default;
+}
+
+.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
+.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  display: inline-block;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+
+.oo-ui-buttonedElement-frameless {
+  position: relative;
+  display: inline-block;
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+  display: inline-block;
+  margin-left: 0.25em;
+  vertical-align: middle;
+}
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
+  display: inline-block;
+  padding: 0.2em 0.8em;
+  margin: 0.1em 0;
+  text-align: center;
+  vertical-align: top;
+}
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+  display: inline-block;
+  line-height: 1.9em;
+  vertical-align: middle;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  margin-right: -0.5em;
+  margin-left: -0.5em;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-iconedElement.oo-ui-labeledElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  margin-right: 0.3em;
+  margin-left: -0.5em;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+  cursor: default;
+}
+
+.oo-ui-clippableElement-clippable {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.oo-ui-bookletLayout-stackLayout.oo-ui-stackLayout-continuous .oo-ui-panelLayout-scrollable {
+  overflow-y: hidden;
+}
+
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
+  width: 100%;
+  padding: 1.5em;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
+}
+
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-padded {
+  padding: 2em;
+}
+
+.oo-ui-bookletLayout-outlinePanel-editable .oo-ui-outlineWidget {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 3em;
+  left: 0;
+  overflow-y: auto;
+}
+
+.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  left: 0;
+}
+
+.oo-ui-fieldLayout {
+  margin-bottom: 1em;
+}
+
+.oo-ui-fieldLayout:last-child {
+  margin-bottom: 0;
+}
+
+.oo-ui-fieldLayout:before,
+.oo-ui-fieldLayout:after {
+  display: table;
+  content: " ";
+}
+
+.oo-ui-fieldLayout:after {
+  clear: both;
+}
+
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labeledElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labeledElement-label {
+  display: block;
+  float: left;
+  width: 35%;
+  padding-top: 0.5em;
+  margin-right: 5%;
+}
+
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
+  display: block;
+  float: left;
+  width: 60%;
+}
+
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labeledElement-label {
+  text-align: right;
+}
+
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labeledElement-label {
+  display: inline-block;
+  padding: 0.75em 0.5em 0.5em 0.5em;
+  vertical-align: middle;
+}
+
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
+  display: inline-block;
+  padding: 0.5em 0;
+  vertical-align: middle;
+}
+
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labeledElement-label {
+  padding: 0.5em 0;
+}
+
+.oo-ui-fieldsetLayout {
+  position: relative;
+  padding: 0;
+  margin: 0;
+}
+
+.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
+  margin-top: 2em;
+}
+
+.oo-ui-fieldsetLayout-labeled {
+  margin-top: -0.75em;
+}
+
+.oo-ui-fieldsetLayout > legend.oo-ui-labeledElement-label {
+  padding: 0.25em 0;
+  margin-bottom: 0.5em;
+}
+
+.oo-ui-fieldsetLayout.oo-ui-iconedElement > legend.oo-ui-labeledElement-label {
+  padding-left: 1.75em;
+}
+
+.oo-ui-fieldsetLayout.oo-ui-iconedElement > .oo-ui-iconedElement-icon {
+  position: absolute;
+  top: 0;
+  left: 0;
+  display: block;
+  width: 2em;
+  height: 2em;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+
+.oo-ui-gridLayout {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+}
+
+.oo-ui-labelWidget {
+  padding: 0.5em 0;
+}
+
+.oo-ui-panelLayout {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+}
+
+.oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
+}
+
+.oo-ui-panelLayout-padded {
+  padding: 2em;
+}
+
+.oo-ui-stackLayout > .oo-ui-panelLayout {
+  display: none;
+}
+
+.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
+  position: relative;
+  display: block;
+}
+
+.oo-ui-barToolGroup > .oo-ui-iconedElement-icon,
+.oo-ui-barToolGroup > .oo-ui-labeledElement-label {
+  display: none;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool {
+  position: relative;
+  display: inline-block;
+  vertical-align: top;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-link {
+  display: block;
+  height: 1.5em;
+  padding: 0.25em;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  display: block;
+  width: 1.5em;
+  height: 1.5em;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  display: none;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-title,
+.oo-ui-barToolGroup .oo-ui-tool-accel {
+  display: none;
+}
+
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-link {
+  cursor: pointer;
+}
+
+.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
+  padding: 0.25em;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool {
+  display: inline-block;
+  width: 100%;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool-link {
+  display: block;
+  padding-right: 0.5em;
+  white-space: nowrap;
+  cursor: pointer;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+
+.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+  min-width: 8em;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool {
+  display: block;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+  display: block;
+  padding: 0.25em 1em 0.25em 0.25em;
+  white-space: nowrap;
+  cursor: pointer;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  background-image: none;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  background-image: /* @embed */ url(images/icons/check.png);
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
+}
+
+.oo-ui-popupToolGroup {
+  position: relative;
+  height: 2em;
+  min-width: 2.5em;
+}
+
+.oo-ui-popupToolGroup.oo-ui-indicatedElement.oo-ui-iconedElement {
+  min-width: 3.5em;
+}
+
+.oo-ui-popupToolGroup-handle {
+  display: block;
+  cursor: pointer;
+}
+
+.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
+  position: absolute;
+  top: 0;
+  width: 2em;
+  height: 2em;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+
+.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator {
+  right: 0;
+}
+
+.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
+  left: 0.25em;
+}
+
+.oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
+  margin: 0 1em;
+  font-size: 0.8em;
+  line-height: 2.6em;
+}
+
+.oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
+  cursor: default;
+}
+
+.oo-ui-popupToolGroup.oo-ui-iconedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
+  margin-left: 3em;
+}
+
+.oo-ui-popupToolGroup.oo-ui-indicatedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
+  margin-right: 2.25em;
+}
+
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+  position: absolute;
+  top: 2em;
+  left: -1px;
+  z-index: 4;
+  display: none;
+}
+
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools .oo-ui-iconedElement-icon {
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled > .oo-ui-toolGroup-tools {
+  display: block;
+}
+
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  display: inline-block;
+  width: 2em;
+  height: 2em;
+  margin-right: 0.25em;
+  vertical-align: middle;
+}
+
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  display: inline-block;
+  font-size: 0.8em;
+  line-height: 2em;
+  vertical-align: middle;
+}
+
+.oo-ui-popupToolGroup .oo-ui-tool-accel {
+  display: none;
+}
+
+.oo-ui-popupTool .oo-ui-popupWidget {
+  margin-left: 1.25em;
+  font-size: 0.8em;
+}
+
+.oo-ui-popupTool .oo-ui-popupWidget-popup,
+.oo-ui-popupTool .oo-ui-popupWidget-tail {
+  z-index: 4;
+}
+
+.oo-ui-iconWidget {
+  display: inline-block;
+  width: 1.9em;
+  height: 1.9em;
+  line-height: 2.5em;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+  opacity: 0.8;
+}
+
+.oo-ui-iconWidget.oo-ui-widget-disabled {
+  opacity: 0.2;
+}
+
+.oo-ui-indicatorWidget {
+  display: inline-block;
+  width: 1.9em;
+  height: 1.9em;
+  line-height: 2.5em;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
+  opacity: 0.8;
+}
+
+.oo-ui-indicatorWidget.oo-ui-widget-disabled {
+  opacity: 0.2;
+}
+
+.oo-ui-selectWidget {
+  padding: 0;
+  margin: 0;
+  list-style: none;
+}
+
+.oo-ui-optionWidget {
+  position: relative;
+  display: block;
+  margin: 0;
+  list-style: none;
+  cursor: pointer;
+  border: none;
+}
+
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+  cursor: default;
+}
+
+.oo-ui-optionWidget .oo-ui-labeledElement-label {
+  display: block;
+  overflow: hidden;
+  line-height: 1.5em;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.oo-ui-optionWidget .oo-ui-iconedElement-icon,
+.oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
+  position: absolute;
+  top: 50%;
+  width: 2em;
+  height: 2em;
+  margin-top: -1em;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+
+.oo-ui-optionWidget .oo-ui-iconedElement-icon {
+  left: 0.5em;
+}
+
+.oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
+  right: 0.5em;
+}
+
+.oo-ui-menuWidget {
+  position: absolute;
+}
+
+.oo-ui-menuWidget input {
+  position: absolute;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+  opacity: 0;
+}
+
+.oo-ui-popupWidget-popup {
+  position: absolute;
+  overflow: hidden;
+}
+
+.oo-ui-popupWidget-tail {
+  display: none;
+}
+
+.oo-ui-popupWidget-tailed .oo-ui-popupWidget-popup {
+  margin-top: 7px;
+}
+
+.oo-ui-popupWidget-tailed .oo-ui-popupWidget-tail {
+  position: absolute;
+  display: block;
+  background-repeat: no-repeat;
+}
+
+.oo-ui-popupWidget-head {
+  height: 2.5em;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
+}
+
+.oo-ui-popupWidget-head .oo-ui-buttonWidget {
+  float: right;
+  margin: 0.25em;
+}
+
+.oo-ui-popupWidget-head .oo-ui-labeledElement-label {
+  float: left;
+  margin: 0.75em 1em;
+  cursor: default;
+}
+
+.oo-ui-popupWidget-body {
+  clear: both;
+}
+
+.oo-ui-buttonGroupWidget {
+  border-radius: 0.3em;
+}
+
+.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
+  margin-bottom: -1px;
+  margin-left: -1px;
+  border-radius: 0;
+}
+
+.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:first-child .oo-ui-buttonedElement-button {
+  margin-left: 0;
+  border-bottom-left-radius: 0.3em;
+  border-top-left-radius: 0.3em;
+}
+
+.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:last-child .oo-ui-buttonedElement-button {
+  border-top-right-radius: 0.3em;
+  border-bottom-right-radius: 0.3em;
+}
+
+.oo-ui-buttonOptionWidget {
+  display: inline-block;
+  background-color: transparent;
+}
+
+.oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
+  position: relative;
+  height: 1.9em;
+}
+
+.oo-ui-buttonOptionWidget.oo-ui-iconedElement .oo-ui-iconedElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatedElement .oo-ui-indicatedElement-indicator {
+  position: static;
+  display: inline-block;
+  height: 1.9em;
+  margin-top: 0;
+  vertical-align: middle;
+}
+
+.oo-ui-buttonSelectWidget {
+  display: inline-block;
+  white-space: nowrap;
+}
+
+.oo-ui-buttonWidget {
+  display: inline-block;
+  vertical-align: middle;
+}
+
+.oo-ui-inlineMenuWidget {
+  position: relative;
+  display: inline-block;
+  min-width: 20em;
+  margin: 0.25em 0;
+}
+
+.oo-ui-inlineMenuWidget-handle {
+  display: inline-block;
+  width: 100%;
+  height: 2.5em;
+  cursor: pointer;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
+}
+
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator,
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
+  position: absolute;
+  top: 0;
+  width: 2.5em;
+  height: 2.5em;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator {
+  right: 0;
+}
+
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
+  left: 0.25em;
+}
+
+.oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
+  margin: 0 0.5em;
+  line-height: 2.5em;
+}
+
+.oo-ui-inlineMenuWidget.oo-ui-iconedElement .oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
+  margin-left: 3em;
+}
+
+.oo-ui-inlineMenuWidget.oo-ui-indicatedElement .oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
+  margin-right: 2em;
+}
+
+.oo-ui-inlineMenuWidget .oo-ui-menuWidget {
+  z-index: 1;
+  width: 100%;
+}
+
+.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
+  cursor: default;
+}
+
+.oo-ui-menuItemWidget {
+  position: relative;
+}
+
+.oo-ui-menuItemWidget .oo-ui-iconedElement-icon {
+  display: none;
+}
+
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+  background-color: transparent;
+}
+
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected .oo-ui-iconedElement-icon {
+  display: block;
+}
+
+.oo-ui-menuSectionItemWidget {
+  cursor: default;
+}
+
+.oo-ui-outlineControlsWidget {
+  height: 3em;
+}
+
+.oo-ui-outlineControlsWidget-adders,
+.oo-ui-outlineControlsWidget-movers {
+  float: left;
+  height: 2em;
+  padding: 0;
+  margin: 0.5em;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.oo-ui-outlineControlsWidget > .oo-ui-iconedElement-icon {
+  float: left;
+  width: 1.5em;
+  height: 2em;
+  margin: 0.5em 0 0.5em 0.5em;
+  background-position: right center;
+  background-repeat: no-repeat;
+}
+
+.oo-ui-outlineControlsWidget-adders {
+  float: left;
+  margin-left: 0;
+}
+
+.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget {
+  float: left;
+}
+
+.oo-ui-outlineControlsWidget-movers {
+  float: right;
+}
+
+.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
+  float: right;
+}
+
+.oo-ui-outlineItemWidget {
+  position: relative;
+  padding: 0.75em;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
+}
+
+.oo-ui-popupButtonWidget {
+  position: relative;
+}
+
+.oo-ui-popupButtonWidget .oo-ui-popupWidget {
+  position: absolute;
+  left: 1em;
+  cursor: auto;
+}
+
+.oo-ui-searchWidget-query {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  height: 4em;
+  padding: 0 1em;
+}
+
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+  width: 100%;
+  margin: 0.75em 0;
+}
+
+.oo-ui-searchWidget-results {
+  position: absolute;
+  top: 4em;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1em;
+  overflow-x: hidden;
+  overflow-y: auto;
+  line-height: 0;
+}
+
+.oo-ui-textInputWidget {
+  position: relative;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  display: inline-block;
+  width: 100%;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+  resize: none;
+}
+
+.oo-ui-textInputWidget-icon {
+  position: absolute;
+  top: 0;
+  left: 0;
+  height: 100%;
+  background-position: right center;
+  background-repeat: no-repeat;
+}
+
+.oo-ui-toggleSwitchWidget {
+  position: relative;
+  display: inline-block;
+  width: 4em;
+  height: 2em;
+  overflow: hidden;
+  vertical-align: middle;
+  cursor: pointer;
+  -webkit-transform: translateZ(0);
+     -moz-transform: translateZ(0);
+      -ms-transform: translateZ(0);
+       -o-transform: translateZ(0);
+          transform: translateZ(0);
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+  cursor: default;
+}
+
+.oo-ui-toggleSwitchWidget-grip {
+  position: absolute;
+  top: 0.25em;
+  left: 0.25em;
+  display: block;
+  width: 1.5em;
+  height: 1.5em;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+  -webkit-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+     -moz-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+      -ms-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+       -o-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+          transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+}
+
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  -webkit-transition: opacity 200ms ease-in-out;
+     -moz-transition: opacity 200ms ease-in-out;
+      -ms-transition: opacity 200ms ease-in-out;
+       -o-transition: opacity 200ms ease-in-out;
+          transition: opacity 200ms ease-in-out;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
+}
+
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+  left: 2.25em;
+  margin-left: -2px;
+}
+
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
+  left: 0.25em;
+  margin-left: 0;
+}
+
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+  display: none;
+}
+
+/* Icons */
+
+.oo-ui-icon-add-item {
+  background-image: /* @embed */ url(images/icons/add-item.svg);
+}
+
+.oo-ui-icon-advanced {
+  background-image: /* @embed */ url(images/icons/advanced.svg);
+}
+
+.oo-ui-icon-alert {
+  background-image: /* @embed */ url(images/icons/alert.svg);
+}
+
+.oo-ui-icon-check {
+  background-image: /* @embed */ url(images/icons/check.svg);
+}
+
+.oo-ui-icon-clear {
+  background-image: /* @embed */ url(images/icons/clear.svg);
+}
+
+.oo-ui-icon-close {
+  background-image: /* @embed */ url(images/icons/close.svg);
+}
+
+.oo-ui-icon-code {
+  background-image: /* @embed */ url(images/icons/code.svg);
+}
+
+.oo-ui-icon-collapse {
+  background-image: /* @embed */ url(images/icons/collapse.svg);
+}
+
+.oo-ui-icon-comment {
+  background-image: /* @embed */ url(images/icons/comment.svg);
+}
+
+.oo-ui-icon-expand {
+  background-image: /* @embed */ url(images/icons/expand.svg);
+}
+
+.oo-ui-icon-help {
+  background-image: /* @embed */ url(images/icons/help.svg);
+}
+
+.oo-ui-icon-link {
+  background-image: /* @embed */ url(images/icons/link.svg);
+}
+
+.oo-ui-icon-menu {
+  background-image: /* @embed */ url(images/icons/menu.svg);
+}
+
+.oo-ui-icon-next {
+  background-image: /* @embed */ url(images/icons/move-ltr.svg);
+}
+
+.oo-ui-icon-picture {
+  background-image: /* @embed */ url(images/icons/picture.svg);
+}
+
+.oo-ui-icon-previous {
+  background-image: /* @embed */ url(images/icons/move-rtl.svg);
+}
+
+.oo-ui-icon-redo {
+  background-image: /* @embed */ url(images/icons/arched-arrow-ltr.svg);
+}
+
+.oo-ui-icon-remove {
+  background-image: /* @embed */ url(images/icons/remove.svg);
+}
+
+.oo-ui-icon-search {
+  background-image: /* @embed */ url(images/icons/search.svg);
+}
+
+.oo-ui-icon-settings {
+  background-image: /* @embed */ url(images/icons/settings.svg);
+}
+
+.oo-ui-icon-tag {
+  background-image: /* @embed */ url(images/icons/tag.svg);
+}
+
+.oo-ui-icon-undo {
+  background-image: /* @embed */ url(images/icons/arched-arrow-rtl.svg);
+}
+
+.oo-ui-icon-window {
+  background-image: /* @embed */ url(images/icons/window.svg);
+}
+
+/* Indicators */
+
+.oo-ui-indicator-down {
+  background-image: /* @embed */ url(images/indicators/down.svg);
+}
+
+.oo-ui-indicator-required {
+  background-image: /* @embed */ url(images/indicators/required.svg);
+}
+
+.oo-ui-indicator-up {
+  background-image: /* @embed */ url(images/indicators/up.svg);
+}
\ No newline at end of file
diff --git a/resources/lib/oojs-ui/update-oojs-ui.sh b/resources/lib/oojs-ui/update-oojs-ui.sh
new file mode 100755 (executable)
index 0000000..3c6dca6
--- /dev/null
@@ -0,0 +1,99 @@
+#!/usr/bin/env bash
+
+# FIXME this script is duplicated from update-oojs.sh - factor this out
+
+# This script generates a commit that updates the oojs-ui distribution
+# ./bin/update-oojs-ui.sh path/to/repo/for/oojs-ui
+
+function oojsuihash() {
+       grep "OOjs UI v" resources/lib/oojs-ui/oojs-ui.js \
+               | head -n 1 \
+               | grep -Eo '\([a-z0-9]+\)' \
+               | sed 's/^(//' \
+               | sed 's/)$//'
+}
+
+function oojsuitag() {
+       grep "OOjs UI v" resources/lib/oojs-ui/oojs-ui.js \
+               | head -n 1 \
+               | grep -Eo '\bv[0-9a-z.-]+\b'
+}
+
+function oojsuiversion() {
+       grep "OOjs UI v" resources/lib/oojs-ui/oojs-ui.js \
+               | head -n 1 \
+               | grep -Eo '\bv[0-9a-z.-]+\b.*$'
+}
+
+# cd to the MW root directory
+cd $(cd $(dirname $0)/../../..; pwd)
+
+if [ "x$1" == "x" ]
+then
+       echo >&2 "Usage: update-oojs-ui.sh path/to/repo/for/oojs-ui"
+       exit 1
+fi
+
+# Undo any changes in the oojs-ui directory
+git reset -- resources/lib/oojs-ui/
+git checkout -- resources/lib/oojs-ui/
+
+git fetch origin
+# Create a branch of MW if needed, and reset it to master
+git checkout -B update-oojsui origin/master
+
+# Get the old oojs-ui version
+OLDVERSION=$(oojsuihash)
+if [ "x$OLDVERSION" == "x" ]
+then
+       TAG=$(oojsuitag)
+fi
+
+# cd to the oojs-ui directory
+cd $1 || exit 1
+if [ "x$OLDVERSION" == "x" ]
+then
+       # Try the tag
+       OLDVERSION=$(git rev-parse $TAG)
+       if [ $? != 0 ]
+       then
+               echo Could not find OOjs UI version
+               cd -
+               exit 1
+       fi
+fi
+if [ "$(git rev-parse $OLDVERSION)" == "$(git rev-parse HEAD)" ]
+then
+       echo "No changes (already at $OLDVERSION)"
+       cd -
+       exit 0
+fi
+# Build the distribution
+npm install || exit 1
+grunt || exit 1
+# Get the list of changes
+NEWCHANGES=$(git log $OLDVERSION.. --oneline --no-merges --reverse --color=never)
+NEWCHANGESDISPLAY=$(git log $OLDVERSION.. --oneline --no-merges --reverse --color=always)
+# cd back to the VisualEditor directory
+cd -
+
+# Copy files from dist/ to resources/lib/oojs-ui
+cp -a $1/dist/{oojs-ui.js,oojs-ui.svg.css,oojs-ui-apex.css,oojs-ui-agora.css,images,i18n} resources/lib/oojs-ui/
+# Figure out what the new version is
+NEWVERSION=$(oojsuiversion)
+# Generate commit summary
+COMMITMSG=$(cat <<END
+Update OOjs UI to $NEWVERSION
+
+New changes:
+$NEWCHANGES
+END
+)
+# Commit
+git commit resources/lib/oojs-ui/ -m "$COMMITMSG"
+cat >&2 <<END
+
+
+Created commit with changes:
+$NEWCHANGESDISPLAY
+END
diff --git a/resources/lib/oojs/oojs.js b/resources/lib/oojs/oojs.js
new file mode 100644 (file)
index 0000000..8ca3aed
--- /dev/null
@@ -0,0 +1,844 @@
+/*!
+ * OOjs v1.0.9
+ * https://www.mediawiki.org/wiki/OOjs
+ *
+ * Copyright 2011-2014 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: Wed Apr 02 2014 14:20:50 GMT-0700 (PDT)
+ */
+( function ( global ) {
+
+'use strict';
+var
+       /**
+        * Namespace for all classes, static methods and static properties.
+        * @class OO
+        * @singleton
+        */
+       oo = {},
+       hasOwn = oo.hasOwnProperty,
+       toString = oo.toString;
+
+/* Class Methods */
+
+/**
+ * Assert whether a value is a plain object or not.
+ *
+ * @param {Mixed} obj
+ * @return {boolean}
+ */
+oo.isPlainObject = function ( obj ) {
+       // Any object or value whose internal [[Class]] property is not "[object Object]"
+       if ( toString.call( obj ) !== '[object Object]' ) {
+               return false;
+       }
+
+       // The try/catch suppresses exceptions thrown when attempting to access
+       // the "constructor" property of certain host objects suich as window.location
+       // in Firefox < 20 (https://bugzilla.mozilla.org/814622)
+       try {
+               if ( obj.constructor &&
+                               !hasOwn.call( obj.constructor.prototype, 'isPrototypeOf' ) ) {
+                       return false;
+               }
+       } catch ( e ) {
+               return false;
+       }
+
+       return true;
+};
+
+/**
+ * Utility to initialize a class for OO inheritance.
+ *
+ * Currently this just initializes an empty static object.
+ *
+ * @param {Function} fn
+ */
+oo.initClass = function ( fn ) {
+       fn.static = fn.static || {};
+};
+
+/**
+ * Utility for common usage of Object#create for inheriting from one
+ * prototype to another.
+ *
+ * Beware: This redefines the prototype, call before setting your prototypes.
+ * Beware: This redefines the prototype, can only be called once on a function.
+ *  If called multiple times on the same function, the previous prototype is lost.
+ *  This is how prototypal inheritance works, it can only be one straight chain
+ *  (just like classical inheritance in PHP for example). If you need to work with
+ *  multiple constructors consider storing an instance of the other constructor in a
+ *  property instead, or perhaps use a mixin (see OO.mixinClass).
+ *
+ *     function Thing() {}
+ *     Thing.prototype.exists = function () {};
+ *
+ *     function Person() {
+ *         Person.super.apply( this, arguments );
+ *     }
+ *     OO.inheritClass( Person, Thing );
+ *     Person.static.defaultEyeCount = 2;
+ *     Person.prototype.walk = function () {};
+ *
+ *     function Jumper() {
+ *         Jumper.super.apply( this, arguments );
+ *     }
+ *     OO.inheritClass( Jumper, Person );
+ *     Jumper.prototype.jump = function () {};
+ *
+ *     Jumper.static.defaultEyeCount === 2;
+ *     var x = new Jumper();
+ *     x.jump();
+ *     x.walk();
+ *     x instanceof Thing && x instanceof Person && x instanceof Jumper;
+ *
+ * @param {Function} targetFn
+ * @param {Function} originFn
+ * @throws {Error} If target already inherits from origin
+ */
+oo.inheritClass = function ( targetFn, originFn ) {
+       if ( targetFn.prototype instanceof originFn ) {
+               throw new Error( 'Target already inherits from origin' );
+       }
+
+       var targetConstructor = targetFn.prototype.constructor;
+
+       targetFn.super = originFn;
+       targetFn.prototype = Object.create( originFn.prototype, {
+               // Restore constructor property of targetFn
+               constructor: {
+                       value: targetConstructor,
+                       enumerable: false,
+                       writable: true,
+                       configurable: true
+               }
+       } );
+
+       // Extend static properties - always initialize both sides
+       oo.initClass( originFn );
+       targetFn.static = Object.create( originFn.static );
+};
+
+/**
+ * Utility to copy over *own* prototype properties of a mixin.
+ * The 'constructor' (whether implicit or explicit) is not copied over.
+ *
+ * This does not create inheritance to the origin. If inheritance is needed
+ * use oo.inheritClass instead.
+ *
+ * Beware: This can redefine a prototype property, call before setting your prototypes.
+ * Beware: Don't call before oo.inheritClass.
+ *
+ *     function Foo() {}
+ *     function Context() {}
+ *
+ *     // Avoid repeating this code
+ *     function ContextLazyLoad() {}
+ *     ContextLazyLoad.prototype.getContext = function () {
+ *         if ( !this.context ) {
+ *             this.context = new Context();
+ *         }
+ *         return this.context;
+ *     };
+ *
+ *     function FooBar() {}
+ *     OO.inheritClass( FooBar, Foo );
+ *     OO.mixinClass( FooBar, ContextLazyLoad );
+ *
+ * @param {Function} targetFn
+ * @param {Function} originFn
+ */
+oo.mixinClass = function ( targetFn, originFn ) {
+       var key;
+
+       // Copy prototype properties
+       for ( key in originFn.prototype ) {
+               if ( key !== 'constructor' && hasOwn.call( originFn.prototype, key ) ) {
+                       targetFn.prototype[key] = originFn.prototype[key];
+               }
+       }
+
+       // Copy static properties - always initialize both sides
+       oo.initClass( targetFn );
+       if ( originFn.static ) {
+               for ( key in originFn.static ) {
+                       if ( hasOwn.call( originFn.static, key ) ) {
+                               targetFn.static[key] = originFn.static[key];
+                       }
+               }
+       } else {
+               oo.initClass( originFn );
+       }
+};
+
+/* Object Methods */
+
+/**
+ * Create a new object that is an instance of the same
+ * constructor as the input, inherits from the same object
+ * and contains the same own properties.
+ *
+ * This makes a shallow non-recursive copy of own properties.
+ * To create a recursive copy of plain objects, use #copy.
+ *
+ *     var foo = new Person( mom, dad );
+ *     foo.setAge( 21 );
+ *     var foo2 = OO.cloneObject( foo );
+ *     foo.setAge( 22 );
+ *
+ *     // Then
+ *     foo2 !== foo; // true
+ *     foo2 instanceof Person; // true
+ *     foo2.getAge(); // 21
+ *     foo.getAge(); // 22
+ *
+ * @param {Object} origin
+ * @return {Object} Clone of origin
+ */
+oo.cloneObject = function ( origin ) {
+       var key, r;
+
+       r = Object.create( origin.constructor.prototype );
+
+       for ( key in origin ) {
+               if ( hasOwn.call( origin, key ) ) {
+                       r[key] = origin[key];
+               }
+       }
+
+       return r;
+};
+
+/**
+ * Get an array of all property values in an object.
+ *
+ * @param {Object} Object to get values from
+ * @return {Array} List of object values
+ */
+oo.getObjectValues = function ( obj ) {
+       var key, values;
+
+       if ( obj !== Object( obj ) ) {
+               throw new TypeError( 'Called on non-object' );
+       }
+
+       values = [];
+       for ( key in obj ) {
+               if ( hasOwn.call( obj, key ) ) {
+                       values[values.length] = obj[key];
+               }
+       }
+
+       return values;
+};
+
+/**
+ * Recursively compares properties between two objects.
+ *
+ * A false result may be caused by property inequality or by properties in one object missing from
+ * the other. An asymmetrical test may also be performed, which checks only that properties in the
+ * first object are present in the second object, but not the inverse.
+ *
+ * @param {Object} a First object to compare
+ * @param {Object} b Second object to compare
+ * @param {boolean} [asymmetrical] Whether to check only that b contains values from a
+ * @return {boolean} If the objects contain the same values as each other
+ */
+oo.compare = function ( a, b, asymmetrical ) {
+       var aValue, bValue, aType, bType, k;
+
+       if ( a === b ) {
+               return true;
+       }
+
+       for ( k in a ) {
+               aValue = a[k];
+               bValue = b[k];
+               aType = typeof aValue;
+               bType = typeof bValue;
+               if ( aType !== bType ||
+                       ( ( aType === 'string' || aType === 'number' ) && aValue !== bValue ) ||
+                       ( aValue === Object( aValue ) && !oo.compare( aValue, bValue, asymmetrical ) ) ) {
+                       return false;
+               }
+       }
+       // If the check is not asymmetrical, recursing with the arguments swapped will verify our result
+       return asymmetrical ? true : oo.compare( b, a, true );
+};
+
+/**
+ * Create a plain deep copy of any kind of object.
+ *
+ * Copies are deep, and will either be an object or an array depending on `source`.
+ *
+ * @param {Object} source Object to copy
+ * @param {Function} [callback] Applied to leaf values before they added to the clone
+ * @return {Object} Copy of source object
+ */
+oo.copy = function ( source, callback ) {
+       var key, sourceValue, sourceType, destination;
+
+       if ( typeof source.clone === 'function' ) {
+               return source.clone();
+       }
+
+       destination = Array.isArray( source ) ? new Array( source.length ) : {};
+
+       for ( key in source ) {
+               sourceValue = source[key];
+               sourceType = typeof sourceValue;
+               if ( Array.isArray( sourceValue ) ) {
+                       // Array
+                       destination[key] = oo.copy( sourceValue, callback );
+               } else if ( sourceValue && typeof sourceValue.clone === 'function' ) {
+                       // Duck type object with custom clone method
+                       destination[key] = callback ?
+                               callback( sourceValue.clone() ) : sourceValue.clone();
+               } else if ( sourceValue && typeof sourceValue.cloneNode === 'function' ) {
+                       // DOM Node
+                       destination[key] = callback ?
+                               callback( sourceValue.cloneNode( true ) ) : sourceValue.cloneNode( true );
+               } else if ( oo.isPlainObject( sourceValue ) ) {
+                       // Plain objects
+                       destination[key] = oo.copy( sourceValue, callback );
+               } else {
+                       // Non-plain objects (incl. functions) and primitive values
+                       destination[key] = callback ? callback( sourceValue ) : sourceValue;
+               }
+       }
+
+       return destination;
+};
+
+/**
+ * Generate a hash of an object based on its name and data.
+ *
+ * Performance optimization: <http://jsperf.com/ve-gethash-201208#/toJson_fnReplacerIfAoForElse>
+ *
+ * To avoid two objects with the same values generating different hashes, we utilize the replacer
+ * argument of JSON.stringify and sort the object by key as it's being serialized. This may or may
+ * not be the fastest way to do this; we should investigate this further.
+ *
+ * Objects and arrays are hashed recursively. When hashing an object that has a .getHash()
+ * function, we call that function and use its return value rather than hashing the object
+ * ourselves. This allows classes to define custom hashing.
+ *
+ * @param {Object} val Object to generate hash for
+ * @return {string} Hash of object
+ */
+oo.getHash = function ( val ) {
+       return JSON.stringify( val, oo.getHash.keySortReplacer );
+};
+
+/**
+ * Helper function for OO.getHash which sorts objects by key.
+ *
+ * This is a callback passed into JSON.stringify.
+ *
+ * @method getHash_keySortReplacer
+ * @param {string} key Property name of value being replaced
+ * @param {Mixed} val Property value to replace
+ * @return {Mixed} Replacement value
+ */
+oo.getHash.keySortReplacer = function ( key, val ) {
+       var normalized, keys, i, len;
+       if ( val && typeof val.getHashObject === 'function' ) {
+               // This object has its own custom hash function, use it
+               val = val.getHashObject();
+       }
+       if ( !Array.isArray( val ) && Object( val ) === val ) {
+               // Only normalize objects when the key-order is ambiguous
+               // (e.g. any object not an array).
+               normalized = {};
+               keys = Object.keys( val ).sort();
+               i = 0;
+               len = keys.length;
+               for ( ; i < len; i += 1 ) {
+                       normalized[keys[i]] = val[keys[i]];
+               }
+               return normalized;
+
+       // Primitive values and arrays get stable hashes
+       // by default. Lets those be stringified as-is.
+       } else {
+               return val;
+       }
+};
+
+/**
+ * Compute the union (duplicate-free merge) of a set of arrays.
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * By building an object (with the values for keys) in parallel with
+ * the array, a new item's existence in the union can be computed faster.
+ *
+ * @param {Array...} arrays Arrays to union
+ * @return {Array} Union of the arrays
+ */
+oo.simpleArrayUnion = function () {
+       var i, ilen, arr, j, jlen,
+               obj = {},
+               result = [];
+
+       for ( i = 0, ilen = arguments.length; i < ilen; i++ ) {
+               arr = arguments[i];
+               for ( j = 0, jlen = arr.length; j < jlen; j++ ) {
+                       if ( !obj[ arr[j] ] ) {
+                               obj[ arr[j] ] = true;
+                               result.push( arr[j] );
+                       }
+               }
+       }
+
+       return result;
+};
+
+/**
+ * Combine arrays (intersection or difference).
+ *
+ * An intersection checks the item exists in 'b' while difference checks it doesn't.
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * By building an object (with the values for keys) of 'b' we can
+ * compute the result faster.
+ *
+ * @private
+ * @param {Array} a First array
+ * @param {Array} b Second array
+ * @param {boolean} includeB Whether to items in 'b'
+ * @return {Array} Combination (intersection or difference) of arrays
+ */
+function simpleArrayCombine( a, b, includeB ) {
+       var i, ilen, isInB,
+               bObj = {},
+               result = [];
+
+       for ( i = 0, ilen = b.length; i < ilen; i++ ) {
+               bObj[ b[i] ] = true;
+       }
+
+       for ( i = 0, ilen = a.length; i < ilen; i++ ) {
+               isInB = !!bObj[ a[i] ];
+               if ( isInB === includeB ) {
+                       result.push( a[i] );
+               }
+       }
+
+       return result;
+}
+
+/**
+ * Compute the intersection of two arrays (items in both arrays).
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * @param {Array} a First array
+ * @param {Array} b Second array
+ * @return {Array} Intersection of arrays
+ */
+oo.simpleArrayIntersection = function ( a, b ) {
+       return simpleArrayCombine( a, b, true );
+};
+
+/**
+ * Compute the difference of two arrays (items in 'a' but not 'b').
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * @param {Array} a First array
+ * @param {Array} b Second array
+ * @return {Array} Intersection of arrays
+ */
+oo.simpleArrayDifference = function ( a, b ) {
+       return simpleArrayCombine( a, b, false );
+};
+/**
+ * @class OO.EventEmitter
+ *
+ * @constructor
+ */
+oo.EventEmitter = function OoEventEmitter() {
+       // Properties
+
+       /**
+        * Storage of bound event handlers by event name.
+        *
+        * @property
+        */
+       this.bindings = {};
+};
+
+/* Methods */
+
+/**
+ * Add a listener to events of a specific event.
+ *
+ * If the callback/context are already bound to the event, they will not be bound again.
+ *
+ * @param {string} event Type of event to listen to
+ * @param {Function} callback Function to call when event occurs
+ * @param {Array} [args] Arguments to pass to listener, will be prepended to emitted arguments
+ * @param {Object} [context=null] Object to use as context for callback function or call method on
+ * @throws {Error} Listener argument is not a function or method name
+ * @chainable
+ */
+oo.EventEmitter.prototype.on = function ( event, callback, args, context ) {
+       var i, bindings, binding;
+
+       // Validate callback
+       if ( typeof callback !== 'function' ) {
+               throw new Error( 'Invalid callback. Function or method name expected.' );
+       }
+       // Fallback to null context
+       if ( arguments.length < 4 ) {
+               context = null;
+       }
+       if ( this.bindings.hasOwnProperty( event ) ) {
+               // Check for duplicate callback and context for this event
+               bindings = this.bindings[event];
+               i = bindings.length;
+               while ( i-- ) {
+                       binding = bindings[i];
+                       if ( bindings.callback === callback && bindings.context === context ) {
+                               return this;
+                       }
+               }
+       } else {
+               // Auto-initialize bindings list
+               bindings = this.bindings[event] = [];
+       }
+       // Add binding
+       bindings.push( {
+               callback: callback,
+               args: args,
+               context: context
+       } );
+       return this;
+};
+
+/**
+ * Adds a one-time listener to a specific event.
+ *
+ * @param {string} event Type of event to listen to
+ * @param {Function} listener Listener to call when event occurs
+ * @chainable
+ */
+oo.EventEmitter.prototype.once = function ( event, listener ) {
+       var eventEmitter = this;
+       return this.on( event, function listenerWrapper() {
+               eventEmitter.off( event, listenerWrapper );
+               listener.apply( eventEmitter, Array.prototype.slice.call( arguments, 0 ) );
+       } );
+};
+
+/**
+ * Remove a specific listener from a specific event.
+ *
+ * @param {string} event Type of event to remove listener from
+ * @param {Function} [callback] Listener to remove, omit to remove all
+ * @param {Object} [context=null] Object used context for callback function or method
+ * @chainable
+ * @throws {Error} Listener argument is not a function
+ */
+oo.EventEmitter.prototype.off = function ( event, callback, context ) {
+       var i, bindings;
+
+       if ( arguments.length === 1 ) {
+               // Remove all bindings for event
+               if ( event in this.bindings ) {
+                       delete this.bindings[event];
+               }
+       } else {
+               if ( typeof callback !== 'function' ) {
+                       throw new Error( 'Invalid callback. Function expected.' );
+               }
+               if ( !( event in this.bindings ) || !this.bindings[event].length ) {
+                       // No matching bindings
+                       return this;
+               }
+               // Fallback to null context
+               if ( arguments.length < 3 ) {
+                       context = null;
+               }
+               // Remove matching handlers
+               bindings = this.bindings[event];
+               i = bindings.length;
+               while ( i-- ) {
+                       if ( bindings[i].callback === callback && bindings[i].context === context ) {
+                               bindings.splice( i, 1 );
+                       }
+               }
+               // Cleanup if now empty
+               if ( bindings.length === 0 ) {
+                       delete this.bindings[event];
+               }
+       }
+       return this;
+};
+
+/**
+ * Emit an event.
+ *
+ * TODO: Should this be chainable? What is the usefulness of the boolean
+ * return value here?
+ *
+ * @param {string} event Type of event
+ * @param {Mixed} args First in a list of variadic arguments passed to event handler (optional)
+ * @return {boolean} If event was handled by at least one listener
+ */
+oo.EventEmitter.prototype.emit = function ( event ) {
+       var i, len, binding, bindings, args;
+
+       if ( event in this.bindings ) {
+               // Slicing ensures that we don't get tripped up by event handlers that add/remove bindings
+               bindings = this.bindings[event].slice();
+               args = Array.prototype.slice.call( arguments, 1 );
+               for ( i = 0, len = bindings.length; i < len; i++ ) {
+                       binding = bindings[i];
+                       binding.callback.apply(
+                               binding.context,
+                               binding.args ? binding.args.concat( args ) : args
+                       );
+               }
+               return true;
+       }
+       return false;
+};
+
+/**
+ * Connect event handlers to an object.
+ *
+ * @param {Object} context Object to call methods on when events occur
+ * @param {Object.<string,string>|Object.<string,Function>|Object.<string,Array>} methods List of
+ *  event bindings keyed by event name containing either method names, functions or arrays containing
+ *  method name or function followed by a list of arguments to be passed to callback before emitted
+ *  arguments
+ * @chainable
+ */
+oo.EventEmitter.prototype.connect = function ( context, methods ) {
+       var method, callback, args, event;
+
+       for ( event in methods ) {
+               method = methods[event];
+               // Allow providing additional args
+               if ( Array.isArray( method ) ) {
+                       args = method.slice( 1 );
+                       method = method[0];
+               } else {
+                       args = [];
+               }
+               // Allow callback to be a method name
+               if ( typeof method === 'string' ) {
+                       // Validate method
+                       if ( !context[method] || typeof context[method] !== 'function' ) {
+                               throw new Error( 'Method not found: ' + method );
+                       }
+                       // Resolve to function
+                       callback = context[method];
+               } else {
+                       callback = method;
+               }
+               // Add binding
+               this.on.apply( this, [ event, callback, args, context ] );
+       }
+       return this;
+};
+
+/**
+ * Disconnect event handlers from an object.
+ *
+ * @param {Object} context Object to disconnect methods from
+ * @param {Object.<string,string>|Object.<string,Function>|Object.<string,Array>} [methods] List of
+ * event bindings keyed by event name containing either method names or functions
+ * @chainable
+ */
+oo.EventEmitter.prototype.disconnect = function ( context, methods ) {
+       var i, method, callback, event, bindings;
+
+       if ( methods ) {
+               // Remove specific connections to the context
+               for ( event in methods ) {
+                       method = methods[event];
+                       if ( typeof method === 'string' ) {
+                               // Validate method
+                               if ( !context[method] || typeof context[method] !== 'function' ) {
+                                       throw new Error( 'Method not found: ' + method );
+                               }
+                               // Resolve to function
+                               callback = context[method];
+                       } else {
+                               callback = method;
+                       }
+                       this.off( event, callback, context );
+               }
+       } else {
+               // Remove all connections to the context
+               for ( event in this.bindings ) {
+                       bindings = this.bindings[event];
+                       i = bindings.length;
+                       while ( i-- ) {
+                               if ( bindings[i].context === context ) {
+                                       this.off( event, bindings[i].callback, context );
+                               }
+                       }
+               }
+       }
+
+       return this;
+};
+/**
+ * @class OO.Registry
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ */
+oo.Registry = function OoRegistry() {
+       // Mixin constructors
+       oo.EventEmitter.call( this );
+
+       // Properties
+       this.registry = {};
+};
+
+/* Inheritance */
+
+oo.mixinClass( oo.Registry, oo.EventEmitter );
+
+/* Events */
+
+/**
+ * @event register
+ * @param {string} name
+ * @param {Mixed} data
+ */
+
+/* Methods */
+
+/**
+ * Associate one or more symbolic names with some data.
+ *
+ * Only the base name will be registered, overriding any existing entry with the same base name.
+ *
+ * @param {string|string[]} name Symbolic name or list of symbolic names
+ * @param {Mixed} data Data to associate with symbolic name
+ * @fires register
+ * @throws {Error} Name argument must be a string or array
+ */
+oo.Registry.prototype.register = function ( name, data ) {
+       var i, len;
+       if ( typeof name === 'string' ) {
+               this.registry[name] = data;
+               this.emit( 'register', name, data );
+       } else if ( Array.isArray( name ) ) {
+               for ( i = 0, len = name.length; i < len; i++ ) {
+                       this.register( name[i], data );
+               }
+       } else {
+               throw new Error( 'Name must be a string or array, cannot be a ' + typeof name );
+       }
+};
+
+/**
+ * Get data for a given symbolic name.
+ *
+ * Lookups are done using the base name.
+ *
+ * @param {string} name Symbolic name
+ * @return {Mixed|undefined} Data associated with symbolic name
+ */
+oo.Registry.prototype.lookup = function ( name ) {
+       return this.registry[name];
+};
+/**
+ * @class OO.Factory
+ * @extends OO.Registry
+ *
+ * @constructor
+ */
+oo.Factory = function OoFactory() {
+       oo.Factory.super.call( this );
+
+       // Properties
+       this.entries = [];
+};
+
+/* Inheritance */
+
+oo.inheritClass( oo.Factory, oo.Registry );
+
+/* Methods */
+
+/**
+ * Register a constructor with the factory.
+ *
+ * Classes must have a static `name` property to be registered.
+ *
+ *     function MyClass() {};
+ *     OO.initClass( MyClass );
+ *     // Adds a static property to the class defining a symbolic name
+ *     MyClass.static.name = 'mine';
+ *     // Registers class with factory, available via symbolic name 'mine'
+ *     factory.register( MyClass );
+ *
+ * @param {Function} constructor Constructor to use when creating object
+ * @throws {Error} Name must be a string and must not be empty
+ * @throws {Error} Constructor must be a function
+ */
+oo.Factory.prototype.register = function ( constructor ) {
+       var name;
+
+       if ( typeof constructor !== 'function' ) {
+               throw new Error( 'constructor must be a function, cannot be a ' + typeof constructor );
+       }
+       name = constructor.static && constructor.static.name;
+       if ( typeof name !== 'string' || name === '' ) {
+               throw new Error( 'Name must be a string and must not be empty' );
+       }
+       this.entries.push( name );
+
+       oo.Factory.super.prototype.register.call( this, name, constructor );
+};
+
+/**
+ * Create an object based on a name.
+ *
+ * Name is used to look up the constructor to use, while all additional arguments are passed to the
+ * constructor directly, so leaving one out will pass an undefined to the constructor.
+ *
+ * @param {string} name Object name
+ * @param {Mixed...} [args] Arguments to pass to the constructor
+ * @return {Object} The new object
+ * @throws {Error} Unknown object name
+ */
+oo.Factory.prototype.create = function ( name ) {
+       var args, obj, constructor;
+
+       if ( !this.registry.hasOwnProperty( name ) ) {
+               throw new Error( 'No class registered by that name: ' + name );
+       }
+       constructor = this.registry[name];
+
+       // Convert arguments to array and shift the first argument (name) off
+       args = Array.prototype.slice.call( arguments, 1 );
+
+       // We can't use the "new" operator with .apply directly because apply needs a
+       // context. So instead just do what "new" does: create an object that inherits from
+       // the constructor's prototype (which also makes it an "instanceof" the constructor),
+       // then invoke the constructor with the object as context, and return it (ignoring
+       // the constructor's return value).
+       obj = Object.create( constructor.prototype );
+       constructor.apply( obj, args );
+       return obj;
+};
+/*jshint node:true */
+if ( typeof module !== 'undefined' && module.exports ) {
+       module.exports = oo;
+} else {
+       global.OO = oo;
+}
+}( this ) );
diff --git a/resources/lib/sinonjs/sinon-1.9.0.js b/resources/lib/sinonjs/sinon-1.9.0.js
new file mode 100644 (file)
index 0000000..428b729
--- /dev/null
@@ -0,0 +1,4794 @@
+/**
+ * Sinon.JS 1.9.0, 2014/03/05
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
+ *
+ * (The BSD License)
+ * 
+ * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ *     * Neither the name of Christian Johansen nor the names of his contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+this.sinon = (function () {
+var samsam, formatio;
+function define(mod, deps, fn) { if (mod == "samsam") { samsam = deps(); } else { formatio = fn(samsam); } }
+define.amd = true;
+((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
+ (typeof module === "object" &&
+      function (m) { module.exports = m(); }) || // Node
+ function (m) { this.samsam = m(); } // Browser globals
+)(function () {
+    var o = Object.prototype;
+    var div = typeof document !== "undefined" && document.createElement("div");
+
+    function isNaN(value) {
+        // Unlike global isNaN, this avoids type coercion
+        // typeof check avoids IE host object issues, hat tip to
+        // lodash
+        var val = value; // JsLint thinks value !== value is "weird"
+        return typeof value === "number" && value !== val;
+    }
+
+    function getClass(value) {
+        // Returns the internal [[Class]] by calling Object.prototype.toString
+        // with the provided value as this. Return value is a string, naming the
+        // internal class, e.g. "Array"
+        return o.toString.call(value).split(/[ \]]/)[1];
+    }
+
+    /**
+     * @name samsam.isArguments
+     * @param Object object
+     *
+     * Returns ``true`` if ``object`` is an ``arguments`` object,
+     * ``false`` otherwise.
+     */
+    function isArguments(object) {
+        if (typeof object !== "object" || typeof object.length !== "number" ||
+                getClass(object) === "Array") {
+            return false;
+        }
+        if (typeof object.callee == "function") { return true; }
+        try {
+            object[object.length] = 6;
+            delete object[object.length];
+        } catch (e) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @name samsam.isElement
+     * @param Object object
+     *
+     * Returns ``true`` if ``object`` is a DOM element node. Unlike
+     * Underscore.js/lodash, this function will return ``false`` if ``object``
+     * is an *element-like* object, i.e. a regular object with a ``nodeType``
+     * property that holds the value ``1``.
+     */
+    function isElement(object) {
+        if (!object || object.nodeType !== 1 || !div) { return false; }
+        try {
+            object.appendChild(div);
+            object.removeChild(div);
+        } catch (e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * @name samsam.keys
+     * @param Object object
+     *
+     * Return an array of own property names.
+     */
+    function keys(object) {
+        var ks = [], prop;
+        for (prop in object) {
+            if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
+        }
+        return ks;
+    }
+
+    /**
+     * @name samsam.isDate
+     * @param Object value
+     *
+     * Returns true if the object is a ``Date``, or *date-like*. Duck typing
+     * of date objects work by checking that the object has a ``getTime``
+     * function whose return value equals the return value from the object's
+     * ``valueOf``.
+     */
+    function isDate(value) {
+        return typeof value.getTime == "function" &&
+            value.getTime() == value.valueOf();
+    }
+
+    /**
+     * @name samsam.isNegZero
+     * @param Object value
+     *
+     * Returns ``true`` if ``value`` is ``-0``.
+     */
+    function isNegZero(value) {
+        return value === 0 && 1 / value === -Infinity;
+    }
+
+    /**
+     * @name samsam.equal
+     * @param Object obj1
+     * @param Object obj2
+     *
+     * Returns ``true`` if two objects are strictly equal. Compared to
+     * ``===`` there are two exceptions:
+     *
+     *   - NaN is considered equal to NaN
+     *   - -0 and +0 are not considered equal
+     */
+    function identical(obj1, obj2) {
+        if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
+            return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
+        }
+    }
+
+
+    /**
+     * @name samsam.deepEqual
+     * @param Object obj1
+     * @param Object obj2
+     *
+     * Deep equal comparison. Two values are "deep equal" if:
+     *
+     *   - They are equal, according to samsam.identical
+     *   - They are both date objects representing the same time
+     *   - They are both arrays containing elements that are all deepEqual
+     *   - They are objects with the same set of properties, and each property
+     *     in ``obj1`` is deepEqual to the corresponding property in ``obj2``
+     *
+     * Supports cyclic objects.
+     */
+    function deepEqualCyclic(obj1, obj2) {
+
+        // used for cyclic comparison
+        // contain already visited objects
+        var objects1 = [],
+            objects2 = [],
+        // contain pathes (position in the object structure)
+        // of the already visited objects
+        // indexes same as in objects arrays
+            paths1 = [],
+            paths2 = [],
+        // contains combinations of already compared objects
+        // in the manner: { "$1['ref']$2['ref']": true }
+            compared = {};
+
+        /**
+         * used to check, if the value of a property is an object
+         * (cyclic logic is only needed for objects)
+         * only needed for cyclic logic
+         */
+        function isObject(value) {
+
+            if (typeof value === 'object' && value !== null &&
+                    !(value instanceof Boolean) &&
+                    !(value instanceof Date)    &&
+                    !(value instanceof Number)  &&
+                    !(value instanceof RegExp)  &&
+                    !(value instanceof String)) {
+
+                return true;
+            }
+
+            return false;
+        }
+
+        /**
+         * returns the index of the given object in the
+         * given objects array, -1 if not contained
+         * only needed for cyclic logic
+         */
+        function getIndex(objects, obj) {
+
+            var i;
+            for (i = 0; i < objects.length; i++) {
+                if (objects[i] === obj) {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+
+        // does the recursion for the deep equal check
+        return (function deepEqual(obj1, obj2, path1, path2) {
+            var type1 = typeof obj1;
+            var type2 = typeof obj2;
+
+            // == null also matches undefined
+            if (obj1 === obj2 ||
+                    isNaN(obj1) || isNaN(obj2) ||
+                    obj1 == null || obj2 == null ||
+                    type1 !== "object" || type2 !== "object") {
+
+                return identical(obj1, obj2);
+            }
+
+            // Elements are only equal if identical(expected, actual)
+            if (isElement(obj1) || isElement(obj2)) { return false; }
+
+            var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
+            if (isDate1 || isDate2) {
+                if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
+                    return false;
+                }
+            }
+
+            if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
+                if (obj1.toString() !== obj2.toString()) { return false; }
+            }
+
+            var class1 = getClass(obj1);
+            var class2 = getClass(obj2);
+            var keys1 = keys(obj1);
+            var keys2 = keys(obj2);
+
+            if (isArguments(obj1) || isArguments(obj2)) {
+                if (obj1.length !== obj2.length) { return false; }
+            } else {
+                if (type1 !== type2 || class1 !== class2 ||
+                        keys1.length !== keys2.length) {
+                    return false;
+                }
+            }
+
+            var key, i, l,
+                // following vars are used for the cyclic logic
+                value1, value2,
+                isObject1, isObject2,
+                index1, index2,
+                newPath1, newPath2;
+
+            for (i = 0, l = keys1.length; i < l; i++) {
+                key = keys1[i];
+                if (!o.hasOwnProperty.call(obj2, key)) {
+                    return false;
+                }
+
+                // Start of the cyclic logic
+
+                value1 = obj1[key];
+                value2 = obj2[key];
+
+                isObject1 = isObject(value1);
+                isObject2 = isObject(value2);
+
+                // determine, if the objects were already visited
+                // (it's faster to check for isObject first, than to
+                // get -1 from getIndex for non objects)
+                index1 = isObject1 ? getIndex(objects1, value1) : -1;
+                index2 = isObject2 ? getIndex(objects2, value2) : -1;
+
+                // determine the new pathes of the objects
+                // - for non cyclic objects the current path will be extended
+                //   by current property name
+                // - for cyclic objects the stored path is taken
+                newPath1 = index1 !== -1
+                    ? paths1[index1]
+                    : path1 + '[' + JSON.stringify(key) + ']';
+                newPath2 = index2 !== -1
+                    ? paths2[index2]
+                    : path2 + '[' + JSON.stringify(key) + ']';
+
+                // stop recursion if current objects are already compared
+                if (compared[newPath1 + newPath2]) {
+                    return true;
+                }
+
+                // remember the current objects and their pathes
+                if (index1 === -1 && isObject1) {
+                    objects1.push(value1);
+                    paths1.push(newPath1);
+                }
+                if (index2 === -1 && isObject2) {
+                    objects2.push(value2);
+                    paths2.push(newPath2);
+                }
+
+                // remember that the current objects are already compared
+                if (isObject1 && isObject2) {
+                    compared[newPath1 + newPath2] = true;
+                }
+
+                // End of cyclic logic
+
+                // neither value1 nor value2 is a cycle
+                // continue with next level
+                if (!deepEqual(value1, value2, newPath1, newPath2)) {
+                    return false;
+                }
+            }
+
+            return true;
+
+        }(obj1, obj2, '$1', '$2'));
+    }
+
+    var match;
+
+    function arrayContains(array, subset) {
+        if (subset.length === 0) { return true; }
+        var i, l, j, k;
+        for (i = 0, l = array.length; i < l; ++i) {
+            if (match(array[i], subset[0])) {
+                for (j = 0, k = subset.length; j < k; ++j) {
+                    if (!match(array[i + j], subset[j])) { return false; }
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @name samsam.match
+     * @param Object object
+     * @param Object matcher
+     *
+     * Compare arbitrary value ``object`` with matcher.
+     */
+    match = function match(object, matcher) {
+        if (matcher && typeof matcher.test === "function") {
+            return matcher.test(object);
+        }
+
+        if (typeof matcher === "function") {
+            return matcher(object) === true;
+        }
+
+        if (typeof matcher === "string") {
+            matcher = matcher.toLowerCase();
+            var notNull = typeof object === "string" || !!object;
+            return notNull &&
+                (String(object)).toLowerCase().indexOf(matcher) >= 0;
+        }
+
+        if (typeof matcher === "number") {
+            return matcher === object;
+        }
+
+        if (typeof matcher === "boolean") {
+            return matcher === object;
+        }
+
+        if (getClass(object) === "Array" && getClass(matcher) === "Array") {
+            return arrayContains(object, matcher);
+        }
+
+        if (matcher && typeof matcher === "object") {
+            var prop;
+            for (prop in matcher) {
+                if (!match(object[prop], matcher[prop])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        throw new Error("Matcher was not a string, a number, a " +
+                        "function, a boolean or an object");
+    };
+
+    return {
+        isArguments: isArguments,
+        isElement: isElement,
+        isDate: isDate,
+        isNegZero: isNegZero,
+        identical: identical,
+        deepEqual: deepEqualCyclic,
+        match: match,
+        keys: keys
+    };
+});
+((typeof define === "function" && define.amd && function (m) {
+    define("formatio", ["samsam"], m);
+}) || (typeof module === "object" && function (m) {
+    module.exports = m(require("samsam"));
+}) || function (m) { this.formatio = m(this.samsam); }
+)(function (samsam) {
+    
+    var formatio = {
+        excludeConstructors: ["Object", /^.$/],
+        quoteStrings: true
+    };
+
+    var hasOwn = Object.prototype.hasOwnProperty;
+
+    var specialObjects = [];
+    if (typeof global !== "undefined") {
+        specialObjects.push({ object: global, value: "[object global]" });
+    }
+    if (typeof document !== "undefined") {
+        specialObjects.push({
+            object: document,
+            value: "[object HTMLDocument]"
+        });
+    }
+    if (typeof window !== "undefined") {
+        specialObjects.push({ object: window, value: "[object Window]" });
+    }
+
+    function functionName(func) {
+        if (!func) { return ""; }
+        if (func.displayName) { return func.displayName; }
+        if (func.name) { return func.name; }
+        var matches = func.toString().match(/function\s+([^\(]+)/m);
+        return (matches && matches[1]) || "";
+    }
+
+    function constructorName(f, object) {
+        var name = functionName(object && object.constructor);
+        var excludes = f.excludeConstructors ||
+                formatio.excludeConstructors || [];
+
+        var i, l;
+        for (i = 0, l = excludes.length; i < l; ++i) {
+            if (typeof excludes[i] === "string" && excludes[i] === name) {
+                return "";
+            } else if (excludes[i].test && excludes[i].test(name)) {
+                return "";
+            }
+        }
+
+        return name;
+    }
+
+    function isCircular(object, objects) {
+        if (typeof object !== "object") { return false; }
+        var i, l;
+        for (i = 0, l = objects.length; i < l; ++i) {
+            if (objects[i] === object) { return true; }
+        }
+        return false;
+    }
+
+    function ascii(f, object, processed, indent) {
+        if (typeof object === "string") {
+            var qs = f.quoteStrings;
+            var quote = typeof qs !== "boolean" || qs;
+            return processed || quote ? '"' + object + '"' : object;
+        }
+
+        if (typeof object === "function" && !(object instanceof RegExp)) {
+            return ascii.func(object);
+        }
+
+        processed = processed || [];
+
+        if (isCircular(object, processed)) { return "[Circular]"; }
+
+        if (Object.prototype.toString.call(object) === "[object Array]") {
+            return ascii.array.call(f, object, processed);
+        }
+
+        if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
+        if (samsam.isElement(object)) { return ascii.element(object); }
+
+        if (typeof object.toString === "function" &&
+                object.toString !== Object.prototype.toString) {
+            return object.toString();
+        }
+
+        var i, l;
+        for (i = 0, l = specialObjects.length; i < l; i++) {
+            if (object === specialObjects[i].object) {
+                return specialObjects[i].value;
+            }
+        }
+
+        return ascii.object.call(f, object, processed, indent);
+    }
+
+    ascii.func = function (func) {
+        return "function " + functionName(func) + "() {}";
+    };
+
+    ascii.array = function (array, processed) {
+        processed = processed || [];
+        processed.push(array);
+        var i, l, pieces = [];
+        for (i = 0, l = array.length; i < l; ++i) {
+            pieces.push(ascii(this, array[i], processed));
+        }
+        return "[" + pieces.join(", ") + "]";
+    };
+
+    ascii.object = function (object, processed, indent) {
+        processed = processed || [];
+        processed.push(object);
+        indent = indent || 0;
+        var pieces = [], properties = samsam.keys(object).sort();
+        var length = 3;
+        var prop, str, obj, i, l;
+
+        for (i = 0, l = properties.length; i < l; ++i) {
+            prop = properties[i];
+            obj = object[prop];
+
+            if (isCircular(obj, processed)) {
+                str = "[Circular]";
+            } else {
+                str = ascii(this, obj, processed, indent + 2);
+            }
+
+            str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
+            length += str.length;
+            pieces.push(str);
+        }
+
+        var cons = constructorName(this, object);
+        var prefix = cons ? "[" + cons + "] " : "";
+        var is = "";
+        for (i = 0, l = indent; i < l; ++i) { is += " "; }
+
+        if (length + indent > 80) {
+            return prefix + "{\n  " + is + pieces.join(",\n  " + is) + "\n" +
+                is + "}";
+        }
+        return prefix + "{ " + pieces.join(", ") + " }";
+    };
+
+    ascii.element = function (element) {
+        var tagName = element.tagName.toLowerCase();
+        var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
+
+        for (i = 0, l = attrs.length; i < l; ++i) {
+            attr = attrs.item(i);
+            attrName = attr.nodeName.toLowerCase().replace("html:", "");
+            val = attr.nodeValue;
+            if (attrName !== "contenteditable" || val !== "inherit") {
+                if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
+            }
+        }
+
+        var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
+        var content = element.innerHTML;
+
+        if (content.length > 20) {
+            content = content.substr(0, 20) + "[...]";
+        }
+
+        var res = formatted + pairs.join(" ") + ">" + content +
+                "</" + tagName + ">";
+
+        return res.replace(/ contentEditable="inherit"/, "");
+    };
+
+    function Formatio(options) {
+        for (var opt in options) {
+            this[opt] = options[opt];
+        }
+    }
+
+    Formatio.prototype = {
+        functionName: functionName,
+
+        configure: function (options) {
+            return new Formatio(options);
+        },
+
+        constructorName: function (object) {
+            return constructorName(this, object);
+        },
+
+        ascii: function (object, processed, indent) {
+            return ascii(this, object, processed, indent);
+        }
+    };
+
+    return Formatio.prototype;
+});
+/*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
+/*global module, require, __dirname, document*/
+/**
+ * Sinon core utilities. For internal use only.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+var sinon = (function (formatio) {
+    var div = typeof document != "undefined" && document.createElement("div");
+    var hasOwn = Object.prototype.hasOwnProperty;
+
+    function isDOMNode(obj) {
+        var success = false;
+
+        try {
+            obj.appendChild(div);
+            success = div.parentNode == obj;
+        } catch (e) {
+            return false;
+        } finally {
+            try {
+                obj.removeChild(div);
+            } catch (e) {
+                // Remove failed, not much we can do about that
+            }
+        }
+
+        return success;
+    }
+
+    function isElement(obj) {
+        return div && obj && obj.nodeType === 1 && isDOMNode(obj);
+    }
+
+    function isFunction(obj) {
+        return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
+    }
+
+    function mirrorProperties(target, source) {
+        for (var prop in source) {
+            if (!hasOwn.call(target, prop)) {
+                target[prop] = source[prop];
+            }
+        }
+    }
+
+    function isRestorable (obj) {
+        return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
+    }
+
+    var sinon = {
+        wrapMethod: function wrapMethod(object, property, method) {
+            if (!object) {
+                throw new TypeError("Should wrap property of object");
+            }
+
+            if (typeof method != "function") {
+                throw new TypeError("Method wrapper should be function");
+            }
+
+            var wrappedMethod = object[property],
+                error;
+
+            if (!isFunction(wrappedMethod)) {
+                error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
+                                    property + " as function");
+            }
+
+            if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
+                error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
+            }
+
+            if (wrappedMethod.calledBefore) {
+                var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
+                error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
+            }
+
+            if (error) {
+                if (wrappedMethod._stack) {
+                    error.stack += '\n--------------\n' + wrappedMethod._stack;
+                }
+                throw error;
+            }
+
+            // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
+            // when using hasOwn.call on objects from other frames.
+            var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
+            object[property] = method;
+            method.displayName = property;
+            // Set up a stack trace which can be used later to find what line of
+            // code the original method was created on.
+            method._stack = (new Error('Stack Trace for original')).stack;
+
+            method.restore = function () {
+                // For prototype properties try to reset by delete first.
+                // If this fails (ex: localStorage on mobile safari) then force a reset
+                // via direct assignment.
+                if (!owned) {
+                    delete object[property];
+                }
+                if (object[property] === method) {
+                    object[property] = wrappedMethod;
+                }
+            };
+
+            method.restore.sinon = true;
+            mirrorProperties(method, wrappedMethod);
+
+            return method;
+        },
+
+        extend: function extend(target) {
+            for (var i = 1, l = arguments.length; i < l; i += 1) {
+                for (var prop in arguments[i]) {
+                    if (arguments[i].hasOwnProperty(prop)) {
+                        target[prop] = arguments[i][prop];
+                    }
+
+                    // DONT ENUM bug, only care about toString
+                    if (arguments[i].hasOwnProperty("toString") &&
+                        arguments[i].toString != target.toString) {
+                        target.toString = arguments[i].toString;
+                    }
+                }
+            }
+
+            return target;
+        },
+
+        create: function create(proto) {
+            var F = function () {};
+            F.prototype = proto;
+            return new F();
+        },
+
+        deepEqual: function deepEqual(a, b) {
+            if (sinon.match && sinon.match.isMatcher(a)) {
+                return a.test(b);
+            }
+            if (typeof a != "object" || typeof b != "object") {
+                return a === b;
+            }
+
+            if (isElement(a) || isElement(b)) {
+                return a === b;
+            }
+
+            if (a === b) {
+                return true;
+            }
+
+            if ((a === null && b !== null) || (a !== null && b === null)) {
+                return false;
+            }
+
+            if (a instanceof RegExp && b instanceof RegExp) {
+              return (a.source === b.source) && (a.global === b.global) && 
+                (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
+            }
+
+            var aString = Object.prototype.toString.call(a);
+            if (aString != Object.prototype.toString.call(b)) {
+                return false;
+            }
+
+            if (aString == "[object Date]") {
+                return a.valueOf() === b.valueOf();
+            }
+
+            var prop, aLength = 0, bLength = 0;
+
+            if (aString == "[object Array]" && a.length !== b.length) {
+                return false;
+            }
+
+            for (prop in a) {
+                aLength += 1;
+
+                if (!deepEqual(a[prop], b[prop])) {
+                    return false;
+                }
+            }
+
+            for (prop in b) {
+                bLength += 1;
+            }
+
+            return aLength == bLength;
+        },
+
+        functionName: function functionName(func) {
+            var name = func.displayName || func.name;
+
+            // Use function decomposition as a last resort to get function
+            // name. Does not rely on function decomposition to work - if it
+            // doesn't debugging will be slightly less informative
+            // (i.e. toString will say 'spy' rather than 'myFunc').
+            if (!name) {
+                var matches = func.toString().match(/function ([^\s\(]+)/);
+                name = matches && matches[1];
+            }
+
+            return name;
+        },
+
+        functionToString: function toString() {
+            if (this.getCall && this.callCount) {
+                var thisValue, prop, i = this.callCount;
+
+                while (i--) {
+                    thisValue = this.getCall(i).thisValue;
+
+                    for (prop in thisValue) {
+                        if (thisValue[prop] === this) {
+                            return prop;
+                        }
+                    }
+                }
+            }
+
+            return this.displayName || "sinon fake";
+        },
+
+        getConfig: function (custom) {
+            var config = {};
+            custom = custom || {};
+            var defaults = sinon.defaultConfig;
+
+            for (var prop in defaults) {
+                if (defaults.hasOwnProperty(prop)) {
+                    config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
+                }
+            }
+
+            return config;
+        },
+
+        format: function (val) {
+            return "" + val;
+        },
+
+        defaultConfig: {
+            injectIntoThis: true,
+            injectInto: null,
+            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
+            useFakeTimers: true,
+            useFakeServer: true
+        },
+
+        timesInWords: function timesInWords(count) {
+            return count == 1 && "once" ||
+                count == 2 && "twice" ||
+                count == 3 && "thrice" ||
+                (count || 0) + " times";
+        },
+
+        calledInOrder: function (spies) {
+            for (var i = 1, l = spies.length; i < l; i++) {
+                if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
+
+        orderByFirstCall: function (spies) {
+            return spies.sort(function (a, b) {
+                // uuid, won't ever be equal
+                var aCall = a.getCall(0);
+                var bCall = b.getCall(0);
+                var aId = aCall && aCall.callId || -1;
+                var bId = bCall && bCall.callId || -1;
+
+                return aId < bId ? -1 : 1;
+            });
+        },
+
+        log: function () {},
+
+        logError: function (label, err) {
+            var msg = label + " threw exception: ";
+            sinon.log(msg + "[" + err.name + "] " + err.message);
+            if (err.stack) { sinon.log(err.stack); }
+
+            setTimeout(function () {
+                err.message = msg + err.message;
+                throw err;
+            }, 0);
+        },
+
+        typeOf: function (value) {
+            if (value === null) {
+                return "null";
+            }
+            else if (value === undefined) {
+                return "undefined";
+            }
+            var string = Object.prototype.toString.call(value);
+            return string.substring(8, string.length - 1).toLowerCase();
+        },
+
+        createStubInstance: function (constructor) {
+            if (typeof constructor !== "function") {
+                throw new TypeError("The constructor should be a function.");
+            }
+            return sinon.stub(sinon.create(constructor.prototype));
+        },
+
+        restore: function (object) {
+            if (object !== null && typeof object === "object") {
+                for (var prop in object) {
+                    if (isRestorable(object[prop])) {
+                        object[prop].restore();
+                    }
+                }
+            }
+            else if (isRestorable(object)) {
+                object.restore();
+            }
+        }
+    };
+
+    var isNode = typeof module !== "undefined" && module.exports;
+    var isAMD = typeof define === 'function' && typeof define.amd === 'object' && define.amd;
+
+    if (isAMD) {
+        define(function(){
+            return sinon;
+        });
+    } else if (isNode) {
+        try {
+            formatio = require("formatio");
+        } catch (e) {}
+        module.exports = sinon;
+        module.exports.spy = require("./sinon/spy");
+        module.exports.spyCall = require("./sinon/call");
+        module.exports.behavior = require("./sinon/behavior");
+        module.exports.stub = require("./sinon/stub");
+        module.exports.mock = require("./sinon/mock");
+        module.exports.collection = require("./sinon/collection");
+        module.exports.assert = require("./sinon/assert");
+        module.exports.sandbox = require("./sinon/sandbox");
+        module.exports.test = require("./sinon/test");
+        module.exports.testCase = require("./sinon/test_case");
+        module.exports.assert = require("./sinon/assert");
+        module.exports.match = require("./sinon/match");
+    }
+
+    if (formatio) {
+        var formatter = formatio.configure({ quoteStrings: false });
+        sinon.format = function () {
+            return formatter.ascii.apply(formatter, arguments);
+        };
+    } else if (isNode) {
+        try {
+            var util = require("util");
+            sinon.format = function (value) {
+                return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
+            };
+        } catch (e) {
+            /* Node, but no util module - would be very old, but better safe than
+             sorry */
+        }
+    }
+
+    return sinon;
+}(typeof formatio == "object" && formatio));
+
+/* @depend ../sinon.js */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+ * Match functions
+ *
+ * @author Maximilian Antoni (mail@maxantoni.de)
+ * @license BSD
+ *
+ * Copyright (c) 2012 Maximilian Antoni
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function assertType(value, type, name) {
+        var actual = sinon.typeOf(value);
+        if (actual !== type) {
+            throw new TypeError("Expected type of " + name + " to be " +
+                type + ", but was " + actual);
+        }
+    }
+
+    var matcher = {
+        toString: function () {
+            return this.message;
+        }
+    };
+
+    function isMatcher(object) {
+        return matcher.isPrototypeOf(object);
+    }
+
+    function matchObject(expectation, actual) {
+        if (actual === null || actual === undefined) {
+            return false;
+        }
+        for (var key in expectation) {
+            if (expectation.hasOwnProperty(key)) {
+                var exp = expectation[key];
+                var act = actual[key];
+                if (match.isMatcher(exp)) {
+                    if (!exp.test(act)) {
+                        return false;
+                    }
+                } else if (sinon.typeOf(exp) === "object") {
+                    if (!matchObject(exp, act)) {
+                        return false;
+                    }
+                } else if (!sinon.deepEqual(exp, act)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    matcher.or = function (m2) {
+        if (!arguments.length) {
+            throw new TypeError("Matcher expected");
+        } else if (!isMatcher(m2)) {
+            m2 = match(m2);
+        }
+        var m1 = this;
+        var or = sinon.create(matcher);
+        or.test = function (actual) {
+            return m1.test(actual) || m2.test(actual);
+        };
+        or.message = m1.message + ".or(" + m2.message + ")";
+        return or;
+    };
+
+    matcher.and = function (m2) {
+        if (!arguments.length) {
+            throw new TypeError("Matcher expected");
+        } else if (!isMatcher(m2)) {
+            m2 = match(m2);
+        }
+        var m1 = this;
+        var and = sinon.create(matcher);
+        and.test = function (actual) {
+            return m1.test(actual) && m2.test(actual);
+        };
+        and.message = m1.message + ".and(" + m2.message + ")";
+        return and;
+    };
+
+    var match = function (expectation, message) {
+        var m = sinon.create(matcher);
+        var type = sinon.typeOf(expectation);
+        switch (type) {
+        case "object":
+            if (typeof expectation.test === "function") {
+                m.test = function (actual) {
+                    return expectation.test(actual) === true;
+                };
+                m.message = "match(" + sinon.functionName(expectation.test) + ")";
+                return m;
+            }
+            var str = [];
+            for (var key in expectation) {
+                if (expectation.hasOwnProperty(key)) {
+                    str.push(key + ": " + expectation[key]);
+                }
+            }
+            m.test = function (actual) {
+                return matchObject(expectation, actual);
+            };
+            m.message = "match(" + str.join(", ") + ")";
+            break;
+        case "number":
+            m.test = function (actual) {
+                return expectation == actual;
+            };
+            break;
+        case "string":
+            m.test = function (actual) {
+                if (typeof actual !== "string") {
+                    return false;
+                }
+                return actual.indexOf(expectation) !== -1;
+            };
+            m.message = "match(\"" + expectation + "\")";
+            break;
+        case "regexp":
+            m.test = function (actual) {
+                if (typeof actual !== "string") {
+                    return false;
+                }
+                return expectation.test(actual);
+            };
+            break;
+        case "function":
+            m.test = expectation;
+            if (message) {
+                m.message = message;
+            } else {
+                m.message = "match(" + sinon.functionName(expectation) + ")";
+            }
+            break;
+        default:
+            m.test = function (actual) {
+              return sinon.deepEqual(expectation, actual);
+            };
+        }
+        if (!m.message) {
+            m.message = "match(" + expectation + ")";
+        }
+        return m;
+    };
+
+    match.isMatcher = isMatcher;
+
+    match.any = match(function () {
+        return true;
+    }, "any");
+
+    match.defined = match(function (actual) {
+        return actual !== null && actual !== undefined;
+    }, "defined");
+
+    match.truthy = match(function (actual) {
+        return !!actual;
+    }, "truthy");
+
+    match.falsy = match(function (actual) {
+        return !actual;
+    }, "falsy");
+
+    match.same = function (expectation) {
+        return match(function (actual) {
+            return expectation === actual;
+        }, "same(" + expectation + ")");
+    };
+
+    match.typeOf = function (type) {
+        assertType(type, "string", "type");
+        return match(function (actual) {
+            return sinon.typeOf(actual) === type;
+        }, "typeOf(\"" + type + "\")");
+    };
+
+    match.instanceOf = function (type) {
+        assertType(type, "function", "type");
+        return match(function (actual) {
+            return actual instanceof type;
+        }, "instanceOf(" + sinon.functionName(type) + ")");
+    };
+
+    function createPropertyMatcher(propertyTest, messagePrefix) {
+        return function (property, value) {
+            assertType(property, "string", "property");
+            var onlyProperty = arguments.length === 1;
+            var message = messagePrefix + "(\"" + property + "\"";
+            if (!onlyProperty) {
+                message += ", " + value;
+            }
+            message += ")";
+            return match(function (actual) {
+                if (actual === undefined || actual === null ||
+                        !propertyTest(actual, property)) {
+                    return false;
+                }
+                return onlyProperty || sinon.deepEqual(value, actual[property]);
+            }, message);
+        };
+    }
+
+    match.has = createPropertyMatcher(function (actual, property) {
+        if (typeof actual === "object") {
+            return property in actual;
+        }
+        return actual[property] !== undefined;
+    }, "has");
+
+    match.hasOwn = createPropertyMatcher(function (actual, property) {
+        return actual.hasOwnProperty(property);
+    }, "hasOwn");
+
+    match.bool = match.typeOf("boolean");
+    match.number = match.typeOf("number");
+    match.string = match.typeOf("string");
+    match.object = match.typeOf("object");
+    match.func = match.typeOf("function");
+    match.array = match.typeOf("array");
+    match.regexp = match.typeOf("regexp");
+    match.date = match.typeOf("date");
+
+    if (commonJSModule) {
+        module.exports = match;
+    } else {
+        sinon.match = match;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+  * @depend ../sinon.js
+  * @depend match.js
+  */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+  * Spy calls
+  *
+  * @author Christian Johansen (christian@cjohansen.no)
+  * @author Maximilian Antoni (mail@maxantoni.de)
+  * @license BSD
+  *
+  * Copyright (c) 2010-2013 Christian Johansen
+  * Copyright (c) 2013 Maximilian Antoni
+  */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function throwYieldError(proxy, text, args) {
+        var msg = sinon.functionName(proxy) + text;
+        if (args.length) {
+            msg += " Received [" + slice.call(args).join(", ") + "]";
+        }
+        throw new Error(msg);
+    }
+
+    var slice = Array.prototype.slice;
+
+    var callProto = {
+        calledOn: function calledOn(thisValue) {
+            if (sinon.match && sinon.match.isMatcher(thisValue)) {
+                return thisValue.test(this.thisValue);
+            }
+            return this.thisValue === thisValue;
+        },
+
+        calledWith: function calledWith() {
+            for (var i = 0, l = arguments.length; i < l; i += 1) {
+                if (!sinon.deepEqual(arguments[i], this.args[i])) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
+
+        calledWithMatch: function calledWithMatch() {
+            for (var i = 0, l = arguments.length; i < l; i += 1) {
+                var actual = this.args[i];
+                var expectation = arguments[i];
+                if (!sinon.match || !sinon.match(expectation).test(actual)) {
+                    return false;
+                }
+            }
+            return true;
+        },
+
+        calledWithExactly: function calledWithExactly() {
+            return arguments.length == this.args.length &&
+                this.calledWith.apply(this, arguments);
+        },
+
+        notCalledWith: function notCalledWith() {
+            return !this.calledWith.apply(this, arguments);
+        },
+
+        notCalledWithMatch: function notCalledWithMatch() {
+            return !this.calledWithMatch.apply(this, arguments);
+        },
+
+        returned: function returned(value) {
+            return sinon.deepEqual(value, this.returnValue);
+        },
+
+        threw: function threw(error) {
+            if (typeof error === "undefined" || !this.exception) {
+                return !!this.exception;
+            }
+
+            return this.exception === error || this.exception.name === error;
+        },
+
+        calledWithNew: function calledWithNew() {
+            return this.proxy.prototype && this.thisValue instanceof this.proxy;
+        },
+
+        calledBefore: function (other) {
+            return this.callId < other.callId;
+        },
+
+        calledAfter: function (other) {
+            return this.callId > other.callId;
+        },
+
+        callArg: function (pos) {
+            this.args[pos]();
+        },
+
+        callArgOn: function (pos, thisValue) {
+            this.args[pos].apply(thisValue);
+        },
+
+        callArgWith: function (pos) {
+            this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
+        },
+
+        callArgOnWith: function (pos, thisValue) {
+            var args = slice.call(arguments, 2);
+            this.args[pos].apply(thisValue, args);
+        },
+
+        "yield": function () {
+            this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
+        },
+
+        yieldOn: function (thisValue) {
+            var args = this.args;
+            for (var i = 0, l = args.length; i < l; ++i) {
+                if (typeof args[i] === "function") {
+                    args[i].apply(thisValue, slice.call(arguments, 1));
+                    return;
+                }
+            }
+            throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
+        },
+
+        yieldTo: function (prop) {
+            this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
+        },
+
+        yieldToOn: function (prop, thisValue) {
+            var args = this.args;
+            for (var i = 0, l = args.length; i < l; ++i) {
+                if (args[i] && typeof args[i][prop] === "function") {
+                    args[i][prop].apply(thisValue, slice.call(arguments, 2));
+                    return;
+                }
+            }
+            throwYieldError(this.proxy, " cannot yield to '" + prop +
+                "' since no callback was passed.", args);
+        },
+
+        toString: function () {
+            var callStr = this.proxy.toString() + "(";
+            var args = [];
+
+            for (var i = 0, l = this.args.length; i < l; ++i) {
+                args.push(sinon.format(this.args[i]));
+            }
+
+            callStr = callStr + args.join(", ") + ")";
+
+            if (typeof this.returnValue != "undefined") {
+                callStr += " => " + sinon.format(this.returnValue);
+            }
+
+            if (this.exception) {
+                callStr += " !" + this.exception.name;
+
+                if (this.exception.message) {
+                    callStr += "(" + this.exception.message + ")";
+                }
+            }
+
+            return callStr;
+        }
+    };
+
+    callProto.invokeCallback = callProto.yield;
+
+    function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
+        if (typeof id !== "number") {
+            throw new TypeError("Call id is not a number");
+        }
+        var proxyCall = sinon.create(callProto);
+        proxyCall.proxy = spy;
+        proxyCall.thisValue = thisValue;
+        proxyCall.args = args;
+        proxyCall.returnValue = returnValue;
+        proxyCall.exception = exception;
+        proxyCall.callId = id;
+
+        return proxyCall;
+    }
+    createSpyCall.toString = callProto.toString; // used by mocks
+
+    if (commonJSModule) {
+        module.exports = createSpyCall;
+    } else {
+        sinon.spyCall = createSpyCall;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+
+/**
+  * @depend ../sinon.js
+  * @depend call.js
+  */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+  * Spy functions
+  *
+  * @author Christian Johansen (christian@cjohansen.no)
+  * @license BSD
+  *
+  * Copyright (c) 2010-2013 Christian Johansen
+  */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+    var push = Array.prototype.push;
+    var slice = Array.prototype.slice;
+    var callId = 0;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function spy(object, property) {
+        if (!property && typeof object == "function") {
+            return spy.create(object);
+        }
+
+        if (!object && !property) {
+            return spy.create(function () { });
+        }
+
+        var method = object[property];
+        return sinon.wrapMethod(object, property, spy.create(method));
+    }
+
+    function matchingFake(fakes, args, strict) {
+        if (!fakes) {
+            return;
+        }
+
+        for (var i = 0, l = fakes.length; i < l; i++) {
+            if (fakes[i].matches(args, strict)) {
+                return fakes[i];
+            }
+        }
+    }
+
+    function incrementCallCount() {
+        this.called = true;
+        this.callCount += 1;
+        this.notCalled = false;
+        this.calledOnce = this.callCount == 1;
+        this.calledTwice = this.callCount == 2;
+        this.calledThrice = this.callCount == 3;
+    }
+
+    function createCallProperties() {
+        this.firstCall = this.getCall(0);
+        this.secondCall = this.getCall(1);
+        this.thirdCall = this.getCall(2);
+        this.lastCall = this.getCall(this.callCount - 1);
+    }
+
+    var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
+    function createProxy(func) {
+        // Retain the function length:
+        var p;
+        if (func.length) {
+            eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) +
+                ") { return p.invoke(func, this, slice.call(arguments)); });");
+        }
+        else {
+            p = function proxy() {
+                return p.invoke(func, this, slice.call(arguments));
+            };
+        }
+        return p;
+    }
+
+    var uuid = 0;
+
+    // Public API
+    var spyApi = {
+        reset: function () {
+            this.called = false;
+            this.notCalled = true;
+            this.calledOnce = false;
+            this.calledTwice = false;
+            this.calledThrice = false;
+            this.callCount = 0;
+            this.firstCall = null;
+            this.secondCall = null;
+            this.thirdCall = null;
+            this.lastCall = null;
+            this.args = [];
+            this.returnValues = [];
+            this.thisValues = [];
+            this.exceptions = [];
+            this.callIds = [];
+            if (this.fakes) {
+                for (var i = 0; i < this.fakes.length; i++) {
+                    this.fakes[i].reset();
+                }
+            }
+        },
+
+        create: function create(func) {
+            var name;
+
+            if (typeof func != "function") {
+                func = function () { };
+            } else {
+                name = sinon.functionName(func);
+            }
+
+            var proxy = createProxy(func);
+
+            sinon.extend(proxy, spy);
+            delete proxy.create;
+            sinon.extend(proxy, func);
+
+            proxy.reset();
+            proxy.prototype = func.prototype;
+            proxy.displayName = name || "spy";
+            proxy.toString = sinon.functionToString;
+            proxy._create = sinon.spy.create;
+            proxy.id = "spy#" + uuid++;
+
+            return proxy;
+        },
+
+        invoke: function invoke(func, thisValue, args) {
+            var matching = matchingFake(this.fakes, args);
+            var exception, returnValue;
+
+            incrementCallCount.call(this);
+            push.call(this.thisValues, thisValue);
+            push.call(this.args, args);
+            push.call(this.callIds, callId++);
+
+            try {
+                if (matching) {
+                    returnValue = matching.invoke(func, thisValue, args);
+                } else {
+                    returnValue = (this.func || func).apply(thisValue, args);
+                }
+
+                var thisCall = this.getCall(this.callCount - 1);
+                if (thisCall.calledWithNew() && typeof returnValue !== 'object') {
+                    returnValue = thisValue;
+                }
+            } catch (e) {
+                exception = e;
+            }
+
+            push.call(this.exceptions, exception);
+            push.call(this.returnValues, returnValue);
+
+            createCallProperties.call(this);
+
+            if (exception !== undefined) {
+                throw exception;
+            }
+
+            return returnValue;
+        },
+
+        getCall: function getCall(i) {
+            if (i < 0 || i >= this.callCount) {
+                return null;
+            }
+
+            return sinon.spyCall(this, this.thisValues[i], this.args[i],
+                                    this.returnValues[i], this.exceptions[i],
+                                    this.callIds[i]);
+        },
+
+        getCalls: function () {
+            var calls = [];
+            var i;
+
+            for (i = 0; i < this.callCount; i++) {
+                calls.push(this.getCall(i));
+            }
+
+            return calls;
+        },
+
+        calledBefore: function calledBefore(spyFn) {
+            if (!this.called) {
+                return false;
+            }
+
+            if (!spyFn.called) {
+                return true;
+            }
+
+            return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
+        },
+
+        calledAfter: function calledAfter(spyFn) {
+            if (!this.called || !spyFn.called) {
+                return false;
+            }
+
+            return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
+        },
+
+        withArgs: function () {
+            var args = slice.call(arguments);
+
+            if (this.fakes) {
+                var match = matchingFake(this.fakes, args, true);
+
+                if (match) {
+                    return match;
+                }
+            } else {
+                this.fakes = [];
+            }
+
+            var original = this;
+            var fake = this._create();
+            fake.matchingAguments = args;
+            fake.parent = this;
+            push.call(this.fakes, fake);
+
+            fake.withArgs = function () {
+                return original.withArgs.apply(original, arguments);
+            };
+
+            for (var i = 0; i < this.args.length; i++) {
+                if (fake.matches(this.args[i])) {
+                    incrementCallCount.call(fake);
+                    push.call(fake.thisValues, this.thisValues[i]);
+                    push.call(fake.args, this.args[i]);
+                    push.call(fake.returnValues, this.returnValues[i]);
+                    push.call(fake.exceptions, this.exceptions[i]);
+                    push.call(fake.callIds, this.callIds[i]);
+                }
+            }
+            createCallProperties.call(fake);
+
+            return fake;
+        },
+
+        matches: function (args, strict) {
+            var margs = this.matchingAguments;
+
+            if (margs.length <= args.length &&
+                sinon.deepEqual(margs, args.slice(0, margs.length))) {
+                return !strict || margs.length == args.length;
+            }
+        },
+
+        printf: function (format) {
+            var spy = this;
+            var args = slice.call(arguments, 1);
+            var formatter;
+
+            return (format || "").replace(/%(.)/g, function (match, specifyer) {
+                formatter = spyApi.formatters[specifyer];
+
+                if (typeof formatter == "function") {
+                    return formatter.call(null, spy, args);
+                } else if (!isNaN(parseInt(specifyer, 10))) {
+                    return sinon.format(args[specifyer - 1]);
+                }
+
+                return "%" + specifyer;
+            });
+        }
+    };
+
+    function delegateToCalls(method, matchAny, actual, notCalled) {
+        spyApi[method] = function () {
+            if (!this.called) {
+                if (notCalled) {
+                    return notCalled.apply(this, arguments);
+                }
+                return false;
+            }
+
+            var currentCall;
+            var matches = 0;
+
+            for (var i = 0, l = this.callCount; i < l; i += 1) {
+                currentCall = this.getCall(i);
+
+                if (currentCall[actual || method].apply(currentCall, arguments)) {
+                    matches += 1;
+
+                    if (matchAny) {
+                        return true;
+                    }
+                }
+            }
+
+            return matches === this.callCount;
+        };
+    }
+
+    delegateToCalls("calledOn", true);
+    delegateToCalls("alwaysCalledOn", false, "calledOn");
+    delegateToCalls("calledWith", true);
+    delegateToCalls("calledWithMatch", true);
+    delegateToCalls("alwaysCalledWith", false, "calledWith");
+    delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
+    delegateToCalls("calledWithExactly", true);
+    delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
+    delegateToCalls("neverCalledWith", false, "notCalledWith",
+        function () { return true; });
+    delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch",
+        function () { return true; });
+    delegateToCalls("threw", true);
+    delegateToCalls("alwaysThrew", false, "threw");
+    delegateToCalls("returned", true);
+    delegateToCalls("alwaysReturned", false, "returned");
+    delegateToCalls("calledWithNew", true);
+    delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
+    delegateToCalls("callArg", false, "callArgWith", function () {
+        throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
+    });
+    spyApi.callArgWith = spyApi.callArg;
+    delegateToCalls("callArgOn", false, "callArgOnWith", function () {
+        throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
+    });
+    spyApi.callArgOnWith = spyApi.callArgOn;
+    delegateToCalls("yield", false, "yield", function () {
+        throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
+    });
+    // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
+    spyApi.invokeCallback = spyApi.yield;
+    delegateToCalls("yieldOn", false, "yieldOn", function () {
+        throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
+    });
+    delegateToCalls("yieldTo", false, "yieldTo", function (property) {
+        throw new Error(this.toString() + " cannot yield to '" + property +
+            "' since it was not yet invoked.");
+    });
+    delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
+        throw new Error(this.toString() + " cannot yield to '" + property +
+            "' since it was not yet invoked.");
+    });
+
+    spyApi.formatters = {
+        "c": function (spy) {
+            return sinon.timesInWords(spy.callCount);
+        },
+
+        "n": function (spy) {
+            return spy.toString();
+        },
+
+        "C": function (spy) {
+            var calls = [];
+
+            for (var i = 0, l = spy.callCount; i < l; ++i) {
+                var stringifiedCall = "    " + spy.getCall(i).toString();
+                if (/\n/.test(calls[i - 1])) {
+                    stringifiedCall = "\n" + stringifiedCall;
+                }
+                push.call(calls, stringifiedCall);
+            }
+
+            return calls.length > 0 ? "\n" + calls.join("\n") : "";
+        },
+
+        "t": function (spy) {
+            var objects = [];
+
+            for (var i = 0, l = spy.callCount; i < l; ++i) {
+                push.call(objects, sinon.format(spy.thisValues[i]));
+            }
+
+            return objects.join(", ");
+        },
+
+        "*": function (spy, args) {
+            var formatted = [];
+
+            for (var i = 0, l = args.length; i < l; ++i) {
+                push.call(formatted, sinon.format(args[i]));
+            }
+
+            return formatted.join(", ");
+        }
+    };
+
+    sinon.extend(spy, spyApi);
+
+    spy.spyCall = sinon.spyCall;
+
+    if (commonJSModule) {
+        module.exports = spy;
+    } else {
+        sinon.spy = spy;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global module, require, sinon, process, setImmediate, setTimeout*/
+/**
+ * Stub behavior
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @author Tim Fischbach (mail@timfischbach.de)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    var slice = Array.prototype.slice;
+    var join = Array.prototype.join;
+    var proto;
+
+    var nextTick = (function () {
+        if (typeof process === "object" && typeof process.nextTick === "function") {
+            return process.nextTick;
+        } else if (typeof setImmediate === "function") {
+            return setImmediate;
+        } else {
+            return function (callback) {
+                setTimeout(callback, 0);
+            };
+        }
+    })();
+
+    function throwsException(error, message) {
+        if (typeof error == "string") {
+            this.exception = new Error(message || "");
+            this.exception.name = error;
+        } else if (!error) {
+            this.exception = new Error("Error");
+        } else {
+            this.exception = error;
+        }
+
+        return this;
+    }
+
+    function getCallback(behavior, args) {
+        var callArgAt = behavior.callArgAt;
+
+        if (callArgAt < 0) {
+            var callArgProp = behavior.callArgProp;
+
+            for (var i = 0, l = args.length; i < l; ++i) {
+                if (!callArgProp && typeof args[i] == "function") {
+                    return args[i];
+                }
+
+                if (callArgProp && args[i] &&
+                    typeof args[i][callArgProp] == "function") {
+                    return args[i][callArgProp];
+                }
+            }
+
+            return null;
+        }
+
+        return args[callArgAt];
+    }
+
+    function getCallbackError(behavior, func, args) {
+        if (behavior.callArgAt < 0) {
+            var msg;
+
+            if (behavior.callArgProp) {
+                msg = sinon.functionName(behavior.stub) +
+                    " expected to yield to '" + behavior.callArgProp +
+                    "', but no object with such a property was passed.";
+            } else {
+                msg = sinon.functionName(behavior.stub) +
+                    " expected to yield, but no callback was passed.";
+            }
+
+            if (args.length > 0) {
+                msg += " Received [" + join.call(args, ", ") + "]";
+            }
+
+            return msg;
+        }
+
+        return "argument at index " + behavior.callArgAt + " is not a function: " + func;
+    }
+
+    function callCallback(behavior, args) {
+        if (typeof behavior.callArgAt == "number") {
+            var func = getCallback(behavior, args);
+
+            if (typeof func != "function") {
+                throw new TypeError(getCallbackError(behavior, func, args));
+            }
+
+            if (behavior.callbackAsync) {
+                nextTick(function() {
+                    func.apply(behavior.callbackContext, behavior.callbackArguments);
+                });
+            } else {
+                func.apply(behavior.callbackContext, behavior.callbackArguments);
+            }
+        }
+    }
+
+    proto = {
+        create: function(stub) {
+            var behavior = sinon.extend({}, sinon.behavior);
+            delete behavior.create;
+            behavior.stub = stub;
+
+            return behavior;
+        },
+
+        isPresent: function() {
+            return (typeof this.callArgAt == 'number' ||
+                    this.exception ||
+                    typeof this.returnArgAt == 'number' ||
+                    this.returnThis ||
+                    this.returnValueDefined);
+        },
+
+        invoke: function(context, args) {
+            callCallback(this, args);
+
+            if (this.exception) {
+                throw this.exception;
+            } else if (typeof this.returnArgAt == 'number') {
+                return args[this.returnArgAt];
+            } else if (this.returnThis) {
+                return context;
+            }
+
+            return this.returnValue;
+        },
+
+        onCall: function(index) {
+            return this.stub.onCall(index);
+        },
+
+        onFirstCall: function() {
+            return this.stub.onFirstCall();
+        },
+
+        onSecondCall: function() {
+            return this.stub.onSecondCall();
+        },
+
+        onThirdCall: function() {
+            return this.stub.onThirdCall();
+        },
+
+        withArgs: function(/* arguments */) {
+            throw new Error('Defining a stub by invoking "stub.onCall(...).withArgs(...)" is not supported. ' +
+                            'Use "stub.withArgs(...).onCall(...)" to define sequential behavior for calls with certain arguments.');
+        },
+
+        callsArg: function callsArg(pos) {
+            if (typeof pos != "number") {
+                throw new TypeError("argument index is not number");
+            }
+
+            this.callArgAt = pos;
+            this.callbackArguments = [];
+            this.callbackContext = undefined;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        callsArgOn: function callsArgOn(pos, context) {
+            if (typeof pos != "number") {
+                throw new TypeError("argument index is not number");
+            }
+            if (typeof context != "object") {
+                throw new TypeError("argument context is not an object");
+            }
+
+            this.callArgAt = pos;
+            this.callbackArguments = [];
+            this.callbackContext = context;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        callsArgWith: function callsArgWith(pos) {
+            if (typeof pos != "number") {
+                throw new TypeError("argument index is not number");
+            }
+
+            this.callArgAt = pos;
+            this.callbackArguments = slice.call(arguments, 1);
+            this.callbackContext = undefined;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        callsArgOnWith: function callsArgWith(pos, context) {
+            if (typeof pos != "number") {
+                throw new TypeError("argument index is not number");
+            }
+            if (typeof context != "object") {
+                throw new TypeError("argument context is not an object");
+            }
+
+            this.callArgAt = pos;
+            this.callbackArguments = slice.call(arguments, 2);
+            this.callbackContext = context;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        yields: function () {
+            this.callArgAt = -1;
+            this.callbackArguments = slice.call(arguments, 0);
+            this.callbackContext = undefined;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        yieldsOn: function (context) {
+            if (typeof context != "object") {
+                throw new TypeError("argument context is not an object");
+            }
+
+            this.callArgAt = -1;
+            this.callbackArguments = slice.call(arguments, 1);
+            this.callbackContext = context;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        yieldsTo: function (prop) {
+            this.callArgAt = -1;
+            this.callbackArguments = slice.call(arguments, 1);
+            this.callbackContext = undefined;
+            this.callArgProp = prop;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        yieldsToOn: function (prop, context) {
+            if (typeof context != "object") {
+                throw new TypeError("argument context is not an object");
+            }
+
+            this.callArgAt = -1;
+            this.callbackArguments = slice.call(arguments, 2);
+            this.callbackContext = context;
+            this.callArgProp = prop;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+
+        "throws": throwsException,
+        throwsException: throwsException,
+
+        returns: function returns(value) {
+            this.returnValue = value;
+            this.returnValueDefined = true;
+
+            return this;
+        },
+
+        returnsArg: function returnsArg(pos) {
+            if (typeof pos != "number") {
+                throw new TypeError("argument index is not number");
+            }
+
+            this.returnArgAt = pos;
+
+            return this;
+        },
+
+        returnsThis: function returnsThis() {
+            this.returnThis = true;
+
+            return this;
+        }
+    };
+
+    // create asynchronous versions of callsArg* and yields* methods
+    for (var method in proto) {
+        // need to avoid creating anotherasync versions of the newly added async methods
+        if (proto.hasOwnProperty(method) &&
+            method.match(/^(callsArg|yields)/) &&
+            !method.match(/Async/)) {
+            proto[method + 'Async'] = (function (syncFnName) {
+                return function () {
+                    var result = this[syncFnName].apply(this, arguments);
+                    this.callbackAsync = true;
+                    return result;
+                };
+            })(method);
+        }
+    }
+
+    if (commonJSModule) {
+        module.exports = proto;
+    } else {
+        sinon.behavior = proto;
+    }
+}(typeof sinon == "object" && sinon || null));
+/**
+ * @depend ../sinon.js
+ * @depend spy.js
+ * @depend behavior.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global module, require, sinon*/
+/**
+ * Stub functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function stub(object, property, func) {
+        if (!!func && typeof func != "function") {
+            throw new TypeError("Custom stub should be function");
+        }
+
+        var wrapper;
+
+        if (func) {
+            wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
+        } else {
+            wrapper = stub.create();
+        }
+
+        if (!object && typeof property === "undefined") {
+            return sinon.stub.create();
+        }
+
+        if (typeof property === "undefined" && typeof object == "object") {
+            for (var prop in object) {
+                if (typeof object[prop] === "function") {
+                    stub(object, prop);
+                }
+            }
+
+            return object;
+        }
+
+        return sinon.wrapMethod(object, property, wrapper);
+    }
+
+    function getDefaultBehavior(stub) {
+        return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub);
+    }
+
+    function getParentBehaviour(stub) {
+        return (stub.parent && getCurrentBehavior(stub.parent));
+    }
+
+    function getCurrentBehavior(stub) {
+        var behavior = stub.behaviors[stub.callCount - 1];
+        return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub);
+    }
+
+    var uuid = 0;
+
+    sinon.extend(stub, (function () {
+        var proto = {
+            create: function create() {
+                var functionStub = function () {
+                    return getCurrentBehavior(functionStub).invoke(this, arguments);
+                };
+
+                functionStub.id = "stub#" + uuid++;
+                var orig = functionStub;
+                functionStub = sinon.spy.create(functionStub);
+                functionStub.func = orig;
+
+                sinon.extend(functionStub, stub);
+                functionStub._create = sinon.stub.create;
+                functionStub.displayName = "stub";
+                functionStub.toString = sinon.functionToString;
+
+                functionStub.defaultBehavior = null;
+                functionStub.behaviors = [];
+
+                return functionStub;
+            },
+
+            resetBehavior: function () {
+                var i;
+
+                this.defaultBehavior = null;
+                this.behaviors = [];
+
+                delete this.returnValue;
+                delete this.returnArgAt;
+                this.returnThis = false;
+
+                if (this.fakes) {
+                    for (i = 0; i < this.fakes.length; i++) {
+                        this.fakes[i].resetBehavior();
+                    }
+                }
+            },
+
+            onCall: function(index) {
+                if (!this.behaviors[index]) {
+                    this.behaviors[index] = sinon.behavior.create(this);
+                }
+
+                return this.behaviors[index];
+            },
+
+            onFirstCall: function() {
+                return this.onCall(0);
+            },
+
+            onSecondCall: function() {
+                return this.onCall(1);
+            },
+
+            onThirdCall: function() {
+                return this.onCall(2);
+            }
+        };
+
+        for (var method in sinon.behavior) {
+            if (sinon.behavior.hasOwnProperty(method) &&
+                !proto.hasOwnProperty(method) &&
+                method != 'create' &&
+                method != 'withArgs' &&
+                method != 'invoke') {
+                proto[method] = (function(behaviorMethod) {
+                    return function() {
+                        this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
+                        this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
+                        return this;
+                    };
+                }(method));
+            }
+        }
+
+        return proto;
+    }()));
+
+    if (commonJSModule) {
+        module.exports = stub;
+    } else {
+        sinon.stub = stub;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ */
+/*jslint eqeqeq: false, onevar: false, nomen: false*/
+/*global module, require, sinon*/
+/**
+ * Mock functions.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+    var push = [].push;
+    var match;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    match = sinon.match;
+
+    if (!match && commonJSModule) {
+        match = require("./match");
+    }
+
+    function mock(object) {
+        if (!object) {
+            return sinon.expectation.create("Anonymous mock");
+        }
+
+        return mock.create(object);
+    }
+
+    sinon.mock = mock;
+
+    sinon.extend(mock, (function () {
+        function each(collection, callback) {
+            if (!collection) {
+                return;
+            }
+
+            for (var i = 0, l = collection.length; i < l; i += 1) {
+                callback(collection[i]);
+            }
+        }
+
+        return {
+            create: function create(object) {
+                if (!object) {
+                    throw new TypeError("object is null");
+                }
+
+                var mockObject = sinon.extend({}, mock);
+                mockObject.object = object;
+                delete mockObject.create;
+
+                return mockObject;
+            },
+
+            expects: function expects(method) {
+                if (!method) {
+                    throw new TypeError("method is falsy");
+                }
+
+                if (!this.expectations) {
+                    this.expectations = {};
+                    this.proxies = [];
+                }
+
+                if (!this.expectations[method]) {
+                    this.expectations[method] = [];
+                    var mockObject = this;
+
+                    sinon.wrapMethod(this.object, method, function () {
+                        return mockObject.invokeMethod(method, this, arguments);
+                    });
+
+                    push.call(this.proxies, method);
+                }
+
+                var expectation = sinon.expectation.create(method);
+                push.call(this.expectations[method], expectation);
+
+                return expectation;
+            },
+
+            restore: function restore() {
+                var object = this.object;
+
+                each(this.proxies, function (proxy) {
+                    if (typeof object[proxy].restore == "function") {
+                        object[proxy].restore();
+                    }
+                });
+            },
+
+            verify: function verify() {
+                var expectations = this.expectations || {};
+                var messages = [], met = [];
+
+                each(this.proxies, function (proxy) {
+                    each(expectations[proxy], function (expectation) {
+                        if (!expectation.met()) {
+                            push.call(messages, expectation.toString());
+                        } else {
+                            push.call(met, expectation.toString());
+                        }
+                    });
+                });
+
+                this.restore();
+
+                if (messages.length > 0) {
+                    sinon.expectation.fail(messages.concat(met).join("\n"));
+                } else {
+                    sinon.expectation.pass(messages.concat(met).join("\n"));
+                }
+
+                return true;
+            },
+
+            invokeMethod: function invokeMethod(method, thisValue, args) {
+                var expectations = this.expectations && this.expectations[method];
+                var length = expectations && expectations.length || 0, i;
+
+                for (i = 0; i < length; i += 1) {
+                    if (!expectations[i].met() &&
+                        expectations[i].allowsCall(thisValue, args)) {
+                        return expectations[i].apply(thisValue, args);
+                    }
+                }
+
+                var messages = [], available, exhausted = 0;
+
+                for (i = 0; i < length; i += 1) {
+                    if (expectations[i].allowsCall(thisValue, args)) {
+                        available = available || expectations[i];
+                    } else {
+                        exhausted += 1;
+                    }
+                    push.call(messages, "    " + expectations[i].toString());
+                }
+
+                if (exhausted === 0) {
+                    return available.apply(thisValue, args);
+                }
+
+                messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
+                    proxy: method,
+                    args: args
+                }));
+
+                sinon.expectation.fail(messages.join("\n"));
+            }
+        };
+    }()));
+
+    var times = sinon.timesInWords;
+
+    sinon.expectation = (function () {
+        var slice = Array.prototype.slice;
+        var _invoke = sinon.spy.invoke;
+
+        function callCountInWords(callCount) {
+            if (callCount == 0) {
+                return "never called";
+            } else {
+                return "called " + times(callCount);
+            }
+        }
+
+        function expectedCallCountInWords(expectation) {
+            var min = expectation.minCalls;
+            var max = expectation.maxCalls;
+
+            if (typeof min == "number" && typeof max == "number") {
+                var str = times(min);
+
+                if (min != max) {
+                    str = "at least " + str + " and at most " + times(max);
+                }
+
+                return str;
+            }
+
+            if (typeof min == "number") {
+                return "at least " + times(min);
+            }
+
+            return "at most " + times(max);
+        }
+
+        function receivedMinCalls(expectation) {
+            var hasMinLimit = typeof expectation.minCalls == "number";
+            return !hasMinLimit || expectation.callCount >= expectation.minCalls;
+        }
+
+        function receivedMaxCalls(expectation) {
+            if (typeof expectation.maxCalls != "number") {
+                return false;
+            }
+
+            return expectation.callCount == expectation.maxCalls;
+        }
+
+        function verifyMatcher(possibleMatcher, arg){
+            if (match && match.isMatcher(possibleMatcher)) {
+                return possibleMatcher.test(arg);
+            } else {
+                return true;
+            }
+        }
+
+        return {
+            minCalls: 1,
+            maxCalls: 1,
+
+            create: function create(methodName) {
+                var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
+                delete expectation.create;
+                expectation.method = methodName;
+
+                return expectation;
+            },
+
+            invoke: function invoke(func, thisValue, args) {
+                this.verifyCallAllowed(thisValue, args);
+
+                return _invoke.apply(this, arguments);
+            },
+
+            atLeast: function atLeast(num) {
+                if (typeof num != "number") {
+                    throw new TypeError("'" + num + "' is not number");
+                }
+
+                if (!this.limitsSet) {
+                    this.maxCalls = null;
+                    this.limitsSet = true;
+                }
+
+                this.minCalls = num;
+
+                return this;
+            },
+
+            atMost: function atMost(num) {
+                if (typeof num != "number") {
+                    throw new TypeError("'" + num + "' is not number");
+                }
+
+                if (!this.limitsSet) {
+                    this.minCalls = null;
+                    this.limitsSet = true;
+                }
+
+                this.maxCalls = num;
+
+                return this;
+            },
+
+            never: function never() {
+                return this.exactly(0);
+            },
+
+            once: function once() {
+                return this.exactly(1);
+            },
+
+            twice: function twice() {
+                return this.exactly(2);
+            },
+
+            thrice: function thrice() {
+                return this.exactly(3);
+            },
+
+            exactly: function exactly(num) {
+                if (typeof num != "number") {
+                    throw new TypeError("'" + num + "' is not a number");
+                }
+
+                this.atLeast(num);
+                return this.atMost(num);
+            },
+
+            met: function met() {
+                return !this.failed && receivedMinCalls(this);
+            },
+
+            verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
+                if (receivedMaxCalls(this)) {
+                    this.failed = true;
+                    sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
+                }
+
+                if ("expectedThis" in this && this.expectedThis !== thisValue) {
+                    sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
+                        this.expectedThis);
+                }
+
+                if (!("expectedArguments" in this)) {
+                    return;
+                }
+
+                if (!args) {
+                    sinon.expectation.fail(this.method + " received no arguments, expected " +
+                        sinon.format(this.expectedArguments));
+                }
+
+                if (args.length < this.expectedArguments.length) {
+                    sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
+                        "), expected " + sinon.format(this.expectedArguments));
+                }
+
+                if (this.expectsExactArgCount &&
+                    args.length != this.expectedArguments.length) {
+                    sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
+                        "), expected " + sinon.format(this.expectedArguments));
+                }
+
+                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
+
+                    if (!verifyMatcher(this.expectedArguments[i],args[i])) {
+                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
+                            ", didn't match " + this.expectedArguments.toString());
+                    }
+
+                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
+                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
+                            ", expected " + sinon.format(this.expectedArguments));
+                    }
+                }
+            },
+
+            allowsCall: function allowsCall(thisValue, args) {
+                if (this.met() && receivedMaxCalls(this)) {
+                    return false;
+                }
+
+                if ("expectedThis" in this && this.expectedThis !== thisValue) {
+                    return false;
+                }
+
+                if (!("expectedArguments" in this)) {
+                    return true;
+                }
+
+                args = args || [];
+
+                if (args.length < this.expectedArguments.length) {
+                    return false;
+                }
+
+                if (this.expectsExactArgCount &&
+                    args.length != this.expectedArguments.length) {
+                    return false;
+                }
+
+                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
+                    if (!verifyMatcher(this.expectedArguments[i],args[i])) {
+                        return false;
+                    }
+
+                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
+                        return false;
+                    }
+                }
+
+                return true;
+            },
+
+            withArgs: function withArgs() {
+                this.expectedArguments = slice.call(arguments);
+                return this;
+            },
+
+            withExactArgs: function withExactArgs() {
+                this.withArgs.apply(this, arguments);
+                this.expectsExactArgCount = true;
+                return this;
+            },
+
+            on: function on(thisValue) {
+                this.expectedThis = thisValue;
+                return this;
+            },
+
+            toString: function () {
+                var args = (this.expectedArguments || []).slice();
+
+                if (!this.expectsExactArgCount) {
+                    push.call(args, "[...]");
+                }
+
+                var callStr = sinon.spyCall.toString.call({
+                    proxy: this.method || "anonymous mock expectation",
+                    args: args
+                });
+
+                var message = callStr.replace(", [...", "[, ...") + " " +
+                    expectedCallCountInWords(this);
+
+                if (this.met()) {
+                    return "Expectation met: " + message;
+                }
+
+                return "Expected " + message + " (" +
+                    callCountInWords(this.callCount) + ")";
+            },
+
+            verify: function verify() {
+                if (!this.met()) {
+                    sinon.expectation.fail(this.toString());
+                } else {
+                    sinon.expectation.pass(this.toString());
+                }
+
+                return true;
+            },
+
+            pass: function(message) {
+              sinon.assert.pass(message);
+            },
+            fail: function (message) {
+                var exception = new Error(message);
+                exception.name = "ExpectationError";
+
+                throw exception;
+            }
+        };
+    }());
+
+    if (commonJSModule) {
+        module.exports = mock;
+    } else {
+        sinon.mock = mock;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ * @depend mock.js
+ */
+/*jslint eqeqeq: false, onevar: false, forin: true*/
+/*global module, require, sinon*/
+/**
+ * Collections of stubs, spies and mocks.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+    var push = [].push;
+    var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function getFakes(fakeCollection) {
+        if (!fakeCollection.fakes) {
+            fakeCollection.fakes = [];
+        }
+
+        return fakeCollection.fakes;
+    }
+
+    function each(fakeCollection, method) {
+        var fakes = getFakes(fakeCollection);
+
+        for (var i = 0, l = fakes.length; i < l; i += 1) {
+            if (typeof fakes[i][method] == "function") {
+                fakes[i][method]();
+            }
+        }
+    }
+
+    function compact(fakeCollection) {
+        var fakes = getFakes(fakeCollection);
+        var i = 0;
+        while (i < fakes.length) {
+          fakes.splice(i, 1);
+        }
+    }
+
+    var collection = {
+        verify: function resolve() {
+            each(this, "verify");
+        },
+
+        restore: function restore() {
+            each(this, "restore");
+            compact(this);
+        },
+
+        verifyAndRestore: function verifyAndRestore() {
+            var exception;
+
+            try {
+                this.verify();
+            } catch (e) {
+                exception = e;
+            }
+
+            this.restore();
+
+            if (exception) {
+                throw exception;
+            }
+        },
+
+        add: function add(fake) {
+            push.call(getFakes(this), fake);
+            return fake;
+        },
+
+        spy: function spy() {
+            return this.add(sinon.spy.apply(sinon, arguments));
+        },
+
+        stub: function stub(object, property, value) {
+            if (property) {
+                var original = object[property];
+
+                if (typeof original != "function") {
+                    if (!hasOwnProperty.call(object, property)) {
+                        throw new TypeError("Cannot stub non-existent own property " + property);
+                    }
+
+                    object[property] = value;
+
+                    return this.add({
+                        restore: function () {
+                            object[property] = original;
+                        }
+                    });
+                }
+            }
+            if (!property && !!object && typeof object == "object") {
+                var stubbedObj = sinon.stub.apply(sinon, arguments);
+
+                for (var prop in stubbedObj) {
+                    if (typeof stubbedObj[prop] === "function") {
+                        this.add(stubbedObj[prop]);
+                    }
+                }
+
+                return stubbedObj;
+            }
+
+            return this.add(sinon.stub.apply(sinon, arguments));
+        },
+
+        mock: function mock() {
+            return this.add(sinon.mock.apply(sinon, arguments));
+        },
+
+        inject: function inject(obj) {
+            var col = this;
+
+            obj.spy = function () {
+                return col.spy.apply(col, arguments);
+            };
+
+            obj.stub = function () {
+                return col.stub.apply(col, arguments);
+            };
+
+            obj.mock = function () {
+                return col.mock.apply(col, arguments);
+            };
+
+            return obj;
+        }
+    };
+
+    if (commonJSModule) {
+        module.exports = collection;
+    } else {
+        sinon.collection = collection;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
+/*global module, require, window*/
+/**
+ * Fake timer API
+ * setTimeout
+ * setInterval
+ * clearTimeout
+ * clearInterval
+ * tick
+ * reset
+ * Date
+ *
+ * Inspired by jsUnitMockTimeOut from JsUnit
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+if (typeof sinon == "undefined") {
+    var sinon = {};
+}
+
+(function (global) {
+    var id = 1;
+
+    function addTimer(args, recurring) {
+        if (args.length === 0) {
+            throw new Error("Function requires at least 1 parameter");
+        }
+
+        if (typeof args[0] === "undefined") {
+            throw new Error("Callback must be provided to timer calls");
+        }
+
+        var toId = id++;
+        var delay = args[1] || 0;
+
+        if (!this.timeouts) {
+            this.timeouts = {};
+        }
+
+        this.timeouts[toId] = {
+            id: toId,
+            func: args[0],
+            callAt: this.now + delay,
+            invokeArgs: Array.prototype.slice.call(args, 2)
+        };
+
+        if (recurring === true) {
+            this.timeouts[toId].interval = delay;
+        }
+
+        return toId;
+    }
+
+    function parseTime(str) {
+        if (!str) {
+            return 0;
+        }
+
+        var strings = str.split(":");
+        var l = strings.length, i = l;
+        var ms = 0, parsed;
+
+        if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
+            throw new Error("tick only understands numbers and 'h:m:s'");
+        }
+
+        while (i--) {
+            parsed = parseInt(strings[i], 10);
+
+            if (parsed >= 60) {
+                throw new Error("Invalid time " + str);
+            }
+
+            ms += parsed * Math.pow(60, (l - i - 1));
+        }
+
+        return ms * 1000;
+    }
+
+    function createObject(object) {
+        var newObject;
+
+        if (Object.create) {
+            newObject = Object.create(object);
+        } else {
+            var F = function () {};
+            F.prototype = object;
+            newObject = new F();
+        }
+
+        newObject.Date.clock = newObject;
+        return newObject;
+    }
+
+    sinon.clock = {
+        now: 0,
+
+        create: function create(now) {
+            var clock = createObject(this);
+
+            if (typeof now == "number") {
+                clock.now = now;
+            }
+
+            if (!!now && typeof now == "object") {
+                throw new TypeError("now should be milliseconds since UNIX epoch");
+            }
+
+            return clock;
+        },
+
+        setTimeout: function setTimeout(callback, timeout) {
+            return addTimer.call(this, arguments, false);
+        },
+
+        clearTimeout: function clearTimeout(timerId) {
+            if (!this.timeouts) {
+                this.timeouts = [];
+            }
+
+            if (timerId in this.timeouts) {
+                delete this.timeouts[timerId];
+            }
+        },
+
+        setInterval: function setInterval(callback, timeout) {
+            return addTimer.call(this, arguments, true);
+        },
+
+        clearInterval: function clearInterval(timerId) {
+            this.clearTimeout(timerId);
+        },
+
+        setImmediate: function setImmediate(callback) {
+            var passThruArgs = Array.prototype.slice.call(arguments, 1);
+
+            return addTimer.call(this, [callback, 0].concat(passThruArgs), false);
+        },
+
+        clearImmediate: function clearImmediate(timerId) {
+            this.clearTimeout(timerId);
+        },
+
+        tick: function tick(ms) {
+            ms = typeof ms == "number" ? ms : parseTime(ms);
+            var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
+            var timer = this.firstTimerInRange(tickFrom, tickTo);
+
+            var firstException;
+            while (timer && tickFrom <= tickTo) {
+                if (this.timeouts[timer.id]) {
+                    tickFrom = this.now = timer.callAt;
+                    try {
+                      this.callTimer(timer);
+                    } catch (e) {
+                      firstException = firstException || e;
+                    }
+                }
+
+                timer = this.firstTimerInRange(previous, tickTo);
+                previous = tickFrom;
+            }
+
+            this.now = tickTo;
+
+            if (firstException) {
+              throw firstException;
+            }
+
+            return this.now;
+        },
+
+        firstTimerInRange: function (from, to) {
+            var timer, smallest = null, originalTimer;
+
+            for (var id in this.timeouts) {
+                if (this.timeouts.hasOwnProperty(id)) {
+                    if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
+                        continue;
+                    }
+
+                    if (smallest === null || this.timeouts[id].callAt < smallest) {
+                        originalTimer = this.timeouts[id];
+                        smallest = this.timeouts[id].callAt;
+
+                        timer = {
+                            func: this.timeouts[id].func,
+                            callAt: this.timeouts[id].callAt,
+                            interval: this.timeouts[id].interval,
+                            id: this.timeouts[id].id,
+                            invokeArgs: this.timeouts[id].invokeArgs
+                        };
+                    }
+                }
+            }
+
+            return timer || null;
+        },
+
+        callTimer: function (timer) {
+            if (typeof timer.interval == "number") {
+                this.timeouts[timer.id].callAt += timer.interval;
+            } else {
+                delete this.timeouts[timer.id];
+            }
+
+            try {
+                if (typeof timer.func == "function") {
+                    timer.func.apply(null, timer.invokeArgs);
+                } else {
+                    eval(timer.func);
+                }
+            } catch (e) {
+              var exception = e;
+            }
+
+            if (!this.timeouts[timer.id]) {
+                if (exception) {
+                  throw exception;
+                }
+                return;
+            }
+
+            if (exception) {
+              throw exception;
+            }
+        },
+
+        reset: function reset() {
+            this.timeouts = {};
+        },
+
+        Date: (function () {
+            var NativeDate = Date;
+
+            function ClockDate(year, month, date, hour, minute, second, ms) {
+                // Defensive and verbose to avoid potential harm in passing
+                // explicit undefined when user does not pass argument
+                switch (arguments.length) {
+                case 0:
+                    return new NativeDate(ClockDate.clock.now);
+                case 1:
+                    return new NativeDate(year);
+                case 2:
+                    return new NativeDate(year, month);
+                case 3:
+                    return new NativeDate(year, month, date);
+                case 4:
+                    return new NativeDate(year, month, date, hour);
+                case 5:
+                    return new NativeDate(year, month, date, hour, minute);
+                case 6:
+                    return new NativeDate(year, month, date, hour, minute, second);
+                default:
+                    return new NativeDate(year, month, date, hour, minute, second, ms);
+                }
+            }
+
+            return mirrorDateProperties(ClockDate, NativeDate);
+        }())
+    };
+
+    function mirrorDateProperties(target, source) {
+        if (source.now) {
+            target.now = function now() {
+                return target.clock.now;
+            };
+        } else {
+            delete target.now;
+        }
+
+        if (source.toSource) {
+            target.toSource = function toSource() {
+                return source.toSource();
+            };
+        } else {
+            delete target.toSource;
+        }
+
+        target.toString = function toString() {
+            return source.toString();
+        };
+
+        target.prototype = source.prototype;
+        target.parse = source.parse;
+        target.UTC = source.UTC;
+        target.prototype.toUTCString = source.prototype.toUTCString;
+
+        for (var prop in source) {
+            if (source.hasOwnProperty(prop)) {
+                target[prop] = source[prop];
+            }
+        }
+
+        return target;
+    }
+
+    var methods = ["Date", "setTimeout", "setInterval",
+                   "clearTimeout", "clearInterval"];
+
+    if (typeof global.setImmediate !== "undefined") {
+        methods.push("setImmediate");
+    }
+
+    if (typeof global.clearImmediate !== "undefined") {
+        methods.push("clearImmediate");
+    }
+
+    function restore() {
+        var method;
+
+        for (var i = 0, l = this.methods.length; i < l; i++) {
+            method = this.methods[i];
+
+            if (global[method].hadOwnProperty) {
+                global[method] = this["_" + method];
+            } else {
+                try {
+                    delete global[method];
+                } catch (e) {}
+            }
+        }
+
+        // Prevent multiple executions which will completely remove these props
+        this.methods = [];
+    }
+
+    function stubGlobal(method, clock) {
+        clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(global, method);
+        clock["_" + method] = global[method];
+
+        if (method == "Date") {
+            var date = mirrorDateProperties(clock[method], global[method]);
+            global[method] = date;
+        } else {
+            global[method] = function () {
+                return clock[method].apply(clock, arguments);
+            };
+
+            for (var prop in clock[method]) {
+                if (clock[method].hasOwnProperty(prop)) {
+                    global[method][prop] = clock[method][prop];
+                }
+            }
+        }
+
+        global[method].clock = clock;
+    }
+
+    sinon.useFakeTimers = function useFakeTimers(now) {
+        var clock = sinon.clock.create(now);
+        clock.restore = restore;
+        clock.methods = Array.prototype.slice.call(arguments,
+                                                   typeof now == "number" ? 1 : 0);
+
+        if (clock.methods.length === 0) {
+            clock.methods = methods;
+        }
+
+        for (var i = 0, l = clock.methods.length; i < l; i++) {
+            stubGlobal(clock.methods[i], clock);
+        }
+
+        return clock;
+    };
+}(typeof global != "undefined" && typeof global !== "function" ? global : this));
+
+sinon.timers = {
+    setTimeout: setTimeout,
+    clearTimeout: clearTimeout,
+    setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
+    clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
+    setInterval: setInterval,
+    clearInterval: clearInterval,
+    Date: Date
+};
+
+if (typeof module !== 'undefined' && module.exports) {
+    module.exports = sinon;
+}
+
+/*jslint eqeqeq: false, onevar: false*/
+/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
+/**
+ * Minimal Event interface implementation
+ *
+ * Original implementation by Sven Fuchs: https://gist.github.com/995028
+ * Modifications and tests by Christian Johansen.
+ *
+ * @author Sven Fuchs (svenfuchs@artweb-design.de)
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2011 Sven Fuchs, Christian Johansen
+ */
+
+if (typeof sinon == "undefined") {
+    this.sinon = {};
+}
+
+(function () {
+    var push = [].push;
+
+    sinon.Event = function Event(type, bubbles, cancelable, target) {
+        this.initEvent(type, bubbles, cancelable, target);
+    };
+
+    sinon.Event.prototype = {
+        initEvent: function(type, bubbles, cancelable, target) {
+            this.type = type;
+            this.bubbles = bubbles;
+            this.cancelable = cancelable;
+            this.target = target;
+        },
+
+        stopPropagation: function () {},
+
+        preventDefault: function () {
+            this.defaultPrevented = true;
+        }
+    };
+
+    sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
+        this.initEvent(type, false, false, target);
+        this.loaded = progressEventRaw.loaded || null;
+        this.total = progressEventRaw.total || null;
+    };
+
+    sinon.ProgressEvent.prototype = new sinon.Event();
+
+    sinon.ProgressEvent.prototype.constructor =  sinon.ProgressEvent;
+
+    sinon.CustomEvent = function CustomEvent(type, customData, target) {
+        this.initEvent(type, false, false, target);
+        this.detail = customData.detail || null;
+    };
+
+    sinon.CustomEvent.prototype = new sinon.Event();
+
+    sinon.CustomEvent.prototype.constructor =  sinon.CustomEvent;
+
+    sinon.EventTarget = {
+        addEventListener: function addEventListener(event, listener) {
+            this.eventListeners = this.eventListeners || {};
+            this.eventListeners[event] = this.eventListeners[event] || [];
+            push.call(this.eventListeners[event], listener);
+        },
+
+        removeEventListener: function removeEventListener(event, listener) {
+            var listeners = this.eventListeners && this.eventListeners[event] || [];
+
+            for (var i = 0, l = listeners.length; i < l; ++i) {
+                if (listeners[i] == listener) {
+                    return listeners.splice(i, 1);
+                }
+            }
+        },
+
+        dispatchEvent: function dispatchEvent(event) {
+            var type = event.type;
+            var listeners = this.eventListeners && this.eventListeners[type] || [];
+
+            for (var i = 0; i < listeners.length; i++) {
+                if (typeof listeners[i] == "function") {
+                    listeners[i].call(this, event);
+                } else {
+                    listeners[i].handleEvent(event);
+                }
+            }
+
+            return !!event.defaultPrevented;
+        }
+    };
+}());
+
+/**
+ * @depend ../../sinon.js
+ * @depend event.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
+/**
+ * Fake XMLHttpRequest object
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+// wrapper for global
+(function(global) {
+    if (typeof sinon === "undefined") {
+        global.sinon = {};
+    }
+
+    var supportsProgress = typeof ProgressEvent !== "undefined";
+    var supportsCustomEvent = typeof CustomEvent !== "undefined";
+    sinon.xhr = { XMLHttpRequest: global.XMLHttpRequest };
+    var xhr = sinon.xhr;
+    xhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
+    xhr.GlobalActiveXObject = global.ActiveXObject;
+    xhr.supportsActiveX = typeof xhr.GlobalActiveXObject != "undefined";
+    xhr.supportsXHR = typeof xhr.GlobalXMLHttpRequest != "undefined";
+    xhr.workingXHR = xhr.supportsXHR ? xhr.GlobalXMLHttpRequest : xhr.supportsActiveX
+                                     ? function() { return new xhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
+    xhr.supportsCORS = 'withCredentials' in (new sinon.xhr.GlobalXMLHttpRequest());
+
+    /*jsl:ignore*/
+    var unsafeHeaders = {
+        "Accept-Charset": true,
+        "Accept-Encoding": true,
+        "Connection": true,
+        "Content-Length": true,
+        "Cookie": true,
+        "Cookie2": true,
+        "Content-Transfer-Encoding": true,
+        "Date": true,
+        "Expect": true,
+        "Host": true,
+        "Keep-Alive": true,
+        "Referer": true,
+        "TE": true,
+        "Trailer": true,
+        "Transfer-Encoding": true,
+        "Upgrade": true,
+        "User-Agent": true,
+        "Via": true
+    };
+    /*jsl:end*/
+
+    function FakeXMLHttpRequest() {
+        this.readyState = FakeXMLHttpRequest.UNSENT;
+        this.requestHeaders = {};
+        this.requestBody = null;
+        this.status = 0;
+        this.statusText = "";
+        this.upload = new UploadProgress();
+        if (sinon.xhr.supportsCORS) {
+            this.withCredentials = false;
+        }
+
+
+        var xhr = this;
+        var events = ["loadstart", "load", "abort", "loadend"];
+
+        function addEventListener(eventName) {
+            xhr.addEventListener(eventName, function (event) {
+                var listener = xhr["on" + eventName];
+
+                if (listener && typeof listener == "function") {
+                    listener.call(this, event);
+                }
+            });
+        }
+
+        for (var i = events.length - 1; i >= 0; i--) {
+            addEventListener(events[i]);
+        }
+
+        if (typeof FakeXMLHttpRequest.onCreate == "function") {
+            FakeXMLHttpRequest.onCreate(this);
+        }
+    }
+
+    // An upload object is created for each
+    // FakeXMLHttpRequest and allows upload
+    // events to be simulated using uploadProgress
+    // and uploadError.
+    function UploadProgress() {
+        this.eventListeners = {
+            "progress": [],
+            "load": [],
+            "abort": [],
+            "error": []
+        }
+    }
+
+    UploadProgress.prototype.addEventListener = function(event, listener) {
+        this.eventListeners[event].push(listener);
+    };
+
+    UploadProgress.prototype.removeEventListener = function(event, listener) {
+        var listeners = this.eventListeners[event] || [];
+
+        for (var i = 0, l = listeners.length; i < l; ++i) {
+            if (listeners[i] == listener) {
+                return listeners.splice(i, 1);
+            }
+        }
+    };
+
+    UploadProgress.prototype.dispatchEvent = function(event) {
+        var listeners = this.eventListeners[event.type] || [];
+
+        for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
+            listener(event);
+        }
+    };
+
+    function verifyState(xhr) {
+        if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
+            throw new Error("INVALID_STATE_ERR");
+        }
+
+        if (xhr.sendFlag) {
+            throw new Error("INVALID_STATE_ERR");
+        }
+    }
+
+    // filtering to enable a white-list version of Sinon FakeXhr,
+    // where whitelisted requests are passed through to real XHR
+    function each(collection, callback) {
+        if (!collection) return;
+        for (var i = 0, l = collection.length; i < l; i += 1) {
+            callback(collection[i]);
+        }
+    }
+    function some(collection, callback) {
+        for (var index = 0; index < collection.length; index++) {
+            if(callback(collection[index]) === true) return true;
+        }
+        return false;
+    }
+    // largest arity in XHR is 5 - XHR#open
+    var apply = function(obj,method,args) {
+        switch(args.length) {
+        case 0: return obj[method]();
+        case 1: return obj[method](args[0]);
+        case 2: return obj[method](args[0],args[1]);
+        case 3: return obj[method](args[0],args[1],args[2]);
+        case 4: return obj[method](args[0],args[1],args[2],args[3]);
+        case 5: return obj[method](args[0],args[1],args[2],args[3],args[4]);
+        }
+    };
+
+    FakeXMLHttpRequest.filters = [];
+    FakeXMLHttpRequest.addFilter = function(fn) {
+        this.filters.push(fn)
+    };
+    var IE6Re = /MSIE 6/;
+    FakeXMLHttpRequest.defake = function(fakeXhr,xhrArgs) {
+        var xhr = new sinon.xhr.workingXHR();
+        each(["open","setRequestHeader","send","abort","getResponseHeader",
+              "getAllResponseHeaders","addEventListener","overrideMimeType","removeEventListener"],
+             function(method) {
+                 fakeXhr[method] = function() {
+                   return apply(xhr,method,arguments);
+                 };
+             });
+
+        var copyAttrs = function(args) {
+            each(args, function(attr) {
+              try {
+                fakeXhr[attr] = xhr[attr]
+              } catch(e) {
+                if(!IE6Re.test(navigator.userAgent)) throw e;
+              }
+            });
+        };
+
+        var stateChange = function() {
+            fakeXhr.readyState = xhr.readyState;
+            if(xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
+                copyAttrs(["status","statusText"]);
+            }
+            if(xhr.readyState >= FakeXMLHttpRequest.LOADING) {
+                copyAttrs(["responseText"]);
+            }
+            if(xhr.readyState === FakeXMLHttpRequest.DONE) {
+                copyAttrs(["responseXML"]);
+            }
+            if(fakeXhr.onreadystatechange) fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
+        };
+        if(xhr.addEventListener) {
+          for(var event in fakeXhr.eventListeners) {
+              if(fakeXhr.eventListeners.hasOwnProperty(event)) {
+                  each(fakeXhr.eventListeners[event],function(handler) {
+                      xhr.addEventListener(event, handler);
+                  });
+              }
+          }
+          xhr.addEventListener("readystatechange",stateChange);
+        } else {
+          xhr.onreadystatechange = stateChange;
+        }
+        apply(xhr,"open",xhrArgs);
+    };
+    FakeXMLHttpRequest.useFilters = false;
+
+    function verifyRequestOpened(xhr) {
+        if (xhr.readyState != FakeXMLHttpRequest.OPENED) {
+            throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
+        }
+    }
+
+    function verifyRequestSent(xhr) {
+        if (xhr.readyState == FakeXMLHttpRequest.DONE) {
+            throw new Error("Request done");
+        }
+    }
+
+    function verifyHeadersReceived(xhr) {
+        if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
+            throw new Error("No headers received");
+        }
+    }
+
+    function verifyResponseBodyType(body) {
+        if (typeof body != "string") {
+            var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
+                                 body + ", which is not a string.");
+            error.name = "InvalidBodyException";
+            throw error;
+        }
+    }
+
+    sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
+        async: true,
+
+        open: function open(method, url, async, username, password) {
+            this.method = method;
+            this.url = url;
+            this.async = typeof async == "boolean" ? async : true;
+            this.username = username;
+            this.password = password;
+            this.responseText = null;
+            this.responseXML = null;
+            this.requestHeaders = {};
+            this.sendFlag = false;
+            if(sinon.FakeXMLHttpRequest.useFilters === true) {
+                var xhrArgs = arguments;
+                var defake = some(FakeXMLHttpRequest.filters,function(filter) {
+                    return filter.apply(this,xhrArgs)
+                });
+                if (defake) {
+                  return sinon.FakeXMLHttpRequest.defake(this,arguments);
+                }
+            }
+            this.readyStateChange(FakeXMLHttpRequest.OPENED);
+        },
+
+        readyStateChange: function readyStateChange(state) {
+            this.readyState = state;
+
+            if (typeof this.onreadystatechange == "function") {
+                try {
+                    this.onreadystatechange();
+                } catch (e) {
+                    sinon.logError("Fake XHR onreadystatechange handler", e);
+                }
+            }
+
+            this.dispatchEvent(new sinon.Event("readystatechange"));
+
+            switch (this.readyState) {
+                case FakeXMLHttpRequest.DONE:
+                    this.dispatchEvent(new sinon.Event("load", false, false, this));
+                    this.dispatchEvent(new sinon.Event("loadend", false, false, this));
+                    this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
+                    if (supportsProgress) {
+                        this.upload.dispatchEvent(new sinon.ProgressEvent('progress', {loaded: 100, total: 100}));
+                    }
+                    break;
+            }
+        },
+
+        setRequestHeader: function setRequestHeader(header, value) {
+            verifyState(this);
+
+            if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
+                throw new Error("Refused to set unsafe header \"" + header + "\"");
+            }
+
+            if (this.requestHeaders[header]) {
+                this.requestHeaders[header] += "," + value;
+            } else {
+                this.requestHeaders[header] = value;
+            }
+        },
+
+        // Helps testing
+        setResponseHeaders: function setResponseHeaders(headers) {
+            verifyRequestOpened(this);
+            this.responseHeaders = {};
+
+            for (var header in headers) {
+                if (headers.hasOwnProperty(header)) {
+                    this.responseHeaders[header] = headers[header];
+                }
+            }
+
+            if (this.async) {
+                this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
+            } else {
+                this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
+            }
+        },
+
+        // Currently treats ALL data as a DOMString (i.e. no Document)
+        send: function send(data) {
+            verifyState(this);
+
+            if (!/^(get|head)$/i.test(this.method)) {
+                if (this.requestHeaders["Content-Type"]) {
+                    var value = this.requestHeaders["Content-Type"].split(";");
+                    this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
+                } else {
+                    this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
+                }
+
+                this.requestBody = data;
+            }
+
+            this.errorFlag = false;
+            this.sendFlag = this.async;
+            this.readyStateChange(FakeXMLHttpRequest.OPENED);
+
+            if (typeof this.onSend == "function") {
+                this.onSend(this);
+            }
+
+            this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
+        },
+
+        abort: function abort() {
+            this.aborted = true;
+            this.responseText = null;
+            this.errorFlag = true;
+            this.requestHeaders = {};
+
+            if (this.readyState > sinon.FakeXMLHttpRequest.UNSENT && this.sendFlag) {
+                this.readyStateChange(sinon.FakeXMLHttpRequest.DONE);
+                this.sendFlag = false;
+            }
+
+            this.readyState = sinon.FakeXMLHttpRequest.UNSENT;
+
+            this.dispatchEvent(new sinon.Event("abort", false, false, this));
+
+            this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
+
+            if (typeof this.onerror === "function") {
+                this.onerror();
+            }
+        },
+
+        getResponseHeader: function getResponseHeader(header) {
+            if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
+                return null;
+            }
+
+            if (/^Set-Cookie2?$/i.test(header)) {
+                return null;
+            }
+
+            header = header.toLowerCase();
+
+            for (var h in this.responseHeaders) {
+                if (h.toLowerCase() == header) {
+                    return this.responseHeaders[h];
+                }
+            }
+
+            return null;
+        },
+
+        getAllResponseHeaders: function getAllResponseHeaders() {
+            if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
+                return "";
+            }
+
+            var headers = "";
+
+            for (var header in this.responseHeaders) {
+                if (this.responseHeaders.hasOwnProperty(header) &&
+                    !/^Set-Cookie2?$/i.test(header)) {
+                    headers += header + ": " + this.responseHeaders[header] + "\r\n";
+                }
+            }
+
+            return headers;
+        },
+
+        setResponseBody: function setResponseBody(body) {
+            verifyRequestSent(this);
+            verifyHeadersReceived(this);
+            verifyResponseBodyType(body);
+
+            var chunkSize = this.chunkSize || 10;
+            var index = 0;
+            this.responseText = "";
+
+            do {
+                if (this.async) {
+                    this.readyStateChange(FakeXMLHttpRequest.LOADING);
+                }
+
+                this.responseText += body.substring(index, index + chunkSize);
+                index += chunkSize;
+            } while (index < body.length);
+
+            var type = this.getResponseHeader("Content-Type");
+
+            if (this.responseText &&
+                (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
+                try {
+                    this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
+                } catch (e) {
+                    // Unable to parse XML - no biggie
+                }
+            }
+
+            if (this.async) {
+                this.readyStateChange(FakeXMLHttpRequest.DONE);
+            } else {
+                this.readyState = FakeXMLHttpRequest.DONE;
+            }
+        },
+
+        respond: function respond(status, headers, body) {
+            this.status = typeof status == "number" ? status : 200;
+            this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
+            this.setResponseHeaders(headers || {});
+            this.setResponseBody(body || "");
+        },
+
+        uploadProgress: function uploadProgress(progressEventRaw) {
+            if (supportsProgress) {
+                this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
+            }
+        },
+
+        uploadError: function uploadError(error) {
+            if (supportsCustomEvent) {
+                this.upload.dispatchEvent(new sinon.CustomEvent("error", {"detail": error}));
+            }
+        }
+    });
+
+    sinon.extend(FakeXMLHttpRequest, {
+        UNSENT: 0,
+        OPENED: 1,
+        HEADERS_RECEIVED: 2,
+        LOADING: 3,
+        DONE: 4
+    });
+
+    // Borrowed from JSpec
+    FakeXMLHttpRequest.parseXML = function parseXML(text) {
+        var xmlDoc;
+
+        if (typeof DOMParser != "undefined") {
+            var parser = new DOMParser();
+            xmlDoc = parser.parseFromString(text, "text/xml");
+        } else {
+            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+            xmlDoc.async = "false";
+            xmlDoc.loadXML(text);
+        }
+
+        return xmlDoc;
+    };
+
+    FakeXMLHttpRequest.statusCodes = {
+        100: "Continue",
+        101: "Switching Protocols",
+        200: "OK",
+        201: "Created",
+        202: "Accepted",
+        203: "Non-Authoritative Information",
+        204: "No Content",
+        205: "Reset Content",
+        206: "Partial Content",
+        300: "Multiple Choice",
+        301: "Moved Permanently",
+        302: "Found",
+        303: "See Other",
+        304: "Not Modified",
+        305: "Use Proxy",
+        307: "Temporary Redirect",
+        400: "Bad Request",
+        401: "Unauthorized",
+        402: "Payment Required",
+        403: "Forbidden",
+        404: "Not Found",
+        405: "Method Not Allowed",
+        406: "Not Acceptable",
+        407: "Proxy Authentication Required",
+        408: "Request Timeout",
+        409: "Conflict",
+        410: "Gone",
+        411: "Length Required",
+        412: "Precondition Failed",
+        413: "Request Entity Too Large",
+        414: "Request-URI Too Long",
+        415: "Unsupported Media Type",
+        416: "Requested Range Not Satisfiable",
+        417: "Expectation Failed",
+        422: "Unprocessable Entity",
+        500: "Internal Server Error",
+        501: "Not Implemented",
+        502: "Bad Gateway",
+        503: "Service Unavailable",
+        504: "Gateway Timeout",
+        505: "HTTP Version Not Supported"
+    };
+
+    sinon.useFakeXMLHttpRequest = function () {
+        sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
+            if (xhr.supportsXHR) {
+                global.XMLHttpRequest = xhr.GlobalXMLHttpRequest;
+            }
+
+            if (xhr.supportsActiveX) {
+                global.ActiveXObject = xhr.GlobalActiveXObject;
+            }
+
+            delete sinon.FakeXMLHttpRequest.restore;
+
+            if (keepOnCreate !== true) {
+                delete sinon.FakeXMLHttpRequest.onCreate;
+            }
+        };
+        if (xhr.supportsXHR) {
+            global.XMLHttpRequest = sinon.FakeXMLHttpRequest;
+        }
+
+        if (xhr.supportsActiveX) {
+            global.ActiveXObject = function ActiveXObject(objId) {
+                if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
+
+                    return new sinon.FakeXMLHttpRequest();
+                }
+
+                return new xhr.GlobalActiveXObject(objId);
+            };
+        }
+
+        return sinon.FakeXMLHttpRequest;
+    };
+
+    sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
+
+})(typeof global === "object" ? global : this);
+
+if (typeof module !== 'undefined' && module.exports) {
+    module.exports = sinon;
+}
+
+/**
+ * @depend fake_xml_http_request.js
+ */
+/*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/
+/*global module, require, window*/
+/**
+ * The Sinon "server" mimics a web server that receives requests from
+ * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
+ * both synchronously and asynchronously. To respond synchronuously, canned
+ * answers have to be provided upfront.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+if (typeof sinon == "undefined") {
+    var sinon = {};
+}
+
+sinon.fakeServer = (function () {
+    var push = [].push;
+    function F() {}
+
+    function create(proto) {
+        F.prototype = proto;
+        return new F();
+    }
+
+    function responseArray(handler) {
+        var response = handler;
+
+        if (Object.prototype.toString.call(handler) != "[object Array]") {
+            response = [200, {}, handler];
+        }
+
+        if (typeof response[2] != "string") {
+            throw new TypeError("Fake server response body should be string, but was " +
+                                typeof response[2]);
+        }
+
+        return response;
+    }
+
+    var wloc = typeof window !== "undefined" ? window.location : {};
+    var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
+
+    function matchOne(response, reqMethod, reqUrl) {
+        var rmeth = response.method;
+        var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
+        var url = response.url;
+        var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
+
+        return matchMethod && matchUrl;
+    }
+
+    function match(response, request) {
+        var requestUrl = request.url;
+
+        if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
+            requestUrl = requestUrl.replace(rCurrLoc, "");
+        }
+
+        if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
+            if (typeof response.response == "function") {
+                var ru = response.url;
+                var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []);
+                return response.response.apply(response, args);
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    function log(response, request) {
+        var str;
+
+        str =  "Request:\n"  + sinon.format(request)  + "\n\n";
+        str += "Response:\n" + sinon.format(response) + "\n\n";
+
+        sinon.log(str);
+    }
+
+    return {
+        create: function () {
+            var server = create(this);
+            this.xhr = sinon.useFakeXMLHttpRequest();
+            server.requests = [];
+
+            this.xhr.onCreate = function (xhrObj) {
+                server.addRequest(xhrObj);
+            };
+
+            return server;
+        },
+
+        addRequest: function addRequest(xhrObj) {
+            var server = this;
+            push.call(this.requests, xhrObj);
+
+            xhrObj.onSend = function () {
+                server.handleRequest(this);
+
+                if (server.autoRespond && !server.responding) {
+                    setTimeout(function () {
+                        server.responding = false;
+                        server.respond();
+                    }, server.autoRespondAfter || 10);
+
+                    server.responding = true;
+                }
+            };
+        },
+
+        getHTTPMethod: function getHTTPMethod(request) {
+            if (this.fakeHTTPMethods && /post/i.test(request.method)) {
+                var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
+                return !!matches ? matches[1] : request.method;
+            }
+
+            return request.method;
+        },
+
+        handleRequest: function handleRequest(xhr) {
+            if (xhr.async) {
+                if (!this.queue) {
+                    this.queue = [];
+                }
+
+                push.call(this.queue, xhr);
+            } else {
+                this.processRequest(xhr);
+            }
+        },
+
+        respondWith: function respondWith(method, url, body) {
+            if (arguments.length == 1 && typeof method != "function") {
+                this.response = responseArray(method);
+                return;
+            }
+
+            if (!this.responses) { this.responses = []; }
+
+            if (arguments.length == 1) {
+                body = method;
+                url = method = null;
+            }
+
+            if (arguments.length == 2) {
+                body = url;
+                url = method;
+                method = null;
+            }
+
+            push.call(this.responses, {
+                method: method,
+                url: url,
+                response: typeof body == "function" ? body : responseArray(body)
+            });
+        },
+
+        respond: function respond() {
+            if (arguments.length > 0) this.respondWith.apply(this, arguments);
+            var queue = this.queue || [];
+            var requests = queue.splice(0);
+            var request;
+
+            while(request = requests.shift()) {
+                this.processRequest(request);
+            }
+        },
+
+        processRequest: function processRequest(request) {
+            try {
+                if (request.aborted) {
+                    return;
+                }
+
+                var response = this.response || [404, {}, ""];
+
+                if (this.responses) {
+                    for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
+                        if (match.call(this, this.responses[i], request)) {
+                            response = this.responses[i].response;
+                            break;
+                        }
+                    }
+                }
+
+                if (request.readyState != 4) {
+                    log(response, request);
+
+                    request.respond(response[0], response[1], response[2]);
+                }
+            } catch (e) {
+                sinon.logError("Fake server request processing", e);
+            }
+        },
+
+        restore: function restore() {
+            return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
+        }
+    };
+}());
+
+if (typeof module !== 'undefined' && module.exports) {
+    module.exports = sinon;
+}
+
+/**
+ * @depend fake_server.js
+ * @depend fake_timers.js
+ */
+/*jslint browser: true, eqeqeq: false, onevar: false*/
+/*global sinon*/
+/**
+ * Add-on for sinon.fakeServer that automatically handles a fake timer along with
+ * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
+ * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
+ * it polls the object for completion with setInterval. Dispite the direct
+ * motivation, there is nothing jQuery-specific in this file, so it can be used
+ * in any environment where the ajax implementation depends on setInterval or
+ * setTimeout.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function () {
+    function Server() {}
+    Server.prototype = sinon.fakeServer;
+
+    sinon.fakeServerWithClock = new Server();
+
+    sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
+        if (xhr.async) {
+            if (typeof setTimeout.clock == "object") {
+                this.clock = setTimeout.clock;
+            } else {
+                this.clock = sinon.useFakeTimers();
+                this.resetClock = true;
+            }
+
+            if (!this.longestTimeout) {
+                var clockSetTimeout = this.clock.setTimeout;
+                var clockSetInterval = this.clock.setInterval;
+                var server = this;
+
+                this.clock.setTimeout = function (fn, timeout) {
+                    server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
+
+                    return clockSetTimeout.apply(this, arguments);
+                };
+
+                this.clock.setInterval = function (fn, timeout) {
+                    server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
+
+                    return clockSetInterval.apply(this, arguments);
+                };
+            }
+        }
+
+        return sinon.fakeServer.addRequest.call(this, xhr);
+    };
+
+    sinon.fakeServerWithClock.respond = function respond() {
+        var returnVal = sinon.fakeServer.respond.apply(this, arguments);
+
+        if (this.clock) {
+            this.clock.tick(this.longestTimeout || 0);
+            this.longestTimeout = 0;
+
+            if (this.resetClock) {
+                this.clock.restore();
+                this.resetClock = false;
+            }
+        }
+
+        return returnVal;
+    };
+
+    sinon.fakeServerWithClock.restore = function restore() {
+        if (this.clock) {
+            this.clock.restore();
+        }
+
+        return sinon.fakeServer.restore.apply(this, arguments);
+    };
+}());
+
+/**
+ * @depend ../sinon.js
+ * @depend collection.js
+ * @depend util/fake_timers.js
+ * @depend util/fake_server_with_clock.js
+ */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global require, module*/
+/**
+ * Manages fake collections as well as fake utilities such as Sinon's
+ * timers and fake XHR implementation in one convenient object.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+if (typeof module !== 'undefined' && module.exports) {
+    var sinon = require("../sinon");
+    sinon.extend(sinon, require("./util/fake_timers"));
+}
+
+(function () {
+    var push = [].push;
+
+    function exposeValue(sandbox, config, key, value) {
+        if (!value) {
+            return;
+        }
+
+        if (config.injectInto && !(key in config.injectInto)) {
+            config.injectInto[key] = value;
+            sandbox.injectedKeys.push(key);
+        } else {
+            push.call(sandbox.args, value);
+        }
+    }
+
+    function prepareSandboxFromConfig(config) {
+        var sandbox = sinon.create(sinon.sandbox);
+
+        if (config.useFakeServer) {
+            if (typeof config.useFakeServer == "object") {
+                sandbox.serverPrototype = config.useFakeServer;
+            }
+
+            sandbox.useFakeServer();
+        }
+
+        if (config.useFakeTimers) {
+            if (typeof config.useFakeTimers == "object") {
+                sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
+            } else {
+                sandbox.useFakeTimers();
+            }
+        }
+
+        return sandbox;
+    }
+
+    sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
+        useFakeTimers: function useFakeTimers() {
+            this.clock = sinon.useFakeTimers.apply(sinon, arguments);
+
+            return this.add(this.clock);
+        },
+
+        serverPrototype: sinon.fakeServer,
+
+        useFakeServer: function useFakeServer() {
+            var proto = this.serverPrototype || sinon.fakeServer;
+
+            if (!proto || !proto.create) {
+                return null;
+            }
+
+            this.server = proto.create();
+            return this.add(this.server);
+        },
+
+        inject: function (obj) {
+            sinon.collection.inject.call(this, obj);
+
+            if (this.clock) {
+                obj.clock = this.clock;
+            }
+
+            if (this.server) {
+                obj.server = this.server;
+                obj.requests = this.server.requests;
+            }
+
+            return obj;
+        },
+
+        restore: function () {
+            sinon.collection.restore.apply(this, arguments);
+            this.restoreContext();
+        },
+
+        restoreContext: function () {
+            if (this.injectedKeys) {
+                for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
+                    delete this.injectInto[this.injectedKeys[i]];
+                }
+                this.injectedKeys = [];
+            }
+        },
+
+        create: function (config) {
+            if (!config) {
+                return sinon.create(sinon.sandbox);
+            }
+
+            var sandbox = prepareSandboxFromConfig(config);
+            sandbox.args = sandbox.args || [];
+            sandbox.injectedKeys = [];
+            sandbox.injectInto = config.injectInto;
+            var prop, value, exposed = sandbox.inject({});
+
+            if (config.properties) {
+                for (var i = 0, l = config.properties.length; i < l; i++) {
+                    prop = config.properties[i];
+                    value = exposed[prop] || prop == "sandbox" && sandbox;
+                    exposeValue(sandbox, config, prop, value);
+                }
+            } else {
+                exposeValue(sandbox, config, "sandbox", value);
+            }
+
+            return sandbox;
+        }
+    });
+
+    sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
+
+    if (typeof module !== 'undefined' && module.exports) {
+        module.exports = sinon.sandbox;
+    }
+}());
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ * @depend mock.js
+ * @depend sandbox.js
+ */
+/*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
+/*global module, require, sinon*/
+/**
+ * Test function, sandboxes fakes
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function test(callback) {
+        var type = typeof callback;
+
+        if (type != "function") {
+            throw new TypeError("sinon.test needs to wrap a test function, got " + type);
+        }
+
+        return function () {
+            var config = sinon.getConfig(sinon.config);
+            config.injectInto = config.injectIntoThis && this || config.injectInto;
+            var sandbox = sinon.sandbox.create(config);
+            var exception, result;
+            var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
+
+            try {
+                result = callback.apply(this, args);
+            } catch (e) {
+                exception = e;
+            }
+
+            if (typeof exception !== "undefined") {
+                sandbox.restore();
+                throw exception;
+            }
+            else {
+                sandbox.verifyAndRestore();
+            }
+
+            return result;
+        };
+    }
+
+    test.config = {
+        injectIntoThis: true,
+        injectInto: null,
+        properties: ["spy", "stub", "mock", "clock", "server", "requests"],
+        useFakeTimers: true,
+        useFakeServer: true
+    };
+
+    if (commonJSModule) {
+        module.exports = test;
+    } else {
+        sinon.test = test;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend test.js
+ */
+/*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
+/*global module, require, sinon*/
+/**
+ * Test case, sandboxes all test functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon || !Object.prototype.hasOwnProperty) {
+        return;
+    }
+
+    function createTest(property, setUp, tearDown) {
+        return function () {
+            if (setUp) {
+                setUp.apply(this, arguments);
+            }
+
+            var exception, result;
+
+            try {
+                result = property.apply(this, arguments);
+            } catch (e) {
+                exception = e;
+            }
+
+            if (tearDown) {
+                tearDown.apply(this, arguments);
+            }
+
+            if (exception) {
+                throw exception;
+            }
+
+            return result;
+        };
+    }
+
+    function testCase(tests, prefix) {
+        /*jsl:ignore*/
+        if (!tests || typeof tests != "object") {
+            throw new TypeError("sinon.testCase needs an object with test functions");
+        }
+        /*jsl:end*/
+
+        prefix = prefix || "test";
+        var rPrefix = new RegExp("^" + prefix);
+        var methods = {}, testName, property, method;
+        var setUp = tests.setUp;
+        var tearDown = tests.tearDown;
+
+        for (testName in tests) {
+            if (tests.hasOwnProperty(testName)) {
+                property = tests[testName];
+
+                if (/^(setUp|tearDown)$/.test(testName)) {
+                    continue;
+                }
+
+                if (typeof property == "function" && rPrefix.test(testName)) {
+                    method = property;
+
+                    if (setUp || tearDown) {
+                        method = createTest(property, setUp, tearDown);
+                    }
+
+                    methods[testName] = sinon.test(method);
+                } else {
+                    methods[testName] = tests[testName];
+                }
+            }
+        }
+
+        return methods;
+    }
+
+    if (commonJSModule) {
+        module.exports = testCase;
+    } else {
+        sinon.testCase = testCase;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ */
+/*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+ * Assertions matching the test spy retrieval interface.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon, global) {
+    var commonJSModule = typeof module !== "undefined" && module.exports;
+    var slice = Array.prototype.slice;
+    var assert;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function verifyIsStub() {
+        var method;
+
+        for (var i = 0, l = arguments.length; i < l; ++i) {
+            method = arguments[i];
+
+            if (!method) {
+                assert.fail("fake is not a spy");
+            }
+
+            if (typeof method != "function") {
+                assert.fail(method + " is not a function");
+            }
+
+            if (typeof method.getCall != "function") {
+                assert.fail(method + " is not stubbed");
+            }
+        }
+    }
+
+    function failAssertion(object, msg) {
+        object = object || global;
+        var failMethod = object.fail || assert.fail;
+        failMethod.call(object, msg);
+    }
+
+    function mirrorPropAsAssertion(name, method, message) {
+        if (arguments.length == 2) {
+            message = method;
+            method = name;
+        }
+
+        assert[name] = function (fake) {
+            verifyIsStub(fake);
+
+            var args = slice.call(arguments, 1);
+            var failed = false;
+
+            if (typeof method == "function") {
+                failed = !method(fake);
+            } else {
+                failed = typeof fake[method] == "function" ?
+                    !fake[method].apply(fake, args) : !fake[method];
+            }
+
+            if (failed) {
+                failAssertion(this, fake.printf.apply(fake, [message].concat(args)));
+            } else {
+                assert.pass(name);
+            }
+        };
+    }
+
+    function exposedName(prefix, prop) {
+        return !prefix || /^fail/.test(prop) ? prop :
+            prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
+    }
+
+    assert = {
+        failException: "AssertError",
+
+        fail: function fail(message) {
+            var error = new Error(message);
+            error.name = this.failException || assert.failException;
+
+            throw error;
+        },
+
+        pass: function pass(assertion) {},
+
+        callOrder: function assertCallOrder() {
+            verifyIsStub.apply(null, arguments);
+            var expected = "", actual = "";
+
+            if (!sinon.calledInOrder(arguments)) {
+                try {
+                    expected = [].join.call(arguments, ", ");
+                    var calls = slice.call(arguments);
+                    var i = calls.length;
+                    while (i) {
+                        if (!calls[--i].called) {
+                            calls.splice(i, 1);
+                        }
+                    }
+                    actual = sinon.orderByFirstCall(calls).join(", ");
+                } catch (e) {
+                    // If this fails, we'll just fall back to the blank string
+                }
+
+                failAssertion(this, "expected " + expected + " to be " +
+                              "called in order but were called as " + actual);
+            } else {
+                assert.pass("callOrder");
+            }
+        },
+
+        callCount: function assertCallCount(method, count) {
+            verifyIsStub(method);
+
+            if (method.callCount != count) {
+                var msg = "expected %n to be called " + sinon.timesInWords(count) +
+                    " but was called %c%C";
+                failAssertion(this, method.printf(msg));
+            } else {
+                assert.pass("callCount");
+            }
+        },
+
+        expose: function expose(target, options) {
+            if (!target) {
+                throw new TypeError("target is null or undefined");
+            }
+
+            var o = options || {};
+            var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
+            var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
+
+            for (var method in this) {
+                if (method != "export" && (includeFail || !/^(fail)/.test(method))) {
+                    target[exposedName(prefix, method)] = this[method];
+                }
+            }
+
+            return target;
+        },
+
+        match: function match(actual, expectation) {
+            var matcher = sinon.match(expectation);
+            if (matcher.test(actual)) {
+                assert.pass("match");
+            } else {
+                var formatted = [
+                    "expected value to match",
+                    "    expected = " + sinon.format(expectation),
+                    "    actual = " + sinon.format(actual)
+                ]
+                failAssertion(this, formatted.join("\n"));
+            }
+        }
+    };
+
+    mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
+    mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
+                          "expected %n to not have been called but was called %c%C");
+    mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
+    mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
+    mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
+    mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
+    mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
+    mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
+    mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
+    mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
+    mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
+    mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
+    mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
+    mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
+    mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
+    mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
+    mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
+    mirrorPropAsAssertion("threw", "%n did not throw exception%C");
+    mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
+
+    if (commonJSModule) {
+        module.exports = assert;
+    } else {
+        sinon.assert = assert;
+    }
+}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
+
+return sinon;}.call(typeof window != 'undefined' && window || {}));
diff --git a/resources/lib/sinonjs/sinon-ie-1.9.0.js b/resources/lib/sinonjs/sinon-ie-1.9.0.js
new file mode 100644 (file)
index 0000000..c9fbd9d
--- /dev/null
@@ -0,0 +1,86 @@
+/**
+ * Sinon.JS 1.9.0, 2014/03/05
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
+ *
+ * (The BSD License)
+ * 
+ * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ *     * Neither the name of Christian Johansen nor the names of his contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*global sinon, setTimeout, setInterval, clearTimeout, clearInterval, Date*/
+/**
+ * Helps IE run the fake timers. By defining global functions, IE allows
+ * them to be overwritten at a later point. If these are not defined like
+ * this, overwriting them will result in anything from an exception to browser
+ * crash.
+ *
+ * If you don't require fake timers to work in IE, don't include this file.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+function setTimeout() {}
+function clearTimeout() {}
+function setImmediate() {}
+function clearImmediate() {}
+function setInterval() {}
+function clearInterval() {}
+function Date() {}
+
+// Reassign the original functions. Now their writable attribute
+// should be true. Hackish, I know, but it works.
+setTimeout = sinon.timers.setTimeout;
+clearTimeout = sinon.timers.clearTimeout;
+setImmediate = sinon.timers.setImmediate;
+clearImmediate = sinon.timers.clearImmediate;
+setInterval = sinon.timers.setInterval;
+clearInterval = sinon.timers.clearInterval;
+Date = sinon.timers.Date;
+
+/*global sinon*/
+/**
+ * Helps IE run the fake XMLHttpRequest. By defining global functions, IE allows
+ * them to be overwritten at a later point. If these are not defined like
+ * this, overwriting them will result in anything from an exception to browser
+ * crash.
+ *
+ * If you don't require fake XHR to work in IE, don't include this file.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+function XMLHttpRequest() {}
+
+// Reassign the original function. Now its writable attribute
+// should be true. Hackish, I know, but it works.
+XMLHttpRequest = sinon.xhr.XMLHttpRequest || undefined;
diff --git a/resources/mediawiki.action/images/green-checkmark.png b/resources/mediawiki.action/images/green-checkmark.png
deleted file mode 100644 (file)
index 8ec604e..0000000
Binary files a/resources/mediawiki.action/images/green-checkmark.png and /dev/null differ
diff --git a/resources/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css b/resources/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css
deleted file mode 100644 (file)
index 1af4a7a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Styles for collapsible lists of templates used and hidden categories */
-.mw-editfooter-toggler {
-       cursor: pointer;
-       background-position: left center;
-       padding-left: 16px;
-}
-
-.mw-editfooter-list {
-       margin-bottom: 1em;
-       margin-left: 2.5em;
-}
-
-/* Show/hide animation is incorrect if the table has a margin set. Extra
- * "table.wikitable" is needed in the selector for CSS specificity. */
-table.wikitable.preview-limit-report {
-       margin: 0;
-}
diff --git a/resources/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js b/resources/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js
deleted file mode 100644 (file)
index 7ae51ab..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-jQuery( document ).ready( function ( $ ) {
-       var collapsibleLists, i, handleOne;
-
-       // Collapsible lists of categories and templates
-       collapsibleLists = [
-               {
-                       $list: $( '.templatesUsed ul' ),
-                       $toggler: $( '.mw-templatesUsedExplanation' ),
-                       cookieName: 'templates-used-list'
-               },
-               {
-                       $list: $( '.hiddencats ul' ),
-                       $toggler: $( '.mw-hiddenCategoriesExplanation' ),
-                       cookieName: 'hidden-categories-list'
-               },
-               {
-                       $list: $( '.preview-limit-report-wrapper' ),
-                       $toggler: $( '.mw-limitReportExplanation' ),
-                       cookieName: 'preview-limit-report'
-               }
-       ];
-
-       handleOne = function ( $list, $toggler, cookieName ) {
-               var isCollapsed = $.cookie( cookieName ) !== 'expanded';
-
-               // Style the toggler with an arrow icon and add a tabIndex and a role for accessibility
-               $toggler.addClass( 'mw-editfooter-toggler' ).prop( 'tabIndex', 0 ).attr( 'role', 'button' );
-               $list.addClass( 'mw-editfooter-list' );
-
-               $list.makeCollapsible( {
-                       $customTogglers: $toggler,
-                       linksPassthru: true,
-                       plainMode: true,
-                       collapsed: isCollapsed
-               } );
-
-               $toggler.addClass( isCollapsed ? 'mw-icon-arrow-collapsed' : 'mw-icon-arrow-expanded' );
-
-               $list.on( 'beforeExpand.mw-collapsible', function () {
-                       $toggler.removeClass( 'mw-icon-arrow-collapsed' ).addClass( 'mw-icon-arrow-expanded' );
-                       $.cookie( cookieName, 'expanded' );
-               } );
-
-               $list.on( 'beforeCollapse.mw-collapsible', function () {
-                       $toggler.removeClass( 'mw-icon-arrow-expanded' ).addClass( 'mw-icon-arrow-collapsed' );
-                       $.cookie( cookieName, 'collapsed' );
-               } );
-       };
-
-       for ( i = 0; i < collapsibleLists.length; i++ ) {
-               // Pass to a function for iteration-local variables
-               handleOne( collapsibleLists[i].$list, collapsibleLists[i].$toggler, collapsibleLists[i].cookieName );
-       }
-} );
diff --git a/resources/mediawiki.action/mediawiki.action.edit.editWarning.js b/resources/mediawiki.action/mediawiki.action.edit.editWarning.js
deleted file mode 100644 (file)
index f8448e6..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Javascript for module editWarning
- */
-( function ( mw, $ ) {
-       $( function () {
-               // Check if EditWarning is enabled and if we need it
-               if ( $( '#wpTextbox1' ).length === 0 ) {
-                       return true;
-               }
-               // Get the original values of some form elements
-               $( '#wpTextbox1, #wpSummary' ).each( function () {
-                       $( this ).data( 'origtext', $( this ).val() );
-               } );
-               var savedWindowOnBeforeUnload;
-               $( window )
-                       .on( 'beforeunload.editwarning', function () {
-                               var retval;
-
-                               // Check if the current values of some form elements are the same as
-                               // the original values
-                               if (
-                                       mw.config.get( 'wgAction' ) === 'submit' ||
-                                               $( '#wpTextbox1' ).data( 'origtext' ) !== $( '#wpTextbox1' ).val() ||
-                                               $( '#wpSummary' ).data( 'origtext' ) !== $( '#wpSummary' ).val()
-                               ) {
-                                       // Return our message
-                                       retval = mw.msg( 'editwarning-warning' );
-                               }
-
-                               // Unset the onbeforeunload handler so we don't break page caching in Firefox
-                               savedWindowOnBeforeUnload = window.onbeforeunload;
-                               window.onbeforeunload = null;
-                               if ( retval !== undefined ) {
-                                       // ...but if the user chooses not to leave the page, we need to rebind it
-                                       setTimeout( function () {
-                                               window.onbeforeunload = savedWindowOnBeforeUnload;
-                                       }, 1 );
-                                       return retval;
-                               }
-                       } )
-                       .on( 'pageshow.editwarning', function () {
-                               // Re-add onbeforeunload handler
-                               if ( !window.onbeforeunload ) {
-                                       window.onbeforeunload = savedWindowOnBeforeUnload;
-                               }
-                       } );
-
-               // Add form submission handler
-               $( '#editform' ).submit( function () {
-                       // Unbind our handlers
-                       $( window ).off( '.editwarning' );
-               } );
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.action/mediawiki.action.edit.js b/resources/mediawiki.action/mediawiki.action.edit.js
deleted file mode 100644 (file)
index bbffe79..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/**
- * Interface for the classic edit toolbar.
- *
- * @class mw.toolbar
- * @singleton
- */
-( function ( mw, $ ) {
-       var toolbar, isReady, $toolbar, queue, slice, $currentFocused;
-
-       /**
-        * Internal helper that does the actual insertion of the button into the toolbar.
-        *
-        * See #addButton for parameter documentation.
-        *
-        * @private
-        */
-       function insertButton( b, speedTip, tagOpen, tagClose, sampleText, imageId ) {
-               // Backwards compatibility
-               if ( typeof b !== 'object' ) {
-                       b = {
-                               imageFile: b,
-                               speedTip: speedTip,
-                               tagOpen: tagOpen,
-                               tagClose: tagClose,
-                               sampleText: sampleText,
-                               imageId: imageId
-                       };
-               }
-               var $image = $( '<img>' ).attr( {
-                       width: 23,
-                       height: 22,
-                       src: b.imageFile,
-                       alt: b.speedTip,
-                       title: b.speedTip,
-                       id: b.imageId || undefined,
-                       'class': 'mw-toolbar-editbutton'
-               } ).click( function () {
-                       toolbar.insertTags( b.tagOpen, b.tagClose, b.sampleText );
-                       return false;
-               } );
-
-               $toolbar.append( $image );
-       }
-
-       isReady = false;
-       $toolbar = false;
-       /**
-        * @private
-        * @property {Array}
-        * Contains button objects (and for backwards compatibilty, it can
-        * also contains an arguments array for insertButton).
-        */
-       queue = [];
-       slice = queue.slice;
-
-       toolbar = {
-
-               /**
-                * Add buttons to the toolbar.
-                *
-                * Takes care of race conditions and time-based dependencies
-                * by placing buttons in a queue if this method is called before
-                * the toolbar is created.
-                *
-                * For compatiblity, passing the properties listed below as separate arguments
-                * (in the listed order) is also supported.
-                *
-                * @param {Object} button Object with the following properties:
-                * @param {string} button.imageFile
-                * @param {string} button.speedTip
-                * @param {string} button.tagOpen
-                * @param {string} button.tagClose
-                * @param {string} button.sampleText
-                * @param {string} [button.imageId]
-                */
-               addButton: function () {
-                       if ( isReady ) {
-                               insertButton.apply( toolbar, arguments );
-                       } else {
-                               // Convert arguments list to array
-                               queue.push( slice.call( arguments ) );
-                       }
-               },
-               /**
-                * Example usage:
-                *     addButtons( [ { .. }, { .. }, { .. } ] );
-                *     addButtons( { .. }, { .. } );
-                *
-                * @param {Object|Array} [buttons...] An array of button objects or the first
-                *  button object in a list of variadic arguments.
-                */
-               addButtons: function ( buttons ) {
-                       if ( !$.isArray( buttons ) ) {
-                               buttons = slice.call( arguments );
-                       }
-                       if ( isReady ) {
-                               $.each( buttons, function () {
-                                       insertButton( this );
-                               } );
-                       } else {
-                               // Push each button into the queue
-                               queue.push.apply( queue, buttons );
-                       }
-               },
-
-               /**
-                * Apply tagOpen/tagClose to selection in currently focused textarea.
-                *
-                * Uses `sampleText` if selection is empty.
-                *
-                * @param {string} tagOpen
-                * @param {string} tagClose
-                * @param {string} sampleText
-                */
-               insertTags: function ( tagOpen, tagClose, sampleText ) {
-                       if ( $currentFocused && $currentFocused.length ) {
-                               $currentFocused.textSelection(
-                                       'encapsulateSelection', {
-                                               pre: tagOpen,
-                                               peri: sampleText,
-                                               post: tagClose
-                                       }
-                               );
-                       }
-               },
-
-               // For backwards compatibility,
-               // Called from EditPage.php, maybe in other places as well.
-               init: function () {}
-       };
-
-       // Legacy (for compatibility with the code previously in skins/common.edit.js)
-       mw.log.deprecate( window, 'addButton', toolbar.addButton, 'Use mw.toolbar.addButton instead' );
-       mw.log.deprecate( window, 'insertTags', toolbar.insertTags, 'Use mw.toolbar.insertTags instead' );
-
-       // Expose API publicly
-       mw.toolbar = toolbar;
-
-       $( function () {
-               var i, b, $iframe, editBox, scrollTop, $editForm;
-
-               // currentFocus is used to determine where to insert tags
-               $currentFocused = $( '#wpTextbox1' );
-
-               // Populate the selector cache for $toolbar
-               $toolbar = $( '#toolbar' );
-
-               for ( i = 0; i < queue.length; i++ ) {
-                       b = queue[i];
-                       if ( $.isArray( b ) ) {
-                               // Forwarded arguments array from mw.toolbar.addButton
-                               insertButton.apply( toolbar, b );
-                       } else {
-                               // Raw object from mw.toolbar.addButtons
-                               insertButton( b );
-                       }
-               }
-
-               // Clear queue
-               queue.length = 0;
-
-               // This causes further calls to addButton to go to insertion directly
-               // instead of to the queue.
-               // It is important that this is after the one and only loop through
-               // the the queue
-               isReady = true;
-
-               // Make sure edit summary does not exceed byte limit
-               $( '#wpSummary' ).byteLimit( 255 );
-
-               // Restore the edit box scroll state following a preview operation,
-               // and set up a form submission handler to remember this state.
-               editBox = document.getElementById( 'wpTextbox1' );
-               scrollTop = document.getElementById( 'wpScrolltop' );
-               $editForm = $( '#editform' );
-               if ( $editForm.length && editBox && scrollTop ) {
-                       if ( scrollTop.value ) {
-                               editBox.scrollTop = scrollTop.value;
-                       }
-                       $editForm.submit( function () {
-                               scrollTop.value = editBox.scrollTop;
-                       });
-               }
-
-               // Apply to dynamically created textboxes as well as normal ones
-               $( document ).on( 'focus', 'textarea, input:text', function () {
-                       $currentFocused = $( this );
-               } );
-
-               // HACK: make $currentFocused work with the usability iframe
-               // With proper focus detection support (HTML 5!) this'll be much cleaner
-               // TODO: Get rid of this WikiEditor code from MediaWiki core!
-               $iframe = $( '.wikiEditor-ui-text iframe' );
-               if ( $iframe.length > 0 ) {
-                       $( $iframe.get( 0 ).contentWindow.document )
-                               // for IE
-                               .add( $iframe.get( 0 ).contentWindow.document.body )
-                               .focus( function () {
-                                       $currentFocused = $iframe;
-                               } );
-               }
-       });
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.action/mediawiki.action.edit.preview.js b/resources/mediawiki.action/mediawiki.action.edit.preview.js
deleted file mode 100644 (file)
index 4c2fc3a..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- * Live edit preview.
- */
-( function ( mw, $ ) {
-
-       /**
-        * @param {jQuery.Event} e
-        */
-       function doLivePreview( e ) {
-               var $wikiPreview, $editform, copySelectors, $copyElements, $spinner,
-                       targetUrl, postData, $previewDataHolder;
-
-               e.preventDefault();
-
-               // Deprecated: Use mw.hook instead
-               $( mw ).trigger( 'LivePreviewPrepare' );
-
-               $wikiPreview = $( '#wikiPreview' );
-               $editform = $( '#editform' );
-
-               // Show #wikiPreview if it's hidden to be able to scroll to it
-               // (if it is hidden, it's also empty, so nothing changes in the rendering)
-               $wikiPreview.show();
-
-               // Jump to where the preview will appear
-               $wikiPreview[0].scrollIntoView();
-
-               // List of selectors matching elements that we will
-               // update from from the ajax-loaded preview page.
-               copySelectors = [
-                       // Main
-                       '#firstHeading',
-                       '#wikiPreview',
-                       '#wikiDiff',
-                       '#catlinks',
-                       '.hiddencats',
-                       '#p-lang',
-                       // Editing-related
-                       '.templatesUsed',
-                       '.limitreport',
-                       '.mw-summary-preview'
-               ];
-               $copyElements = $( copySelectors.join( ',' ) );
-
-               // Not shown during normal preview, to be removed if present
-               $( '.mw-newarticletext' ).remove();
-
-               $spinner = $.createSpinner( {
-                       size: 'large',
-                       type: 'block'
-               } );
-               $wikiPreview.before( $spinner );
-               $spinner.css( {
-                       marginTop: $spinner.height()
-               } );
-
-               // Can't use fadeTo because it calls show(), and we might want to keep some elements hidden
-               // (e.g. empty #catlinks)
-               $copyElements.animate( { opacity: 0.4 }, 'fast' );
-
-               $previewDataHolder = $( '<div>' );
-               targetUrl = $editform.attr( 'action' );
-               targetUrl += targetUrl.indexOf( '?' ) !== -1 ? '&' : '?';
-               targetUrl += $.param( {
-                       debug: mw.config.get( 'debug' ),
-                       uselang: mw.config.get( 'wgUserLanguage' ),
-                       useskin: mw.config.get( 'skin' )
-               } );
-
-               // Gather all the data from the form
-               postData = $editform.formToArray();
-               postData.push( {
-                       name: e.target.name,
-                       value: ''
-               } );
-
-               // Load new preview data.
-               // TODO: This should use the action=parse API instead of loading the entire page,
-               // although that requires figuring out how to convert that raw data into proper HTML.
-               $previewDataHolder.load( targetUrl + ' ' + copySelectors.join( ',' ), postData, function () {
-                       var i, $from, $next, $parent;
-
-                       // Copy the contents of the specified elements from the loaded page to the real page.
-                       // Also copy their class attributes.
-                       for ( i = 0; i < copySelectors.length; i++ ) {
-                               $from = $previewDataHolder.find( copySelectors[i] );
-
-                               if ( copySelectors[i] === '#wikiPreview' ) {
-                                       $next = $wikiPreview.next();
-                                       // If there is no next node, use parent instead.
-                                       // Only query parent if needed, false otherwise.
-                                       $parent = !$next.length && $wikiPreview.parent();
-
-                                       $wikiPreview
-                                               .detach()
-                                               .empty()
-                                               .append( $from.contents() )
-                                               .attr( 'class', $from.attr( 'class' ) );
-
-                                       mw.hook( 'wikipage.content' ).fire( $wikiPreview );
-
-                                       // Reattach
-                                       if ( $parent ) {
-                                               $parent.append( $wikiPreview );
-                                       } else {
-                                               $next.before( $wikiPreview );
-                                       }
-
-                               } else {
-                                       $( copySelectors[i] )
-                                               .empty()
-                                               .append( $from.contents() )
-                                               .attr( 'class', $from.attr( 'class' ) );
-                               }
-                       }
-
-                       // Deprecated: Use mw.hook instead
-                       $( mw ).trigger( 'LivePreviewDone', [copySelectors] );
-
-                       $spinner.remove();
-                       $copyElements.animate( {
-                               opacity: 1
-                       }, 'fast' );
-               } );
-       }
-
-       $( function () {
-               // Do not enable on user .js/.css pages, as there's no sane way of "previewing"
-               // the scripts or styles without reloading the page.
-               if ( $( '#mw-userjsyoucanpreview' ).length || $( '#mw-usercssyoucanpreview' ).length ) {
-                       return;
-               }
-
-               // The following elements can change in a preview but are not output
-               // by the server when they're empty until the preview response.
-               // TODO: Make the server output these always (in a hidden state), so we don't
-               // have to fish and (hopefully) put them in the right place (since skins
-               // can change where they are output).
-
-               if ( !document.getElementById( 'p-lang' ) && document.getElementById( 'p-tb' ) ) {
-                       $( '#p-tb' ).after(
-                               $( '<div>' ).attr( 'id', 'p-lang' )
-                       );
-               }
-
-               if ( !$( '.mw-summary-preview' ).length ) {
-                       $( '.editCheckboxes' ).before(
-                               $( '<div>' ).addClass( 'mw-summary-preview' )
-                       );
-               }
-
-               if ( !document.getElementById( 'wikiDiff' ) && document.getElementById( 'wikiPreview' ) ) {
-                       $( '#wikiPreview' ).after(
-                               $( '<div>' ).attr( 'id', 'wikiDiff' )
-                       );
-               }
-
-               // This should be moved down to '#editform', but is kept on the body for now
-               // because the LiquidThreads extension is re-using this module with only half
-               // the EditPage (doesn't include #editform presumably, bug 55463).
-               $( document.body ).on( 'click', '#wpPreview, #wpDiff', doLivePreview );
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.action/mediawiki.action.edit.styles.css b/resources/mediawiki.action/mediawiki.action.edit.styles.css
deleted file mode 100644 (file)
index 4a2bab3..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Styles for elements of the editing form.
- */
-
-/* General layout */
-#wpTextbox1 {
-       margin: 0;
-       display: block;
-}
-
-.editOptions {
-       background-color: #F0F0F0;
-       border: 1px solid silver;
-       border-top: none;
-       padding: 1em 1em 1.5em 1em;
-       margin-bottom: 2em;
-}
-
-/* Adjustments to edit form elements */
-.editCheckboxes {
-       margin-bottom: 1em;
-}
-
-.editCheckboxes input:first-child {
-       margin-left: 0;
-}
-
-.cancelLink {
-       margin-left: 0.5em;
-}
-
-#editpage-copywarn {
-       font-size: 0.9em;
-}
-
-#wpSummary {
-       display: block;
-       margin-top: 0;
-       margin-bottom: 0.5em;
-}
-
-.editButtons input:first-child {
-       margin-left: .1em;
-}
diff --git a/resources/mediawiki.action/mediawiki.action.history.diff.css b/resources/mediawiki.action/mediawiki.action.history.diff.css
deleted file mode 100644 (file)
index 31ca107..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-** Diff rendering
-*/
-table.diff {
-       background-color: white;
-       border: none;
-       border-spacing: 4px;
-       margin: 0;
-       width: 100%;
-       /* Ensure that colums are of equal width */
-       table-layout: fixed;
-}
-
-table.diff td {
-       padding: 0.33em 0.5em;
-}
-
-table.diff td.diff-marker {
-       /* Compensate padding for increased font-size */
-       padding: 0.25em;
-}
-
-table.diff col.diff-marker {
-       width: 2%;
-}
-
-table.diff col.diff-content {
-       width: 48%;
-}
-
-table.diff td div {
-       /* Force-wrap very long lines such as URLs or page-widening char strings */
-       word-wrap: break-word;
-}
-
-td.diff-otitle,
-td.diff-ntitle {
-       text-align: center;
-}
-
-td.diff-lineno {
-       font-weight: bold;
-}
-
-td.diff-marker {
-       text-align: right;
-       font-weight: bold;
-       font-size: 1.25em;
-}
-
-td.diff-addedline,
-td.diff-deletedline,
-td.diff-context {
-       font-size: 88%;
-       vertical-align: top;
-       white-space: -moz-pre-wrap;
-       white-space: pre-wrap;
-       border-style: solid;
-       border-width: 1px 1px 1px 4px;
-       border-radius: 0.33em;
-}
-
-td.diff-addedline {
-       border-color: #a3d3ff;
-}
-
-td.diff-deletedline {
-       border-color: #ffe49c;
-}
-
-td.diff-context {
-       background: #f9f9f9;
-       border-color: #e6e6e6;
-       color: #333333;
-}
-
-.diffchange {
-       font-weight: bold;
-       text-decoration: none;
-}
-
-td.diff-addedline .diffchange,
-td.diff-deletedline .diffchange {
-       border-radius: 0.33em;
-       padding: 0.25em 0;
-}
-
-td.diff-addedline .diffchange {
-       background: #d8ecff;
-}
-
-td.diff-deletedline .diffchange {
-       background: #feeec8;
-}
diff --git a/resources/mediawiki.action/mediawiki.action.history.js b/resources/mediawiki.action/mediawiki.action.history.js
deleted file mode 100644 (file)
index 2a02d87..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/**
- * JavaScript for History action
- */
-jQuery( function ( $ ) {
-       var     $historyCompareForm = $( '#mw-history-compare' ),
-               $historySubmitter,
-               $lis = $( '#pagehistory > li' );
-
-       /**
-        * @context {Element} input
-        * @param e {jQuery.Event}
-        */
-       function updateDiffRadios() {
-               var diffLi = false, // the li where the diff radio is checked
-                       oldLi = false; // the li where the oldid radio is checked
-
-               if ( !$lis.length ) {
-                       return true;
-               }
-
-               $lis
-               .removeClass( 'selected' )
-               .each( function () {
-                       var     $li = $( this ),
-                               $inputs = $li.find( 'input[type="radio"]' ),
-                               $oldidRadio = $inputs.filter( '[name="oldid"]' ).eq( 0 ),
-                               $diffRadio = $inputs.filter( '[name="diff"]' ).eq( 0 );
-
-                       if ( !$oldidRadio.length || !$diffRadio.length ) {
-                               return true;
-                       }
-
-                       if ( $oldidRadio.prop( 'checked' ) ) {
-                               oldLi = true;
-                               $li.addClass( 'selected' );
-                               $oldidRadio.css( 'visibility', 'visible' );
-                               $diffRadio.css( 'visibility', 'hidden' );
-
-                       } else if ( $diffRadio.prop( 'checked' ) ) {
-                               diffLi = true;
-                               $li.addClass( 'selected' );
-                               $oldidRadio.css( 'visibility', 'hidden' );
-                               $diffRadio.css( 'visibility', 'visible' );
-
-                       // This list item has neither checked
-                       } else {
-                               // We're below the selected radios
-                               if ( diffLi && oldLi ) {
-                                       $oldidRadio.css( 'visibility', 'visible' );
-                                       $diffRadio.css( 'visibility', 'hidden' );
-
-                               // We're between the selected radios
-                               } else if ( diffLi ) {
-                                       $diffRadio.css( 'visibility', 'visible' );
-                                       $oldidRadio.css( 'visibility', 'visible' );
-
-                               // We're above the selected radios
-                               } else {
-                                       $diffRadio.css( 'visibility', 'visible' );
-                                       $oldidRadio.css( 'visibility', 'hidden' );
-                               }
-                       }
-               } );
-
-               return true;
-       }
-
-       $lis.find( 'input[name="diff"], input[name="oldid"]' ).click( updateDiffRadios );
-
-       // Set initial state
-       updateDiffRadios();
-
-       // Prettify url output for HistoryAction submissions,
-       // to cover up action=historysubmit construction.
-
-       // Ideally we'd use e.target instead of $historySubmitter, but e.target points
-       // to the form element for submit actions, so.
-       $historyCompareForm.find( '.historysubmit' ).click( function () {
-               $historySubmitter = $( this );
-       } );
-
-       // On submit we clone the form element, remove unneeded fields in the clone
-       // that pollute the query parameter with stuff from the other "use case",
-       // and then submit the clone.
-       // Without the cloning we'd be changing the real form, which is slower, could make
-       // the page look broken for a second in slow browsers and might show the form broken
-       // again when coming back from a "next" page.
-       $historyCompareForm.submit( function ( e ) {
-               var     $copyForm, $copyRadios, $copyAction;
-
-               if ( $historySubmitter ) {
-                       $copyForm = $historyCompareForm.clone();
-                       $copyRadios = $copyForm.find( '#pagehistory > li' ).find( 'input[name="diff"], input[name="oldid"]' );
-                       $copyAction = $copyForm.find( '> [name="action"]' );
-
-                       // Remove action=historysubmit and ids[..]=..
-                       if ( $historySubmitter.hasClass( 'mw-history-compareselectedversions-button' ) ) {
-                               $copyAction.remove();
-                               $copyForm.find( 'input[name^="ids["]:checked' ).prop( 'checked', false );
-
-                       // Remove diff=&oldid=, change action=historysubmit to revisiondelete, remove revisiondelete
-                       } else if ( $historySubmitter.hasClass( 'mw-history-revisiondelete-button' ) ) {
-                               $copyRadios.remove();
-                               $copyAction.val( $historySubmitter.attr( 'name' ) );
-                               $copyForm.find( ':submit' ).remove();
-                       }
-
-                       // IE7 doesn't do submission from an off-DOM clone, so insert hidden into document first
-                       // Also remove potentially conflicting id attributes that we don't need anyway
-                       $copyForm
-                               .css( 'display', 'none' )
-                               .find( '[id]' )
-                                       .removeAttr( 'id' )
-                               .end()
-                               .insertAfter( $historyCompareForm )
-                               .submit();
-
-                       e.preventDefault();
-                       return false; // Because the submit is special, return false as well.
-               }
-
-               // Continue natural browser handling other wise
-               return true;
-       } );
-} );
diff --git a/resources/mediawiki.action/mediawiki.action.view.dblClickEdit.js b/resources/mediawiki.action/mediawiki.action.view.dblClickEdit.js
deleted file mode 100644 (file)
index 727a525..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * This module enables double-click-to-edit functionality.
- */
-( function ( mw, $ ) {
-       $( function () {
-               mw.util.$content.dblclick( function ( e ) {
-                       e.preventDefault();
-                       // Trigger native HTMLElement click instead of opening URL (bug 43052)
-                       $( '#ca-edit a' ).get( 0 ).click();
-               } );
-       } );
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.action/mediawiki.action.view.metadata.js b/resources/mediawiki.action/mediawiki.action.view.metadata.js
deleted file mode 100644 (file)
index 21f40c5..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Exif metadata display for MediaWiki file uploads
- *
- * Add an expand/collapse link and collapse by default if set to
- * (with JS disabled, user will see all items)
- *
- * See also:
- * - ImagePage.php#makeMetadataTable (creates the HTML)
- * - skins/common/shared.css (hides tr.collapsable inside table.collapsed)
- */
-( function ( mw, $ ) {
-       $( function () {
-               var $row, $col, $link,
-                       showText = mw.msg( 'metadata-expand' ),
-                       hideText = mw.msg( 'metadata-collapse' ),
-                       $table = $( '#mw_metadata' ),
-                       $tbody = $table.find( 'tbody' );
-
-               if ( !$tbody.length || !$tbody.find( '.collapsable' ).length ) {
-                       return;
-               }
-
-               $row = $( '<tr class="mw-metadata-show-hide-extended"></tr>' );
-               $col = $( '<td colspan="2"></td>' );
-
-               $link = $( '<a>', {
-                       text: showText,
-                       href: '#'
-               } ).click( function () {
-                       if ( $table.hasClass( 'collapsed' ) ) {
-                               $( this ).text( hideText );
-                       } else {
-                               $( this ).text( showText );
-                       }
-                       $table.toggleClass( 'expanded collapsed' );
-                       return false;
-               } );
-
-               $col.append( $link );
-               $row.append( $col );
-               $tbody.append( $row );
-
-               // And collapse!
-               $table.addClass( 'collapsed' );
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.action/mediawiki.action.view.postEdit.css b/resources/mediawiki.action/mediawiki.action.view.postEdit.css
deleted file mode 100644 (file)
index be88337..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-.postedit-container {
-       margin: 0 auto;
-       position: fixed;
-       top: 0;
-       height: 0;
-       left: 50%;
-       z-index: 1000;
-       font-size: 13px;
-}
-
-.postedit-container:hover {
-       cursor: pointer;
-}
-
-.postedit {
-       position: relative;
-       top: 0.6em;
-       left: -50%;
-       padding: .6em 3.6em .6em 1.1em;
-       line-height: 1.5625em;
-       color: #626465;
-       background-color: #f4f4f4;
-       border: 1px solid #dcd9d9;
-       text-shadow: 0 0.0625em 0 rgba(255, 255, 255, 0.5);
-       border-radius: 5px;
-       -webkit-box-shadow: 0 2px 5px 0 #ccc;
-       box-shadow: 0 2px 5px 0 #ccc;
-       -webkit-transition: all 0.25s ease-in-out;
-       -moz-transition: all 0.25s ease-in-out;
-       -ms-transition: all 0.25s ease-in-out;
-       -o-transition: all 0.25s ease-in-out;
-       transition: all 0.25s ease-in-out;
-}
-
-.skin-monobook .postedit {
-       top: 6em !important;
-}
-
-.postedit-faded {
-       opacity: 0;
-}
-
-.postedit-icon {
-       padding-left: 41px; /* 25 + 8 + 8 */
-       /* like min-height, but old IE compatible and keeps text vertically aligned, too */
-       line-height: 25px;
-       background-repeat: no-repeat;
-       background-position: 8px 50%;
-}
-
-.postedit-icon-checkmark {
-       /* @embed */
-       background-image: url(images/green-checkmark.png);
-       background-position: left;
-}
-
-.postedit-close {
-       position: absolute;
-       padding: 0 .8em;
-       right: 0;
-       top: 0;
-       font-size: 1.25em;
-       font-weight: bold;
-       line-height: 2.3em;
-       color: black;
-       text-shadow: 0 0.0625em 0 white;
-       text-decoration: none;
-       opacity: 0.2;
-       filter: alpha(opacity=20);
-}
-
-.postedit-close:hover {
-       color: black;
-       text-decoration: none;
-       opacity: 0.4;
-       filter: alpha(opacity=40);
-}
diff --git a/resources/mediawiki.action/mediawiki.action.view.postEdit.js b/resources/mediawiki.action/mediawiki.action.view.postEdit.js
deleted file mode 100644 (file)
index 6e4df9f..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-( function ( mw, $ ) {
-       'use strict';
-
-       /**
-        * @event postEdit
-        * @member mw.hook
-        * @param {Object} [data] Optional data
-        * @param {string|jQuery|Array} [data.message] Message that listeners
-        *  should use when displaying notifications. String for plain text,
-        *  use array or jQuery object to pass actual nodes.
-        * @param {string|mw.user} [data.user=mw.user] User that made the edit.
-        */
-
-       /**
-        * After the listener for #postEdit removes the notification.
-        *
-        * @event postEdit_afterRemoval
-        * @member mw.hook
-        */
-
-       var config = mw.config.get( [ 'wgAction', 'wgCookiePrefix', 'wgCurRevisionId' ] ),
-               // This should match EditPage::POST_EDIT_COOKIE_KEY_PREFIX:
-               cookieKey = config.wgCookiePrefix + 'PostEditRevision' + config.wgCurRevisionId,
-               $div, id;
-
-       function showConfirmation( data ) {
-               data = data || {};
-               if ( data.message === undefined ) {
-                       data.message = $.parseHTML( mw.message( 'postedit-confirmation', data.user || mw.user ).escaped() );
-               }
-
-               $div = $(
-                       '<div class="postedit-container">' +
-                               '<div class="postedit">' +
-                                       '<div class="postedit-icon postedit-icon-checkmark postedit-content"></div>' +
-                                       '<a href="#" class="postedit-close">&times;</a>' +
-                               '</div>' +
-                       '</div>'
-               );
-
-               if ( typeof data.message === 'string' ) {
-                       $div.find( '.postedit-content' ).text( data.message );
-               } else if ( typeof data.message === 'object' ) {
-                       $div.find( '.postedit-content' ).append( data.message );
-               }
-
-               $div
-                       .click( fadeOutConfirmation )
-                       .prependTo( 'body' );
-
-               id = setTimeout( fadeOutConfirmation, 3000 );
-       }
-
-       function fadeOutConfirmation() {
-               clearTimeout( id );
-               $div.find( '.postedit' ).addClass( 'postedit postedit-faded' );
-               setTimeout( removeConfirmation, 500 );
-
-               return false;
-       }
-
-       function removeConfirmation() {
-               $div.remove();
-               mw.hook( 'postEdit.afterRemoval' ).fire();
-       }
-
-       mw.hook( 'postEdit' ).add( showConfirmation );
-
-       if ( config.wgAction === 'view' && $.cookie( cookieKey ) === '1' ) {
-               $.cookie( cookieKey, null, { path: '/' } );
-               mw.config.set( 'wgPostEdit', true );
-
-               mw.hook( 'postEdit' ).fire();
-       }
-
-} ( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.action/mediawiki.action.view.redirectToFragment.js b/resources/mediawiki.action/mediawiki.action.view.redirectToFragment.js
deleted file mode 100644 (file)
index 1e2d624..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * JavaScript to scroll the page to an id, when a redirect with fragment is viewed.
- */
-( function ( mw, $ ) {
-       var profile = $.client.profile(),
-               fragment = mw.config.get( 'wgRedirectToFragment' );
-
-       if ( fragment === null ) {
-               // nothing to do
-               return;
-       }
-
-       if ( profile.layout === 'webkit' && profile.layoutVersion < 420 ) {
-               // Released Safari w/ WebKit 418.9.1 messes up horribly
-               // Nightlies of 420+ are ok
-               return;
-       }
-       if ( !window.location.hash ) {
-               window.location.hash = fragment;
-
-               // Mozilla needs to wait until after load, otherwise the window doesn't
-               // scroll.  See <https://bugzilla.mozilla.org/show_bug.cgi?id=516293>.
-               // There's no obvious way to detect this programmatically, so we use
-               // version-testing.  If Firefox fixes the bug, they'll jump twice, but
-               // better twice than not at all, so make the fix hit future versions as
-               // well.
-               if ( profile.layout === 'gecko' ) {
-                       $( function () {
-                               if ( window.location.hash === fragment ) {
-                                       window.location.hash = fragment;
-                               }
-                       } );
-               }
-       }
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.action/mediawiki.action.view.rightClickEdit.js b/resources/mediawiki.action/mediawiki.action.view.rightClickEdit.js
deleted file mode 100644 (file)
index 93befe3..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * JavaScript to enable right click edit functionality.
- * When the user right-clicks in a heading, it will open the
- * edit screen.
- */
-jQuery( function ( $ ) {
-       // Select all h1-h6 elements that contain editsection links
-       // Don't use the ":has:(.mw-editsection a)" selector because it performs very bad.
-       // http://jsperf.com/jq-1-7-2-vs-jq-1-8-1-performance-of-mw-has/2
-       $( document ).on( 'contextmenu', 'h1, h2, h3, h4, h5, h6', function ( e ) {
-               var $edit = $( this ).find( '.mw-editsection a' );
-               if ( !$edit.length ) {
-                       return;
-               }
-
-               // Headings can contain rich text.
-               // Make sure to not block contextmenu events on (other) anchor tags
-               // inside the heading (e.g. to do things like copy URL, open in new tab, ..).
-               // e.target can be the heading, but it can also be anything inside the heading.
-               if ( e.target.nodeName.toLowerCase() !== 'a' ) {
-                       // Trigger native HTMLElement click instead of opening URL (bug 43052)
-                       e.preventDefault();
-                       $edit.get( 0 ).click();
-               }
-       } );
-} );
diff --git a/resources/mediawiki.api/mediawiki.api.category.js b/resources/mediawiki.api/mediawiki.api.category.js
deleted file mode 100644 (file)
index a90617d..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/**
- * @class mw.Api.plugin.category
- */
-( function ( mw, $ ) {
-
-       var msg = 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.';
-       $.extend( mw.Api.prototype, {
-               /**
-                * Determine if a category exists.
-                *
-                * @param {mw.Title|string} title
-                * @param {Function} [ok] Success callback (deprecated)
-                * @param {Function} [err] Error callback (deprecated)
-                * @return {jQuery.Promise}
-                * @return {Function} return.done
-                * @return {boolean} return.done.isCategory Whether the category exists.
-                */
-               isCategory: function ( title, ok, err ) {
-                       var apiPromise = this.get( {
-                               prop: 'categoryinfo',
-                               titles: String( title )
-                       } );
-
-                       if ( ok || err ) {
-                               mw.track( 'mw.deprecate', 'api.cbParam' );
-                               mw.log.warn( msg );
-                       }
-
-                       return apiPromise
-                               .then( function ( data ) {
-                                       var exists = false;
-                                       if ( data.query && data.query.pages ) {
-                                               $.each( data.query.pages, function ( id, page ) {
-                                                       if ( page.categoryinfo ) {
-                                                               exists = true;
-                                                       }
-                                               } );
-                                       }
-                                       return exists;
-                               } )
-                               .done( ok )
-                               .fail( err )
-                               .promise( { abort: apiPromise.abort } );
-               },
-
-               /**
-                * Get a list of categories that match a certain prefix.
-                *
-                * E.g. given "Foo", return "Food", "Foolish people", "Foosball tables"...
-                *
-                * @param {string} prefix Prefix to match.
-                * @param {Function} [ok] Success callback (deprecated)
-                * @param {Function} [err] Error callback (deprecated)
-                * @return {jQuery.Promise}
-                * @return {Function} return.done
-                * @return {string[]} return.done.categories Matched categories
-                */
-               getCategoriesByPrefix: function ( prefix, ok, err ) {
-                       // Fetch with allpages to only get categories that have a corresponding description page.
-                       var apiPromise = this.get( {
-                               list: 'allpages',
-                               apprefix: prefix,
-                               apnamespace: mw.config.get( 'wgNamespaceIds' ).category
-                       } );
-
-                       if ( ok || err ) {
-                               mw.track( 'mw.deprecate', 'api.cbParam' );
-                               mw.log.warn( msg );
-                       }
-
-                       return apiPromise
-                               .then( function ( data ) {
-                                       var texts = [];
-                                       if ( data.query && data.query.allpages ) {
-                                               $.each( data.query.allpages, function ( i, category ) {
-                                                       texts.push( new mw.Title( category.title ).getNameText() );
-                                               } );
-                                       }
-                                       return texts;
-                               } )
-                               .done( ok )
-                               .fail( err )
-                               .promise( { abort: apiPromise.abort } );
-               },
-
-               /**
-                * Get the categories that a particular page on the wiki belongs to.
-                *
-                * @param {mw.Title|string} title
-                * @param {Function} [ok] Success callback (deprecated)
-                * @param {Function} [err] Error callback (deprecated)
-                * @param {boolean} [async=true] Asynchronousness (deprecated)
-                * @return {jQuery.Promise}
-                * @return {Function} return.done
-                * @return {boolean|mw.Title[]} return.done.categories List of category titles or false
-                *  if title was not found.
-                */
-               getCategories: function ( title, ok, err, async ) {
-                       var apiPromise = this.get( {
-                               prop: 'categories',
-                               titles: String( title )
-                       }, {
-                               async: async === undefined ? true : async
-                       } );
-
-                       if ( ok || err ) {
-                               mw.track( 'mw.deprecate', 'api.cbParam' );
-                               mw.log.warn( msg );
-                       }
-                       if ( async !== undefined ) {
-                               mw.track( 'mw.deprecate', 'api.async' );
-                               mw.log.warn(
-                                       'Use of mediawiki.api async=false param is deprecated. ' +
-                                       'The sychronous mode will be removed in the future.'
-                               );
-                       }
-
-                       return apiPromise
-                               .then( function ( data ) {
-                                       var titles = false;
-                                       if ( data.query && data.query.pages ) {
-                                               $.each( data.query.pages, function ( id, page ) {
-                                                       if ( page.categories ) {
-                                                               if ( titles === false ) {
-                                                                       titles = [];
-                                                               }
-                                                               $.each( page.categories, function ( i, cat ) {
-                                                                       titles.push( new mw.Title( cat.title ) );
-                                                               } );
-                                                       }
-                                               } );
-                                       }
-                                       return titles;
-                               } )
-                               .done( ok )
-                               .fail( err )
-                               .promise( { abort: apiPromise.abort } );
-               }
-       } );
-
-       /**
-        * @class mw.Api
-        * @mixins mw.Api.plugin.category
-        */
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.api/mediawiki.api.edit.js b/resources/mediawiki.api/mediawiki.api.edit.js
deleted file mode 100644 (file)
index edfb34a..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * @class mw.Api.plugin.edit
- */
-( function ( mw, $ ) {
-
-       var msg = 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.';
-       $.extend( mw.Api.prototype, {
-
-               /**
-                * Post to API with edit token. If we have no token, get one and try to post.
-                * If we have a cached token try using that, and if it fails, blank out the
-                * cached token and start over.
-                *
-                * @param {Object} params API parameters
-                * @param {Function} [ok] Success callback (deprecated)
-                * @param {Function} [err] Error callback (deprecated)
-                * @return {jQuery.Promise} See #post
-                */
-               postWithEditToken: function ( params, ok, err ) {
-                       if ( ok || err ) {
-                               mw.track( 'mw.deprecate', 'api.cbParam' );
-                               mw.log.warn( msg );
-                       }
-                       return this.postWithToken( 'edit', params ).done( ok ).fail( err );
-               },
-
-               /**
-                * Api helper to grab an edit token.
-                *
-                * @param {Function} [ok] Success callback (deprecated)
-                * @param {Function} [err] Error callback (deprecated)
-                * @return {jQuery.Promise}
-                * @return {Function} return.done
-                * @return {string} return.done.token Received token.
-                */
-               getEditToken: function ( ok, err ) {
-                       if ( ok || err ) {
-                               mw.track( 'mw.deprecate', 'api.cbParam' );
-                               mw.log.warn( msg );
-                       }
-                       return this.getToken( 'edit' ).done( ok ).fail( err );
-               },
-
-               /**
-                * Create a new section of the page.
-                * @see #postWithEditToken
-                * @param {mw.Title|String} title Target page
-                * @param {string} header
-                * @param {string} message wikitext message
-                * @param {Function} [ok] Success handler (deprecated)
-                * @param {Function} [err] Error handler (deprecated)
-                * @return {jQuery.Promise}
-                */
-               newSection: function ( title, header, message, ok, err ) {
-                       if ( ok || err ) {
-                               mw.track( 'mw.deprecate', 'api.cbParam' );
-                               mw.log.warn( msg );
-                       }
-                       return this.postWithEditToken( {
-                               action: 'edit',
-                               section: 'new',
-                               format: 'json',
-                               title: String( title ),
-                               summary: header,
-                               text: message
-                       } ).done( ok ).fail( err );
-               }
-       } );
-
-       /**
-        * @class mw.Api
-        * @mixins mw.Api.plugin.edit
-        */
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.api/mediawiki.api.js b/resources/mediawiki.api/mediawiki.api.js
deleted file mode 100644 (file)
index 04919d3..0000000
+++ /dev/null
@@ -1,324 +0,0 @@
-( function ( mw, $ ) {
-
-       // We allow people to omit these default parameters from API requests
-       // there is very customizable error handling here, on a per-call basis
-       // wondering, would it be simpler to make it easy to clone the api object,
-       // change error handling, and use that instead?
-       var defaultOptions = {
-
-                       // Query parameters for API requests
-                       parameters: {
-                               action: 'query',
-                               format: 'json'
-                       },
-
-                       // Ajax options for jQuery.ajax()
-                       ajax: {
-                               url: mw.util.wikiScript( 'api' ),
-
-                               timeout: 30 * 1000, // 30 seconds
-
-                               dataType: 'json'
-                       }
-               },
-               tokenCache = {};
-
-       /**
-        * Constructor to create an object to interact with the API of a particular MediaWiki server.
-        * mw.Api objects represent the API of a particular MediaWiki server.
-        *
-        * TODO: Share API objects with exact same config.
-        *
-        *     var api = new mw.Api();
-        *     api.get( {
-        *         action: 'query',
-        *         meta: 'userinfo'
-        *     } ).done ( function ( data ) {
-        *         console.log( data );
-        *     } );
-        *
-        * @class
-        *
-        * @constructor
-        * @param {Object} options See defaultOptions documentation above. Ajax options can also be
-        *  overridden for each individual request to {@link jQuery#ajax} later on.
-        */
-       mw.Api = function ( options ) {
-
-               if ( options === undefined ) {
-                       options = {};
-               }
-
-               // Force a string if we got a mw.Uri object
-               if ( options.ajax && options.ajax.url !== undefined ) {
-                       options.ajax.url = String( options.ajax.url );
-               }
-
-               options.parameters = $.extend( {}, defaultOptions.parameters, options.parameters );
-               options.ajax = $.extend( {}, defaultOptions.ajax, options.ajax );
-
-               this.defaults = options;
-       };
-
-       mw.Api.prototype = {
-
-               /**
-                * Normalize the ajax options for compatibility and/or convenience methods.
-                *
-                * @param {Object} [arg] An object contaning one or more of options.ajax.
-                * @return {Object} Normalized ajax options.
-                */
-               normalizeAjaxOptions: function ( arg ) {
-                       // Arg argument is usually empty
-                       // (before MW 1.20 it was used to pass ok callbacks)
-                       var opts = arg || {};
-                       // Options can also be a success callback handler
-                       if ( typeof arg === 'function' ) {
-                               opts = { ok: arg };
-                       }
-                       return opts;
-               },
-
-               /**
-                * Perform API get request
-                *
-                * @param {Object} parameters
-                * @param {Object|Function} [ajaxOptions]
-                * @return {jQuery.Promise}
-                */
-               get: function ( parameters, ajaxOptions ) {
-                       ajaxOptions = this.normalizeAjaxOptions( ajaxOptions );
-                       ajaxOptions.type = 'GET';
-                       return this.ajax( parameters, ajaxOptions );
-               },
-
-               /**
-                * Perform API post request
-                *
-                * TODO: Post actions for non-local hostnames will need proxy.
-                *
-                * @param {Object} parameters
-                * @param {Object|Function} [ajaxOptions]
-                * @return {jQuery.Promise}
-                */
-               post: function ( parameters, ajaxOptions ) {
-                       ajaxOptions = this.normalizeAjaxOptions( ajaxOptions );
-                       ajaxOptions.type = 'POST';
-                       return this.ajax( parameters, ajaxOptions );
-               },
-
-               /**
-                * Perform the API call.
-                *
-                * @param {Object} parameters
-                * @param {Object} [ajaxOptions]
-                * @return {jQuery.Promise} Done: API response data and the jqXHR object.
-                *  Fail: Error code
-                */
-               ajax: function ( parameters, ajaxOptions ) {
-                       var token,
-                               apiDeferred = $.Deferred(),
-                               msg = 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.',
-                               xhr;
-
-                       parameters = $.extend( {}, this.defaults.parameters, parameters );
-                       ajaxOptions = $.extend( {}, this.defaults.ajax, ajaxOptions );
-
-                       // Ensure that token parameter is last (per [[mw:API:Edit#Token]]).
-                       if ( parameters.token ) {
-                               token = parameters.token;
-                               delete parameters.token;
-                       }
-                       // Some deployed MediaWiki >= 1.17 forbid periods in URLs, due to an IE XSS bug
-                       // So let's escape them here. See bug #28235
-                       // This works because jQuery accepts data as a query string or as an Object
-                       ajaxOptions.data = $.param( parameters ).replace( /\./g, '%2E' );
-
-                       // If we extracted a token parameter, add it back in.
-                       if ( token ) {
-                               ajaxOptions.data += '&token=' + encodeURIComponent( token );
-                       }
-
-                       // Backwards compatibility: Before MediaWiki 1.20,
-                       // callbacks were done with the 'ok' and 'err' property in ajaxOptions.
-                       if ( ajaxOptions.ok ) {
-                               mw.track( 'mw.deprecate', 'api.cbParam' );
-                               mw.log.warn( msg );
-                               apiDeferred.done( ajaxOptions.ok );
-                               delete ajaxOptions.ok;
-                       }
-                       if ( ajaxOptions.err ) {
-                               mw.track( 'mw.deprecate', 'api.cbParam' );
-                               mw.log.warn( msg );
-                               apiDeferred.fail( ajaxOptions.err );
-                               delete ajaxOptions.err;
-                       }
-
-                       // Make the AJAX request
-                       xhr = $.ajax( ajaxOptions )
-                               // If AJAX fails, reject API call with error code 'http'
-                               // and details in second argument.
-                               .fail( function ( xhr, textStatus, exception ) {
-                                       apiDeferred.reject( 'http', {
-                                               xhr: xhr,
-                                               textStatus: textStatus,
-                                               exception: exception
-                                       } );
-                               } )
-                               // AJAX success just means "200 OK" response, also check API error codes
-                               .done( function ( result, textStatus, jqXHR ) {
-                                       if ( result === undefined || result === null || result === '' ) {
-                                               apiDeferred.reject( 'ok-but-empty',
-                                                       'OK response but empty result (check HTTP headers?)'
-                                               );
-                                       } else if ( result.error ) {
-                                               var code = result.error.code === undefined ? 'unknown' : result.error.code;
-                                               apiDeferred.reject( code, result );
-                                       } else {
-                                               apiDeferred.resolve( result, jqXHR );
-                                       }
-                               } );
-
-                       // Return the Promise
-                       return apiDeferred.promise( { abort: xhr.abort } ).fail( function ( code, details ) {
-                               mw.log( 'mw.Api error: ', code, details );
-                       } );
-               },
-
-               /**
-                * Post to API with specified type of token. If we have no token, get one and try to post.
-                * If we have a cached token try using that, and if it fails, blank out the
-                * cached token and start over. For example to change an user option you could do:
-                *
-                *     new mw.Api().postWithToken( 'options', {
-                *         action: 'options',
-                *         optionname: 'gender',
-                *         optionvalue: 'female'
-                *     } );
-                *
-                * @param {string} tokenType The name of the token, like options or edit.
-                * @param {Object} params API parameters
-                * @return {jQuery.Promise} See #post
-                * @since 1.22
-                */
-               postWithToken: function ( tokenType, params ) {
-                       var api = this, hasOwn = tokenCache.hasOwnProperty;
-                       if ( hasOwn.call( tokenCache, tokenType ) && tokenCache[tokenType] !== undefined ) {
-                               params.token = tokenCache[tokenType];
-                               return api.post( params ).then(
-                                       null,
-                                       function ( code ) {
-                                               if ( code === 'badtoken' ) {
-                                                       // force a new token, clear any old one
-                                                       tokenCache[tokenType] = params.token = undefined;
-                                                       return api.post( params );
-                                               }
-                                               // Pass the promise forward, so the caller gets error codes
-                                               return this;
-                                       }
-                               );
-                       } else {
-                               return api.getToken( tokenType ).then( function ( token ) {
-                                       tokenCache[tokenType] = params.token = token;
-                                       return api.post( params );
-                               } );
-                       }
-               },
-
-               /**
-                * Api helper to grab any token.
-                *
-                * @param {string} type Token type.
-                * @return {jQuery.Promise}
-                * @return {Function} return.done
-                * @return {string} return.done.token Received token.
-                * @since 1.22
-                */
-               getToken: function ( type ) {
-                       var apiPromise,
-                               d = $.Deferred();
-
-                       apiPromise = this.get( {
-                                       action: 'tokens',
-                                       type: type
-                               } )
-                               .done( function ( data ) {
-                                       // If token type is not available for this user,
-                                       // key '...token' is missing or can contain Boolean false
-                                       if ( data.tokens && data.tokens[type + 'token'] ) {
-                                               d.resolve( data.tokens[type + 'token'] );
-                                       } else {
-                                               d.reject( 'token-missing', data );
-                                       }
-                               } )
-                               .fail( d.reject );
-
-                       return d.promise( { abort: apiPromise.abort } );
-               }
-       };
-
-       /**
-        * @static
-        * @property {Array}
-        * List of errors we might receive from the API.
-        * For now, this just documents our expectation that there should be similar messages
-        * available.
-        */
-       mw.Api.errors = [
-               // occurs when POST aborted
-               // jQuery 1.4 can't distinguish abort or lost connection from 200 OK + empty result
-               'ok-but-empty',
-
-               // timeout
-               'timeout',
-
-               // really a warning, but we treat it like an error
-               'duplicate',
-               'duplicate-archive',
-
-               // upload succeeded, but no image info.
-               // this is probably impossible, but might as well check for it
-               'noimageinfo',
-               // remote errors, defined in API
-               'uploaddisabled',
-               'nomodule',
-               'mustbeposted',
-               'badaccess-groups',
-               'stashfailed',
-               'missingresult',
-               'missingparam',
-               'invalid-file-key',
-               'copyuploaddisabled',
-               'mustbeloggedin',
-               'empty-file',
-               'file-too-large',
-               'filetype-missing',
-               'filetype-banned',
-               'filetype-banned-type',
-               'filename-tooshort',
-               'illegal-filename',
-               'verification-error',
-               'hookaborted',
-               'unknown-error',
-               'internal-error',
-               'overwrite',
-               'badtoken',
-               'fetchfileerror',
-               'fileexists-shared-forbidden',
-               'invalidtitle',
-               'notloggedin'
-       ];
-
-       /**
-        * @static
-        * @property {Array}
-        * List of warnings we might receive from the API.
-        * For now, this just documents our expectation that there should be similar messages
-        * available.
-        */
-       mw.Api.warnings = [
-               'duplicate',
-               'exists'
-       ];
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.api/mediawiki.api.login.js b/resources/mediawiki.api/mediawiki.api.login.js
deleted file mode 100644 (file)
index ccbae06..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Make the two-step login easier.
- * @author Niklas Laxström
- * @class mw.Api.plugin.login
- * @since 1.22
- */
-( function ( mw, $ ) {
-       'use strict';
-
-       $.extend( mw.Api.prototype, {
-               /**
-                * @param {string} username
-                * @param {string} password
-                * @return {jQuery.Promise} See mw.Api#post
-                */
-               login: function ( username, password ) {
-                       var params, request,
-                               deferred = $.Deferred(),
-                               api = this;
-
-                       params = {
-                               action: 'login',
-                               lgname: username,
-                               lgpassword: password
-                       };
-
-                       request = api.post( params );
-                       request.fail( deferred.reject );
-                       request.done( function ( data ) {
-                               params.lgtoken = data.login.token;
-                               api.post( params )
-                                       .fail( deferred.reject )
-                                       .done( function ( data ) {
-                                               var code;
-                                               if ( data.login && data.login.result === 'Success' ) {
-                                                       deferred.resolve( data );
-                                               } else {
-                                                       // Set proper error code whenever possible
-                                                       code = data.error && data.error.code || 'unknown';
-                                                       deferred.reject( code, data );
-                                               }
-                                       } );
-                       } );
-
-                       return deferred.promise( { abort: request.abort } );
-               }
-       } );
-
-       /**
-        * @class mw.Api
-        * @mixins mw.Api.plugin.login
-        */
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.api/mediawiki.api.parse.js b/resources/mediawiki.api/mediawiki.api.parse.js
deleted file mode 100644 (file)
index b1f1d2b..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * @class mw.Api.plugin.parse
- */
-( function ( mw, $ ) {
-
-       $.extend( mw.Api.prototype, {
-               /**
-                * Convenience method for 'action=parse'.
-                *
-                * @param {string} wikitext
-                * @param {Function} [ok] Success callback (deprecated)
-                * @param {Function} [err] Error callback (deprecated)
-                * @return {jQuery.Promise}
-                * @return {Function} return.done
-                * @return {string} return.done.data Parsed HTML of `wikitext`.
-                */
-               parse: function ( wikitext, ok, err ) {
-                       var apiPromise = this.get( {
-                               action: 'parse',
-                               contentmodel: 'wikitext',
-                               text: wikitext
-                       } );
-
-                       // Backwards compatibility (< MW 1.20)
-                       if ( ok || err ) {
-                               mw.track( 'mw.deprecate', 'api.cbParam' );
-                               mw.log.warn( 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.' );
-                       }
-
-                       return apiPromise
-                               .then( function ( data ) {
-                                       return data.parse.text['*'];
-                               } )
-                               .done( ok )
-                               .fail( err )
-                               .promise( { abort: apiPromise.abort } );
-               }
-       } );
-
-       /**
-        * @class mw.Api
-        * @mixins mw.Api.plugin.parse
-        */
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.api/mediawiki.api.watch.js b/resources/mediawiki.api/mediawiki.api.watch.js
deleted file mode 100644 (file)
index aa33d86..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * @class mw.Api.plugin.watch
- * @since 1.19
- */
-( function ( mw, $ ) {
-
-       /**
-        * @private
-        * @static
-        * @context mw.Api
-        *
-        * @param {string|mw.Title|string[]|mw.Title[]} pages Full page name or instance of mw.Title, or an
-        *  array thereof. If an array is passed, the return value passed to the promise will also be an
-        *  array of appropriate objects.
-        * @param {Function} [ok] Success callback (deprecated)
-        * @param {Function} [err] Error callback (deprecated)
-        * @return {jQuery.Promise}
-        * @return {Function} return.done
-        * @return {Object|Object[]} return.done.watch Object or list of objects (depends on the `pages`
-        *  parameter)
-        * @return {string} return.done.watch.title Full pagename
-        * @return {boolean} return.done.watch.watched Whether the page is now watched or unwatched
-        * @return {string} return.done.watch.message Parsed HTML of the confirmational interface message
-        */
-       function doWatchInternal( pages, ok, err, addParams ) {
-               // XXX: Parameter addParams is undocumented because we inherit this
-               // documentation in the public method...
-               var apiPromise = this.post(
-                       $.extend(
-                               {
-                                       action: 'watch',
-                                       titles: $.isArray( pages ) ? pages.join( '|' ) : String( pages ),
-                                       token: mw.user.tokens.get( 'watchToken' ),
-                                       uselang: mw.config.get( 'wgUserLanguage' )
-                               },
-                               addParams
-                       )
-               );
-
-               // Backwards compatibility (< MW 1.20)
-               if ( ok || err ) {
-                       mw.track( 'mw.deprecate', 'api.cbParam' );
-                       mw.log.warn( 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.' );
-               }
-
-               return apiPromise
-                       .then( function ( data ) {
-                               // If a single page was given (not an array) respond with a single item as well.
-                               return $.isArray( pages ) ? data.watch : data.watch[0];
-                       } )
-                       .done( ok )
-                       .fail( err )
-                       .promise( { abort: apiPromise.abort } );
-       }
-
-       $.extend( mw.Api.prototype, {
-               /**
-                * Convenience method for `action=watch`.
-                *
-                * @inheritdoc #doWatchInternal
-                */
-               watch: function ( pages, ok, err ) {
-                       return doWatchInternal.call( this, pages, ok, err );
-               },
-               /**
-                * Convenience method for `action=watch&unwatch=1`.
-                *
-                * @inheritdoc #doWatchInternal
-                */
-               unwatch: function ( pages, ok, err ) {
-                       return doWatchInternal.call( this, pages, ok, err, { unwatch: 1 } );
-               }
-       } );
-
-       /**
-        * @class mw.Api
-        * @mixins mw.Api.plugin.watch
-        */
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.language/languages/bs.js b/resources/mediawiki.language/languages/bs.js
deleted file mode 100644 (file)
index b56e4b2..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*!
- * Bosnian (bosanski) language functions
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms = mediaWiki.language.getData( 'bs', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-       switch ( form ) {
-               case 'instrumental': // instrumental
-                       word = 's ' + word;
-                       break;
-               case 'lokativ': // locative
-                       word = 'o ' + word;
-                       break;
-       }
-       return word;
-};
diff --git a/resources/mediawiki.language/languages/dsb.js b/resources/mediawiki.language/languages/dsb.js
deleted file mode 100644 (file)
index 69c36cc..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*!
- * Lower Sorbian (Dolnoserbski) language functions
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms = mediaWiki.language.getData( 'dsb', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-       switch ( form ) {
-               case 'instrumental': // instrumental
-                       word = 'z ' + word;
-                       break;
-               case 'lokatiw': // lokatiw
-                       word = 'wo ' + word;
-                       break;
-       }
-       return word;
-};
diff --git a/resources/mediawiki.language/languages/fi.js b/resources/mediawiki.language/languages/fi.js
deleted file mode 100644 (file)
index 2382aae..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*!
- * Finnish (Suomi) language functions
- * @author Santhosh Thottingal
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms, aou, origWord;
-
-       grammarForms = mediaWiki.language.getData( 'fi', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-
-       // vowel harmony flag
-       aou = word.match( /[aou][^äöy]*$/i );
-       origWord = word;
-       if ( word.match( /wiki$/i ) ) {
-               aou = false;
-       }
-       //append i after final consonant
-       if ( word.match( /[bcdfghjklmnpqrstvwxz]$/i ) ) {
-               word += 'i';
-       }
-
-       switch ( form ) {
-               case 'genitive':
-                       word += 'n';
-                       break;
-               case 'elative':
-                       word += ( aou ? 'sta' : 'stä' );
-                       break;
-               case 'partitive':
-                       word += ( aou ? 'a' : 'ä' );
-                       break;
-               case 'illative':
-                       // Double the last letter and add 'n'
-                       word += word.substr(  word.length - 1 ) + 'n';
-                       break;
-               case 'inessive':
-                       word += ( aou ? 'ssa' : 'ssä' );
-                       break;
-               default:
-                       word = origWord;
-                       break;
-       }
-       return word;
-};
diff --git a/resources/mediawiki.language/languages/ga.js b/resources/mediawiki.language/languages/ga.js
deleted file mode 100644 (file)
index fb4e939..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*!
- * Irish (Gaeilge) language functions
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       /*jshint onecase:true */
-       var grammarForms = mediaWiki.language.getData( 'ga', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-       switch ( form ) {
-               case 'ainmlae':
-                       switch ( word ) {
-                               case 'an Domhnach':
-                                       word = 'Dé Domhnaigh';
-                                       break;
-                               case 'an Luan':
-                                       word = 'Dé Luain';
-                                       break;
-                               case 'an Mháirt':
-                                       word = 'Dé Mháirt';
-                                       break;
-                               case 'an Chéadaoin':
-                                       word = 'Dé Chéadaoin';
-                                       break;
-                               case 'an Déardaoin':
-                                       word = 'Déardaoin';
-                                       break;
-                               case 'an Aoine':
-                                       word = 'Dé hAoine';
-                                       break;
-                               case 'an Satharn':
-                                       word = 'Dé Sathairn';
-                                       break;
-                       }
-       }
-       return word;
-};
diff --git a/resources/mediawiki.language/languages/he.js b/resources/mediawiki.language/languages/he.js
deleted file mode 100644 (file)
index 486e993..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*!
- * Hebrew (עברית) language functions
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms = mediaWiki.language.getData( 'he', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-       switch ( form ) {
-               case 'prefixed':
-               case 'תחילית': // the same word in Hebrew
-                       // Duplicate prefixed "Waw", but only if it's not already double
-                       if ( word.substr( 0, 1 ) === 'ו' && word.substr( 0, 2 ) !== 'וו' ) {
-                               word = 'ו' + word;
-                       }
-
-                       // Remove the "He" if prefixed
-                       if ( word.substr( 0, 1 ) === 'ה' ) {
-                               word = word.substr( 1, word.length );
-                       }
-
-                       // Add a hyphen (maqaf) before numbers and non-Hebrew letters
-                       if (  word.substr( 0, 1 ) < 'א' ||  word.substr( 0, 1 ) > 'ת' ) {
-                               word = '־' + word;
-                       }
-       }
-       return word;
-};
diff --git a/resources/mediawiki.language/languages/hsb.js b/resources/mediawiki.language/languages/hsb.js
deleted file mode 100644 (file)
index 2d6b733..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*!
- * Upper Sorbian (Hornjoserbsce) language functions
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms = mediaWiki.language.getData( 'hsb', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-       switch ( form ) {
-               case 'instrumental': // instrumental
-                       word = 'z ' + word;
-                       break;
-               case 'lokatiw': // lokatiw
-                       word = 'wo ' + word;
-                       break;
-               }
-       return word;
-};
diff --git a/resources/mediawiki.language/languages/hu.js b/resources/mediawiki.language/languages/hu.js
deleted file mode 100644 (file)
index d72a1c0..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*!
- * Hungarian language functions
- * @author Santhosh Thottingal
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms = mediaWiki.language.getData( 'hu', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-       switch ( form ) {
-               case 'rol':
-                       word += 'ról';
-                       break;
-               case 'ba':
-                       word += 'ba';
-                       break;
-               case 'k':
-                       word += 'k';
-                       break;
-       }
-       return word;
-};
diff --git a/resources/mediawiki.language/languages/hy.js b/resources/mediawiki.language/languages/hy.js
deleted file mode 100644 (file)
index ae16f24..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*!
- * Armenian (Հայերեն) language functions
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       /*jshint onecase:true */
-       var grammarForms = mediaWiki.language.getData( 'hy', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-
-       // These rules are not perfect, but they are currently only used for site names so it doesn't
-       // matter if they are wrong sometimes. Just add a special case for your site name if necessary.
-
-       switch ( form ) {
-               case 'genitive': // սեռական հոլով
-                       if ( word.substr( -1 ) === 'ա' ) {
-                               word = word.substr( 0, word.length - 1 ) + 'այի';
-                       } else if ( word.substr( -1 ) === 'ո' ) {
-                               word = word.substr( 0, word.length - 1 ) + 'ոյի';
-                       } else if ( word.substr( -4 ) === 'գիրք' ) {
-                               word = word.substr( 0, word.length - 4 ) + 'գրքի';
-                       } else {
-                               word = word + 'ի';
-                       }
-                       break;
-               }
-       return word;
-};
diff --git a/resources/mediawiki.language/languages/la.js b/resources/mediawiki.language/languages/la.js
deleted file mode 100644 (file)
index 04b7d0a..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*!
- * Latin (lingua Latina) language functions
- * @author Santhosh Thottingal
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms = mediaWiki.language.getData( 'la', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-       switch ( form ) {
-               case 'genitive':
-                       // only a few declensions, and even for those mostly the singular only
-                       word = word.replace( /u[ms]$/i, 'i' ); // 2nd declension singular
-                       word = word.replace( /ommunia$/i, 'ommunium' ); // 3rd declension neuter plural (partly)
-                       word = word.replace( /a$/i, 'ae' ); // 1st declension singular
-                       word = word.replace( /libri$/i,'librorum' ); // 2nd declension plural (partly)
-                       word = word.replace( /nuntii$/i, 'nuntiorum' ); // 2nd declension plural (partly)
-                       word = word.replace( /tio$/i,'tionis' ); // 3rd declension singular (partly)
-                       word = word.replace( /ns$/i, 'ntis' );
-                       word = word.replace( /as$/i, 'atis' );
-                       word = word.replace( /es$/i, 'ei' ); // 5th declension singular
-                       break;
-               case 'accusative':
-                       // only a few declensions, and even for those mostly the singular only
-                       word = word.replace( /u[ms]$/i, 'um' ); // 2nd declension singular
-                       word = word.replace( /ommunia$/i, 'am' ); // 3rd declension neuter plural (partly)
-                       word = word.replace( /a$/i, 'ommunia' ); // 1st declension singular
-                       word = word.replace( /libri$/i,'libros' ); // 2nd declension plural (partly)
-                       word = word.replace( /nuntii$/i, 'nuntios' );// 2nd declension plural (partly)
-                       word = word.replace( /tio$/i,'tionem' ); // 3rd declension singular (partly)
-                       word = word.replace( /ns$/i, 'ntem' );
-                       word = word.replace( /as$/i, 'atem');
-                       word = word.replace( /es$/i, 'em' ); // 5th declension singular
-                       break;
-               case 'ablative':
-                       // only a few declensions, and even for those mostly the singular only
-                       word = word.replace( /u[ms]$/i, 'o' ); // 2nd declension singular
-                       word = word.replace( /ommunia$/i, 'ommunibus' ); // 3rd declension neuter plural (partly)
-                       word = word.replace( /a$/i, 'a' ); // 1st declension singular
-                       word = word.replace( /libri$/i,'libris' ); // 2nd declension plural (partly)
-                       word = word.replace( /nuntii$/i, 'nuntiis' ); // 2nd declension plural (partly)
-                       word = word.replace( /tio$/i,'tione' ); // 3rd declension singular (partly)
-                       word = word.replace( /ns$/i, 'nte' );
-                       word = word.replace( /as$/i, 'ate');
-                       word = word.replace( /es$/i, 'e' ); // 5th declension singular
-                       break;
-       }
-       return word;
-};
diff --git a/resources/mediawiki.language/languages/os.js b/resources/mediawiki.language/languages/os.js
deleted file mode 100644 (file)
index bdf59be..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*!
- * Ossetian (Ирон) language functions
- * @author Santhosh Thottingal
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms = mediaWiki.language.getData( 'os', 'grammarForms' ),
-               // Ending for allative case
-               endAllative = 'мæ',
-               // Variable for 'j' beetwen vowels
-               jot = '',
-               // Variable for "-" for not Ossetic words
-               hyphen = '',
-               // Variable for ending
-               ending = '';
-
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-       // Checking if the $word is in plural form
-       if ( word.match( /тæ$/i ) ) {
-               word = word.substring( 0, word.length - 1 );
-               endAllative = 'æм';
-       }
-       // Works if word is in singular form.
-       // Checking if word ends on one of the vowels: е, ё, и, о, ы, э, ю, я.
-       else if ( word.match( /[аæеёиоыэюя]$/i ) ) {
-               jot = 'й';
-       }
-       // Checking if word ends on 'у'. 'У' can be either consonant 'W' or vowel 'U' in cyrillic Ossetic.
-       // Examples: {{grammar:genitive|аунеу}} = аунеуы, {{grammar:genitive|лæппу}} = лæппуйы.
-       else if ( word.match( /у$/i ) ) {
-               if ( !word.substring( word.length - 2, word.length - 1 ).match( /[аæеёиоыэюя]$/i ) ) {
-                       jot = 'й';
-               }
-       } else if ( !word.match( /[бвгджзйклмнопрстфхцчшщьъ]$/i ) ) {
-               hyphen = '-';
-       }
-
-       switch ( form ) {
-               case 'genitive':
-                       ending = hyphen + jot + 'ы';
-                       break;
-               case 'dative':
-                       ending = hyphen + jot + 'æн';
-                       break;
-               case 'allative':
-                       ending = hyphen + endAllative;
-                       break;
-               case 'ablative':
-                       if ( jot === 'й' ) {
-                               ending = hyphen + jot + 'æ';
-                       }
-                       else {
-                               ending = hyphen + jot + 'æй';
-                       }
-                       break;
-               case 'superessive':
-                       ending = hyphen + jot + 'ыл';
-                       break;
-               case 'equative':
-                       ending = hyphen + jot + 'ау';
-                       break;
-               case 'comitative':
-                       ending = hyphen + 'имæ';
-                       break;
-       }
-       return word + ending;
-};
diff --git a/resources/mediawiki.language/languages/ru.js b/resources/mediawiki.language/languages/ru.js
deleted file mode 100644 (file)
index e66b9cd..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*!
- * Russian (Русский) language functions
- */
-
-// These tests were originally made for names of Wikimedia
-// websites, so they don't currently cover all the possible
-// cases.
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       'use strict';
-
-       var grammarForms = mediaWiki.language.getData( 'ru', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-       switch ( form ) {
-               case 'genitive': // родительный падеж
-                       if ( word.substr( word.length - 1 ) === 'ь' ) {
-                               word = word.substr(0, word.length - 1 ) + 'я';
-                       } else if ( word.substr( word.length - 2 ) === 'ия' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ии';
-                       } else if ( word.substr( word.length - 2 ) === 'ка' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ки';
-                       } else if ( word.substr( word.length - 2 )  === 'ти' ) {
-                               word = word.substr(0, word.length - 2 ) + 'тей';
-                       } else if ( word.substr( word.length - 2 ) === 'ды' ) {
-                               word = word.substr(0, word.length - 2 ) + 'дов';
-                       } else if ( word.substr( word.length - 3 ) === 'ные' ) {
-                               word = word.substr(0, word.length - 3 ) + 'ных';
-                       } else if ( word.substr( word.length - 3 ) === 'ник' ) {
-                               word = word.substr(0, word.length - 3 ) + 'ника';
-                       }
-                       break;
-               case 'prepositional': // предложный падеж
-                       if ( word.substr( word.length - 1 ) === 'ь' ) {
-                               word = word.substr(0, word.length - 1 ) + 'е';
-                       } else if ( word.substr( word.length - 2 ) === 'ия' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ии';
-                       } else if ( word.substr( word.length - 2 ) === 'ка' ) {
-                               word = word.substr(0, word.length - 2 ) + 'ке';
-                       } else if ( word.substr( word.length - 2 )  === 'ти' ) {
-                               word = word.substr(0, word.length - 2 ) + 'тях';
-                       } else if ( word.substr( word.length - 2 ) === 'ды' ) {
-                               word = word.substr(0, word.length - 2 ) + 'дах';
-                       } else if ( word.substr( word.length - 3 ) === 'ные' ) {
-                               word = word.substr(0, word.length - 3 ) + 'ных';
-                       } else if ( word.substr( word.length - 3 ) === 'ник' ) {
-                               word = word.substr(0, word.length - 3 ) + 'нике';
-                       }
-                       break;
-       }
-       return word;
-};
diff --git a/resources/mediawiki.language/languages/sl.js b/resources/mediawiki.language/languages/sl.js
deleted file mode 100644 (file)
index d20d0b3..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*!
- * Slovenian (Slovenščina) language functions
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms = mediaWiki.language.getData( 'sl', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-       switch ( form ) {
-               case 'mestnik': // locative
-                       word = 'o ' + word;
-                       break;
-               case 'orodnik': // instrumental
-                       word = 'z ' + word;
-                       break;
-       }
-       return word;
-};
diff --git a/resources/mediawiki.language/languages/uk.js b/resources/mediawiki.language/languages/uk.js
deleted file mode 100644 (file)
index 69f7ec5..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*!
- * Ukrainian (Українська) language functions
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms = mediaWiki.language.getData( 'uk', 'grammarForms' );
-       if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word];
-       }
-       switch ( form ) {
-               case 'genitive': // родовий відмінок
-                       if ( word.substr( word.length - 4 ) !== 'вікі' && word.substr( word.length - 4 ) !== 'Вікі' ) {
-                               if ( word.substr( word.length - 1 ) === 'ь' ) {
-                                       word = word.substr(0, word.length - 1 ) + 'я';
-                               } else if ( word.substr( word.length - 2 ) === 'ія' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'ії';
-                               } else if ( word.substr( word.length - 2 ) === 'ка' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'ки';
-                               } else if ( word.substr( word.length - 2 ) === 'ти' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'тей';
-                               } else if ( word.substr( word.length - 2 ) === 'ды' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'дов';
-                               } else if ( word.substr( word.length - 3 ) === 'ник' ) {
-                                       word = word.substr(0, word.length - 3 ) + 'ника';
-                               }
-                       }
-                       break;
-               case 'accusative': // знахідний відмінок
-                       if ( word.substr( word.length - 4 ) !== 'вікі' && word.substr( word.length - 4 ) !== 'Вікі' ) {
-                               if ( word.substr( word.length - 2 ) === 'ія' ) {
-                                       word = word.substr(0, word.length - 2 ) + 'ію';
-                               }
-                       }
-                       break;
-       }
-       return word;
-};
diff --git a/resources/mediawiki.language/mediawiki.cldr.js b/resources/mediawiki.language/mediawiki.cldr.js
deleted file mode 100644 (file)
index f6fb8f1..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-( function ( mw ) {
-       'use strict';
-
-       /**
-        * Namespace for CLDR-related utility methods.
-        *
-        * @class
-        * @singleton
-        */
-       mw.cldr = {
-               /**
-                * Get the plural form index for the number.
-                *
-                * In case none of the rules passed, we return `pluralRules.length` -
-                * that means it is the "other" form.
-                *
-                * @param {number} number
-                * @param {Array} pluralRules
-                * @return {number} plural form index
-                */
-               getPluralForm: function ( number, pluralRules ) {
-                       var i;
-                       for ( i = 0; i < pluralRules.length; i++ ) {
-                               if ( mw.libs.pluralRuleParser( pluralRules[i], number ) ) {
-                                       break;
-                               }
-                       }
-                       return i;
-               }
-       };
-
-}( mediaWiki ) );
diff --git a/resources/mediawiki.language/mediawiki.language.init.js b/resources/mediawiki.language/mediawiki.language.init.js
deleted file mode 100644 (file)
index fd77025..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-( function ( mw ) {
-       /**
-        * Base language object with methods related to language support, attempting to mirror some of the
-        * functionality of the Language class in MediaWiki:
-        *
-        *   - storing and retrieving language data
-        *   - transforming message syntax (`{{PLURAL:}}`, `{{GRAMMAR:}}`, `{{GENDER:}}`)
-        *   - formatting numbers
-        *
-        * @class
-        * @singleton
-        */
-       mw.language = {
-               /**
-                * Language-related data (keyed by language, contains instances of mw.Map). Loaded dynamically
-                * (see ResourceLoaderLanguageDataModule in PHP docs, aka mediawiki.language.data module).
-                *
-                * To set data:
-                *
-                *     // Override, extend or create the language data object of 'nl'
-                *     mw.language.setData( 'nl', 'myKey', 'My value' );
-                *
-                *     // Set multiple values at once
-                *     mw.language.setData( 'nl', { foo: 'X', bar: 'Y' } );
-                *
-                * To get GrammarForms data for language 'nl':
-                *
-                *     var grammarForms = mw.language.getData( 'nl', 'grammarForms' );
-                *
-                * Possible data keys:
-                *
-                *  - `digitTransformTable`
-                *  - `separatorTransformTable`
-                *  - `grammarForms`
-                *  - `pluralRules`
-                *  - `digitGroupingPattern`
-                *
-                * @property
-                */
-               data: {},
-
-               /**
-                * Convenience method for retrieving language data.
-                *
-                * Structured by language code and data key, covering for the potential inexistence of a
-                * data object for this language.
-                *
-                * @param {string} langCode
-                * @param {string} dataKey
-                * @return {Mixed} Value stored in the mw.Map (or `undefined` if there is no map for the specified
-                *  langCode).
-                */
-               getData: function ( langCode, dataKey ) {
-                       var langData = mw.language.data;
-                       if ( langData && langData[langCode] instanceof mw.Map ) {
-                               return langData[langCode].get( dataKey );
-                       }
-                       return undefined;
-               },
-
-               /**
-                * Convenience method for setting language data.
-                *
-                * Creates the data mw.Map if there isn't one for the specified language already.
-                *
-                * @param {string} langCode
-                * @param {string|Object} dataKey Key or object of key/values.
-                * @param {Mixed} value Value for dataKey, ignored if dataKey is an object.
-                */
-               setData: function ( langCode, dataKey, value ) {
-                       var langData = mw.language.data;
-                       if ( !( langData[langCode] instanceof mw.Map ) ) {
-                               langData[langCode] = new mw.Map();
-                       }
-                       langData[langCode].set( dataKey, value );
-               }
-       };
-
-}( mediaWiki ) );
diff --git a/resources/mediawiki.language/mediawiki.language.js b/resources/mediawiki.language/mediawiki.language.js
deleted file mode 100644 (file)
index a0b5569..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Methods for transforming message syntax.
- */
-( function ( mw, $ ) {
-
-/**
- * @class mw.language
- */
-$.extend( mw.language, {
-
-       /**
-        * Process the PLURAL template substitution
-        *
-        * @private
-        * @param {Object} template Template object
-        * @param {string} template.title
-        * @param {Array} template.parameters
-        * @return {string}
-        */
-       procPLURAL: function ( template ) {
-               if ( template.title && template.parameters && mw.language.convertPlural ) {
-                       // Check if we have forms to replace
-                       if ( template.parameters.length === 0 ) {
-                               return '';
-                       }
-                       // Restore the count into a Number ( if it got converted earlier )
-                       var count = mw.language.convertNumber( template.title, true );
-                       // Do convertPlural call
-                       return mw.language.convertPlural( parseInt( count, 10 ), template.parameters );
-               }
-               // Could not process plural return first form or nothing
-               if ( template.parameters[0] ) {
-                       return template.parameters[0];
-               }
-               return '';
-       },
-
-       /**
-        * Plural form transformations, needed for some languages.
-        *
-        * @param {number} count Non-localized quantifier
-        * @param {Array} forms List of plural forms
-        * @return {string} Correct form for quantifier in this language
-        */
-       convertPlural: function ( count, forms ) {
-               var pluralRules,
-                       formCount,
-                       form,
-                       index,
-                       equalsPosition,
-                       pluralFormIndex = 0;
-
-               if ( !forms || forms.length === 0 ) {
-                       return '';
-               }
-
-               // Handle for explicit n= forms
-               for ( index = 0; index < forms.length; index++ ) {
-                       form = forms[index];
-                       if ( /^\d+=/.test( form ) ) {
-                               equalsPosition = form.indexOf( '=' );
-                               formCount = parseInt( form.substring( 0, equalsPosition ), 10 );
-                               if ( formCount === count ) {
-                                       return form.substr( equalsPosition + 1 );
-                               }
-                               forms[index] = undefined;
-                       }
-               }
-
-               // Remove explicit plural forms from the forms.
-               forms = $.map( forms, function ( form ) {
-                       return form;
-               } );
-
-               if ( forms.length === 0 ) {
-                       return '';
-               }
-
-               pluralRules = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'pluralRules' );
-               if ( !pluralRules ) {
-                       // default fallback.
-                       return ( count === 1 ) ? forms[0] : forms[1];
-               }
-               pluralFormIndex = mw.cldr.getPluralForm( count, pluralRules );
-               pluralFormIndex = Math.min( pluralFormIndex, forms.length - 1 );
-               return forms[pluralFormIndex];
-       },
-
-       /**
-        * Pads an array to a specific length by copying the last one element.
-        *
-        * @private
-        * @param {Array} forms Number of forms given to convertPlural
-        * @param {number} count Number of forms required
-        * @return {Array} Padded array of forms
-        */
-       preConvertPlural: function ( forms, count ) {
-               while ( forms.length < count ) {
-                       forms.push( forms[ forms.length - 1 ] );
-               }
-               return forms;
-       },
-
-       /**
-        * Provides an alternative text depending on specified gender.
-        *
-        * Usage in message text: `{{gender:[gender|user object]|masculine|feminine|neutral}}`.
-        * If second or third parameter are not specified, masculine is used.
-        *
-        * These details may be overriden per language.
-        *
-        * @param {string} gender 'male', 'female', or anything else for neutral.
-        * @param {Array} forms List of gender forms
-        * @return string
-        */
-       gender: function ( gender, forms ) {
-               if ( !forms || forms.length === 0 ) {
-                       return '';
-               }
-               forms = mw.language.preConvertPlural( forms, 2 );
-               if ( gender === 'male' ) {
-                       return forms[0];
-               }
-               if ( gender === 'female' ) {
-                       return forms[1];
-               }
-               return ( forms.length === 3 ) ? forms[2] : forms[0];
-       },
-
-       /**
-        * Grammatical transformations, needed for inflected languages.
-        * Invoked by putting `{{grammar:form|word}}` in a message.
-        *
-        * The rules can be defined in $wgGrammarForms global or computed
-        * dynamically by overriding this method per language.
-        *
-        * @param {string} word
-        * @param {string} form
-        * @return {string}
-        */
-       convertGrammar: function ( word, form ) {
-               var grammarForms = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'grammarForms' );
-               if ( grammarForms && grammarForms[form] ) {
-                       return grammarForms[form][word] || word;
-               }
-               return word;
-       }
-
-} );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.language/mediawiki.language.months.js b/resources/mediawiki.language/mediawiki.language.months.js
deleted file mode 100644 (file)
index 5a1a5cb..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Transfer of month names from messages into mw.language.
- *
- * Loading this module also ensures the availability of appropriate messages via mw.msg.
- */
-( function ( mw, $ ) {
-       var
-               monthMessages = [
-                       'january', 'february', 'march', 'april',
-                       'may_long', 'june', 'july', 'august',
-                       'september', 'october', 'november', 'december'
-               ],
-               monthGenMessages = [
-                       'january-gen', 'february-gen', 'march-gen', 'april-gen',
-                       'may-gen', 'june-gen', 'july-gen', 'august-gen',
-                       'september-gen', 'october-gen', 'november-gen', 'december-gen'
-               ],
-               monthAbbrevMessages = [
-                       'jan', 'feb', 'mar', 'apr',
-                       'may', 'jun', 'jul', 'aug',
-                       'sep', 'oct', 'nov', 'dec'
-               ];
-
-       // Function suitable for passing to jQuery.map
-       // Can't use mw.msg directly because jQuery.map passes element index as second argument
-       function mwMsgMapper( key ) {
-               return mw.msg( key );
-       }
-
-       /**
-        * Information about month names in current UI language.
-        *
-        * Object keys:
-        *
-        * - `names`: array of month names (in nominative case in languages which have the distinction),
-        *   zero-indexed
-        * - `genitive`: array of month names in genitive case, zero-indexed
-        * - `abbrev`: array of three-letter-long abbreviated month names, zero-indexed
-        * - `keys`: object with three keys like the above, containing zero-indexed arrays of message keys
-        *   for appropriate messages which can be passed to mw.msg.
-        *
-        * @property
-        * @member mw.language
-        */
-       mw.language.months = {
-               keys: {
-                       names: monthMessages,
-                       genitive: monthGenMessages,
-                       abbrev: monthAbbrevMessages
-               },
-               names: $.map( monthMessages, mwMsgMapper ),
-               genitive: $.map( monthGenMessages, mwMsgMapper ),
-               abbrev: $.map( monthAbbrevMessages, mwMsgMapper )
-       };
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.language/mediawiki.language.numbers.js b/resources/mediawiki.language/mediawiki.language.numbers.js
deleted file mode 100644 (file)
index 56fa0da..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Number-related utilities for mediawiki.language.
- */
-( function ( mw, $ ) {
-       /**
-        * @class mw.language
-        */
-
-       /**
-        * Pad a string to guarantee that it is at least `size` length by
-        * filling with the character `ch` at either the start or end of the
-        * string. Pads at the start, by default.
-        *
-        * Example: Fill the string to length 10 with '+' characters on the right.
-        *
-        *     pad( 'blah', 10, '+', true ); // => 'blah++++++'
-        *
-        * @private
-        * @param {string} text The string to pad
-        * @param {number} size The length to pad to
-        * @param {string} [ch='0'] Character to pad with
-        * @param {boolean} [end=false] Adds padding at the end if true, otherwise pads at start
-        * @return {string}
-        */
-       function pad( text, size, ch, end ) {
-               if ( !ch ) {
-                       ch = '0';
-               }
-
-               var out = String( text ),
-                       padStr = replicate( ch, Math.ceil( ( size - out.length ) / ch.length ) );
-
-               return end ? out + padStr : padStr + out;
-       }
-
-       /**
-        * Efficiently replicate a string `n` times.
-        *
-        * @private
-        * @param {string} str The string to replicate
-        * @param {number} num Number of times to replicate the string
-        * @return {string}
-        */
-       function replicate( str, num ) {
-               if ( num <= 0 || !str ) {
-                       return '';
-               }
-
-               var buf = [];
-               while (num) {
-                       buf.push( str );
-                       str += str;
-               }
-               return buf.join( '' );
-       }
-
-       /**
-        * Apply numeric pattern to absolute value using options. Gives no
-        * consideration to local customs.
-        *
-        * Adapted from dojo/number library with thanks
-        * <http://dojotoolkit.org/reference-guide/1.8/dojo/number.html>
-        *
-        * @private
-        * @param {number} value the number to be formatted, ignores sign
-        * @param {string} pattern the number portion of a pattern (e.g. `#,##0.00`)
-        * @param {Object} [options] If provided, both option keys must be present:
-        * @param {string} options.decimal The decimal separator. Defaults to: `'.'`.
-        * @param {string} options.group The group separator. Defaults to: `','`.
-        * @return {string}
-        */
-       function commafyNumber( value, pattern, options ) {
-               options = options || {
-                       group: ',',
-                       decimal: '.'
-               };
-
-               if ( isNaN( value) ) {
-                       return value;
-               }
-
-               var padLength,
-                       patternDigits,
-                       index,
-                       whole,
-                       off,
-                       remainder,
-                       patternParts = pattern.split( '.' ),
-                       maxPlaces = ( patternParts[1] || [] ).length,
-                       valueParts = String( Math.abs( value ) ).split( '.' ),
-                       fractional = valueParts[1] || '',
-                       groupSize = 0,
-                       groupSize2 = 0,
-                       pieces = [];
-
-               if ( patternParts[1] ) {
-                       // Pad fractional with trailing zeros
-                       padLength = ( patternParts[1] && patternParts[1].lastIndexOf( '0' ) + 1 );
-
-                       if ( padLength > fractional.length ) {
-                               valueParts[1] = pad( fractional, padLength, '0', true );
-                       }
-
-                       // Truncate fractional
-                       if ( maxPlaces < fractional.length ) {
-                               valueParts[1] = fractional.substr( 0, maxPlaces );
-                       }
-               } else {
-                       if ( valueParts[1] ) {
-                               valueParts.pop();
-                       }
-               }
-
-               // Pad whole with leading zeros
-               patternDigits = patternParts[0].replace( ',', '' );
-
-               padLength = patternDigits.indexOf( '0' );
-
-               if ( padLength !== -1 ) {
-                       padLength = patternDigits.length - padLength;
-
-                       if ( padLength > valueParts[0].length ) {
-                               valueParts[0] = pad( valueParts[0], padLength );
-                       }
-
-                       // Truncate whole
-                       if ( patternDigits.indexOf( '#' ) === -1 ) {
-                               valueParts[0] = valueParts[0].substr( valueParts[0].length - padLength );
-                       }
-               }
-
-               // Add group separators
-               index = patternParts[0].lastIndexOf( ',' );
-
-               if ( index !== -1 ) {
-                       groupSize = patternParts[0].length - index - 1;
-                       remainder = patternParts[0].substr( 0, index );
-                       index = remainder.lastIndexOf( ',' );
-                       if ( index !== -1 ) {
-                               groupSize2 = remainder.length - index - 1;
-                       }
-               }
-
-               for ( whole = valueParts[0]; whole; ) {
-                       off = whole.length - groupSize;
-
-                       pieces.push( ( off > 0 ) ? whole.substr( off ) : whole );
-                       whole = ( off > 0 ) ? whole.slice( 0, off ) : '';
-
-                       if ( groupSize2 ) {
-                               groupSize = groupSize2;
-                       }
-               }
-               valueParts[0] = pieces.reverse().join( options.group );
-
-               return valueParts.join( options.decimal );
-       }
-
-       $.extend( mw.language, {
-
-               /**
-                * Converts a number using #getDigitTransformTable.
-                *
-                * @param {number} num Value to be converted
-                * @param {boolean} [integer=false] Whether to convert the return value to an integer
-                * @return {number|string} Formatted number
-                */
-               convertNumber: function ( num, integer ) {
-                       var i, tmp, transformTable, numberString, convertedNumber, pattern;
-
-                       pattern = mw.language.getData( mw.config.get( 'wgUserLanguage' ),
-                               'digitGroupingPattern' ) || '#,##0.###';
-
-                       // Set the target transform table:
-                       transformTable = mw.language.getDigitTransformTable();
-
-                       if ( !transformTable ) {
-                               return num;
-                       }
-
-                       // Check if the 'restore' to Latin number flag is set:
-                       if ( integer ) {
-                               if ( parseInt( num, 10 ) === num ) {
-                                       return num;
-                               }
-                               tmp = [];
-                               for ( i in transformTable ) {
-                                       tmp[ transformTable[ i ] ] = i;
-                               }
-                               transformTable = tmp;
-                               numberString = num + '';
-                       } else {
-                               numberString = mw.language.commafy( num, pattern );
-                       }
-
-                       convertedNumber = '';
-                       for ( i = 0; i < numberString.length; i++ ) {
-                               if ( transformTable[ numberString[i] ] ) {
-                                       convertedNumber += transformTable[numberString[i]];
-                               } else {
-                                       convertedNumber += numberString[i];
-                               }
-                       }
-                       return integer ? parseInt( convertedNumber, 10 ) : convertedNumber;
-               },
-
-               /**
-                * Get the  digit transform table for current UI language.
-                * @return {Object|Array}
-                */
-               getDigitTransformTable: function () {
-                       return mw.language.getData( mw.config.get( 'wgUserLanguage' ),
-                               'digitTransformTable' ) || [];
-               },
-
-               /**
-                * Get the  separator transform table for current UI language.
-                * @return {Object|Array}
-                */
-               getSeparatorTransformTable: function () {
-                       return mw.language.getData( mw.config.get( 'wgUserLanguage' ),
-                               'separatorTransformTable' ) || [];
-               },
-
-               /**
-                * Apply pattern to format value as a string.
-                *
-                * Using patterns from [Unicode TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns).
-                *
-                * @param {number} value
-                * @param {string} pattern Pattern string as described by Unicode TR35
-                * @throws {Error} If unable to find a number expression in `pattern`.
-                * @return {string}
-                */
-               commafy: function ( value, pattern ) {
-                       var numberPattern,
-                               transformTable = mw.language.getSeparatorTransformTable(),
-                               group = transformTable[','] || ',',
-                               numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/, // not precise, but good enough
-                               decimal = transformTable['.'] || '.',
-                               patternList = pattern.split( ';' ),
-                               positivePattern = patternList[0];
-
-                       pattern = patternList[ ( value < 0 ) ? 1 : 0] || ( '-' + positivePattern );
-                       numberPattern = positivePattern.match( numberPatternRE );
-
-                       if ( !numberPattern ) {
-                               throw new Error( 'unable to find a number expression in pattern: ' + pattern );
-                       }
-
-                       return pattern.replace( numberPatternRE, commafyNumber( value, numberPattern[0], {
-                               decimal: decimal,
-                               group: group
-                       } ) );
-               }
-
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.less/mediawiki.mixins.animation.less b/resources/mediawiki.less/mediawiki.mixins.animation.less
deleted file mode 100644 (file)
index ec3cddc..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-.animation (...) {
-       -webkit-animation: @arguments;
-       -moz-animation: @arguments;
-       -o-animation: @arguments;
-       animation: @arguments;
-}
-
-.transform-rotate (@deg) {
-       -webkit-transform: rotate(@deg);
-       -moz-transform: rotate(@deg);
-       transform: rotate(@deg);
-}
\ No newline at end of file
diff --git a/resources/mediawiki.less/mediawiki.mixins.less b/resources/mediawiki.less/mediawiki.mixins.less
deleted file mode 100644 (file)
index 80b68cc..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * Common LESS mixin library for MediaWiki
- *
- * By default the folder containing this file is included in $wgResourceLoaderLESSImportPaths,
- * which makes this file importable by all less files via '@import "mediawiki.mixins";'.
- *
- * The mixins included below are considered a public interface for MediaWiki extensions.
- * The signatures of parametrized mixins should be kept as stable as possible.
- *
- * See <http://lesscss.org/#-mixins> for more information about how to write mixins.
- */
-
-.background-image(@url) when (embeddable(@url)) {
-       background-image: embed(@url);
-       background-image: url(@url)!ie;
-}
-
-.background-image(@url) when not (embeddable(@url)) {
-       background-image: url(@url);
-}
-
-.vertical-gradient ( @startColor: gray, @endColor: white, @startPos: 0, @endPos: 100% ) {
-       background-color: @endColor;
-       background-image: -moz-linear-gradient( top, @startColor @startPos, @endColor @endPos ); // Firefox 3.6+
-       background-image: -webkit-gradient( linear, left top, left bottom, color-stop( @startPos, @startColor ), color-stop( @endPos, @endColor ) ); // Safari 4+, Chrome 2+
-       background-image: -webkit-linear-gradient( top, @startColor @startPos, @endColor @endPos ); // Safari 5.1+, Chrome 10+
-       background-image: linear-gradient( @startColor @startPos, @endColor @endPos ); // Standard
-}
-
-/* Note gzip compression means that it is okay to embed twice */
-/* http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique */
-.background-image-svg(@svg, @fallback) {
-       background-image: url(@fallback);
-       /* SVG support using a transparent gradient to guarantee cross-browser
-        * compatibility (browsers able to understand gradient syntax support also SVG) */
-       /* @embed */ background-image: -webkit-linear-gradient(transparent, transparent), url(@svg);
-       /* @embed */ background-image: linear-gradient(transparent, transparent), url(@svg);
-}
-
-/* Caution: Does not support localisable images */
-.list-style-image(@url) when (embeddable(@url)) {
-       list-style-image: embed(@url);
-       list-style-image: url(@url)!ie;
-}
-
-.list-style-image(@url) when not (embeddable(@url)) {
-       list-style-image: url(@url);
-}
-
-.transition(@string) {
-       -webkit-transition: @string;
-       transition: @string;
-}
diff --git a/resources/mediawiki.less/mediawiki.mixins.rotation.less b/resources/mediawiki.less/mediawiki.mixins.rotation.less
deleted file mode 100644 (file)
index e28b333..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// This is a separate file because importing the mixin causes
-// the keyframes blocks to be included in the output, regardless
-// of whether .rotation is used.
-@import "mediawiki.mixins.animation";
-
-.rotate-frames () {
-       from {
-               .transform-rotate(0deg);
-       }
-       to {
-               .transform-rotate(360deg);
-       }
-}
-
-@-webkit-keyframes rotate {
-       .rotate-frames;
-}
-
-@-moz-keyframes rotate {
-       .rotate-frames;
-}
-
-@-o-keyframes rotate {
-       .rotate-frames;
-}
-
-@keyframes rotate {
-       .rotate-frames;
-}
-
-.rotation( @time ) {
-       .animation(rotate, @time, infinite, linear);
-}
diff --git a/resources/mediawiki.libs/CLDRPluralRuleParser.js b/resources/mediawiki.libs/CLDRPluralRuleParser.js
deleted file mode 100644 (file)
index 83c2524..0000000
+++ /dev/null
@@ -1,475 +0,0 @@
-/* This is CLDRPluralRuleParser v1.1, ported to MediaWiki ResourceLoader */
-
-/**
-* CLDRPluralRuleParser.js
-* A parser engine for CLDR plural rules.
-*
-* Copyright 2012 GPLV3+, Santhosh Thottingal
-*
-* @version 0.1.0-alpha
-* @source https://github.com/santhoshtr/CLDRPluralRuleParser
-* @author Santhosh Thottingal <santhosh.thottingal@gmail.com>
-* @author Timo Tijhof
-* @author Amir Aharoni
-*/
-
-( function ( mw ) {
-/**
- * Evaluates a plural rule in CLDR syntax for a number
- * @param {string} rule
- * @param {integer} number
- * @return {boolean} true if evaluation passed, false if evaluation failed.
- */
-
-function pluralRuleParser(rule, number) {
-       /*
-       Syntax: see http://unicode.org/reports/tr35/#Language_Plural_Rules
-       -----------------------------------------------------------------
-       condition     = and_condition ('or' and_condition)*
-               ('@integer' samples)?
-               ('@decimal' samples)?
-       and_condition = relation ('and' relation)*
-       relation      = is_relation | in_relation | within_relation
-       is_relation   = expr 'is' ('not')? value
-       in_relation   = expr (('not')? 'in' | '=' | '!=') range_list
-       within_relation = expr ('not')? 'within' range_list
-       expr          = operand (('mod' | '%') value)?
-       operand       = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
-       range_list    = (range | value) (',' range_list)*
-       value         = digit+
-       digit         = 0|1|2|3|4|5|6|7|8|9
-       range         = value'..'value
-       samples       = sampleRange (',' sampleRange)* (',' ('…'|'...'))?
-       sampleRange   = decimalValue '~' decimalValue
-       decimalValue  = value ('.' value)?
-       */
-
-       // we don't evaluate the samples section of the rule. Ignore it.
-       rule = rule.split('@')[0].replace(/^\s*/, '').replace(/\s*$/, '');
-
-       if (!rule.length) {
-               // empty rule or 'other' rule.
-               return true;
-       }
-       // Indicates current position in the rule as we parse through it.
-       // Shared among all parsing functions below.
-       var pos = 0,
-               operand,
-               expression,
-               relation,
-               result,
-               whitespace = makeRegexParser(/^\s+/),
-               value = makeRegexParser(/^\d+/),
-               _n_ = makeStringParser('n'),
-               _i_ = makeStringParser('i'),
-               _f_ = makeStringParser('f'),
-               _t_ = makeStringParser('t'),
-               _v_ = makeStringParser('v'),
-               _w_ = makeStringParser('w'),
-               _is_ = makeStringParser('is'),
-               _isnot_ = makeStringParser('is not'),
-               _isnot_sign_ = makeStringParser('!='),
-               _equal_ = makeStringParser('='),
-               _mod_ = makeStringParser('mod'),
-               _percent_ = makeStringParser('%'),
-               _not_ = makeStringParser('not'),
-               _in_ = makeStringParser('in'),
-               _within_ = makeStringParser('within'),
-               _range_ = makeStringParser('..'),
-               _comma_ = makeStringParser(','),
-               _or_ = makeStringParser('or'),
-               _and_ = makeStringParser('and');
-
-       function debug() {
-               // console.log.apply(console, arguments);
-       }
-
-       debug('pluralRuleParser', rule, number);
-
-       // Try parsers until one works, if none work return null
-
-       function choice(parserSyntax) {
-               return function() {
-                       for (var i = 0; i < parserSyntax.length; i++) {
-                               var result = parserSyntax[i]();
-                               if (result !== null) {
-                                       return result;
-                               }
-                       }
-                       return null;
-               };
-       }
-
-       // Try several parserSyntax-es in a row.
-       // All must succeed; otherwise, return null.
-       // This is the only eager one.
-
-       function sequence(parserSyntax) {
-               var originalPos = pos;
-               var result = [];
-               for (var i = 0; i < parserSyntax.length; i++) {
-                       var res = parserSyntax[i]();
-                       if (res === null) {
-                               pos = originalPos;
-                               return null;
-                       }
-                       result.push(res);
-               }
-               return result;
-       }
-
-       // Run the same parser over and over until it fails.
-       // Must succeed a minimum of n times; otherwise, return null.
-
-       function nOrMore(n, p) {
-               return function() {
-                       var originalPos = pos;
-                       var result = [];
-                       var parsed = p();
-                       while (parsed !== null) {
-                               result.push(parsed);
-                               parsed = p();
-                       }
-                       if (result.length < n) {
-                               pos = originalPos;
-                               return null;
-                       }
-                       return result;
-               };
-       }
-
-       // Helpers -- just make parserSyntax out of simpler JS builtin types
-       function makeStringParser(s) {
-               var len = s.length;
-               return function() {
-                       var result = null;
-                       if (rule.substr(pos, len) === s) {
-                               result = s;
-                               pos += len;
-                       }
-
-                       return result;
-               };
-       }
-
-       function makeRegexParser(regex) {
-               return function() {
-                       var matches = rule.substr(pos).match(regex);
-                       if (matches === null) {
-                               return null;
-                       }
-                       pos += matches[0].length;
-                       return matches[0];
-               };
-       }
-
-       /*
-        * integer digits of n.
-        */
-       function i() {
-               var result = _i_();
-               if (result === null) {
-                       debug(' -- failed i', parseInt(number, 10));
-                       return result;
-               }
-               result = parseInt(number, 10);
-               debug(' -- passed i ', result);
-               return result;
-       }
-
-       /*
-        * absolute value of the source number (integer and decimals).
-        */
-       function n() {
-               var result = _n_();
-               if (result === null) {
-                       debug(' -- failed n ', number);
-                       return result;
-               }
-               result = parseFloat(number, 10);
-               debug(' -- passed n ', result);
-               return result;
-       }
-
-       /*
-        * visible fractional digits in n, with trailing zeros.
-        */
-       function f() {
-               var result = _f_();
-               if (result === null) {
-                       debug(' -- failed f ', number);
-                       return result;
-               }
-               result = (number + '.').split('.')[1] || 0;
-               debug(' -- passed f ', result);
-               return result;
-       }
-
-       /*
-        * visible fractional digits in n, without trailing zeros.
-        */
-       function t() {
-               var result = _t_();
-               if (result === null) {
-                       debug(' -- failed t ', number);
-                       return result;
-               }
-               result = (number + '.').split('.')[1].replace(/0$/, '') || 0;
-               debug(' -- passed t ', result);
-               return result;
-       }
-
-       /*
-        * number of visible fraction digits in n, with trailing zeros.
-        */
-       function v() {
-               var result = _v_();
-               if (result === null) {
-                       debug(' -- failed v ', number);
-                       return result;
-               }
-               result = (number + '.').split('.')[1].length || 0;
-               debug(' -- passed v ', result);
-               return result;
-       }
-
-       /*
-        * number of visible fraction digits in n, without trailing zeros.
-        */
-       function w() {
-               var result = _w_();
-               if (result === null) {
-                       debug(' -- failed w ', number);
-                       return result;
-               }
-               result = (number + '.').split('.')[1].replace(/0$/, '').length || 0;
-               debug(' -- passed w ', result);
-               return result;
-       }
-
-       // operand       = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
-       operand = choice([n, i, f, t, v, w]);
-
-       // expr          = operand (('mod' | '%') value)?
-       expression = choice([mod, operand]);
-
-       function mod() {
-               var result = sequence([operand, whitespace, choice([_mod_, _percent_]), whitespace, value]);
-               if (result === null) {
-                       debug(' -- failed mod');
-                       return null;
-               }
-               debug(' -- passed ' + parseInt(result[0], 10) + ' ' + result[2] + ' ' + parseInt(result[4], 10));
-               return parseInt(result[0], 10) % parseInt(result[4], 10);
-       }
-
-       function not() {
-               var result = sequence([whitespace, _not_]);
-               if (result === null) {
-                       debug(' -- failed not');
-                       return null;
-               }
-
-               return result[1];
-       }
-
-       // is_relation   = expr 'is' ('not')? value
-       function is() {
-               var result = sequence([expression, whitespace, choice([_is_]), whitespace, value]);
-               if (result !== null) {
-                       debug(' -- passed is : ' + result[0] + ' == ' + parseInt(result[4], 10));
-                       return result[0] === parseInt(result[4], 10);
-               }
-               debug(' -- failed is');
-               return null;
-       }
-
-       // is_relation   = expr 'is' ('not')? value
-       function isnot() {
-               var result = sequence([expression, whitespace, choice([_isnot_, _isnot_sign_]), whitespace, value]);
-               if (result !== null) {
-                       debug(' -- passed isnot: ' + result[0] + ' != ' + parseInt(result[4], 10));
-                       return result[0] !== parseInt(result[4], 10);
-               }
-               debug(' -- failed isnot');
-               return null;
-       }
-
-       function not_in() {
-               var result = sequence([expression, whitespace, _isnot_sign_, whitespace, rangeList]);
-               if (result !== null) {
-                       debug(' -- passed not_in: ' + result[0] + ' != ' + result[4]);
-                       var range_list = result[4];
-                       for (var i = 0; i < range_list.length; i++) {
-                               if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) {
-                                       return false;
-                               }
-                       }
-                       return true;
-               }
-               debug(' -- failed not_in');
-               return null;
-       }
-
-       // range_list    = (range | value) (',' range_list)*
-       function rangeList() {
-               var result = sequence([choice([range, value]), nOrMore(0, rangeTail)]);
-               var resultList = [];
-               if (result !== null) {
-                       resultList = resultList.concat(result[0]);
-                       if (result[1][0]) {
-                               resultList = resultList.concat(result[1][0]);
-                       }
-                       return resultList;
-               }
-               debug(' -- failed rangeList');
-               return null;
-       }
-
-       function rangeTail() {
-               // ',' range_list
-               var result = sequence([_comma_, rangeList]);
-               if (result !== null) {
-                       return result[1];
-               }
-               debug(' -- failed rangeTail');
-               return null;
-       }
-
-       // range         = value'..'value
-
-       function range() {
-               var i;
-               var result = sequence([value, _range_, value]);
-               if (result !== null) {
-                       debug(' -- passed range');
-                       var array = [];
-                       var left = parseInt(result[0], 10);
-                       var right = parseInt(result[2], 10);
-                       for (i = left; i <= right; i++) {
-                               array.push(i);
-                       }
-                       return array;
-               }
-               debug(' -- failed range');
-               return null;
-       }
-
-       function _in() {
-               // in_relation   = expr ('not')? 'in' range_list
-               var result = sequence([expression, nOrMore(0, not), whitespace, choice([_in_, _equal_]), whitespace, rangeList]);
-               if (result !== null) {
-                       debug(' -- passed _in:' + result);
-                       var range_list = result[5];
-                       for (var i = 0; i < range_list.length; i++) {
-                               if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) {
-                                       return (result[1][0] !== 'not');
-                               }
-                       }
-                       return (result[1][0] === 'not');
-               }
-               debug(' -- failed _in ');
-               return null;
-       }
-
-       /*
-        * The difference between in and within is that in only includes integers in the specified range,
-        * while within includes all values.
-        */
-
-       function within() {
-               // within_relation = expr ('not')? 'within' range_list
-               var result = sequence([expression, nOrMore(0, not), whitespace, _within_, whitespace, rangeList]);
-               if (result !== null) {
-                       debug(' -- passed within');
-                       var range_list = result[5];
-                       if ((result[0] >= parseInt(range_list[0], 10)) &&
-                               (result[0] < parseInt(range_list[range_list.length - 1], 10))) {
-                               return (result[1][0] !== 'not');
-                       }
-                       return (result[1][0] === 'not');
-               }
-               debug(' -- failed within ');
-               return null;
-       }
-
-       // relation      = is_relation | in_relation | within_relation
-       relation = choice([is, not_in, isnot, _in, within]);
-
-       // and_condition = relation ('and' relation)*
-       function and() {
-               var result = sequence([relation, nOrMore(0, andTail)]);
-               if (result) {
-                       if (!result[0]) {
-                               return false;
-                       }
-                       for (var i = 0; i < result[1].length; i++) {
-                               if (!result[1][i]) {
-                                       return false;
-                               }
-                       }
-                       return true;
-               }
-               debug(' -- failed and');
-               return null;
-       }
-
-       // ('and' relation)*
-       function andTail() {
-               var result = sequence([whitespace, _and_, whitespace, relation]);
-               if (result !== null) {
-                       debug(' -- passed andTail' + result);
-                       return result[3];
-               }
-               debug(' -- failed andTail');
-               return null;
-
-       }
-       //  ('or' and_condition)*
-       function orTail() {
-               var result = sequence([whitespace, _or_, whitespace, and]);
-               if (result !== null) {
-                       debug(' -- passed orTail: ' + result[3]);
-                       return result[3];
-               }
-               debug(' -- failed orTail');
-               return null;
-
-       }
-
-       // condition     = and_condition ('or' and_condition)*
-       function condition() {
-               var result = sequence([and, nOrMore(0, orTail)]);
-               if (result) {
-                       for (var i = 0; i < result[1].length; i++) {
-                               if (result[1][i]) {
-                                       return true;
-                               }
-                       }
-                       return result[0];
-
-               }
-               return false;
-       }
-
-       result = condition();
-       /*
-        * For success, the pos must have gotten to the end of the rule
-        * and returned a non-null.
-        * n.b. This is part of language infrastructure, so we do not throw an internationalizable message.
-        */
-       if (result === null) {
-               throw new Error('Parse error at position ' + pos.toString() + ' for rule: ' + rule);
-       }
-
-       if (pos !== rule.length) {
-               debug('Warning: Rule not parsed completely. Parser stopped at ' + rule.substr(0, pos) + ' for rule: ' + rule);
-       }
-
-       return result;
-}
-
-/* pluralRuleParser ends here */
-mw.libs.pluralRuleParser = pluralRuleParser;
-
-} )( mediaWiki );
diff --git a/resources/mediawiki.libs/mediawiki.libs.jpegmeta.js b/resources/mediawiki.libs/mediawiki.libs.jpegmeta.js
deleted file mode 100644 (file)
index b3ed88c..0000000
+++ /dev/null
@@ -1,737 +0,0 @@
-/**
- * This is JsJpegMeta v1.0
- * From: https://code.google.com/p/jsjpegmeta/downloads/list
- * From: https://github.com/bennoleslie/jsjpegmeta/blob/v1.0.0/jpegmeta.js
- *
- * Ported to MediaWiki ResourceLoader by Bryan Tong Minh
- * Changes:
- * - Add closure.
- * - Add this.JpegMeta assignment to expose it as global.
- * - Add mw.libs.jpegmeta wrapper.
- */
-
-( function () {
-       /*
-       Copyright (c) 2009 Ben Leslie
-       
-       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.
-       */
-       
-       /*
-        This JavaScript library is used to parse meta-data from files 
-        with mime-type image/jpeg.
-       
-        Include it with something like:
-       
-          <script type="text/javascript" src="jpegmeta.js"></script>
-       
-        This adds a single 'module' object called 'JpegMeta' to the global
-        namespace.
-       
-        Public Functions
-        ----------------
-        JpegMeta.parseNum - parse unsigned integers from binary data
-        JpegMeta.parseSnum - parse signed integers from binary data
-       
-        Public Classes
-        --------------
-        JpegMeta.Rational - A rational number class
-        JpegMeta.JfifSegment
-        JpegMeta.ExifSegment
-        JpegMeta.JpegFile - Primary class for Javascript parsing
-       */
-
-       var JpegMeta = {};
-       // MediaWiki: Expose as global
-       this.JpegMeta = JpegMeta;
-       
-       /* 
-          parse an unsigned number of size bytes at offset in some binary string data.
-          If endian
-          is "<" parse the data as little endian, if endian
-          is ">" parse as big-endian.
-       */
-       JpegMeta.parseNum = function parseNum(endian, data, offset, size) {
-           var i;
-           var ret;
-           var big_endian = (endian === ">");
-           if (offset === undefined) offset = 0;
-           if (size === undefined) size = data.length - offset;
-           for (big_endian ? i = offset : i = offset + size - 1; 
-                big_endian ? i < offset + size : i >= offset; 
-                big_endian ? i++ : i--) {
-               ret <<= 8;
-               ret += data.charCodeAt(i);
-           }
-           return ret;
-       };
-       
-       /* 
-          parse an signed number of size bytes at offset in some binary string data.
-          If endian
-          is "<" parse the data as little endian, if endian
-          is ">" parse as big-endian.
-       */
-       JpegMeta.parseSnum = function parseSnum(endian, data, offset, size) {
-           var i;
-           var ret;
-           var neg;
-           var big_endian = (endian === ">");
-           if (offset === undefined) offset = 0;
-           if (size === undefined) size = data.length - offset;
-           for (big_endian ? i = offset : i = offset + size - 1; 
-                big_endian ? i < offset + size : i >= offset; 
-                big_endian ? i++ : i--) {
-               if (neg === undefined) {
-                   /* Negative if top bit is set */
-                   neg = (data.charCodeAt(i) & 0x80) === 0x80;
-               }
-               ret <<= 8;
-               /* If it is negative we invert the bits */
-               ret += neg ? ~data.charCodeAt(i) & 0xff: data.charCodeAt(i);
-           }
-           if (neg) {
-               /* If it is negative we do two's complement */
-               ret += 1;
-               ret *= -1;
-           }
-           return ret;
-       };
-       
-       /* Rational number class */
-       JpegMeta.Rational = function Rational(num, den)
-       {
-           this.num = num;
-           this.den = den || 1;
-           return this;
-       };
-       
-       /* Rational number methods */
-       JpegMeta.Rational.prototype.toString = function toString() {
-           if (this.num === 0) {
-               return "" + this.num;
-           }
-           if (this.den === 1) {
-               return "" + this.num;
-           }
-           if (this.num === 1) {
-               return this.num + " / " + this.den;
-           }
-           return this.num / this.den; // + "/" + this.den;
-       };
-       
-       JpegMeta.Rational.prototype.asFloat = function asFloat() {
-           return this.num / this.den;
-       };
-       
-       /* MetaGroup class */
-       JpegMeta.MetaGroup = function MetaGroup(fieldName, description) {
-           this.fieldName = fieldName;
-           this.description = description;
-           this.metaProps = {};
-           return this;
-       };
-       
-       JpegMeta.MetaGroup.prototype._addProperty = function _addProperty(fieldName, description, value) {
-           var property = new JpegMeta.MetaProp(fieldName, description, value);
-           this[property.fieldName] = property;
-           this.metaProps[property.fieldName] = property;
-       };
-       
-       JpegMeta.MetaGroup.prototype.toString = function toString() {
-           return "[MetaGroup " + this.description + "]";
-       };
-
-       /* MetaProp class */
-       JpegMeta.MetaProp = function MetaProp(fieldName, description, value) {
-           this.fieldName = fieldName;
-           this.description = description;
-           this.value = value;
-           return this;
-       };
-       
-       JpegMeta.MetaProp.prototype.toString = function toString() {
-           return "" + this.value;
-       };
-
-       /* JpegFile class */
-       JpegMeta.JpegFile = function JpegFile(binary_data, filename) {
-           /* Change this to EOI if we want to parse. */
-           var break_segment = this._SOS;
-           
-           this.metaGroups = {};
-           this._binary_data = binary_data;
-           this.filename = filename;
-           
-           /* Go through and parse. */
-           var pos = 0;
-           var pos_start_of_segment = 0;
-           var delim;
-           var mark;
-           var _mark;
-           var segsize;
-           var headersize;
-           var mark_code;
-           var mark_fn;
-       
-           /* Check to see if this looks like a JPEG file */
-           if (this._binary_data.slice(0, 2) !== this._SOI_MARKER) {
-               throw new Error("Doesn't look like a JPEG file. First two bytes are " + 
-                               this._binary_data.charCodeAt(0) + "," + 
-                               this._binary_data.charCodeAt(1) + ".");
-           }
-           
-           pos += 2;
-           
-           while (pos < this._binary_data.length) {
-               delim = this._binary_data.charCodeAt(pos++);
-               mark = this._binary_data.charCodeAt(pos++);
-               
-               pos_start_of_segment = pos;
-               
-               if (delim != this._DELIM) {
-                   break;
-               }
-               
-               if (mark === break_segment) {
-                   break;
-               }
-               
-               headersize = JpegMeta.parseNum(">", this._binary_data, pos, 2);
-               
-               /* Find the end */
-               pos += headersize;
-               while (pos < this._binary_data.length) {
-                   delim = this._binary_data.charCodeAt(pos++);
-                   if (delim == this._DELIM) {
-                       _mark = this._binary_data.charCodeAt(pos++);
-                       if (_mark != 0x0) {
-                           pos -= 2;
-                           break;
-                       }
-                   }
-               }
-               
-               segsize = pos - pos_start_of_segment;
-               
-               if (this._markers[mark]) {
-                   mark_code = this._markers[mark][0];
-                   mark_fn = this._markers[mark][1];
-               } else {
-                   mark_code = "UNKN";
-                   mark_fn = undefined;
-               }
-               
-               if (mark_fn) {
-                   this[mark_fn](mark, pos_start_of_segment + 2);
-               }
-               
-           }
-           
-           if (this.general === undefined) {
-               throw Error("Invalid JPEG file.");
-           }
-           
-           return this;
-       };
-       
-       this.JpegMeta.JpegFile.prototype.toString = function () {
-           return "[JpegFile " + this.filename + " " + 
-               this.general.type + " " + 
-               this.general.pixelWidth + "x" + 
-               this.general.pixelHeight +
-               " Depth: " + this.general.depth + "]";
-       };
-       
-       /* Some useful constants */
-       this.JpegMeta.JpegFile.prototype._SOI_MARKER = '\xff\xd8';
-       this.JpegMeta.JpegFile.prototype._DELIM = 0xff;
-       this.JpegMeta.JpegFile.prototype._EOI = 0xd9;
-       this.JpegMeta.JpegFile.prototype._SOS = 0xda;
-       
-       this.JpegMeta.JpegFile.prototype._sofHandler = function _sofHandler (mark, pos) {
-           if (this.general !== undefined) {
-               throw Error("Unexpected multiple-frame image");
-           }
-       
-           this._addMetaGroup("general", "General");
-           this.general._addProperty("depth", "Depth", JpegMeta.parseNum(">", this._binary_data, pos, 1));
-           this.general._addProperty("pixelHeight", "Pixel Height", JpegMeta.parseNum(">", this._binary_data, pos + 1, 2));
-           this.general._addProperty("pixelWidth", "Pixel Width",JpegMeta.parseNum(">", this._binary_data, pos + 3, 2));
-           this.general._addProperty("type", "Type", this._markers[mark][2]);
-       };
-       
-       /* JFIF idents */
-       this.JpegMeta.JpegFile.prototype._JFIF_IDENT = "JFIF\x00";
-       this.JpegMeta.JpegFile.prototype._JFXX_IDENT = "JFXX\x00";
-       
-       /* Exif idents */
-       this.JpegMeta.JpegFile.prototype._EXIF_IDENT = "Exif\x00";
-       
-       /* TIFF types */
-       this.JpegMeta.JpegFile.prototype._types = {
-           /* The format is identifier : ["type name", type_size_in_bytes ] */
-           1 : ["BYTE", 1],
-           2 : ["ASCII", 1],
-           3 : ["SHORT", 2],
-           4 : ["LONG", 4],
-           5 : ["RATIONAL", 8],
-           6 : ["SBYTE", 1],
-           7 : ["UNDEFINED", 1],
-           8 : ["SSHORT", 2],
-           9 : ["SLONG", 4],
-           10 : ["SRATIONAL", 8],
-           11 : ["FLOAT", 4],
-           12 : ["DOUBLE", 8]
-       };
-       
-       this.JpegMeta.JpegFile.prototype._tifftags = {
-           /* A. Tags relating to image data structure */
-           256 : ["Image width", "ImageWidth"],
-           257 : ["Image height", "ImageLength"],
-           258 : ["Number of bits per component", "BitsPerSample"],
-           259 : ["Compression scheme", "Compression", 
-                  {1 : "uncompressed", 6 : "JPEG compression" }],
-           262 : ["Pixel composition", "PhotmetricInerpretation",
-                  {2 : "RGB", 6 : "YCbCr"}],
-           274 : ["Orientation of image", "Orientation",
-                  /* FIXME: Check the mirror-image / reverse encoding and rotation */
-                  {1 : "Normal", 2 : "Reverse?", 
-                   3 : "Upside-down", 4 : "Upside-down Reverse",
-                   5 : "90 degree CW", 6 : "90 degree CW reverse",
-                   7 : "90 degree CCW", 8 : "90 degree CCW reverse"}],
-           277 : ["Number of components", "SamplesPerPixel"],
-           284 : ["Image data arrangement", "PlanarConfiguration",
-                  {1 : "chunky format", 2 : "planar format"}],
-           530 : ["Subsampling ratio of Y to C", "YCbCrSubSampling"],
-           531 : ["Y and C positioning", "YCbCrPositioning",
-                  {1 : "centered", 2 : "co-sited"}],
-           282 : ["X Resolution", "XResolution"],
-           283 : ["Y Resolution", "YResolution"],
-           296 : ["Resolution Unit", "ResolutionUnit",
-                  {2 : "inches", 3 : "centimeters"}],
-           /* B. Tags realting to recording offset */
-           273 : ["Image data location", "StripOffsets"],
-           278 : ["Number of rows per strip", "RowsPerStrip"],
-           279 : ["Bytes per compressed strip", "StripByteCounts"],
-           513 : ["Offset to JPEG SOI", "JPEGInterchangeFormat"],
-           514 : ["Bytes of JPEG Data", "JPEGInterchangeFormatLength"],
-           /* C. Tags relating to image data characteristics */
-           301 : ["Transfer function", "TransferFunction"],
-           318 : ["White point chromaticity", "WhitePoint"],
-           319 : ["Chromaticities of primaries", "PrimaryChromaticities"],
-           529 : ["Color space transformation matrix coefficients", "YCbCrCoefficients"],
-           532 : ["Pair of black and white reference values", "ReferenceBlackWhite"],
-           /* D. Other tags */
-           306 : ["Date and time", "DateTime"],
-           270 : ["Image title", "ImageDescription"],
-           271 : ["Make", "Make"],
-           272 : ["Model", "Model"],
-           305 : ["Software", "Software"],
-           315 : ["Person who created the image", "Artist"],
-           316 : ["Host Computer", "HostComputer"],
-           33432 : ["Copyright holder", "Copyright"],
-           
-           34665 : ["Exif tag", "ExifIfdPointer"],
-           34853 : ["GPS tag", "GPSInfoIfdPointer"]
-       };
-       
-       this.JpegMeta.JpegFile.prototype._exiftags = {
-           /* Tag Support Levels (2) - 0th IFX Exif Private Tags */
-           /* A. Tags Relating to Version */
-           36864 : ["Exif Version", "ExifVersion"],
-           40960 : ["FlashPix Version", "FlashpixVersion"],
-           
-           /* B. Tag Relating to Image Data Characteristics */
-           40961 : ["Color Space", "ColorSpace"],
-           
-           /* C. Tags Relating to Image Configuration */
-           37121 : ["Meaning of each component", "ComponentsConfiguration"],
-           37122 : ["Compressed Bits Per Pixel", "CompressedBitsPerPixel"],
-           40962 : ["Pixel X Dimension", "PixelXDimension"],
-           40963 : ["Pixel Y Dimension", "PixelYDimension"],
-           
-           /* D. Tags Relating to User Information */
-           37500 : ["Manufacturer notes", "MakerNote"],
-           37510 : ["User comments", "UserComment"],
-           
-           /* E. Tag Relating to Related File Information */
-           40964 : ["Related audio file", "RelatedSoundFile"],
-           
-           /* F. Tags Relating to Date and Time */
-           36867 : ["Date Time Original", "DateTimeOriginal"],
-           36868 : ["Date Time Digitized", "DateTimeDigitized"],
-           37520 : ["DateTime subseconds", "SubSecTime"],
-           37521 : ["DateTimeOriginal subseconds", "SubSecTimeOriginal"],
-           37522 : ["DateTimeDigitized subseconds", "SubSecTimeDigitized"],
-           
-           /* G. Tags Relating to Picture-Taking Conditions */
-           33434 : ["Exposure time", "ExposureTime"],
-           33437 : ["FNumber", "FNumber"],
-           34850 : ["Exposure program", "ExposureProgram"],
-           34852 : ["Spectral sensitivity", "SpectralSensitivity"],
-           34855 : ["ISO Speed Ratings", "ISOSpeedRatings"],
-           34856 : ["Optoelectric coefficient", "OECF"],
-           37377 : ["Shutter Speed",  "ShutterSpeedValue"],
-           37378 : ["Aperture Value", "ApertureValue"],
-           37379 : ["Brightness", "BrightnessValue"],
-           37380 : ["Exposure Bias Value", "ExposureBiasValue"],
-           37381 : ["Max Aperture Value", "MaxApertureValue"],
-           37382 : ["Subject Distance", "SubjectDistance"],
-           37383 : ["Metering Mode", "MeteringMode"],
-           37384 : ["Light Source", "LightSource"],
-           37385 : ["Flash", "Flash"],
-           37386 : ["Focal Length", "FocalLength"],
-           37396 : ["Subject Area", "SubjectArea"],
-           41483 : ["Flash Energy", "FlashEnergy"],
-           41484 : ["Spatial Frequency Response", "SpatialFrequencyResponse"],
-           41486 : ["Focal Plane X Resolution", "FocalPlaneXResolution"],
-           41487 : ["Focal Plane Y Resolution", "FocalPlaneYResolution"],
-           41488 : ["Focal Plane Resolution Unit", "FocalPlaneResolutionUnit"],
-           41492 : ["Subject Location", "SubjectLocation"],
-           41493 : ["Exposure Index", "ExposureIndex"],
-           41495 : ["Sensing Method", "SensingMethod"],
-           41728 : ["File Source", "FileSource"],
-           41729 : ["Scene Type", "SceneType"],
-           41730 : ["CFA Pattern", "CFAPattern"],
-           41985 : ["Custom Rendered", "CustomRendered"],
-           41986 : ["Exposure Mode", "Exposure Mode"],
-           41987 : ["White Balance", "WhiteBalance"],
-           41988 : ["Digital Zoom Ratio", "DigitalZoomRatio"],
-           41990 : ["Scene Capture Type", "SceneCaptureType"],
-           41991 : ["Gain Control", "GainControl"],
-           41992 : ["Contrast", "Contrast"],
-           41993 : ["Saturation", "Saturation"],
-           41994 : ["Sharpness", "Sharpness"],
-           41995 : ["Device settings description", "DeviceSettingDescription"],
-           41996 : ["Subject distance range", "SubjectDistanceRange"],
-           
-           /* H. Other Tags */
-           42016 : ["Unique image ID", "ImageUniqueID"],
-           
-           40965 : ["Interoperability tag", "InteroperabilityIFDPointer"]
-       };
-       
-       this.JpegMeta.JpegFile.prototype._gpstags = {
-           /* A. Tags Relating to GPS */
-           0 : ["GPS tag version", "GPSVersionID"],
-           1 : ["North or South Latitude", "GPSLatitudeRef"],
-           2 : ["Latitude", "GPSLatitude"],
-           3 : ["East or West Longitude", "GPSLongitudeRef"],
-           4 : ["Longitude", "GPSLongitude"],
-           5 : ["Altitude reference", "GPSAltitudeRef"],
-           6 : ["Altitude", "GPSAltitude"],
-           7 : ["GPS time (atomic clock)", "GPSTimeStamp"],
-           8 : ["GPS satellites usedd for measurement", "GPSSatellites"],
-           9 : ["GPS receiver status", "GPSStatus"],
-           10 : ["GPS mesaurement mode", "GPSMeasureMode"],
-           11 : ["Measurement precision", "GPSDOP"],
-           12 : ["Speed unit", "GPSSpeedRef"],
-           13 : ["Speed of GPS receiver", "GPSSpeed"],
-           14 : ["Reference for direction of movement", "GPSTrackRef"],
-           15 : ["Direction of movement", "GPSTrack"],
-           16 : ["Reference for direction of image", "GPSImgDirectionRef"],
-           17 : ["Direction of image", "GPSImgDirection"],
-           18 : ["Geodetic survey data used", "GPSMapDatum"],
-           19 : ["Reference for latitude of destination", "GPSDestLatitudeRef"],
-           20 : ["Latitude of destination", "GPSDestLatitude"],
-           21 : ["Reference for longitude of destination", "GPSDestLongitudeRef"],
-           22 : ["Longitude of destination", "GPSDestLongitude"],
-           23 : ["Reference for bearing of destination", "GPSDestBearingRef"],
-           24 : ["Bearing of destination", "GPSDestBearing"],
-           25 : ["Reference for distance to destination", "GPSDestDistanceRef"],
-           26 : ["Distance to destination", "GPSDestDistance"],
-           27 : ["Name of GPS processing method", "GPSProcessingMethod"],
-           28 : ["Name of GPS area", "GPSAreaInformation"],
-           29 : ["GPS Date", "GPSDateStamp"],
-           30 : ["GPS differential correction", "GPSDifferential"]
-       };
-
-       this.JpegMeta.JpegFile.prototype._markers = {
-           /* Start Of Frame markers, non-differential, Huffman coding */
-           0xc0: ["SOF0", "_sofHandler", "Baseline DCT"],
-           0xc1: ["SOF1", "_sofHandler", "Extended sequential DCT"],
-           0xc2: ["SOF2", "_sofHandler", "Progressive DCT"],
-           0xc3: ["SOF3", "_sofHandler", "Lossless (sequential)"],
-           
-           /* Start Of Frame markers, differential, Huffman coding */
-           0xc5: ["SOF5", "_sofHandler", "Differential sequential DCT"],
-           0xc6: ["SOF6", "_sofHandler", "Differential progressive DCT"],
-           0xc7: ["SOF7", "_sofHandler", "Differential lossless (sequential)"],
-           
-           /* Start Of Frame markers, non-differential, arithmetic coding */
-           0xc8: ["JPG", null, "Reserved for JPEG extensions"],
-           0xc9: ["SOF9", "_sofHandler", "Extended sequential DCT"],
-           0xca: ["SOF10", "_sofHandler", "Progressive DCT"],
-           0xcb: ["SOF11", "_sofHandler", "Lossless (sequential)"],
-           
-           /* Start Of Frame markers, differential, arithmetic coding */
-           0xcd: ["SOF13", "_sofHandler", "Differential sequential DCT"],
-           0xce: ["SOF14", "_sofHandler", "Differential progressive DCT"],
-           0xcf: ["SOF15", "_sofHandler", "Differential lossless (sequential)"],
-           
-           /* Huffman table specification */
-           0xc4: ["DHT", null, "Define Huffman table(s)"],
-           0xcc: ["DAC", null, "Define arithmetic coding conditioning(s)"],
-           
-           /* Restart interval termination" */
-           0xd0: ["RST0", null, "Restart with modulo 8 count “0”"],
-           0xd1: ["RST1", null, "Restart with modulo 8 count “1”"],
-           0xd2: ["RST2", null, "Restart with modulo 8 count “2”"],
-           0xd3: ["RST3", null, "Restart with modulo 8 count “3”"],
-           0xd4: ["RST4", null, "Restart with modulo 8 count “4”"],
-           0xd5: ["RST5", null, "Restart with modulo 8 count “5”"],
-           0xd6: ["RST6", null, "Restart with modulo 8 count “6”"],
-           0xd7: ["RST7", null, "Restart with modulo 8 count “7”"],
-           
-           /* Other markers */
-           0xd8: ["SOI", null, "Start of image"],
-           0xd9: ["EOI", null, "End of image"],
-           0xda: ["SOS", null, "Start of scan"],
-           0xdb: ["DQT", null, "Define quantization table(s)"],
-           0xdc: ["DNL", null, "Define number of lines"],
-           0xdd: ["DRI", null, "Define restart interval"],
-           0xde: ["DHP", null, "Define hierarchical progression"],
-           0xdf: ["EXP", null, "Expand reference component(s)"],
-           0xe0: ["APP0", "_app0Handler", "Reserved for application segments"],
-           0xe1: ["APP1", "_app1Handler"],
-           0xe2: ["APP2", null],
-           0xe3: ["APP3", null],
-           0xe4: ["APP4", null],
-           0xe5: ["APP5", null],
-           0xe6: ["APP6", null],
-           0xe7: ["APP7", null],
-           0xe8: ["APP8", null],
-           0xe9: ["APP9", null],
-           0xea: ["APP10", null],
-           0xeb: ["APP11", null],
-           0xec: ["APP12", null],
-           0xed: ["APP13", null],
-           0xee: ["APP14", null],
-           0xef: ["APP15", null],
-           0xf0: ["JPG0", null], /* Reserved for JPEG extensions */
-           0xf1: ["JPG1", null],
-           0xf2: ["JPG2", null],
-           0xf3: ["JPG3", null],
-           0xf4: ["JPG4", null],
-           0xf5: ["JPG5", null],
-           0xf6: ["JPG6", null],
-           0xf7: ["JPG7", null],
-           0xf8: ["JPG8", null],
-           0xf9: ["JPG9", null],
-           0xfa: ["JPG10", null],
-           0xfb: ["JPG11", null],
-           0xfc: ["JPG12", null],
-           0xfd: ["JPG13", null],
-           0xfe: ["COM", null], /* Comment */
-           
-           /* Reserved markers */
-           0x01: ["JPG13", null] /* For temporary private use in arithmetic coding */
-           /* 02 -> bf are reserverd */
-       };
-
-       /* Private methods */
-       this.JpegMeta.JpegFile.prototype._addMetaGroup = function _addMetaGroup(name, description) {
-           var group = new JpegMeta.MetaGroup(name, description);
-           this[group.fieldName] = group;
-           this.metaGroups[group.fieldName] = group;
-           return group;
-       };
-
-       this.JpegMeta.JpegFile.prototype._parseIfd = function _parseIfd(endian, _binary_data, base, ifd_offset, tags, name, description) {
-           var num_fields = JpegMeta.parseNum(endian, _binary_data, base + ifd_offset, 2);
-           /* Per tag variables */
-           var i, j;
-           var tag_base;
-           var tag_field;
-           var type, type_field, type_size;
-           var num_values;
-           var value_offset;
-           var value;
-           var _val;
-           var num;
-           var den;
-           
-           var group;
-           
-           group = this._addMetaGroup(name, description);
-       
-           for (var i = 0; i < num_fields; i++) {
-               /* parse the field */
-               tag_base = base + ifd_offset + 2 + (i * 12);
-               tag_field = JpegMeta.parseNum(endian, _binary_data, tag_base, 2);
-               type_field = JpegMeta.parseNum(endian, _binary_data, tag_base + 2, 2);
-               num_values = JpegMeta.parseNum(endian, _binary_data, tag_base + 4, 4);
-               value_offset = JpegMeta.parseNum(endian, _binary_data, tag_base + 8, 4);
-               if (this._types[type_field] === undefined) {
-                   continue;
-               }
-               type = this._types[type_field][0];
-               type_size = this._types[type_field][1];
-               
-               if (type_size * num_values <= 4) {
-                   /* Data is in-line */
-                   value_offset = tag_base + 8;
-               } else {
-                   value_offset = base + value_offset;
-               }
-               
-               /* Read the value */
-               if (type == "UNDEFINED") {
-                   value = _binary_data.slice(value_offset, value_offset + num_values);
-               } else if (type == "ASCII") {
-                   value = _binary_data.slice(value_offset, value_offset + num_values);
-                   value = value.split('\x00')[0];
-                   /* strip trail nul */
-               } else {
-                   value = new Array();
-                   for (j = 0; j < num_values; j++, value_offset += type_size) {
-                       if (type == "BYTE" || type == "SHORT" || type == "LONG") {
-                           value.push(JpegMeta.parseNum(endian, _binary_data, value_offset, type_size));
-                       }
-                       if (type == "SBYTE" || type == "SSHORT" || type == "SLONG") {
-                           value.push(JpegMeta.parseSnum(endian, _binary_data, value_offset, type_size));
-                       }
-                       if (type == "RATIONAL") {
-                           num = JpegMeta.parseNum(endian, _binary_data, value_offset, 4);
-                           den = JpegMeta.parseNum(endian, _binary_data, value_offset + 4, 4);
-                           value.push(new JpegMeta.Rational(num, den));
-                       }
-                       if (type == "SRATIONAL") {
-                           num = JpegMeta.parseSnum(endian, _binary_data, value_offset, 4);
-                           den = JpegMeta.parseSnum(endian, _binary_data, value_offset + 4, 4);
-                           value.push(new JpegMeta.Rational(num, den));
-                       }
-                       value.push();
-                   }
-                   if (num_values === 1) {
-                       value = value[0];
-                   }
-               }
-               if (tags[tag_field] !== undefined) {
-                       group._addProperty(tags[tag_field][1], tags[tag_field][0], value);
-               }
-           }
-       };
-
-       this.JpegMeta.JpegFile.prototype._jfifHandler = function _jfifHandler(mark, pos) {
-           if (this.jfif !== undefined) {
-               throw Error("Multiple JFIF segments found");
-           }
-           this._addMetaGroup("jfif", "JFIF");
-           this.jfif._addProperty("version_major", "Version Major", this._binary_data.charCodeAt(pos + 5));
-           this.jfif._addProperty("version_minor", "Version Minor", this._binary_data.charCodeAt(pos + 6));
-           this.jfif._addProperty("version", "JFIF Version", this.jfif.version_major.value + "." + this.jfif.version_minor.value);
-           this.jfif._addProperty("units", "Density Unit", this._binary_data.charCodeAt(pos + 7));
-           this.jfif._addProperty("Xdensity", "X density", JpegMeta.parseNum(">", this._binary_data, pos + 8, 2));
-           this.jfif._addProperty("Ydensity", "Y Density", JpegMeta.parseNum(">", this._binary_data, pos + 10, 2));
-           this.jfif._addProperty("Xthumbnail", "X Thumbnail", JpegMeta.parseNum(">", this._binary_data, pos + 12, 1));
-           this.jfif._addProperty("Ythumbnail", "Y Thumbnail", JpegMeta.parseNum(">", this._binary_data, pos + 13, 1));
-       };
-
-       /* Handle app0 segments */
-       this.JpegMeta.JpegFile.prototype._app0Handler = function app0Handler(mark, pos) {
-           var ident = this._binary_data.slice(pos, pos + 5);
-           if (ident == this._JFIF_IDENT) {
-               this._jfifHandler(mark, pos);
-           } else if (ident == this._JFXX_IDENT) {
-               /* Don't handle JFXX Ident yet */
-           } else {
-               /* Don't know about other idents */
-           }
-       };
-
-       /* Handle app1 segments */
-       this.JpegMeta.JpegFile.prototype._app1Handler = function _app1Handler(mark, pos) {
-           var ident = this._binary_data.slice(pos, pos + 5);
-           if (ident == this._EXIF_IDENT) {
-               this._exifHandler(mark, pos + 6);
-           } else {
-               /* Don't know about other idents */
-           }
-       };
-
-       /* Handle exif segments */
-       JpegMeta.JpegFile.prototype._exifHandler = function _exifHandler(mark, pos) {
-           if (this.exif !== undefined) {
-               throw new Error("Multiple JFIF segments found");
-           }
-           
-           /* Parse this TIFF header */
-           var endian;
-           var magic_field;
-           var ifd_offset;
-           var primary_ifd, exif_ifd, gps_ifd;
-           var endian_field = this._binary_data.slice(pos, pos + 2);
-           
-           /* Trivia: This 'I' is for Intel, the 'M' is for Motorola */
-           if (endian_field === "II") {
-               endian = "<";
-           } else if (endian_field === "MM") {
-               endian = ">";
-           } else {
-               throw new Error("Malformed TIFF meta-data. Unknown endianess: " + endian_field);
-           }
-           
-           magic_field = JpegMeta.parseNum(endian, this._binary_data, pos + 2, 2);
-           
-           if (magic_field !== 42) {
-               throw new Error("Malformed TIFF meta-data. Bad magic: " + magic_field);
-           }
-           
-           ifd_offset = JpegMeta.parseNum(endian, this._binary_data, pos + 4, 4);
-           
-           /* Parse 0th IFD */
-           this._parseIfd(endian, this._binary_data, pos, ifd_offset, this._tifftags, "tiff", "TIFF");
-           
-           if (this.tiff.ExifIfdPointer) {
-               this._parseIfd(endian, this._binary_data, pos, this.tiff.ExifIfdPointer.value, this._exiftags, "exif", "Exif");
-           }
-           
-           if (this.tiff.GPSInfoIfdPointer) {
-               this._parseIfd(endian, this._binary_data, pos, this.tiff.GPSInfoIfdPointer.value, this._gpstags, "gps", "GPS");
-               if (this.gps.GPSLatitude) {
-                   var latitude;
-                   latitude = this.gps.GPSLatitude.value[0].asFloat() + 
-                       (1 / 60) * this.gps.GPSLatitude.value[1].asFloat() + 
-                       (1 / 3600) * this.gps.GPSLatitude.value[2].asFloat();
-                   if (this.gps.GPSLatitudeRef.value === "S") {
-                       latitude = -latitude;
-                   }
-                   this.gps._addProperty("latitude", "Dec. Latitude", latitude);
-               }
-               if (this.gps.GPSLongitude) {
-                   var longitude;
-                   longitude = this.gps.GPSLongitude.value[0].asFloat() + 
-                       (1 / 60) * this.gps.GPSLongitude.value[1].asFloat() + 
-                       (1 / 3600) * this.gps.GPSLongitude.value[2].asFloat();
-                   if (this.gps.GPSLongitudeRef.value === "W") {
-                       longitude = -longitude;
-                   }
-                   this.gps._addProperty("longitude", "Dec. Longitude", longitude);
-               }
-           }
-       };
-
-       // MediaWiki: Add mw.libs wrapper
-       mw.libs.jpegmeta = function( fileReaderResult, fileName ) {
-               return new JpegMeta.JpegFile( fileReaderResult, fileName );
-       };
-
-}() );
diff --git a/resources/mediawiki.page/mediawiki.page.gallery.js b/resources/mediawiki.page/mediawiki.page.gallery.js
deleted file mode 100644 (file)
index f92d372..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/**
- * Show gallery captions when focused. Copied directly from jquery.mw-jump.js.
- * Also Dynamically resize images to justify them.
- */
-( function ( $, mw ) {
-       $( function () {
-               var isTouchScreen,
-                       gettingFocus,
-                       galleries = 'ul.mw-gallery-packed-overlay, ul.mw-gallery-packed-hover, ul.mw-gallery-packed';
-
-               // Is there a better way to detect a touchscreen? Current check taken from stack overflow.
-               isTouchScreen = !!( window.ontouchstart !== undefined || window.DocumentTouch !== undefined && document instanceof window.DocumentTouch );
-
-               if ( isTouchScreen ) {
-                       // Always show the caption for a touch screen.
-                       $( 'ul.mw-gallery-packed-hover' )
-                               .addClass( 'mw-gallery-packed-overlay' )
-                               .removeClass( 'mw-gallery-packed-hover' );
-               } else {
-                       // Note use of just "a", not a.image, since we want this to trigger if a link in
-                       // the caption receives focus
-                       $( 'ul.mw-gallery-packed-hover li.gallerybox' ).on( 'focus blur', 'a', function ( e ) {
-                               // Confusingly jQuery leaves e.type as focusout for delegated blur events
-                               gettingFocus = e.type !== 'blur' && e.type !== 'focusout';
-                               $( this ).closest( 'li.gallerybox' ).toggleClass( 'mw-gallery-focused', gettingFocus );
-                       } );
-               }
-
-               // Now on to justification.
-               // We may still get ragged edges if someone resizes their window. Could bind to
-               // that event, otoh do we really want to constantly be resizing galleries?
-               $( galleries ).each( function () {
-                       var lastTop,
-                               $img,
-                               imgWidth,
-                               imgHeight,
-                               rows = [],
-                               $gallery = $( this );
-
-                       $gallery.children( 'li' ).each( function () {
-                               // Math.floor to be paranoid if things are off by 0.00000000001
-                               var top = Math.floor( $( this ).position().top ),
-                                       $this = $( this );
-
-                               if ( top !== lastTop ) {
-                                       rows[rows.length] = [];
-                                       lastTop = top;
-                               }
-
-                               $img = $this.find( 'div.thumb a.image img' );
-                               if ( $img.length && $img[0].height ) {
-                                       imgHeight = $img[0].height;
-                                       imgWidth = $img[0].width;
-                               } else {
-                                       // If we don't have a real image, get the containing divs width/height.
-                                       // Note that if we do have a real image, using this method will generally
-                                       // give the same answer, but can be different in the case of a very
-                                       // narrow image where extra padding is added.
-                                       imgHeight = $this.children().children( 'div:first' ).height();
-                                       imgWidth = $this.children().children( 'div:first' ).width();
-                               }
-
-                               // Hack to make an edge case work ok
-                               if ( imgHeight < 30 ) {
-                                       // Don't try and resize this item.
-                                       imgHeight = 0;
-                               }
-
-                               rows[rows.length - 1][rows[rows.length - 1].length] = {
-                                       $elm: $this,
-                                       width: $this.outerWidth(),
-                                       imgWidth: imgWidth,
-                                       // XXX: can divide by 0 ever happen?
-                                       aspect: imgWidth / imgHeight,
-                                       captionWidth: $this.children().children( 'div.gallerytextwrapper' ).width(),
-                                       height: imgHeight
-                               };
-                       } );
-
-                       ( function () {
-                               var maxWidth,
-                                       combinedAspect,
-                                       combinedPadding,
-                                       curRow,
-                                       curRowHeight,
-                                       wantedWidth,
-                                       preferredHeight,
-                                       newWidth,
-                                       padding,
-                                       $outerDiv,
-                                       $innerDiv,
-                                       $imageDiv,
-                                       $imageElm,
-                                       imageElm,
-                                       $caption,
-                                       hookInfo,
-                                       i,
-                                       j,
-                                       avgZoom,
-                                       totalZoom = 0;
-
-                               for ( i = 0; i < rows.length; i++ ) {
-                                       maxWidth = $gallery.width();
-                                       combinedAspect = 0;
-                                       combinedPadding = 0;
-                                       curRow = rows[i];
-                                       curRowHeight = 0;
-
-                                       for ( j = 0; j < curRow.length; j++ ) {
-                                               if ( curRowHeight === 0 ) {
-                                                       if ( isFinite( curRow[j].height ) ) {
-                                                               // Get the height of this row, by taking the first
-                                                               // non-out of bounds height
-                                                               curRowHeight = curRow[j].height;
-                                                       }
-                                               }
-
-                                               if ( curRow[j].aspect === 0 || !isFinite( curRow[j].aspect ) ) {
-                                                       mw.log( 'Skipping item ' + j + ' due to aspect: ' + curRow[j].aspect );
-                                                       // One of the dimensions are 0. Probably should
-                                                       // not try to resize.
-                                                       combinedPadding += curRow[j].width;
-                                               } else {
-                                                       combinedAspect += curRow[j].aspect;
-                                                       combinedPadding += curRow[j].width - curRow[j].imgWidth;
-                                               }
-                                       }
-
-                                       // Add some padding for inter-element spacing.
-                                       combinedPadding += 5 * curRow.length;
-                                       wantedWidth = maxWidth - combinedPadding;
-                                       preferredHeight = wantedWidth / combinedAspect;
-
-                                       if ( preferredHeight > curRowHeight * 1.5 ) {
-                                               // Only expand at most 1.5 times current size
-                                               // As that's as high a resolution as we have.
-                                               // Also on the off chance there is a bug in this
-                                               // code, would prevent accidentally expanding to
-                                               // be 10 billion pixels wide.
-                                               mw.log( 'mw.page.gallery: Cannot fit row, aspect is ' + preferredHeight / curRowHeight );
-                                               if ( i === rows.length - 1 ) {
-                                                       // If its the last row, and we can't fit it,
-                                                       // don't make the entire row huge.
-                                                       avgZoom = ( totalZoom / ( rows.length - 1 ) ) * curRowHeight;
-                                                       if ( isFinite( avgZoom ) && avgZoom >= 1 && avgZoom <= 1.5 ) {
-                                                               preferredHeight = avgZoom;
-                                                       } else {
-                                                               // Probably a single row gallery
-                                                               preferredHeight = curRowHeight;
-                                                       }
-                                               } else {
-                                                       preferredHeight = 1.5 * curRowHeight;
-                                               }
-                                       }
-                                       if ( !isFinite( preferredHeight ) ) {
-                                               // This *definitely* should not happen.
-                                               mw.log( 'mw.page.gallery: Trying to resize row ' + i + ' to ' + preferredHeight + '?!' );
-                                               // Skip this row.
-                                               continue;
-                                       }
-                                       if ( preferredHeight < 5 ) {
-                                               // Well something clearly went wrong...
-                                               mw.log( {
-                                                       maxWidth: maxWidth,
-                                                       combinedPadding: combinedPadding,
-                                                       combinedAspect: combinedAspect,
-                                                       wantedWidth: wantedWidth
-                                               } );
-                                               mw.log( 'mw.page.gallery: [BUG!] Fitting row ' + i + ' to too small a size: ' + preferredHeight );
-                                               // Skip this row.
-                                               continue;
-                                       }
-
-                                       if ( preferredHeight / curRowHeight > 1 ) {
-                                               totalZoom += preferredHeight / curRowHeight;
-                                       } else {
-                                               // If we shrink, still consider that a zoom of 1
-                                               totalZoom += 1;
-                                       }
-
-                                       for ( j = 0; j < curRow.length; j++ ) {
-                                               newWidth = preferredHeight * curRow[j].aspect;
-                                               padding = curRow[j].width - curRow[j].imgWidth;
-                                               $outerDiv = curRow[j].$elm;
-                                               $innerDiv = $outerDiv.children( 'div' ).first();
-                                               $imageDiv = $innerDiv.children( 'div.thumb' );
-                                               $imageElm = $imageDiv.find( 'img' ).first();
-                                               imageElm = $imageElm.length ? $imageElm[0] : null;
-                                               $caption = $outerDiv.find( 'div.gallerytextwrapper' );
-
-                                               // Since we are going to re-adjust the height, the vertical
-                                               // centering margins need to be reset.
-                                               $imageDiv.children( 'div' ).css( 'margin', '0px auto' );
-
-                                               if ( newWidth < 60 || !isFinite( newWidth ) ) {
-                                                       // Making something skinnier than this will mess up captions,
-                                                       mw.log( 'mw.page.gallery: Tried to make image ' + newWidth + 'px wide but too narrow.' );
-                                                       if ( newWidth < 1 || !isFinite( newWidth ) ) {
-                                                               $innerDiv.height( preferredHeight );
-                                                               // Don't even try and touch the image size if it could mean
-                                                               // making it disappear.
-                                                               continue;
-                                                       }
-                                               } else {
-                                                       $outerDiv.width( newWidth + padding );
-                                                       $innerDiv.width( newWidth + padding );
-                                                       $imageDiv.width( newWidth );
-                                                       $caption.width( curRow[j].captionWidth + ( newWidth - curRow[j].imgWidth ) );
-                                               }
-
-                                               hookInfo = {
-                                                       fullWidth: newWidth + padding,
-                                                       imgWidth: newWidth,
-                                                       imgHeight: preferredHeight,
-                                                       $innerDiv: $innerDiv,
-                                                       $imageDiv: $imageDiv,
-                                                       $outerDiv: $outerDiv,
-                                                       // Whether the hook took action
-                                                       resolved: false
-                                               };
-
-                                               /**
-                                                * Gallery resize.
-                                                *
-                                                * If your handler resizes an image, it should also set the resolved
-                                                * property to true. Additionally, because this module only exposes this
-                                                * logic temporarily, you should load your module in position top to
-                                                * ensure it is registered before this runs (FIXME: Don't use mw.hook)
-                                                *
-                                                * See TimedMediaHandler for an example.
-                                                *
-                                                * @event mediawiki_page_gallery_resize
-                                                * @member mw.hook
-                                                * @param {Object} hookInfo
-                                                */
-                                               mw.hook( 'mediawiki.page.gallery.resize' ).fire( hookInfo );
-
-                                               if ( !hookInfo.resolved ) {
-                                                       if ( imageElm ) {
-                                                               // We don't always have an img, e.g. in the case of an invalid file.
-                                                               imageElm.width = newWidth;
-                                                               imageElm.height = preferredHeight;
-                                                       } else {
-                                                               // Not a file box.
-                                                               $imageDiv.height( preferredHeight );
-                                                       }
-                                               }
-                                       }
-                               }
-                       } )();
-               } );
-       } );
-} )( jQuery, mediaWiki );
diff --git a/resources/mediawiki.page/mediawiki.page.image.pagination.js b/resources/mediawiki.page/mediawiki.page.image.pagination.js
deleted file mode 100644 (file)
index 50301bd..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Change multi-page image navigation so that the current page display can be changed
- * without a page reload. Currently, the only image formats that can be multi-page images are
- * PDF and DjVu files
- */
-( function ( mw, $ ) {
-
-       // Initialize ajax request variable
-       var xhr;
-
-       // Use jQuery's load function to specifically select and replace table.multipageimage's child
-       // tr with the new page's table.multipageimage's tr element.
-       // table.multipageimage always has only one row.
-       function loadPage( page, hist ) {
-               if ( xhr ) {
-                       // Abort previous requests to prevent backlog created by
-                       // repeatedly pressing back/forwards buttons
-                       xhr.abort();
-               }
-
-               var $multipageimage = $( 'table.multipageimage' ),
-                       $spinner;
-
-               // Add a new spinner if one doesn't already exist
-               if ( !$multipageimage.find( '.mw-spinner' ).length ) {
-
-                       $spinner = $.createSpinner( {
-                               size: 'large',
-                               type: 'block'
-                       } )
-                               // Set the spinner's dimensions equal to the table's dimensions so that
-                               // the current scroll position is not lost after the table is emptied prior to
-                               // its contents being updated
-                               .css( {
-                                       height: $multipageimage.find( 'tr' ).height(),
-                                       width: $multipageimage.find( 'tr' ).width()
-                               } );
-
-                       $multipageimage.empty().append( $spinner );
-               }
-
-               xhr = $.ajax( {
-                       url: page,
-                       success: function ( data ) {
-                               // Load the page
-                               $multipageimage.empty().append( $( data ).find( 'table.multipageimage tr' ) );
-                               // Fire hook because the page's content has changed
-                               mw.hook( 'wikipage.content' ).fire( $multipageimage );
-                               // Set up the new page for pagination
-                               ajaxifyPageNavigation();
-                               // Add new page of image to history.  To preserve the back-forwards chain in the browser,
-                               // if the user gets here via the back/forward button, don't update the history.
-                               if ( window.history && history.pushState && !hist ) {
-                                       history.pushState( { url: page }, document.title, page );
-                               }
-                       }
-               } );
-       }
-
-       function ajaxifyPageNavigation() {
-               // Intercept the default action of the links in the thumbnail navigation
-               $( '.multipageimagenavbox' ).one( 'click', 'a', function ( e ) {
-                       loadPage( this.href );
-                       e.preventDefault();
-               } );
-
-               // Prevent the submission of the page select form and instead call loadPage
-               $( 'form[name="pageselector"]' ).one( 'change submit', function ( e ) {
-                       loadPage( this.action + '?' + $( this ).serialize() );
-                       e.preventDefault();
-               } );
-       }
-
-       $( document ).ready( function () {
-               // The presence of table.multipageimage signifies that this file is a multi-page image
-               if ( mw.config.get( 'wgNamespaceNumber' ) === 6 && $( 'table.multipageimage' ).length !== 0 ) {
-                       ajaxifyPageNavigation();
-
-                       // Set up history.pushState (if available), so that when the user browses to a new page of
-                       // the same file, the browser's history is updated. If the user clicks the back/forward button
-                       // in the midst of navigating a file's pages, load the page inline.
-                       if ( window.history && history.pushState && history.replaceState ) {
-                               history.replaceState( { url: window.location.href }, '' );
-                               $( window ).on( 'popstate', function ( e ) {
-                                       var state = e.originalEvent.state;
-                                       if ( state ) {
-                                               loadPage( state.url, true );
-                                       }
-                               } );
-                       }
-               }
-       } );
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.page/mediawiki.page.patrol.ajax.js b/resources/mediawiki.page/mediawiki.page.patrol.ajax.js
deleted file mode 100644 (file)
index 5fb14dd..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Animate patrol links to use asynchronous API requests to
- * patrol pages, rather than navigating to a different URI.
- *
- * @since 1.21
- * @author Marius Hoch <hoo@online.de>
- */
-( function ( mw, $ ) {
-       if ( !mw.user.tokens.exists( 'patrolToken' ) ) {
-               // Current user has no patrol right, or an old cached version of user.tokens
-               // that didn't have patrolToken yet.
-               return;
-       }
-       $( function () {
-               var $patrolLinks = $( '.patrollink a' );
-               $patrolLinks.on( 'click', function ( e ) {
-                       var $spinner, href, rcid, apiRequest;
-
-                       // Start preloading the notification module (normally loaded by mw.notify())
-                       mw.loader.load( ['mediawiki.notification'], null, true );
-
-                       // Hide the link and create a spinner to show it inside the brackets.
-                       $spinner = $.createSpinner( {
-                               size: 'small',
-                               type: 'inline'
-                       } );
-                       $( this ).hide().after( $spinner );
-
-                       href = $( this ).attr( 'href' );
-                       rcid = mw.util.getParamValue( 'rcid', href );
-                       apiRequest = new mw.Api();
-
-                       apiRequest.post( {
-                               action: 'patrol',
-                               token: mw.user.tokens.get( 'patrolToken' ),
-                               rcid: rcid
-                       } )
-                       .done( function ( data ) {
-                               // Remove all patrollinks from the page (including any spinners inside).
-                               $patrolLinks.closest( '.patrollink' ).remove();
-                               if ( data.patrol !== undefined ) {
-                                       // Success
-                                       var title = new mw.Title( data.patrol.title );
-                                       mw.notify( mw.msg( 'markedaspatrollednotify', title.toText() ) );
-                               } else {
-                                       // This should never happen as errors should trigger fail
-                                       mw.notify( mw.msg( 'markedaspatrollederrornotify' ) );
-                               }
-                       } )
-                       .fail( function ( error ) {
-                               $spinner.remove();
-                               // Restore the patrol link. This allows the user to try again
-                               // (or open it in a new window, bypassing this ajax module).
-                               $patrolLinks.show();
-                               if ( error === 'noautopatrol' ) {
-                                       // Can't patrol own
-                                       mw.notify( mw.msg( 'markedaspatrollederror-noautopatrol' ) );
-                               } else {
-                                       mw.notify( mw.msg( 'markedaspatrollederrornotify' ) );
-                               }
-                       } );
-
-                       e.preventDefault();
-               } );
-       } );
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.page/mediawiki.page.ready.js b/resources/mediawiki.page/mediawiki.page.ready.js
deleted file mode 100644 (file)
index ccddb3e..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-( function ( mw, $ ) {
-       var supportsPlaceholder = 'placeholder' in document.createElement( 'input' );
-
-       mw.hook( 'wikipage.content' ).add( function ( $content ) {
-               var $sortableTables;
-
-               // Run jquery.placeholder polyfill if placeholder is not supported
-               if ( !supportsPlaceholder ) {
-                       $content.find( 'input[placeholder]' ).placeholder();
-               }
-
-               // Run jquery.makeCollapsible
-               $content.find( '.mw-collapsible' ).makeCollapsible();
-
-               // Lazy load jquery.tablesorter
-               $sortableTables = $content.find( 'table.sortable' );
-               if ( $sortableTables.length ) {
-                       mw.loader.using( 'jquery.tablesorter', function () {
-                               $sortableTables.tablesorter();
-                       } );
-               }
-
-               // Run jquery.checkboxShiftClick
-               $content.find( 'input[type="checkbox"]:not(.noshiftselect)' ).checkboxShiftClick();
-       } );
-
-       // Things outside the wikipage content
-       $( function () {
-
-               if ( !supportsPlaceholder ) {
-                       // Exclude content to avoid hitting it twice for the (first) wikipage content
-                       $( 'input[placeholder]' ).not( '#mw-content-text input' ).placeholder();
-               }
-
-               // Add accesskey hints to the tooltips
-               mw.util.updateTooltipAccessKeys();
-
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.page/mediawiki.page.startup.js b/resources/mediawiki.page/mediawiki.page.startup.js
deleted file mode 100644 (file)
index e354106..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-( function ( mw, $ ) {
-
-       mw.page = {};
-
-       // Client profile classes for <html>
-       // Allows for easy hiding/showing of JS or no-JS-specific UI elements
-       $( 'html' )
-               .addClass( 'client-js' )
-               .removeClass( 'client-nojs' );
-
-       $( function () {
-               // Initialize utilities as soon as the document is ready (mw.util.$content,
-               // messageBoxNew, profile, tooltip access keys, Table of contents toggle, ..).
-               // In the domready here instead of in mediawiki.page.ready to ensure that it gets enqueued
-               // before other modules hook into domready, so that mw.util.$content (defined by
-               // mw.util.init), is defined for them.
-               mw.util.init();
-
-               /**
-                * Fired when wiki content is being added to the DOM
-                *
-                * It is encouraged to fire it before the main DOM is changed (when $content
-                * is still detatched).  However, this order is not defined either way, so you
-                * should only rely on $content itself.
-                *
-                * This includes the ready event on a page load (including post-edit loads)
-                * and when content has been previewed with LivePreview.
-                *
-                * @event wikipage_content
-                * @member mw.hook
-                * @param {jQuery} $content The most appropriate element containing the content,
-                *   such as #mw-content-text (regular content root) or #wikiPreview (live preview
-                *   root)
-                */
-               mw.hook( 'wikipage.content' ).fire( $( '#mw-content-text' ) );
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.page/mediawiki.page.watch.ajax.js b/resources/mediawiki.page/mediawiki.page.watch.ajax.js
deleted file mode 100644 (file)
index 850177f..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * Animate watch/unwatch links to use asynchronous API requests to
- * watch pages, rather than navigating to a different URI.
- *
- * @class mw.page.watch.ajax
- */
-( function ( mw, $ ) {
-       // The name of the page to watch or unwatch
-       var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) );
-
-       /**
-        * Update the link text, link href attribute and (if applicable)
-        * "loading" class.
-        *
-        * @param {jQuery} $link Anchor tag of (un)watch link
-        * @param {string} action One of 'watch', 'unwatch'
-        * @param {string} [state="idle"] 'idle' or 'loading'. Default is 'idle'
-        */
-       function updateWatchLink( $link, action, state ) {
-               var accesskeyTip, msgKey, $li, otherAction;
-
-               // A valid but empty jQuery object shouldn't throw a TypeError
-               if ( !$link.length ) {
-                       return;
-               }
-
-               // Invalid actions shouldn't silently turn the page in an unrecoverable state
-               if ( action !== 'watch' && action !== 'unwatch' ) {
-                       throw new Error( 'Invalid action' );
-               }
-
-               // message keys 'watch', 'watching', 'unwatch' or 'unwatching'.
-               msgKey = state === 'loading' ? action + 'ing' : action;
-               otherAction = action === 'watch' ? 'unwatch' : 'watch';
-               accesskeyTip = $link.attr( 'title' ).match( mw.util.tooltipAccessKeyRegexp );
-               $li = $link.closest( 'li' );
-
-               // Trigger a 'watchpage' event for this List item.
-               // Announce the otherAction value as the first param.
-               // Used to monitor the state of watch link.
-               // TODO: Revise when system wide hooks are implemented
-               if ( state === undefined ) {
-                       $li.trigger( 'watchpage.mw', otherAction );
-               }
-
-               $link
-                       .text( mw.msg( msgKey ) )
-                       .attr( 'title', mw.msg( 'tooltip-ca-' + action ) +
-                               ( accesskeyTip ? ' ' + accesskeyTip[0] : '' )
-                       )
-                       .attr( 'href', mw.util.wikiScript() + '?' + $.param( {
-                                       title: title,
-                                       action: action
-                               } )
-                       );
-
-               // Most common ID style
-               if ( $li.prop( 'id' ) === 'ca-' + otherAction ) {
-                       $li.prop( 'id', 'ca-' + action );
-               }
-
-               // Special case for vector icon
-               if ( $li.hasClass( 'icon' ) ) {
-                       if ( state === 'loading' ) {
-                               $link.addClass( 'loading' );
-                       } else {
-                               $link.removeClass( 'loading' );
-                       }
-               }
-       }
-
-       /**
-        * TODO: This should be moved somewhere more accessible.
-        *
-        * @private
-        * @param {string} url
-        * @return {string} The extracted action, defaults to 'view'
-        */
-       function mwUriGetAction( url ) {
-               var action, actionPaths, key, i, m, parts;
-
-               // TODO: Does MediaWiki give action path or query param
-               // precedence? If the former, move this to the bottom
-               action = mw.util.getParamValue( 'action', url );
-               if ( action !== null ) {
-                       return action;
-               }
-
-               actionPaths = mw.config.get( 'wgActionPaths' );
-               for ( key in actionPaths ) {
-                       if ( actionPaths.hasOwnProperty( key ) ) {
-                               parts = actionPaths[key].split( '$1' );
-                               for ( i = 0; i < parts.length; i++ ) {
-                                       parts[i] = $.escapeRE( parts[i] );
-                               }
-                               m = new RegExp( parts.join( '(.+)' ) ).exec( url );
-                               if ( m && m[1] ) {
-                                       return key;
-                               }
-
-                       }
-               }
-
-               return 'view';
-       }
-
-       // Expose public methods
-       mw.page.watch = {
-               updateWatchLink: updateWatchLink
-       };
-
-       $( function () {
-               var $links = $( '.mw-watchlink a, a.mw-watchlink, ' +
-                       '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' +
-                       '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' );
-
-               // Allowing people to add inline animated links is a little scary
-               $links = $links.filter( ':not( #bodyContent *, #content * )' );
-
-               $links.click( function ( e ) {
-                       var action, api, $link;
-
-                       // Start preloading the notification module (normally loaded by mw.notify())
-                       mw.loader.load( ['mediawiki.notification'], null, true );
-
-                       action = mwUriGetAction( this.href );
-
-                       if ( action !== 'watch' && action !== 'unwatch' ) {
-                               // Could not extract target action from link url,
-                               // let native browsing handle it further
-                               return true;
-                       }
-                       e.preventDefault();
-                       e.stopPropagation();
-
-                       $link = $( this );
-
-                       updateWatchLink( $link, action, 'loading' );
-
-                       api = new mw.Api();
-
-                       api[action]( title )
-                               .done( function ( watchResponse ) {
-                                       var otherAction = action === 'watch' ? 'unwatch' : 'watch';
-
-                                       mw.notify( $.parseHTML( watchResponse.message ), {
-                                               tag: 'watch-self'
-                                       } );
-
-                                       // Set link to opposite
-                                       updateWatchLink( $link, otherAction );
-
-                                       // Update the "Watch this page" checkbox on action=edit when the
-                                       // page is watched or unwatched via the tab (bug 12395).
-                                       $( '#wpWatchthis' ).prop( 'checked', watchResponse.watched !== undefined );
-                               } )
-                               .fail( function () {
-                                       var cleanTitle, msg, link;
-
-                                       // Reset link to non-loading mode
-                                       updateWatchLink( $link, action );
-
-                                       // Format error message
-                                       cleanTitle = title.replace( /_/g, ' ' );
-                                       link = mw.html.element(
-                                               'a', {
-                                                       href: mw.util.getUrl( title ),
-                                                       title: cleanTitle
-                                               }, cleanTitle
-                                       );
-                                       msg = mw.message( 'watcherrortext', link );
-
-                                       // Report to user about the error
-                                       mw.notify( msg, { tag: 'watch-self' } );
-                               } );
-               } );
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.special/images/glyph-people-large.png b/resources/mediawiki.special/images/glyph-people-large.png
deleted file mode 100644 (file)
index 0578be0..0000000
Binary files a/resources/mediawiki.special/images/glyph-people-large.png and /dev/null differ
diff --git a/resources/mediawiki.special/images/icon-contributors.png b/resources/mediawiki.special/images/icon-contributors.png
deleted file mode 100644 (file)
index f933aa6..0000000
Binary files a/resources/mediawiki.special/images/icon-contributors.png and /dev/null differ
diff --git a/resources/mediawiki.special/images/icon-edits.png b/resources/mediawiki.special/images/icon-edits.png
deleted file mode 100644 (file)
index 39f4f2d..0000000
Binary files a/resources/mediawiki.special/images/icon-edits.png and /dev/null differ
diff --git a/resources/mediawiki.special/images/icon-lock.png b/resources/mediawiki.special/images/icon-lock.png
deleted file mode 100644 (file)
index 03f0eec..0000000
Binary files a/resources/mediawiki.special/images/icon-lock.png and /dev/null differ
diff --git a/resources/mediawiki.special/images/icon-pages.png b/resources/mediawiki.special/images/icon-pages.png
deleted file mode 100644 (file)
index 59513db..0000000
Binary files a/resources/mediawiki.special/images/icon-pages.png and /dev/null differ
diff --git a/resources/mediawiki.special/mediawiki.special.block.css b/resources/mediawiki.special/mediawiki.special.block.css
deleted file mode 100644 (file)
index 899a9f3..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Styling for Special:Block
- */
-
-label[for="mw-input-wpConfirm"] {
-       font-weight: bold;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.block.js b/resources/mediawiki.special/mediawiki.special.block.js
deleted file mode 100644 (file)
index 8dedb9b..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * JavaScript for Special:Block
- */
-( function ( mw, $ ) {
-       $( function () {
-               var $blockTarget = $( '#mw-bi-target' ),
-                       $anonOnlyRow = $( '#mw-input-wpHardBlock' ).closest( 'tr' ),
-                       $enableAutoblockRow = $( '#mw-input-wpAutoBlock' ).closest( 'tr' ),
-                       $hideUser = $( '#mw-input-wpHideUser' ).closest( 'tr' ),
-                       $watchUser = $( '#mw-input-wpWatch' ).closest( 'tr' );
-
-               function updateBlockOptions( instant ) {
-                       var blocktarget = $.trim( $blockTarget.val() ),
-                               isEmpty = blocktarget === '',
-                               isIp = mw.util.isIPv4Address( blocktarget, true ) || mw.util.isIPv6Address( blocktarget, true ),
-                               isIpRange = isIp && blocktarget.match( /\/\d+$/ );
-
-                       if ( isIp && !isEmpty ) {
-                               $enableAutoblockRow.goOut( instant );
-                               $hideUser.goOut( instant );
-                       } else {
-                               $enableAutoblockRow.goIn( instant );
-                               $hideUser.goIn( instant );
-                       }
-                       if ( !isIp && !isEmpty ) {
-                               $anonOnlyRow.goOut( instant );
-                       } else {
-                               $anonOnlyRow.goIn( instant );
-                       }
-                       if ( isIpRange && !isEmpty ) {
-                               $watchUser.goOut( instant );
-                       } else {
-                               $watchUser.goIn( instant );
-                       }
-               }
-
-               if ( $blockTarget.length ) {
-                       // Bind functions so they're checked whenever stuff changes
-                       $blockTarget.keyup( updateBlockOptions );
-
-                       // Call them now to set initial state (ie. Special:Block/Foobar?wpBlockExpiry=2+hours)
-                       updateBlockOptions( /* instant= */ true );
-               }
-       } );
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.special/mediawiki.special.changeemail.css b/resources/mediawiki.special/mediawiki.special.changeemail.css
deleted file mode 100644 (file)
index 9461fbd..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#mw-emailaddress-validity {
-       padding: 2px 1em;
-}
-#mw-emailaddress-validity {
-       border-bottom-right-radius: 0.8em;
-       border-top-right-radius: 0.8em;
-}
-
-/** colors also used in mediawiki.special.preferences.css */
-#mw-emailaddress-validity.valid {
-       border: 1px solid #80FF80;
-       background-color: #C0FFC0;
-       color: black;
-}
-#mw-emailaddress-validity.invalid {
-       border: 1px solid #FF8080;
-       background-color: #FFC0C0;
-       color: black;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.changeemail.js b/resources/mediawiki.special/mediawiki.special.changeemail.js
deleted file mode 100644 (file)
index bc2a0a2..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * JavaScript for Special:ChangeEmail
- */
-( function ( mw, $ ) {
-       /**
-        * Given an email validity status (true, false, null) update the label CSS class
-        */
-       function updateMailValidityLabel( mail ) {
-               var isValid = mw.util.validateEmail( mail ),
-                       $label = $( '#mw-emailaddress-validity' );
-
-               // Set up the validity notice if it doesn't already exist
-               if ( $label.length === 0 ) {
-                       $label = $( '<label for="wpNewEmail" id="mw-emailaddress-validity"></label>' )
-                               .insertAfter( '#wpNewEmail' );
-               }
-
-               // We allow empty address
-               if ( isValid === null ) {
-                       $label.text( '' ).removeClass( 'valid invalid' );
-
-               // Valid
-               } else if ( isValid ) {
-                       $label.text( mw.msg( 'email-address-validity-valid' ) ).addClass( 'valid' ).removeClass( 'invalid' );
-
-               // Not valid
-               } else {
-                       $label.text( mw.msg( 'email-address-validity-invalid' ) ).addClass( 'invalid' ).removeClass( 'valid' );
-               }
-       }
-
-       $( function () {
-               $( '#wpNewEmail' )
-                       // Lame tip to let user know if its email is valid. See bug 22449.
-                       // Only bind once for 'blur' so that the user can fill it in without errors;
-                       // after that, look at every keypress for immediate feedback.
-                       .one( 'blur', function () {
-                               var $this = $( this );
-                               updateMailValidityLabel( $this.val() );
-                               $this.keyup( function () {
-                                       updateMailValidityLabel( $this.val() );
-                               } );
-                       } )
-                       // Supress built-in validation notice and just call updateMailValidityLabel(),
-                       // to avoid double notice. See bug 40909.
-                       .on( 'invalid', function ( e ) {
-                               e.preventDefault();
-                               updateMailValidityLabel( $( this ).val() );
-                       } );
-       } );
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.special/mediawiki.special.changeslist.css b/resources/mediawiki.special/mediawiki.special.changeslist.css
deleted file mode 100644 (file)
index 5e4af7b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Styling for Special:Watchlist and Special:RecentChanges
- */
-
-.mw-changeslist-line-watched .mw-title {
-       font-weight: bold;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.changeslist.enhanced.css b/resources/mediawiki.special/mediawiki.special.changeslist.enhanced.css
deleted file mode 100644 (file)
index bed580d..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Styling for Special:Watchlist and Special:RecentChanges when preference 'usenewrc'
- * a.k.a. Enhanced Recent Changes is enabled.
- */
-
-table.mw-enhanced-rc {
-       border: 0;
-       border-spacing: 0;
-}
-
-table.mw-enhanced-rc th,
-table.mw-enhanced-rc td {
-       padding: 0;
-       vertical-align: top;
-}
-
-td.mw-enhanced-rc {
-       white-space: nowrap;
-       font-family: monospace;
-}
-
-.mw-enhanced-rc-time {
-       font-family: monospace;
-}
-
-table.mw-enhanced-rc td.mw-enhanced-rc-nested {
-       padding-left: 1em;
-}
-
-/* Show/hide arrows in enhanced changeslist */
-.mw-enhanced-rc .collapsible-expander {
-       float: none;
-}
-
-/* If JS is disabled, the arrows or the placeholder space shouldn't be shown */
-.client-nojs .mw-enhancedchanges-arrow-space {
-       display: none;
-}
-
-/*
- * And if it's enabled, let's optimize the collapsing a little: hide the rows
- * that would be hidden by jquery.makeCollapsible with CSS to save us some
- * reflows and repaints. This doesn't work on browsers that don't fully support
- * CSS2 (IE6), but it's okay, this will be done in JavaScript with old degraded
- * performance instead.
- */
-.client-js table.mw-enhanced-rc.mw-collapsed tr + tr {
-       display: none;
-}
-
-.mw-enhancedchanges-arrow-space {
-       display: inline-block;
-       *display: inline; /* IE7 and below */
-       zoom: 1;
-       width: 15px;
-       height: 15px;
-}
-
-/* let it look like it is clickable */
-.mw-enhancedchanges-arrow.mw-collapsible-toggle {
-       cursor: pointer;
-}
-
-.mw-enhanced-watched .mw-enhanced-rc-time {
-       font-weight: bold;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.changeslist.legend.css b/resources/mediawiki.special/mediawiki.special.changeslist.legend.css
deleted file mode 100644 (file)
index 54d09b4..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Styling for changes list legend
- */
-
-.mw-changeslist-legend {
-       float: right;
-       margin-left: 1em;
-       margin-bottom: 0.5em;
-       clear: right;
-       font-size: 85%;
-       line-height: 1.2em;
-       padding: 0.5em;
-       border: 1px solid #ddd;
-}
-
-.mw-changeslist-legend dl {
-       /* Parent element defines sufficient padding */
-       margin-bottom: 0;
-}
-
-.mw-changeslist-legend dt {
-       float: left;
-       margin-right: 0.5em;
-}
-
-.mw-changeslist-legend dd {
-       margin-left: 1.5em;
-       line-height: 1.3em;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.changeslist.legend.js b/resources/mediawiki.special/mediawiki.special.changeslist.legend.js
deleted file mode 100644 (file)
index 0259155..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Script for changes list legend
- */
-
-/* Remember the collapse state of the legend on recent changes and watchlist pages. */
-jQuery( document ).ready( function ( $ ) {
-       var
-               cookieName = 'changeslist-state',
-               cookieOptions = {
-                       expires: 30,
-                       path: '/'
-               },
-               isCollapsed = $.cookie( cookieName ) === 'collapsed';
-
-       $( '.mw-changeslist-legend' )
-               .makeCollapsible( {
-                       collapsed: isCollapsed
-               } )
-               .on( 'beforeExpand.mw-collapsible', function () {
-                       $.cookie( cookieName, 'expanded', cookieOptions );
-               } )
-               .on( 'beforeCollapse.mw-collapsible', function () {
-                       $.cookie( cookieName, 'collapsed', cookieOptions );
-               } );
-} );
diff --git a/resources/mediawiki.special/mediawiki.special.css b/resources/mediawiki.special/mediawiki.special.css
deleted file mode 100644 (file)
index a877b74..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-
-/**** Special:AllMessages ****/
-#mw-allmessagestable .allmessages-customised td.am_default {
-       background-color: #fcffc4;
-}
-
-#mw-allmessagestable tr.allmessages-customised:hover td.am_default {
-       background-color: #faff90;
-}
-
-#mw-allmessagestable td.am_actual {
-       background-color: #e2ffe2;
-}
-
-#mw-allmessagestable tr.allmessages-customised:hover + tr.allmessages-customised td.am_actual {
-       background-color: #b1ffb1;
-}
-
-/**** Special:Allpages ****/
-table.mw-allpages-table-form, table.mw-allpages-table-chunk {
-       width: 100%;
-}
-td.mw-allpages-alphaindexline {
-       text-align: right;
-}
-.mw-allpages-nav {
-       text-align: right;
-       margin-bottom: 1em;
-}
-table.mw-allpages-table-form tr {
-       vertical-align: top;
-}
-
-/**** Special:Block ****/
-tr.mw-block-hideuser {
-       font-weight: bold;
-}
-
-/**** Special:BlockList ****/
-table.mw-blocklist span.mw-usertoollinks,
-span.mw-blocklist-actions {
-       white-space: nowrap;
-       font-size: 90%;
-}
-
-/**** Special:Contributions ****/
-.mw-uctop {
-       font-weight: bold;
-}
-
-/**** Special:EmailUser ****/
-table.mw-emailuser-table {
-       width: 98%;
-}
-td#mw-emailuser-sender,
-td#mw-emailuser-recipient {
-       font-weight: bold;
-}
-
-/**** Special:ListGroupRights ****/
-table.mw-listgrouprights-table tr {
-       vertical-align: top;
-}
-.listgrouprights-revoked {
-       text-decoration: line-through;
-}
-
-/**** Special:Prefixindex ****/
-table#mw-prefixindex-list-table, /* HTML backwards-compatibility, to be removed before 1.23 */
-table.mw-prefixindex-list-table,
-table#mw-prefixindex-nav-table {
-       width: 98%;
-}
-td#mw-prefixindex-nav-form {
-       margin-bottom: 1em;
-       vertical-align: top;
-}
-.mw-prefixindex-nav {
-       text-align: right;
-}
-
-
-/**** Special:Search ****/
-.searchresults {
-}
-
-.searchresults p {
-       margin-left: 0.4em;
-       margin-top: 1em;
-       margin-bottom: 1.2em;
-}
-div.searchresult {
-       font-size: 95%;
-       width: 38em;
-}
-.mw-search-results {
-       margin-left: 0.4em;
-}
-.mw-search-results li {
-       padding-bottom: 1.2em;
-       list-style: none;
-       list-style-image: none;
-}
-.mw-search-results li a {
-       font-size: 108%;
-}
-.mw-search-result-data {
-       color: green;
-       font-size: 97%;
-}
-.mw-search-formheader {
-       background-color: #f3f3f3;
-       margin-top: 1em;
-       border: 1px solid silver;
-}
-.mw-search-formheader div.search-types {
-       float: left;
-       padding-left: 0.25em;
-}
-.mw-search-formheader div.search-types ul {
-       margin: 0 !important;
-       padding: 0 !important;
-       list-style: none !important;
-}
-.mw-search-formheader div.search-types ul li {
-       float: left;
-       margin: 0;
-       padding: 0;
-}
-.mw-search-formheader div.search-types ul li a {
-       display: block;
-       padding: 0.5em;
-}
-.mw-search-formheader div.search-types ul li.current a {
-       color: #333333;
-       cursor: default;
-}
-.mw-search-formheader div.search-types ul li.current a:hover {
-       text-decoration: none;
-}
-.mw-search-formheader div.results-info {
-       float: right;
-       padding: 0.5em;
-       padding-right: 0.75em;
-}
-.mw-search-formheader div.results-info ul {
-       margin: 0 !important;
-       padding: 0 !important;
-       list-style: none !important;
-}
-.mw-search-formheader div.results-info ul li {
-       float: right;
-       margin: 0;
-       padding: 0;
-}
-fieldset#mw-searchoptions {
-       margin: 0;
-       padding: 0.5em 0.75em 0.75em 0.75em !important;
-       border: none;
-       background-color: #f9f9f9;
-       border: 1px solid silver !important;
-       border-top-width: 0 !important;
-}
-fieldset#mw-searchoptions legend {
-       display: none;
-}
-fieldset#mw-searchoptions h4 {
-       padding: 0;
-       margin: 0;
-       float: left;
-}
-fieldset#mw-searchoptions div#mw-search-togglebox {
-       float: right;
-}
-fieldset#mw-searchoptions div#mw-search-togglebox label {
-       margin-right: 0.25em;
-}
-fieldset#mw-searchoptions div#mw-search-togglebox input {
-       margin-left: 0.25em;
-}
-fieldset#mw-searchoptions table {
-       float: left;
-       margin-right: 3em;
-}
-fieldset#mw-searchoptions table td {
-       padding-right: 1em;
-}
-fieldset#mw-searchoptions div.divider {
-       clear: both;
-       border-bottom: 1px solid #DDDDDD;
-       padding-top: 0.5em;
-       margin-bottom: 0.5em;
-}
-td#mw-search-menu {
-       padding-left:6em;
-       font-size:85%;
-}
-div#mw-search-interwiki {
-       float: right;
-       width: 18em;
-       border: 1px solid #AAAAAA;
-       margin-top: 2ex;
-}
-div#mw-search-interwiki li {
-       font-size: 95%;
-}
-.mw-search-interwiki-more {
-       float: right;
-       font-size: 90%;
-}
-div#mw-search-interwiki-caption {
-       text-align: center;
-       font-weight: bold;
-       font-size: 95%;
-}
-.mw-search-interwiki-project {
-       font-size: 97%;
-       text-align: left;
-       padding: 0.15em 0.15em 0.2em 0.2em;
-       background-color: #ececec;
-       border-top: 1px solid #BBBBBB;
-}
-span.searchalttitle {
-       font-size: 95%;
-}
-div.searchdidyoumean {
-       font-size: 127%;
-       margin-top: 0.8em;
-       /* Note that this color won't affect the link, as desired. */
-       color: #c00;
-}
-div.searchdidyoumean em {
-       font-weight: bold;
-}
-.searchmatch {
-       font-weight: bold;
-}
-/* Advanced PowerSearch box */
-td#mw-search-togglebox {
-       text-align: right;
-}
-table#mw-search-powertable {
-       width: 100%;
-}
-form#powersearch {
-       clear: both;
-}
-
-/**** Special:Specialpages ****/
-.mw-specialpagerestricted {
-       font-weight: bold;
-}
-
-.mw-specialpages-table {
-       margin-top: -1em;
-       margin-bottom: 1em;
-}
-
-.mw-specialpages-table td {
-       vertical-align: top;
-}
-
-/**** Special:Statistics ****/
-td.mw-statistics-numbers {
-       text-align: right;
-}
-
-/**** Special:ProtectedPages ****/
-table.mw-protectedpages span.mw-usertoollinks,
-span.mw-protectedpages-length,
-span.mw-protectedpages-actions {
-       white-space: nowrap;
-       font-size: 90%;
-}
-span.mw-protectedpages-unknown {
-       color: grey;
-       font-size: 90%;
-}
-
-/**** Special:UserRights ****/
-.mw-userrights-disabled {
-       color: #888;
-}
-table.mw-userrights-groups * td,
-table.mw-userrights-groups * th {
-       padding-right: 1.5em;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.javaScriptTest.js b/resources/mediawiki.special/mediawiki.special.javaScriptTest.js
deleted file mode 100644 (file)
index 38f256c..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * JavaScript for Special:JavaScriptTest
- */
-( function ( mw, $ ) {
-       $( function () {
-
-               // Create useskin dropdown menu and reload onchange to the selected skin
-               // (only if a framework was found, not on error pages).
-               $( '#mw-javascripttest-summary.mw-javascripttest-frameworkfound' ).append( function () {
-
-                       var $html = $( '<p><label for="useskin">'
-                                       + mw.message( 'javascripttest-pagetext-skins' ).escaped()
-                                       + ' '
-                                       + '</label></p>' ),
-                               select = '<select name="useskin" id="useskin">';
-
-                       // Build <select> further
-                       $.each( mw.config.get( 'wgAvailableSkins' ), function ( id ) {
-                               select += '<option value="' + id + '"'
-                                       + ( mw.config.get( 'skin' ) === id ? ' selected="selected"' : '' )
-                                       + '>' + mw.message( 'skinname-' + id ).escaped() + '</option>';
-                       } );
-                       select += '</select>';
-
-                       // Bind onchange event handler and append to form
-                       $html.append(
-                               $( select ).change( function () {
-                                       window.location = QUnit.url( { useskin: $( this ).val() } );
-                               } )
-                       );
-
-                       return $html;
-               } );
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.special/mediawiki.special.js b/resources/mediawiki.special/mediawiki.special.js
deleted file mode 100644 (file)
index 8edb1cb..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * Namespace for mediawiki.special.* modules
- */
-
-mediaWiki.special = {};
diff --git a/resources/mediawiki.special/mediawiki.special.movePage.js b/resources/mediawiki.special/mediawiki.special.movePage.js
deleted file mode 100644 (file)
index 922eba5..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * JavaScript for Special:MovePage
- */
-jQuery( function ( $ ) {
-       $( '#wpReason, #wpNewTitleMain' ).byteLimit();
-} );
diff --git a/resources/mediawiki.special/mediawiki.special.pagesWithProp.css b/resources/mediawiki.special/mediawiki.special.pagesWithProp.css
deleted file mode 100644 (file)
index 7ef75d0..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Distinguish actual data from information about it being hidden visually */
-.prop-value-hidden {
-       font-style: italic;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.preferences.css b/resources/mediawiki.special/mediawiki.special.preferences.css
deleted file mode 100644 (file)
index 75ae5ca..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/** Reuses colors from mediawiki.special.changeemail.css */
-.mw-email-not-authenticated .mw-input,
-.mw-email-none .mw-input{
-       border: 1px solid #FF8080;
-       background-color: #FFC0C0;
-       color: black;
-}
-/** Authenticated email field has its own class too. Unstyled by default */
-/*
-.mw-email-authenticated .mw-input { }
-*/
-
-/**
- * Hide, but keep accessible for screen-readers.
- * Like .mw-jump, #jump-to-nav from skins/common/shared.css
- */
-.mw-navigation-hint {
-       overflow: hidden;
-       height: 0;
-       zoom: 1;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.preferences.js b/resources/mediawiki.special/mediawiki.special.preferences.js
deleted file mode 100644 (file)
index 2cd27af..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/**
- * JavaScript for Special:Preferences
- */
-jQuery( function ( $ ) {
-       var $preftoc, $preferences, $fieldsets, $legends,
-               hash, labelFunc,
-               $tzSelect, $tzTextbox, $localtimeHolder, servertime,
-               $checkBoxes;
-
-       labelFunc = function () {
-               return this.id.replace( /^mw-prefsection/g, 'preftab' );
-       };
-
-       $( '#prefsubmit' ).attr( 'id', 'prefcontrol' );
-       $preftoc = $( '<ul id="preftoc"></ul>' )
-               .attr( 'role', 'tablist' );
-       $preferences = $( '#preferences' )
-               .addClass( 'jsprefs' )
-               .before( $preftoc );
-       $fieldsets = $preferences.children( 'fieldset' )
-               .hide()
-               .attr( {
-                       role: 'tabpanel',
-                       'aria-hidden': 'true',
-                       'aria-labelledby': labelFunc
-               } )
-               .addClass( 'prefsection' );
-       $legends = $fieldsets
-               .children( 'legend' )
-               .addClass( 'mainLegend' );
-
-       // Make sure the accessibility tip is selectable so that screen reader users take notice,
-       // but hide it per default to reduce interface clutter. Also make sure it becomes visible
-       // when selected. Similar to jquery.mw-jump
-       $( '<div>' ).addClass( 'mw-navigation-hint' )
-               .text( mediaWiki.msg( 'prefs-tabs-navigation-hint' ) )
-               .attr( 'tabIndex', 0 )
-               .on( 'focus blur', function ( e ) {
-                       if ( e.type === 'blur' || e.type === 'focusout' ) {
-                               $( this ).css( 'height', '0' );
-                       } else {
-                               $( this ).css( 'height', 'auto' );
-                       }
-       } ).insertBefore( $preftoc );
-
-       /**
-        * It uses document.getElementById for security reasons (HTML injections in $()).
-        *
-        * @param String name: the name of a tab without the prefix ("mw-prefsection-")
-        * @param String mode: [optional] A hash will be set according to the current
-        * open section. Set mode 'noHash' to surpress this.
-        */
-       function switchPrefTab( name, mode ) {
-               var $tab, scrollTop;
-               // Handle hash manually to prevent jumping,
-               // therefore save and restore scrollTop to prevent jumping.
-               scrollTop = $( window ).scrollTop();
-               if ( mode !== 'noHash' ) {
-                       window.location.hash = '#mw-prefsection-' + name;
-               }
-               $( window ).scrollTop( scrollTop );
-
-               $preftoc.find( 'li' ).removeClass( 'selected' )
-                       .find( 'a' ).attr( {
-                               tabIndex: -1,
-                               'aria-selected': 'false'
-                       } );
-
-               $tab = $( document.getElementById( 'preftab-' + name ) );
-               if ( $tab.length ) {
-                       $tab.attr( {
-                               tabIndex: 0,
-                               'aria-selected': 'true'
-                       } )
-                       .focus()
-                               .parent().addClass( 'selected' );
-
-                       $preferences.children( 'fieldset' ).hide().attr( 'aria-hidden', 'true' );
-                       $( document.getElementById( 'mw-prefsection-' + name ) ).show().attr( 'aria-hidden', 'false' );
-               }
-       }
-
-       // Populate the prefToc
-       $legends.each( function ( i, legend ) {
-               var $legend = $( legend ),
-                       ident, $li, $a;
-               if ( i === 0 ) {
-                       $legend.parent().show();
-               }
-               ident = $legend.parent().attr( 'id' );
-
-               $li = $( '<li>' )
-                       .attr( 'role', 'presentation' )
-                       .addClass( i === 0 ? 'selected' : '' );
-               $a = $( '<a>' )
-                       .attr( {
-                               id: ident.replace( 'mw-prefsection', 'preftab' ),
-                               href: '#' + ident,
-                               role: 'tab',
-                               tabIndex: i === 0 ? 0 : -1,
-                               'aria-selected': i === 0 ? 'true' : 'false',
-                               'aria-controls': ident
-                       } )
-                       .text( $legend.text() );
-               $li.append( $a );
-               $preftoc.append( $li );
-       } );
-
-       // Enable keyboard users to use left and right keys to switch tabs
-       $preftoc.on( 'keydown', function ( event ) {
-               var keyLeft = 37,
-                       keyRight = 39,
-                       $el;
-
-               if ( event.keyCode === keyLeft ) {
-                       $el = $( '#preftoc li.selected' ).prev().find( 'a' );
-               } else if ( event.keyCode === keyRight ) {
-                       $el = $( '#preftoc li.selected' ).next().find( 'a' );
-               } else {
-                       return;
-               }
-               if ( $el.length > 0 ) {
-                       switchPrefTab( $el.attr( 'href' ).replace( '#mw-prefsection-', '' ) );
-               }
-       } );
-
-       // If we've reloaded the page or followed an open-in-new-window,
-       // make the selected tab visible.
-       hash = window.location.hash;
-       if ( hash.match( /^#mw-prefsection-[\w\-]+/ ) ) {
-               switchPrefTab( hash.replace( '#mw-prefsection-', '' ) );
-       }
-
-       // In browsers that support the onhashchange event we will not bind click
-       // handlers and instead let the browser do the default behavior (clicking the
-       // <a href="#.."> will naturally set the hash, handled by onhashchange.
-       // But other things that change the hash will also be catched (e.g. using
-       // the Back and Forward browser navigation).
-       // Note the special check for IE "compatibility" mode.
-       if ( 'onhashchange' in window &&
-               ( document.documentMode === undefined || document.documentMode >= 8 )
-       ) {
-               $( window ).on( 'hashchange', function () {
-                       var hash = window.location.hash;
-                       if ( hash.match( /^#mw-prefsection-[\w\-]+/ ) ) {
-                               switchPrefTab( hash.replace( '#mw-prefsection-', '' ) );
-                       } else if ( hash === '' ) {
-                               switchPrefTab( 'personal', 'noHash' );
-                       }
-               } );
-       // In older browsers we'll bind a click handler as fallback.
-       // We must not have onhashchange *and* the click handlers, other wise
-       // the click handler calls switchPrefTab() which sets the hash value,
-       // which triggers onhashcange and calls switchPrefTab() again.
-       } else {
-               $preftoc.on( 'click', 'li a', function ( e ) {
-                       switchPrefTab( $( this ).attr( 'href' ).replace( '#mw-prefsection-', '' ) );
-                       e.preventDefault();
-               } );
-       }
-
-       /**
-       * Timezone functions.
-       * Guesses Timezone from browser and updates fields onchange
-       */
-
-       $tzSelect = $( '#mw-input-wptimecorrection' );
-       $tzTextbox = $( '#mw-input-wptimecorrection-other' );
-       $localtimeHolder = $( '#wpLocalTime' );
-       servertime = parseInt( $( 'input[name="wpServerTime"]' ).val(), 10 );
-
-       function minutesToHours( min ) {
-               var tzHour = Math.floor( Math.abs( min ) / 60 ),
-                       tzMin = Math.abs( min ) % 60,
-                       tzString = ( ( min >= 0 ) ? '' : '-' ) + ( ( tzHour < 10 ) ? '0' : '' ) + tzHour +
-                               ':' + ( ( tzMin < 10 ) ? '0' : '' ) + tzMin;
-               return tzString;
-       }
-
-       function hoursToMinutes( hour ) {
-               var minutes,
-                       arr = hour.split( ':' );
-
-               arr[0] = parseInt( arr[0], 10 );
-
-               if ( arr.length === 1 ) {
-                       // Specification is of the form [-]XX
-                       minutes = arr[0] * 60;
-               } else {
-                       // Specification is of the form [-]XX:XX
-                       minutes = Math.abs( arr[0] ) * 60 + parseInt( arr[1], 10 );
-                       if ( arr[0] < 0 ) {
-                               minutes *= -1;
-                       }
-               }
-               // Gracefully handle non-numbers.
-               if ( isNaN( minutes ) ) {
-                       return 0;
-               } else {
-                       return minutes;
-               }
-       }
-
-       function updateTimezoneSelection () {
-               var minuteDiff, localTime,
-                       type = $tzSelect.val();
-
-               if ( type === 'guess' ) {
-                       // Get browser timezone & fill it in
-                       minuteDiff = -( new Date().getTimezoneOffset() );
-                       $tzTextbox.val( minutesToHours( minuteDiff ) );
-                       $tzSelect.val( 'other' );
-                       $tzTextbox.prop( 'disabled', false );
-               } else if ( type === 'other' ) {
-                       // Grab data from the textbox, parse it.
-                       minuteDiff = hoursToMinutes( $tzTextbox.val() );
-               } else {
-                       // Grab data from the $tzSelect value
-                       minuteDiff = parseInt( type.split( '|' )[1], 10 ) || 0;
-                       $tzTextbox.val( minutesToHours( minuteDiff ) );
-               }
-
-               // Determine local time from server time and minutes difference, for display.
-               localTime = servertime + minuteDiff;
-
-               // Bring time within the [0,1440) range.
-               while ( localTime < 0 ) {
-                       localTime += 1440;
-               }
-               while ( localTime >= 1440 ) {
-                       localTime -= 1440;
-               }
-               $localtimeHolder.text( mediaWiki.language.convertNumber( minutesToHours( localTime ) ) );
-       }
-
-       if ( $tzSelect.length && $tzTextbox.length ) {
-               $tzSelect.change( updateTimezoneSelection );
-               $tzTextbox.blur( updateTimezoneSelection );
-               updateTimezoneSelection();
-       }
-
-       // Preserve the tab after saving the preferences
-       // Not using cookies, because their deletion results are inconsistent.
-       // Not using jStorage due to its enormous size (for this feature)
-       if ( window.sessionStorage ) {
-               if ( sessionStorage.getItem( 'mediawikiPreferencesTab' ) !== null ) {
-                       switchPrefTab( sessionStorage.getItem( 'mediawikiPreferencesTab' ), 'noHash' );
-               }
-               // Deleting the key, the tab states should be reset until we press Save
-               sessionStorage.removeItem( 'mediawikiPreferencesTab' );
-
-               $( '#mw-prefs-form' ).submit( function () {
-                       var storageData = $( $preftoc ).find( 'li.selected a' ).attr( 'id' ).replace( 'preftab-', '' );
-                       sessionStorage.setItem( 'mediawikiPreferencesTab', storageData );
-               } );
-       }
-
-       // To disable all 'namespace' checkboxes in Search preferences
-       // when 'Search in all namespaces' checkbox is ticked.
-       $checkBoxes = $( '#mw-htmlform-advancedsearchoptions input[id^=mw-input-wpsearchnamespaces]' );
-       if ( $( '#mw-input-wpsearcheverything' ).prop( 'checked' ) ) {
-               $checkBoxes.prop( 'disabled', true );
-       }
-       $( '#mw-input-wpsearcheverything' ).change( function () {
-               $checkBoxes.prop( 'disabled', $( this ).prop( 'checked' ) );
-       } );
-} );
diff --git a/resources/mediawiki.special/mediawiki.special.recentchanges.js b/resources/mediawiki.special/mediawiki.special.recentchanges.js
deleted file mode 100644 (file)
index 79d793a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * JavaScript for Special:RecentChanges
- */
-( function ( mw, $ ) {
-       var rc, $checkboxes, $select;
-
-       rc = {
-               /**
-                * Handler to disable/enable the namespace selector checkboxes when the
-                * special 'all' namespace is selected/unselected respectively.
-                */
-               updateCheckboxes: function () {
-                       // The option element for the 'all' namespace has an empty value
-                       var isAllNS = $select.val() === '';
-
-                       // Iterates over checkboxes and propagate the selected option
-                       $checkboxes.prop( 'disabled', isAllNS );
-               },
-
-               init: function () {
-                       $select = $( '#namespace' );
-                       $checkboxes = $( '#nsassociated, #nsinvert' );
-
-                       // Bind to change event, and trigger once to set the initial state of the checkboxes.
-                       rc.updateCheckboxes();
-                       $select.change( rc.updateCheckboxes );
-               }
-       };
-
-       $( rc.init );
-
-       mw.special.recentchanges = rc;
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.special/mediawiki.special.search.css b/resources/mediawiki.special/mediawiki.special.search.css
deleted file mode 100644 (file)
index 914e47e..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * Fixes sister projects box moving down the extract
- * of the first result (bug #16886).
- * It only happens when the window is small and
- * This changes slightly the layout for big screens
- * where there was space for the extracts and the
- * sister projects and thus it showed like in any
- * other browser.
- *
- * This will only affect IE 7 and lower
- */
-.searchresult {
-       display: inline !ie;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.search.js b/resources/mediawiki.special/mediawiki.special.search.js
deleted file mode 100644 (file)
index b847f7d..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * JavaScript for Special:Search
- */
-( function ( mw, $ ) {
-       $( function () {
-               var $checkboxes, $headerLinks;
-
-               // Emulate HTML5 autofocus behavior in non HTML5 compliant browsers
-               if ( !( 'autofocus' in document.createElement( 'input' ) ) ) {
-                       $( 'input[autofocus]' ).eq( 0 ).focus();
-               }
-
-               // Create check all/none button
-               $checkboxes = $( '#powersearch input[id^=mw-search-ns]' );
-               $( '#mw-search-togglebox' ).append(
-                       $( '<label>' )
-                               .text( mw.msg( 'powersearch-togglelabel' ) )
-               ).append(
-                       $( '<input type="button" />' )
-                               .attr( 'id', 'mw-search-toggleall' )
-                               .prop( 'value', mw.msg( 'powersearch-toggleall' ) )
-                               .click( function () {
-                                       $checkboxes.prop( 'checked', true );
-                               } )
-               ).append(
-                       $( '<input type="button" />' )
-                               .attr( 'id', 'mw-search-togglenone' )
-                               .prop( 'value', mw.msg( 'powersearch-togglenone' ) )
-                               .click( function () {
-                                       $checkboxes.prop( 'checked', false );
-                               } )
-               );
-
-               // Change the header search links to what user entered
-               $headerLinks = $( '.search-types a' );
-               $( '#searchText, #powerSearchText' ).change( function () {
-                       var searchterm = $( this ).val();
-                       $headerLinks.each( function () {
-                               var parts = $( this ).attr( 'href' ).split( 'search=' ),
-                                       lastpart = '',
-                                       prefix = 'search=';
-                               if ( parts.length > 1 && parts[1].indexOf( '&' ) >= 0 ) {
-                                       lastpart = parts[1].substring( parts[1].indexOf( '&' ) );
-                               } else {
-                                       prefix = '&search=';
-                               }
-                               this.href = parts[0] + prefix + encodeURIComponent( searchterm ) + lastpart;
-                       } );
-               } ).trigger( 'change' );
-
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.special/mediawiki.special.undelete.js b/resources/mediawiki.special/mediawiki.special.undelete.js
deleted file mode 100644 (file)
index 0dea3ef..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * JavaScript for Special:Undelete
- */
-jQuery( function ( $ ) {
-       $( '#mw-undelete-invert' ).click( function ( e ) {
-               $( '#undelete input[type="checkbox"]' ).prop( 'checked', function ( i, val ) {
-                       return !val;
-               } );
-               e.preventDefault();
-       } );
-} );
diff --git a/resources/mediawiki.special/mediawiki.special.upload.js b/resources/mediawiki.special/mediawiki.special.upload.js
deleted file mode 100644 (file)
index 8a5ff59..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-/**
- * JavaScript for Special:Upload
- * Note that additional code still lives in skins/common/upload.js
- */
-( function ( mw, $ ) {
-       /**
-        * Add a preview to the upload form
-        */
-       $( function () {
-               /**
-                * Is the FileAPI available with sufficient functionality?
-                */
-               function hasFileAPI() {
-                       return window.FileReader !== undefined;
-               }
-
-               /**
-                * Check if this is a recognizable image type...
-                * Also excludes files over 10M to avoid going insane on memory usage.
-                *
-                * @todo is there a way we can ask the browser what's supported in <img>s?
-                * @todo put SVG back after working around Firefox 7 bug <https://bugzilla.wikimedia.org/show_bug.cgi?id=31643>
-                *
-                * @param {File} file
-                * @return boolean
-                */
-               function fileIsPreviewable( file ) {
-                       var known = ['image/png', 'image/gif', 'image/jpeg', 'image/svg+xml'],
-                               tooHuge = 10 * 1024 * 1024;
-                       return ( $.inArray( file.type, known ) !== -1 ) && file.size > 0 && file.size < tooHuge;
-               }
-
-               /**
-                * Show a thumbnail preview of PNG, JPEG, GIF, and SVG files prior to upload
-                * in browsers supporting HTML5 FileAPI.
-                *
-                * As of this writing, known good:
-                * - Firefox 3.6+
-                * - Chrome 7.something
-                *
-                * @todo check file size limits and warn of likely failures
-                *
-                * @param {File} file
-                */
-               function showPreview( file ) {
-                       var $canvas,
-                               ctx,
-                               meta,
-                               previewSize = 180,
-                               thumb = $( '<div id="mw-upload-thumbnail" class="thumb tright">' +
-                                                       '<div class="thumbinner">' +
-                                                               '<div class="mw-small-spinner" style="width: 180px; height: 180px"></div>' +
-                                                               '<div class="thumbcaption"><div class="filename"></div><div class="fileinfo"></div></div>' +
-                                                       '</div>' +
-                                               '</div>' );
-
-                       thumb.find( '.filename' ).text( file.name ).end()
-                               .find( '.fileinfo' ).text( prettySize( file.size ) ).end();
-
-                       $canvas = $( '<canvas width="' + previewSize + '" height="' + previewSize + '" ></canvas>' );
-                       ctx = $canvas[0].getContext( '2d' );
-                       $( '#mw-htmlform-source' ).parent().prepend( thumb );
-
-                       fetchPreview( file, function ( dataURL ) {
-                               var img = new Image(),
-                                       rotation = 0;
-
-                               if ( meta && meta.tiff && meta.tiff.Orientation ) {
-                                       rotation = ( 360 - ( function () {
-                                               // See includes/media/Bitmap.php
-                                               switch ( meta.tiff.Orientation.value ) {
-                                                       case 8:
-                                                               return 90;
-                                                       case 3:
-                                                               return 180;
-                                                       case 6:
-                                                               return 270;
-                                                       default:
-                                                               return 0;
-                                               }
-                                       }() ) ) % 360;
-                               }
-
-                               img.onload = function () {
-                                       var info, width, height, x, y, dx, dy, logicalWidth, logicalHeight;
-
-                                       // Fit the image within the previewSizexpreviewSize box
-                                       if ( img.width > img.height ) {
-                                               width = previewSize;
-                                               height = img.height / img.width * previewSize;
-                                       } else {
-                                               height = previewSize;
-                                               width = img.width / img.height * previewSize;
-                                       }
-                                       // Determine the offset required to center the image
-                                       dx = ( 180 - width ) / 2;
-                                       dy = ( 180 - height ) / 2;
-                                       switch ( rotation ) {
-                                               // If a rotation is applied, the direction of the axis
-                                               // changes as well. You can derive the values below by
-                                               // drawing on paper an axis system, rotate it and see
-                                               // where the positive axis direction is
-                                               case 0:
-                                                       x = dx;
-                                                       y = dy;
-                                                       logicalWidth = img.width;
-                                                       logicalHeight = img.height;
-                                                       break;
-                                               case 90:
-
-                                                       x = dx;
-                                                       y = dy - previewSize;
-                                                       logicalWidth = img.height;
-                                                       logicalHeight = img.width;
-                                                       break;
-                                               case 180:
-                                                       x = dx - previewSize;
-                                                       y = dy - previewSize;
-                                                       logicalWidth = img.width;
-                                                       logicalHeight = img.height;
-                                                       break;
-                                               case 270:
-                                                       x = dx - previewSize;
-                                                       y = dy;
-                                                       logicalWidth = img.height;
-                                                       logicalHeight = img.width;
-                                                       break;
-                                       }
-
-                                       ctx.clearRect( 0, 0, 180, 180 );
-                                       ctx.rotate( rotation / 180 * Math.PI );
-                                       ctx.drawImage( img, x, y, width, height );
-                                       thumb.find( '.mw-small-spinner' ).replaceWith( $canvas );
-
-                                       // Image size
-                                       info = mw.msg( 'widthheight', logicalWidth, logicalHeight ) +
-                                               ', ' + prettySize( file.size );
-
-                                       $( '#mw-upload-thumbnail .fileinfo' ).text( info );
-                               };
-                               img.src = dataURL;
-                       }, mw.config.get( 'wgFileCanRotate' ) ? function ( data ) {
-                               /*jshint camelcase:false, nomen:false */
-                               try {
-                                       meta = mw.libs.jpegmeta( data, file.fileName );
-                                       meta._binary_data = null;
-                               } catch ( e ) {
-                                       meta = null;
-                               }
-                       } : null );
-               }
-
-               /**
-                * Start loading a file into memory; when complete, pass it as a
-                * data URL to the callback function. If the callbackBinary is set it will
-                * first be read as binary and afterwards as data URL. Useful if you want
-                * to do preprocessing on the binary data first.
-                *
-                * @param {File} file
-                * @param {function} callback
-                * @param {function} callbackBinary
-                */
-               function fetchPreview( file, callback, callbackBinary ) {
-                       var reader = new FileReader();
-                       if ( callbackBinary && 'readAsBinaryString' in reader ) {
-                               // To fetch JPEG metadata we need a binary string; start there.
-                               // todo:
-                               reader.onload = function () {
-                                       callbackBinary( reader.result );
-
-                                       // Now run back through the regular code path.
-                                       fetchPreview( file, callback );
-                               };
-                               reader.readAsBinaryString( file );
-                       } else if ( callbackBinary && 'readAsArrayBuffer' in reader ) {
-                               // readAsArrayBuffer replaces readAsBinaryString
-                               // However, our JPEG metadata library wants a string.
-                               // So, this is going to be an ugly conversion.
-                               reader.onload = function () {
-                                       var i,
-                                               buffer = new Uint8Array( reader.result ),
-                                               string = '';
-                                       for ( i = 0; i < buffer.byteLength; i++ ) {
-                                               string += String.fromCharCode( buffer[i] );
-                                       }
-                                       callbackBinary( string );
-
-                                       // Now run back through the regular code path.
-                                       fetchPreview( file, callback );
-                               };
-                               reader.readAsArrayBuffer( file );
-                       } else if ( 'URL' in window && 'createObjectURL' in window.URL ) {
-                               // Supported in Firefox 4.0 and above <https://developer.mozilla.org/en/DOM/window.URL.createObjectURL>
-                               // WebKit has it in a namespace for now but that's ok. ;)
-                               //
-                               // Lifetime of this URL is until document close, which is fine
-                               // for Special:Upload -- if this code gets used on longer-running
-                               // pages, add a revokeObjectURL() when it's no longer needed.
-                               //
-                               // Prefer this over readAsDataURL for Firefox 7 due to bug reading
-                               // some SVG files from data URIs <https://bugzilla.mozilla.org/show_bug.cgi?id=694165>
-                               callback( window.URL.createObjectURL( file ) );
-                       } else {
-                               // This ends up decoding the file to base-64 and back again, which
-                               // feels horribly inefficient.
-                               reader.onload = function () {
-                                       callback( reader.result );
-                               };
-                               reader.readAsDataURL( file );
-                       }
-               }
-
-               /**
-                * Format a file size attractively.
-                * @todo match numeric formatting
-                *
-                * @param {number} s
-                * @return string
-                */
-               function prettySize( s ) {
-                       var sizeMsgs = ['size-bytes', 'size-kilobytes', 'size-megabytes', 'size-gigabytes'];
-                       while ( s >= 1024 && sizeMsgs.length > 1 ) {
-                               s /= 1024;
-                               sizeMsgs = sizeMsgs.slice( 1 );
-                       }
-                       return mw.msg( sizeMsgs[0], Math.round( s ) );
-               }
-
-               /**
-                * Clear the file upload preview area.
-                */
-               function clearPreview() {
-                       $( '#mw-upload-thumbnail' ).remove();
-               }
-
-               /**
-                * Check if the file does not exceed the maximum size
-                */
-               function checkMaxUploadSize( file ) {
-                       var maxSize, $error;
-
-                       function getMaxUploadSize( type ) {
-                               var sizes = mw.config.get( 'wgMaxUploadSize' );
-
-                               if ( sizes[type] !== undefined ) {
-                                       return sizes[type];
-                               }
-                               return sizes['*'];
-                       }
-
-                       $( '.mw-upload-source-error' ).remove();
-
-                       maxSize = getMaxUploadSize( 'file' );
-                       if ( file.size > maxSize ) {
-                               $error = $( '<p class="error mw-upload-source-error" id="wpSourceTypeFile-error">' +
-                                       mw.message( 'largefileserver', file.size, maxSize ).escaped() + '</p>' );
-
-                               $( '#wpUploadFile' ).after( $error );
-
-                               return false;
-                       }
-
-                       return true;
-               }
-
-               /**
-                * Initialization
-                */
-               if ( hasFileAPI() ) {
-                       // Update thumbnail when the file selection control is updated.
-                       $( '#wpUploadFile' ).change( function () {
-                               clearPreview();
-                               if ( this.files && this.files.length ) {
-                                       // Note: would need to be updated to handle multiple files.
-                                       var file = this.files[0];
-
-                                       if ( !checkMaxUploadSize( file ) ) {
-                                               return;
-                                       }
-
-                                       if ( fileIsPreviewable( file ) ) {
-                                               showPreview( file );
-                                       }
-                               }
-                       } );
-               }
-       } );
-
-       /**
-        * Disable all upload source fields except the selected one
-        */
-       $( function () {
-               var i, $row,
-                       $rows = $( '.mw-htmlform-field-UploadSourceField' );
-
-               function createHandler( $currentRow ) {
-                       /**
-                        * @param {jQuery.Event}
-                        */
-                       return function () {
-                               $( '.mw-upload-source-error' ).remove();
-                               if ( this.checked ) {
-                                       // Disable all inputs
-                                       $rows.find( 'input[name!="wpSourceType"]' ).prop( 'disabled', true );
-                                       // Re-enable the current one
-                                       $currentRow.find( 'input' ).prop( 'disabled', false );
-                               }
-                       };
-               }
-
-               for ( i = $rows.length; i; i-- ) {
-                       $row = $rows.eq( i - 1 );
-                       $row
-                               .find( 'input[name="wpSourceType"]' )
-                               .change( createHandler( $row ) );
-               }
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.special/mediawiki.special.userlogin.common.css b/resources/mediawiki.special/mediawiki.special.userlogin.common.css
deleted file mode 100644 (file)
index d5fd2b8..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Styles for user login and signup forms */
-#mw-userlogin-help {
-       text-align: center;
-}
-
-.mw-ui-vform .mw-secure {
-       /* @embed */
-       background: url(images/icon-lock.png) no-repeat scroll left center transparent;
-       margin: 0 0 0 1px;
-       padding: 0 0 0 11px;
-}
-
-/*
- * When inside the VForm style, disable the border that Vector and other skins
- * put on the div surrounding the login/create account form.
- * Also disable the margin and padding that Vector puts around the form.
- */
-.mw-ui-container #userloginForm,
-.mw-ui-container #userlogin {
-       border: 0;
-       margin: 0;
-       padding: 0;
-}
-
-/* Reposition and resize language links, which appear on a per-wiki basis */
-.mw-ui-container #languagelinks {
-       margin-bottom: 2em;
-       font-size: 0.8em;
-}
-
-/* Put some space under template's header, which may contain CAPTCHA HTML.*/
-section.mw-form-header {
-       margin-bottom: 10px;
-}
-
-/**** shuffled CAPTCHA ****/
-#wpCaptchaWord {
-       margin-top: 6px;
-}
-
-.mw-createacct-captcha-container {
-       background-color: #f8f8f8;
-       border: 1px solid #c9c9c9;
-       padding: 10px;
-       text-align: center;
-}
-
-.mw-createacct-captcha-assisted {
-       display: block;
-       margin-top: 0.5em;
-}
-
-/* Put a border around the fancycaptcha-image-container. */
-.mw-createacct-captcha-and-reload {
-       border: 1px solid #c9c9c9;
-       /* Other display formats end up too wide */
-       display: table-cell;
-       width: 270px;
-       background-color: #FFF;
-}
-
-/* Make the fancycaptcha-image-container full-width within its parent. */
-.fancycaptcha-image-container {
-       width: 100%;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.userlogin.common.js b/resources/mediawiki.special/mediawiki.special.userlogin.common.js
deleted file mode 100644 (file)
index a899ae7..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * JavaScript for login and signup forms.
- */
-( function ( mw, $ ) {
-       // Move the FancyCaptcha image into a more attractive container.
-       // The CAPTCHA is in a <div class="captcha"> at the top of the form. If it's a FancyCaptcha,
-       // then we remove it and insert it lower down, in a customized div with just what we need (e.g.
-       // no 'fancycaptcha-createaccount' message).
-       function adjustFancyCaptcha( $content, buttonSubmit ) {
-               var $submit = $content.find( buttonSubmit ),
-                       tabIndex,
-                       $captchaStuff,
-                       $captchaImageContainer,
-                       // JavaScript can't yet parse the message 'createacct-imgcaptcha-help' when it
-                       // contains a MediaWiki transclusion, so PHP parses it and sends the HTML.
-                       // This is only set for the signup form (and undefined for login).
-                       helpMsg = mw.config.get( 'wgCreateacctImgcaptchaHelp' ),
-                       helpHtml = '';
-
-               if ( !$submit.length ) {
-                       return;
-               }
-               tabIndex = $submit.prop( 'tabindex' ) - 1;
-               $captchaStuff = $content.find( '.captcha' );
-
-               if ( $captchaStuff.length ) {
-                       // The FancyCaptcha has this class in the ConfirmEdit extension since 2013-04-18.
-                       $captchaImageContainer = $captchaStuff.find( '.fancycaptcha-image-container' );
-                       if ( $captchaImageContainer.length !== 1 ) {
-                               return;
-                       }
-
-                       $captchaStuff.remove();
-
-                       if ( helpMsg ) {
-                               helpHtml = '<small class="mw-createacct-captcha-assisted">' + helpMsg + '</small>';
-                       }
-
-                       // Insert another div before the submit button that will include the
-                       // repositioned FancyCaptcha div, an input field, and possible help.
-                       $submit.closest( 'div' ).before( [
-                               '<div>',
-                                       '<label for="wpCaptchaWord">' + mw.message( 'createacct-captcha' ).escaped() + '</label>',
-                                       '<div class="mw-createacct-captcha-container">',
-                                               '<div class="mw-createacct-captcha-and-reload" />',
-                                               '<input id="wpCaptchaWord" name="wpCaptchaWord" type="text" placeholder="' +
-                                                       mw.message( 'createacct-imgcaptcha-ph' ).escaped() +
-                                                       '" tabindex="' + tabIndex + '" autocapitalize="off" autocorrect="off">',
-                                                       helpHtml,
-                                       '</div>',
-                               '</div>'
-                       ].join( '' ) );
-
-                       // Stick the FancyCaptcha container inside our bordered and framed parents.
-                       $captchaImageContainer
-                               .prependTo( $content.find( '.mw-createacct-captcha-and-reload' ) );
-
-                       // Find the input field, add the text (if any) of the existing CAPTCHA
-                       // field (although usually it's blanked out on every redisplay),
-                       // and after it move over the hidden field that tells the CAPTCHA
-                       // what to do.
-                       $content.find( '#wpCaptchaWord' )
-                               .val( $captchaStuff.find( '#wpCaptchaWord' ).val() )
-                               .after( $captchaStuff.find( '#wpCaptchaId' ) );
-               }
-       }
-
-       $( function () {
-               // Work with both login and signup form
-               adjustFancyCaptcha( $( '#mw-content-text' ), '#wpCreateaccount, #wpLoginAttempt' );
-       } );
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.special/mediawiki.special.userlogin.login.css b/resources/mediawiki.special/mediawiki.special.userlogin.login.css
deleted file mode 100644 (file)
index dc44c84..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* The login form invites users to create an account */
-#mw-createaccount-cta {
-       width: 20em;
-       height: 10em;
-       /* @embed */
-       background: url(images/glyph-people-large.png) no-repeat 50%;
-       margin: 0 auto;
-       padding-top: 4em;
-}
-
-#mw-createaccount-cta,
-#mw-createaccount-another {
-       font-size: 0.9em;
-       font-weight: normal;
-       text-align: center;
-}
-
-#mw-createaccount-join {
-       margin-left: 0.75em;
-       /* Separate from background image */
-       box-shadow: 4px 4px 4px 4px rgba(255, 255, 255, 1);
-       width: auto;
-       display: inline-block;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.userlogin.signup.css b/resources/mediawiki.special/mediawiki.special.userlogin.signup.css
deleted file mode 100644 (file)
index 0998d4c..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Disable the underline that Vector puts on h2 headings, and bold them. */
-.mw-ui-container h2 {
-       border: 0;
-       font-weight: bold;
-}
-
-/* Benefits column CSS to the right (if it fits) of the form. */
-.mw-ui-container #userloginForm {
-       float: left;
-       /* Override the right margin of the form to give space in case a benefits
-        * column appears to the side. */
-       margin-right: 100px;
-}
-
-div.mw-createacct-benefits-container {
-       /* Keeps this column compact and close to the form, but tends to squish contents. */
-       float: left;
-}
-
-div.mw-createacct-benefits-container h2 {
-       margin-bottom: 30px;
-}
-
-.mw-number-text.icon-edits {
-       /* @embed */
-       background: url(images/icon-edits.png) no-repeat left center;
-}
-
-.mw-number-text.icon-pages {
-       /* @embed */
-       background: url(images/icon-pages.png) no-repeat left center;
-}
-
-.mw-number-text.icon-contributors {
-       /* @embed */
-       background: url(images/icon-contributors.png) no-repeat left center;
-}
-
-/*
- * Special font for numbers in benefits, same as Vector's @content-heading-font-family.
- * Needs an ID so that it's more specific than Vector's div#content h3.
- */
-#bodyContent div.mw-number-text h3 {
-       top: 0;
-       margin: 0;
-       padding: 0;
-       color: #252525;
-       font-family: "Linux Libertine", Georgia, Times, serif;
-       font-weight: normal;
-       font-size: 2.2em;
-       line-height: 1.2;
-       text-align: center;
-}
-
-/* Contains a number and explanatory text, with space for an icon */
-div.mw-number-text {
-       display: block;
-       font-size: 1.2em;
-       color: #444;
-       margin-top: 1em;
-       /* 80px wide icon plus "margin" */
-       padding: 0 0 0 95px;
-       /* Matches max icon height, ensures icon emblem is visible */
-       min-height: 75px;
-       text-align: center;
-}
diff --git a/resources/mediawiki.special/mediawiki.special.userlogin.signup.js b/resources/mediawiki.special/mediawiki.special.userlogin.signup.js
deleted file mode 100644 (file)
index 0615932..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- * JavaScript for signup form.
- */
-( function ( mw, $ ) {
-       // When sending password by email, hide the password input fields.
-       $( function () {
-               // Always required if checked, otherwise it depends, so we use the original
-               var $emailLabel = $( 'label[for="wpEmail"]' ),
-                       originalText = $emailLabel.text(),
-                       requiredText = mw.message( 'createacct-emailrequired' ).text(),
-                       $createByMailCheckbox = $( '#wpCreateaccountMail' ),
-                       $beforePwds = $( '.mw-row-password:first' ).prev(),
-                       $pwds;
-
-               function updateForCheckbox() {
-                       var checked = $createByMailCheckbox.prop( 'checked' );
-                       if ( checked ) {
-                               $pwds = $( '.mw-row-password' ).detach();
-                               $emailLabel.text( requiredText );
-                       } else {
-                               if ( $pwds ) {
-                                       $beforePwds.after( $pwds );
-                                       $pwds = null;
-                               }
-                               $emailLabel.text( originalText );
-                       }
-               }
-
-               $createByMailCheckbox.on( 'change', updateForCheckbox );
-               updateForCheckbox();
-       } );
-
-       // Check if the username is invalid or already taken
-       $( function () {
-               var
-                       // We need to hook to all of these events to be sure we are notified of all changes to the
-                       // value of an <input type=text> field.
-                       events = 'keyup keydown change mouseup cut paste focus blur',
-                       $input = $( '#wpName2' ),
-                       $statusContainer = $( '#mw-createacct-status-area' ),
-                       api = new mw.Api(),
-                       currentRequest;
-
-               // Hide any present status messages.
-               function clearStatus() {
-                       $statusContainer.slideUp( function () {
-                               $statusContainer
-                                       .removeAttr( 'class' )
-                                       .empty();
-                       } );
-               }
-
-               // Returns a promise receiving a { state:, username: } object, where:
-               // * 'state' is one of 'invalid', 'taken', 'ok'
-               // * 'username' is the validated username if 'state' is 'ok', null otherwise (if it's not
-               //   possible to register such an account)
-               function checkUsername( username ) {
-                       // We could just use .then() if we didn't have to pass on .abort()…
-                       var d, apiPromise;
-
-                       d = $.Deferred();
-                       apiPromise = api.get( {
-                               action: 'query',
-                               list: 'users',
-                               ususers: username // '|' in usernames is handled below
-                       } )
-                               .done( function ( resp ) {
-                                       var userinfo = resp.query.users[0];
-
-                                       if ( resp.query.users.length !== 1 ) {
-                                               // Happens if the user types '|' into the field
-                                               d.resolve( { state: 'invalid', username: null } );
-                                       } else if ( userinfo.invalid !== undefined ) {
-                                               d.resolve( { state: 'invalid', username: null } );
-                                       } else if ( userinfo.userid !== undefined ) {
-                                               d.resolve( { state: 'taken', username: null } );
-                                       } else {
-                                               d.resolve( { state: 'ok', username: username } );
-                                       }
-                               } )
-                               .fail( d.reject );
-
-                       return d.promise( { abort: apiPromise.abort } );
-               }
-
-               function updateUsernameStatus() {
-                       var
-                               username = $.trim( $input.val() ),
-                               currentRequestInternal;
-
-                       // Abort any pending requests.
-                       if ( currentRequest ) {
-                               currentRequest.abort();
-                       }
-
-                       if ( username === '' ) {
-                               clearStatus();
-                               return;
-                       }
-
-                       currentRequest = currentRequestInternal = checkUsername( username ).done( function ( info ) {
-                               var message;
-
-                               // Another request was fired in the meantime, the result we got here is no longer current.
-                               // This shouldn't happen as we abort pending requests, but you never know.
-                               if ( currentRequest !== currentRequestInternal ) {
-                                       return;
-                               }
-                               // If we're here, then the current request has finished, avoid calling .abort() needlessly.
-                               currentRequest = undefined;
-
-                               if ( info.state === 'ok' ) {
-                                       clearStatus();
-                               } else {
-                                       if ( info.state === 'invalid' ) {
-                                               message = mw.message( 'noname' ).text();
-                                       } else if ( info.state === 'taken' ) {
-                                               message = mw.message( 'userexists' ).text();
-                                       }
-
-                                       $statusContainer
-                                               .attr( 'class', 'errorbox' )
-                                               .empty()
-                                               .append(
-                                                       // Ugh…
-                                                       // @todo Change the HTML structure in includes/templates/Usercreate.php
-                                                       $( '<strong>' ).text( mw.message( 'createacct-error' ).text() ),
-                                                       $( '<br>' ),
-                                                       document.createTextNode( message )
-                                               )
-                                               .slideDown();
-                               }
-                       } ).fail( function () {
-                               clearStatus();
-                       } );
-               }
-
-               $input.on( events, $.debounce( 250, updateUsernameStatus ) );
-       } );
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki.special/mediawiki.special.version.css b/resources/mediawiki.special/mediawiki.special.version.css
deleted file mode 100644 (file)
index 917426a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * Adds additional styling to the extension title/version list
-**/
-.mw-version-ext-name {
-       font-weight: bold;
-}
-
-.mw-version-ext-vcs-timestamp {
-       white-space: nowrap;
-}
-
-th.mw-version-ext-col-label {
-       font-size: 0.9em;
-}
\ No newline at end of file
diff --git a/resources/mediawiki.ui/components/default/buttons.less b/resources/mediawiki.ui/components/default/buttons.less
deleted file mode 100644 (file)
index 54d1608..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-@import "mediawiki.mixins";
-@import "../../settings/typography";
-@import "../../mixins/effects";
-
-// Buttons
-//
-// All buttons start with mw-ui-button class, modified by other classes.
-// It can be any element.  Due to a lack of a CSS reset, the exact styling of
-// the button depends on what type of element is used.
-// There are two kinds of buttons, the default is a "Call to Action" with an obvious border
-// and there is a quiet kind without a border.
-//
-// Styleguide 2.
-
-@buttonBorderRadius: 3px;
-@transitionDuration: .1s;
-@transitionFunction: ease-in-out;
-
-// Neutral button styling
-//
-// Markup:
-// <button class="mw-ui-button">.mw-ui-button</button>
-// <button class="mw-ui-button" disabled>.mw-ui-button</button>
-//
-// Styleguide 2.1.
-.mw-ui-button {
-       // Container layout
-       display: inline-block;
-       padding: .5em 1em;
-       margin: 0;
-
-       // IE6/IE7 hack
-       // http://stackoverflow.com/a/5838575/365238
-       *display: inline;
-       zoom: 1;
-
-       // Container styling
-       .button-colors(@colorWhite);
-       border-radius: @buttonBorderRadius;
-
-       // Ensure that buttons and inputs are nicely aligned when they have differing heights
-       vertical-align: middle;
-
-       // Content styling
-       text-align: center;
-       font-weight: bold;
-       text-shadow: 0 1px rgba(0, 0, 0, .1);
-
-       // Interaction styling
-       cursor: pointer;
-
-       &:disabled {
-               text-shadow: none;
-               cursor: default;
-       }
-
-       .transition(background @transitionDuration @transitionFunction, color @transitionDuration @transitionFunction, box-shadow @transitionDuration @transitionFunction;);
-
-       // Styling for specific button types
-       // -----------------------------------------
-
-       // Big buttons
-       //
-       // Not all buttons are equal. You can emphasise certain actions over others
-       // using the mw-ui-big class.
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-big">.mw-ui-button</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-big">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-big">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-big">.mw-ui-destructive</button>
-       //
-       // Styleguide 2.1.6.
-       &.mw-ui-big {
-               font-size: @baseFontSize * 1.3;
-       }
-
-       // Block buttons
-       //
-       // Some buttons might need to be stacked.
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-block">.mw-ui-button</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-block">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-block">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-block">.mw-ui-destructive</button>
-       //
-       // Styleguide 2.1.5.
-       &.mw-ui-block {
-               display: block;
-               width: 100%;
-       }
-
-       // Progressive buttons
-       //
-       // Use progressive buttons for actions which lead to a next step in the process.
-       // .mw-ui-primary is deprecated, kept for compatibility.
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-progressive">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-progressive" disabled>.mw-ui-progressive</button>
-       //
-       // Styleguide 2.1.1.
-       &.mw-ui-progressive,
-       &.mw-ui-primary {
-               .button-colors(@colorProgressive);
-
-               &.mw-ui-quiet {
-                       .button-colors-quiet(@colorProgressive);
-               }
-       }
-
-       // Constructive buttons
-       //
-       // Use constructive buttons for actions which result in a final action in the process that results
-       // in a change of state.
-       // e.g. save changes button
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-constructive">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-constructive" disabled>.mw-ui-constructive</button>
-       //
-       // Styleguide 2.1.2.
-       &.mw-ui-constructive {
-               .button-colors(@colorConstructive);
-
-               &.mw-ui-quiet {
-                       .button-colors-quiet(@colorConstructive);
-               }
-       }
-
-       // Destructive buttons
-       //
-       // Use destructive buttons for actions which result in the destruction of data.
-       // e.g. deleting a page.
-       // This should not be used for cancel buttons.
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-destructive">.mw-ui-destructive</button>
-       // <button class="mw-ui-button mw-ui-destructive" disabled>.mw-ui-destructive</button>
-       //
-       // Styleguide 2.1.3.
-       &.mw-ui-destructive {
-               .button-colors(@colorDestructive);
-
-               &.mw-ui-quiet {
-                       .button-colors-quiet(@colorDestructive);
-               }
-       }
-
-       // Quiet buttons
-       //
-       // Use quiet buttons when they are less important and alongisde other progressive/destructive/progressive buttons.
-       //
-       // Markup:
-       // <button class="mw-ui-button mw-ui-quiet">.mw-ui-button</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-quiet">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-quiet" disabled>.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet">.mw-ui-destructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet" disabled>.mw-ui-destructive</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet" disabled>.mw-ui-progressive</button>
-       //
-       // Styleguide 2.1.4.
-       &.mw-ui-quiet {
-               background: transparent;
-               border: none;
-               text-shadow: none;
-               .button-colors-quiet(@colorGrayDark);
-
-               &:hover,
-               &:focus {
-                       box-shadow: none;
-               }
-
-               &:active,
-               &:disabled {
-                       background: transparent;
-               }
-       }
-}
-
-a.mw-ui-button {
-       text-decoration: none;
-
-       // This overrides an underline declaration on a:hover and a:focus in
-       // commonElements.css, which the class alone isn't specific enough to do.
-       &:hover,
-       &:focus {
-               text-decoration: none;
-       }
-}
-
-// Button groups
-//
-// Group of buttons. Make sure you clear the floating after using a mw-ui-button-group.
-//
-// Markup:
-// <div class="mw-ui-button-group">
-//   <div class="mw-ui-button">A</div>
-//   <div class="mw-ui-button">B</div>
-//   <div class="mw-ui-button">C</div>
-//   <div class="mw-ui-button">D</div>
-// </div><div style="clear:both"></div>
-//
-// Styleguide 2.2.
-.mw-ui-button-group > * {
-       border-radius: 0;
-       float: left;
-
-       &:first-child {
-               border-top-left-radius: @buttonBorderRadius;
-               border-bottom-left-radius: @buttonBorderRadius;
-       }
-
-       &:not(:first-child) {
-               border-left: none;
-       }
-
-       &:last-child{
-               border-top-right-radius: @buttonBorderRadius;
-               border-bottom-right-radius: @buttonBorderRadius;
-       }
-}
diff --git a/resources/mediawiki.ui/components/default/forms.less b/resources/mediawiki.ui/components/default/forms.less
deleted file mode 100644 (file)
index 6157fa2..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-// Form elements and layouts
-
-@import "../../mixins/utilities";
-@import "../../mixins/forms";
-
-// --------------------------------------------------------------------------
-// Layouts
-// --------------------------------------------------------------------------
-
-// The FancyCaptcha image CAPTCHA used on WMF wikis drives the width of the
-// 'VForm' design, the form can't be narrower than this.
-@captchaContainerWidth: 290px;
-@defaultFormWidth: @captchaContainerWidth;
-
-// Forms
-//
-// Styleguide 3.
-
-// VForm
-//
-// Style a compact vertical stacked form ("VForm") and the elements in divs
-// within it. See button section on guidance of how and when to use mw-ui-constructive.
-//
-// Markup:
-// <form class="mw-ui-vform">
-//   <div class="mw-ui-vform-div">This is a form example.</div>
-//   <div>
-//     <label>Username </label>
-//     <input value="input">
-//   </div>
-//   <div>
-//     <button class="mw-ui-button mw-ui-constructive">Button in vform</button>
-//   </div>
-// </form>
-//
-// Styleguide 3.1.
-.mw-ui-vform {
-       .box-sizing(border-box);
-
-       width: @defaultFormWidth;
-
-       // Immediate divs in a vform are block and spaced-out.
-       // XXX: We shouldn't depend on the tag name here...
-       & > div {
-               display: block;
-               margin: 0 0 15px 0;
-               padding: 0;
-               width: 100%;
-       }
-
-       // MW currently doesn't use the type attribute everywhere on inputs.
-       input,
-       .mw-ui-button {
-               display: block;
-               .box-sizing(border-box);
-               margin: 0;
-               width: 100%;
-       }
-
-       // We exclude these because they'll generally use mw-ui-button.
-       // Otherwise, we'll unintentionally override that.
-       input:not([type=button]):not([type=submit]):not([type=file]), {
-               .agora-field-styling(); // mixins/forms.less
-       }
-
-       label {
-               display: block;
-               .box-sizing(border-box);
-               .agora-label-styling();
-               width: auto;
-               margin: 0 0 0.2em;
-               padding: 0;
-       }
-
-       // Override input styling just for checkboxes and radio inputs.
-       input[type="checkbox"],
-       input[type="radio"] {
-               display: inline;
-               .box-sizing(content-box);
-               width: auto;
-       }
-
-
-       // Styles for information boxes
-       //
-       // Regular HTMLForm uses .error class, some special pages like
-       // SpecialUserlogin (login and create account) use .errorbox.
-       //
-       // Markup:
-       // <form class="mw-ui-vform">
-       //   <div class="errorbox">An error occurred</div>
-       //   <div class="warningbox">A warning to be noted</div>
-       //   <div class="successbox">Action successful!</div>
-       //   <div class="error">A different kind of error</div>
-       //   <div>
-       //     <input type="text" value="input" class="mw-ui-input">
-       //   <div>
-       //   </div>
-       //     <button class="mw-ui-button">Button in vform</button>
-       //   </div>
-       // </form>
-       //
-       // Styleguide 3.1.
-       .error {
-               .box-sizing(border-box);
-               font-size: 0.9em;
-               margin: 0 0 1em;
-               padding: 0.5em;
-               color: #cc0000;
-               border: 1px solid #fac5c5;
-               background-color: #fae3e3;
-               text-shadow: 0 1px #fae3e3;
-               word-wrap: break-word;
-       }
-
-       .errorbox,
-       .warningbox,
-       .successbox {
-               .box-sizing(border-box);
-               font-size: 0.9em;
-               margin: 0 0 1em 0;
-               padding: 0.5em;
-               word-wrap: break-word;
-       }
-
-}
-
-// --------------------------------------------------------------------------
-// Elements
-// --------------------------------------------------------------------------
-
-// Apply this to individual elements to style them.
-// You generally don't need to use this class on divs within an Agora
-// form container such as mw-ui-vform
-// XXX DRY: This repeats earlier styling, use an @include agora-div-styling ?
-// XXX: What is this even for?
-.mw-ui-vform-div {
-       display: block;
-       margin: 0 0 15px;
-       padding: 0;
-       width: 100%;
-}
-
-// Apply mw-ui-input to individual input fields to style them.
-// You generally don't need to use this class if <input> is within an Agora
-// form container such as mw-ui-vform
-.mw-ui-input {
-       .agora-field-styling(); // mixins/forms.less
-}
-
-// Apply mw-ui-label to individual elements to style them.
-// You generally don't need to use this class if <label> is within an Agora
-// form container such as mw-ui-vform
-.mw-ui-label {
-       .agora-label-styling(); // mixins/forms.less
-}
-
-// Nesting an input checkbox or radio button inside a label with this class
-// improves alignment, e.g.
-//     <label class="mw-ui-checkbox-label">
-//             <input type="checkbox">The label text
-//     </label>
-.mw-ui-checkbox-label, .mw-ui-radio-label {
-       .agora-inline-label-styling();
-}
diff --git a/resources/mediawiki.ui/components/utilities.less b/resources/mediawiki.ui/components/utilities.less
deleted file mode 100644 (file)
index 9aea429..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Generic helper classes that could be used in many elements/layouts
-
-// --------------------------------------------------------------------------
-// Positioning
-// --------------------------------------------------------------------------
-
-@import "../mixins/utilities";
-
-.mw-ui-flush-left {
-       .agora-flush-left();
-}
-
-.mw-ui-flush-right {
-       .agora-flush-right();
-}
-
-.mw-ui-center-block {
-       .agora-center-block();
-}
diff --git a/resources/mediawiki.ui/components/vector/buttons.less b/resources/mediawiki.ui/components/vector/buttons.less
deleted file mode 100644 (file)
index 1536338..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-@import "../default/buttons"; // Layer Vector on top of the default settings.
-@import "../../mixins/type";
-
-.mw-ui-button {
-       .vector-type();
-}
diff --git a/resources/mediawiki.ui/components/vector/containers.less b/resources/mediawiki.ui/components/vector/containers.less
deleted file mode 100644 (file)
index 1e9ec05..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// No default settings for containers yet.
-@import "../../mixins/type";
-
-.mw-ui-container {
-       .vector-type();
-}
diff --git a/resources/mediawiki.ui/components/vector/forms.less b/resources/mediawiki.ui/components/vector/forms.less
deleted file mode 100644 (file)
index 2bbd8f0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-@import "../default/forms"; // Layer Vector on top of the default settings.
-@import "../../mixins/type";
-
-.mw-ui-vform,
-.mw-ui-vform input,
-.mw-ui-input {
-       .vector-type();
-}
diff --git a/resources/mediawiki.ui/default.less b/resources/mediawiki.ui/default.less
deleted file mode 100644 (file)
index e576937..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Provide Agora appearance for mw-ui-* classes when using a skin other than
- * Vector.
- */
-
-@import "components/utilities";
-@import "components/default/forms";
diff --git a/resources/mediawiki.ui/mixins/effects.less b/resources/mediawiki.ui/mixins/effects.less
deleted file mode 100644 (file)
index 9daad74..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-@import "../settings/colors";
-// ----------------------------------------------------------------------------
-// Button styling
-// ----------------------------------------------------------------------------
-
-.button-colors(@bgColor) {
-       background: @bgColor;
-
-       &:hover,
-       &:focus {
-               // The inner bottom bevel should match the active background color.
-               box-shadow: 0 1px rgba(0, 0, 0, 10%), inset 0 -3px rgba(0, 0, 0, 20%);
-               outline: none;
-               // remove outline in Firefox
-               &::-moz-focus-inner {
-                       border-color: transparent;
-               }
-       }
-
-       &:active,
-       &.mw-ui-checked {
-               // lessphp doesn't implement shade (https://github.com/leafo/lessphp/issues/528);
-               // it passes it through, then ResourceLoader drops it.
-               // background: shade(@bgColor, 20%);
-               background: mix(#000, @bgColor, 20%);
-               box-shadow: none;
-       }
-}
-
-.button-colors(@bgColor) when (lightness(@bgColor) >= 70%) {
-       color: @colorGrayDark;
-       border: 1px solid @colorGrayLight;
-
-       &:disabled {
-               color: @colorGrayLight;
-
-               // make sure disabled buttons don't have hover and active states
-               &:hover,
-               &:active {
-                       background: @bgColor;
-                       box-shadow: none;
-               }
-       }
-}
-
-.button-colors(@bgColor) when (lightness(@bgColor) < 70%) {
-       color: @colorWhite;
-       border: none;
-
-       &:disabled {
-               background: @colorGrayLight;
-
-               // make sure disabled buttons don't have hover and active states
-               &:hover,
-               &:active,
-               &.mw-ui-checked {
-                       box-shadow: none;
-               }
-       }
-}
-
-.button-colors-quiet(@textColor) {
-       // Quiet buttons all start gray, and reveal
-       // constructive/progressive/destructive color on hover and active.
-       color: @colorGrayDark;
-
-       &:hover,
-       &:focus {
-               // lessphp doesn't implement tint, see above
-               // color: tint(@textColor, 20%);
-               color: mix(#fff, @textColor, 20%);
-       }
-
-       &:active,
-       &.mw-ui-checked {
-               // lessphp doesn't implement shade, see above
-               // color: shade(@textColor, 20%);
-               color: mix(#000, @textColor, 20%);
-       }
-
-       &:disabled {
-               color: @colorGrayLight;
-       }
-}
diff --git a/resources/mediawiki.ui/mixins/forms.less b/resources/mediawiki.ui/mixins/forms.less
deleted file mode 100644 (file)
index 20f42a0..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-@import "../settings/colors";
-
-// Font is not included.
-// For Vector, that should be layered on top with vector-type
-.agora-field-styling() {
-
-       border: 1px solid @colorGrayLight;
-
-       &:focus {
-               // Styling focus of native checkboxes etc on Mac is almost impossible.
-               &:not([type=checkbox]):not([type=radio]) {
-                       outline: 0; // Removes OS field focus
-               }
-
-               box-shadow: @colorProgressiveShadow 0 0 5px;
-
-               border-color: @colorProgressiveShadow;
-       }
-
-       color: @colorText;
-       padding: 0.35em 0.5em 0.35em 0.5em;
-
-       // Ensure that buttons and inputs are nicely aligned when they have differing heights
-       vertical-align: middle;
-}
-
-.agora-label-styling() {
-       //font-weight: bold;
-       font-size: 0.9em;
-       color: darken(@colorGrayLight, 50%);
-
-       * {
-               font-weight: normal;
-       }
-}
-
-.agora-inline-label-styling() {
-       margin-bottom: 0.5em;
-       cursor: pointer;
-       vertical-align: bottom;
-       line-height: normal;
-
-       font-weight: normal;
-
-       & > input[type="checkbox"],
-       & > input[type="radio"] {
-               width: auto;
-               height: auto;
-               margin: 0 0.1em 0 0;
-               padding: 0;
-               border: 1px solid @colorGrayLight;
-               cursor: pointer;
-       }
-}
diff --git a/resources/mediawiki.ui/mixins/type.less b/resources/mediawiki.ui/mixins/type.less
deleted file mode 100644 (file)
index 4a01168..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-@import "../settings/typography";
-
-.vector-type() {
-       font-size: @baseFontSize;
-       line-height: @baseLineHeight;
-}
diff --git a/resources/mediawiki.ui/mixins/utilities.less b/resources/mediawiki.ui/mixins/utilities.less
deleted file mode 100644 (file)
index a201a4e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-.box-sizing(@value) {
-       -moz-box-sizing: @value;
-       -webkit-box-sizing: @value;
-       box-sizing: @value;
-}
-
-.agora-flush-left() {
-       float: left;
-       margin-left: 0;
-       padding-left: 0;
-}
-
-.agora-flush-right() {
-       float: right;
-       margin-right: 0;
-       padding-right: 0;
-}
-
-.agora-center-block() {
-       display: block;
-       margin-left: auto;
-       margin-right: auto;
-}
diff --git a/resources/mediawiki.ui/settings/colors.less b/resources/mediawiki.ui/settings/colors.less
deleted file mode 100644 (file)
index 18661de..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-@colorWhite: #fff;
-@colorGrayLight: #ccc;
-@colorGrayDark: #898989;
-@colorText: #252525;
-@colorProgressive: #347bff;
-// FIXME: remove @colorProgressiveShadow (shadows should be generated
-// in LESS by dimming the original colors)
-@colorProgressiveShadow: #4091ed;
-@colorConstructive: #00af89;
-@colorDestructive: #d11d13;
diff --git a/resources/mediawiki.ui/settings/typography.less b/resources/mediawiki.ui/settings/typography.less
deleted file mode 100644 (file)
index 83651ed..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-@baseFontSize: 1em;
-@baseLineHeight: 1.4 * @baseFontSize;
-@baseFontColor: @colorText;
-
-@smallFontSize: 0.75em;
diff --git a/resources/mediawiki.ui/styleguide.md b/resources/mediawiki.ui/styleguide.md
deleted file mode 100644 (file)
index b7eea54..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#Wikimedia projects
-
-This is the living style guide for MediaWiki UI used in Wikimedia Projects. It is generated from existing CSS programmatically. Please use it as a reference when developing code for MediaWiki to ensure your design is consistent with others across the site. Note this document is a work in progress and subject to change.
-
-##Brand
-
-Imagine a world in which every single human being can freely share in the sum of all knowledge.
-
-Sharing knowledge is the heart of our movement. Specifically, we care about sharing the “… highest possible quality to every single person on the planet in their own language” (Jimmy Wales). The focus of our identity is being credible and is moving toward being more inviting. We want our contributors to keep contributing while our assuring our readers that the information on any of the Wikimedia projects is reliable and accurate. Our personality should embody both of those traits with a slight sense of rebellion. We are unlike traditional projects (for instance, Encyclopedias that are only created by a few select individuals). We are a global movement, and as Jimmy Wales puts it: “Wikipedia is like rock’n’roll; it’s a cultural shift."
-
-##Design Philosophy
-
-The Wikimedia movement is a global volunteer community that aims to collect and develop the world's knowledge and to make it available to everyone for free, for any purpose. “Imagine a world in which every single human being can freely share in the sum of all knowledge.” 
-
-###Credible
-We strive for the most accurate, high quality and neutral information on all Wikimedia projects. We are fact-based and honest. We do not take sides. We are fair and impartial. 
-
-###Inviting
-We are geeky about collecting and developing knowledge. We invite and welcome every single human being to share their knowledge with us and the rest of the world. We are open-minded and have a strong sense of community. Our aesthetics should be clean and encourage interaction. 
-
-###Worldly
-We are thoughtful and are aware of cultural differences. We are careful about words, color usage, and images that might offend. We are also aware of limited connectivity in some areas of the world and are thoughtful of image sizes and loading speed. 
-
-###Humble
-We are respectful of contributors’ effort and knowledge. We have a wealth of knowledge on all projects and many people to thank for that. We are humble. We are helpful and welcome help to expand the sum of all knowledge. 
-
diff --git a/resources/mediawiki.ui/vector.less b/resources/mediawiki.ui/vector.less
deleted file mode 100644 (file)
index 08690a3..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Provide Agora appearance for mw-ui-* classes when using the Vector skin.
- */
-
-// Typography
-//
-// We prefer the usage of Georgia Bold for all headings. Georgia Regular is used to place emphasis on pull-out or short quotations. This latter usage should be used sparingly. 
-//
-// We prefer the use of Helvetica Neue Regular for body copy. Helvetiva Neue Bold for sub-headers. Pull-out quotes within the body copy should use Helvetica Neue Bold. Helvetica Neue is an not open-source font. Hence, below is a list of preferred alternate choices.
-//
-// Second choice: Helvetica
-//
-// Third choice: Arial
-//
-// Our content is predominantly text, hence visual hierarchy must be clear. Use these recommended type sizes to inform and establish information hierarchy and organization. 
-//
-// Unless if you plan to put extra attention and manually adjust spacing, avoid justifying texts and paragraphs as they are harder to read and create unnecessary visual distractions. Along with centered text, they convey a formal and less friendly environment. 
-//
-// It will be important to talk about other languages, scripts and writing direction - with the same level as importance, not as an afterthought.
-//
-// Styleguide 1.
-
-@import "components/utilities";
-@import "components/vector/forms";
-@import "components/vector/containers";
diff --git a/resources/mediawiki/images/arrow-collapsed-ltr.png b/resources/mediawiki/images/arrow-collapsed-ltr.png
deleted file mode 100644 (file)
index b17e578..0000000
Binary files a/resources/mediawiki/images/arrow-collapsed-ltr.png and /dev/null differ
diff --git a/resources/mediawiki/images/arrow-collapsed-ltr.svg b/resources/mediawiki/images/arrow-collapsed-ltr.svg
deleted file mode 100644 (file)
index 15992f8..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   width="12"
-   height="12"
-   id="svg2"
-   inkscape:version="0.48.4 r9939"
-   sodipodi:docname="arrow-collapsed-ltr.svg">
-  <sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="1920"
-     inkscape:window-height="1041"
-     id="namedview7"
-     showgrid="false"
-     inkscape:zoom="27.812867"
-     inkscape:cx="7.833847"
-     inkscape:cy="7.3054094"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="svg2" />
-  <defs
-     id="defs4" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="matrix(1.0559311,0,0,1.0825058,-404.86649,-609.71107)"
-     id="layer1">
-    <path
-       d="m 387.20944,564.65683 0,8.93354 4.49986,-4.49987 z"
-       id="arrow"
-       style="fill:#797979;fill-opacity:1;stroke:none"
-       inkscape:connector-curvature="0" />
-  </g>
-</svg>
diff --git a/resources/mediawiki/images/arrow-collapsed-rtl.png b/resources/mediawiki/images/arrow-collapsed-rtl.png
deleted file mode 100644 (file)
index a834548..0000000
Binary files a/resources/mediawiki/images/arrow-collapsed-rtl.png and /dev/null differ
diff --git a/resources/mediawiki/images/arrow-collapsed-rtl.svg b/resources/mediawiki/images/arrow-collapsed-rtl.svg
deleted file mode 100644 (file)
index a643689..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   width="12"
-   height="12"
-   id="svg2"
-   inkscape:version="0.48.4 r9939"
-   sodipodi:docname="arrow-collapsed-ltr.svg">
-  <sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="1920"
-     inkscape:window-height="1041"
-     id="namedview7"
-     showgrid="false"
-     inkscape:zoom="27.812867"
-     inkscape:cx="14.764482"
-     inkscape:cy="6.45175"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="svg2" />
-  <defs
-     id="defs4" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="matrix(-1.0559311,0,0,1.0825058,416.86649,-609.71107)"
-     id="layer1">
-    <path
-       d="m 387.20944,564.65683 0,8.93354 4.49986,-4.49987 z"
-       id="arrow"
-       style="fill:#797979;fill-opacity:1;stroke:none"
-       inkscape:connector-curvature="0" />
-  </g>
-</svg>
diff --git a/resources/mediawiki/images/arrow-expanded.png b/resources/mediawiki/images/arrow-expanded.png
deleted file mode 100644 (file)
index 2bec798..0000000
Binary files a/resources/mediawiki/images/arrow-expanded.png and /dev/null differ
diff --git a/resources/mediawiki/images/arrow-expanded.svg b/resources/mediawiki/images/arrow-expanded.svg
deleted file mode 100644 (file)
index 4012bb5..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   width="12"
-   height="12"
-   id="svg2"
-   inkscape:version="0.48.4 r9939"
-   sodipodi:docname="arrow-collapsed-rtl.svg">
-  <sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="1920"
-     inkscape:window-height="1041"
-     id="namedview7"
-     showgrid="false"
-     inkscape:zoom="27.812867"
-     inkscape:cx="9.7488178"
-     inkscape:cy="6.45175"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="svg2" />
-  <defs
-     id="defs4" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="matrix(0,1.0559311,1.0825058,0,-610.0796,-405.24226)"
-     id="layer1">
-    <path
-       d="m 387.20944,564.65683 0,8.93354 4.49986,-4.49987 z"
-       id="arrow"
-       style="fill:#797979;fill-opacity:1;stroke:none"
-       inkscape:connector-curvature="0" />
-  </g>
-</svg>
diff --git a/resources/mediawiki/mediawiki.Title.js b/resources/mediawiki/mediawiki.Title.js
deleted file mode 100644 (file)
index b7b818f..0000000
+++ /dev/null
@@ -1,588 +0,0 @@
-/*!
- * @author Neil Kandalgaonkar, 2010
- * @author Timo Tijhof, 2011-2013
- * @since 1.18
- */
-( function ( mw, $ ) {
-
-       /**
-        * @class mw.Title
-        *
-        * Parse titles into an object struture. Note that when using the constructor
-        * directly, passing invalid titles will result in an exception. Use #newFromText to use the
-        * logic directly and get null for invalid titles which is easier to work with.
-        *
-        * @constructor
-        * @param {string} title Title of the page. If no second argument given,
-        *  this will be searched for a namespace
-        * @param {number} [namespace=NS_MAIN] If given, will used as default namespace for the given title
-        * @throws {Error} When the title is invalid
-        */
-       function Title( title, namespace ) {
-               var parsed = parse( title, namespace );
-               if ( !parsed ) {
-                       throw new Error( 'Unable to parse title' );
-               }
-
-               this.namespace = parsed.namespace;
-               this.title = parsed.title;
-               this.ext = parsed.ext;
-               this.fragment = parsed.fragment;
-
-               return this;
-       }
-
-       /* Private members */
-
-       var
-
-       /**
-        * @private
-        * @static
-        * @property NS_MAIN
-        */
-       NS_MAIN = 0,
-
-       /**
-        * @private
-        * @static
-        * @property NS_TALK
-        */
-       NS_TALK = 1,
-
-       /**
-        * @private
-        * @static
-        * @property NS_SPECIAL
-        */
-       NS_SPECIAL = -1,
-
-       /**
-        * Get the namespace id from a namespace name (either from the localized, canonical or alias
-        * name).
-        *
-        * Example: On a German wiki this would return 6 for any of 'File', 'Datei', 'Image' or
-        * even 'Bild'.
-        *
-        * @private
-        * @static
-        * @method getNsIdByName
-        * @param {string} ns Namespace name (case insensitive, leading/trailing space ignored)
-        * @return {number|boolean} Namespace id or boolean false
-        */
-       getNsIdByName = function ( ns ) {
-               var id;
-
-               // Don't cast non-strings to strings, because null or undefined should not result in
-               // returning the id of a potential namespace called "Null:" (e.g. on null.example.org/wiki)
-               // Also, toLowerCase throws exception on null/undefined, because it is a String method.
-               if ( typeof ns !== 'string' ) {
-                       return false;
-               }
-               ns = ns.toLowerCase();
-               id = mw.config.get( 'wgNamespaceIds' )[ns];
-               if ( id === undefined ) {
-                       return false;
-               }
-               return id;
-       },
-
-       rUnderscoreTrim = /^_+|_+$/g,
-
-       rSplit = /^(.+?)_*:_*(.*)$/,
-
-       // See Title.php#getTitleInvalidRegex
-       rInvalid = new RegExp(
-               '[^' + mw.config.get( 'wgLegalTitleChars' ) + ']' +
-               // URL percent encoding sequences interfere with the ability
-               // to round-trip titles -- you can't link to them consistently.
-               '|%[0-9A-Fa-f]{2}' +
-               // XML/HTML character references produce similar issues.
-               '|&[A-Za-z0-9\u0080-\uFFFF]+;' +
-               '|&#[0-9]+;' +
-               '|&#x[0-9A-Fa-f]+;'
-       ),
-
-       /**
-        * Internal helper for #constructor and #newFromtext.
-        *
-        * Based on Title.php#secureAndSplit
-        *
-        * @private
-        * @static
-        * @method parse
-        * @param {string} title
-        * @param {number} [defaultNamespace=NS_MAIN]
-        * @return {Object|boolean}
-        */
-       parse = function ( title, defaultNamespace ) {
-               var namespace, m, id, i, fragment, ext;
-
-               namespace = defaultNamespace === undefined ? NS_MAIN : defaultNamespace;
-
-               title = title
-                       // Normalise whitespace to underscores and remove duplicates
-                       .replace( /[ _\s]+/g, '_' )
-                       // Trim underscores
-                       .replace( rUnderscoreTrim, '' );
-
-               // Process initial colon
-               if ( title !== '' && title.charAt( 0 ) === ':' ) {
-                       // Initial colon means main namespace instead of specified default
-                       namespace = NS_MAIN;
-                       title = title
-                               // Strip colon
-                               .substr( 1 )
-                               // Trim underscores
-                               .replace( rUnderscoreTrim, '' );
-               }
-
-               if ( title === '' ) {
-                       return false;
-               }
-
-               // Process namespace prefix (if any)
-               m = title.match( rSplit );
-               if ( m ) {
-                       id = getNsIdByName( m[1] );
-                       if ( id !== false ) {
-                               // Ordinary namespace
-                               namespace = id;
-                               title = m[2];
-
-                               // For Talk:X pages, make sure X has no "namespace" prefix
-                               if ( namespace === NS_TALK && ( m = title.match( rSplit ) ) ) {
-                                       // Disallow titles like Talk:File:x (subject should roundtrip: talk:file:x -> file:x -> file_talk:x)
-                                       if ( getNsIdByName( m[1] ) !== false ) {
-                                               return false;
-                                       }
-                               }
-                       }
-               }
-
-               // Process fragment
-               i = title.indexOf( '#' );
-               if ( i === -1 ) {
-                       fragment = null;
-               } else {
-                       fragment = title
-                               // Get segment starting after the hash
-                               .substr( i + 1 )
-                               // Convert to text
-                               // NB: Must not be trimmed ("Example#_foo" is not the same as "Example#foo")
-                               .replace( /_/g, ' ' );
-
-                       title = title
-                               // Strip hash
-                               .substr( 0, i )
-                               // Trim underscores, again (strips "_" from "bar" in "Foo_bar_#quux")
-                               .replace( rUnderscoreTrim, '' );
-               }
-
-               // Reject illegal characters
-               if ( title.match( rInvalid ) ) {
-                       return false;
-               }
-
-               // Disallow titles that browsers or servers might resolve as directory navigation
-               if (
-                       title.indexOf( '.' ) !== -1 && (
-                               title === '.' || title === '..' ||
-                               title.indexOf( './' ) === 0 ||
-                               title.indexOf( '../' ) === 0 ||
-                               title.indexOf( '/./' ) !== -1 ||
-                               title.indexOf( '/../' ) !== -1 ||
-                               title.substr( title.length - 2 ) === '/.' ||
-                               title.substr( title.length - 3 ) === '/..'
-                       )
-               ) {
-                       return false;
-               }
-
-               // Disallow magic tilde sequence
-               if ( title.indexOf( '~~~' ) !== -1 ) {
-                       return false;
-               }
-
-               // Disallow titles exceeding the 255 byte size limit (size of underlying database field)
-               // Except for special pages, e.g. [[Special:Block/Long name]]
-               // Note: The PHP implementation also asserts that even in NS_SPECIAL, the title should
-               // be less than 512 bytes.
-               if ( namespace !== NS_SPECIAL && $.byteLength( title ) > 255 ) {
-                       return false;
-               }
-
-               // Can't make a link to a namespace alone.
-               if ( title === '' && namespace !== NS_MAIN ) {
-                       return false;
-               }
-
-               // Any remaining initial :s are illegal.
-               if ( title.charAt( 0 ) === ':' ) {
-                       return false;
-               }
-
-               // For backwards-compatibility with old mw.Title, we separate the extension from the
-               // rest of the title.
-               i = title.lastIndexOf( '.' );
-               if ( i === -1 || title.length <= i + 1 ) {
-                       // Extensions are the non-empty segment after the last dot
-                       ext = null;
-               } else {
-                       ext = title.substr( i + 1 );
-                       title = title.substr( 0, i );
-               }
-
-               return {
-                       namespace: namespace,
-                       title: title,
-                       ext: ext,
-                       fragment: fragment
-               };
-       },
-
-       /**
-        * Convert db-key to readable text.
-        *
-        * @private
-        * @static
-        * @method text
-        * @param {string} s
-        * @return {string}
-        */
-       text = function ( s ) {
-               if ( s !== null && s !== undefined ) {
-                       return s.replace( /_/g, ' ' );
-               } else {
-                       return '';
-               }
-       },
-
-       // Polyfill for ES5 Object.create
-       createObject = Object.create || ( function () {
-               return function ( o ) {
-                       function Title() {}
-                       if ( o !== Object( o ) ) {
-                               throw new Error( 'Cannot inherit from a non-object' );
-                       }
-                       Title.prototype = o;
-                       return new Title();
-               };
-       }() );
-
-       /* Static members */
-
-       /**
-        * Constructor for Title objects with a null return instead of an exception for invalid titles.
-        *
-        * @static
-        * @method
-        * @param {string} title
-        * @param {number} [namespace=NS_MAIN] Default namespace
-        * @return {mw.Title|null} A valid Title object or null if the title is invalid
-        */
-       Title.newFromText = function ( title, namespace ) {
-               var t, parsed = parse( title, namespace );
-               if ( !parsed ) {
-                       return null;
-               }
-
-               t = createObject( Title.prototype );
-               t.namespace = parsed.namespace;
-               t.title = parsed.title;
-               t.ext = parsed.ext;
-               t.fragment = parsed.fragment;
-
-               return t;
-       };
-
-       /**
-        * Get the file title from an image element
-        *
-        *     var title = mw.Title.newFromImg( $( 'img:first' ) );
-        *
-        * @static
-        * @param {HTMLElement|jQuery} img The image to use as a base
-        * @return {mw.Title|null} The file title or null if unsuccessful
-        */
-       Title.newFromImg = function ( img ) {
-               var matches, i, regex, src, decodedSrc,
-
-                       // thumb.php-generated thumbnails
-                       thumbPhpRegex = /thumb\.php/,
-                       regexes = [
-                               // Thumbnails
-                               /\/[a-f0-9]\/[a-f0-9]{2}\/([^\s\/]+)\/[^\s\/]+-(?:\1|thumbnail)[^\s\/]*$/,
-
-                               // Thumbnails in non-hashed upload directories
-                               /\/([^\s\/]+)\/[^\s\/]+-(?:\1|thumbnail)[^\s\/]*$/,
-
-                               // Full size images
-                               /\/[a-f0-9]\/[a-f0-9]{2}\/([^\s\/]+)$/,
-
-                               // Full-size images in non-hashed upload directories
-                               /\/([^\s\/]+)$/
-                       ],
-
-                       recount = regexes.length;
-
-               src = img.jquery ? img[0].src : img.src;
-
-               matches = src.match( thumbPhpRegex );
-
-               if ( matches ) {
-                       return mw.Title.newFromText( 'File:' + mw.util.getParamValue( 'f', src ) );
-               }
-
-               decodedSrc = decodeURIComponent( src );
-
-               for ( i = 0; i < recount; i++ ) {
-                       regex = regexes[i];
-                       matches = decodedSrc.match( regex );
-
-                       if ( matches && matches[1] ) {
-                               return mw.Title.newFromText( 'File:' + matches[1] );
-                       }
-               }
-
-               return null;
-       };
-
-       /**
-        * Whether this title exists on the wiki.
-        *
-        * @static
-        * @param {string|mw.Title} title prefixed db-key name (string) or instance of Title
-        * @return {boolean|null} Boolean if the information is available, otherwise null
-        */
-       Title.exists = function ( title ) {
-               var match,
-                       type = $.type( title ),
-                       obj = Title.exist.pages;
-
-               if ( type === 'string' ) {
-                       match = obj[title];
-               } else if ( type === 'object' && title instanceof Title ) {
-                       match = obj[title.toString()];
-               } else {
-                       throw new Error( 'mw.Title.exists: title must be a string or an instance of Title' );
-               }
-
-               if ( typeof match === 'boolean' ) {
-                       return match;
-               }
-
-               return null;
-       };
-
-       Title.exist = {
-               /**
-                * Boolean true value indicates page does exist.
-                *
-                * @static
-                * @property {Object} exist.pages Keyed by PrefixedDb title.
-                */
-               pages: {},
-
-               /**
-                * Example to declare existing titles:
-                *
-                *     Title.exist.set( ['User:John_Doe', ...] );
-                *
-                * Example to declare titles nonexistent:
-                *
-                *     Title.exist.set( ['File:Foo_bar.jpg', ...], false );
-                *
-                * @static
-                * @property exist.set
-                * @param {string|Array} titles Title(s) in strict prefixedDb title form
-                * @param {boolean} [state=true] State of the given titles
-                * @return {boolean}
-                */
-               set: function ( titles, state ) {
-                       titles = $.isArray( titles ) ? titles : [titles];
-                       state = state === undefined ? true : !!state;
-                       var pages = this.pages, i, len = titles.length;
-                       for ( i = 0; i < len; i++ ) {
-                               pages[ titles[i] ] = state;
-                       }
-                       return true;
-               }
-       };
-
-       /* Public members */
-
-       Title.prototype = {
-               constructor: Title,
-
-               /**
-                * Get the namespace number
-                *
-                * Example: 6 for "File:Example_image.svg".
-                *
-                * @return {number}
-                */
-               getNamespaceId: function () {
-                       return this.namespace;
-               },
-
-               /**
-                * Get the namespace prefix (in the content language)
-                *
-                * Example: "File:" for "File:Example_image.svg".
-                * In #NS_MAIN this is '', otherwise namespace name plus ':'
-                *
-                * @return {string}
-                */
-               getNamespacePrefix: function () {
-                       return this.namespace === NS_MAIN ?
-                               '' :
-                               ( mw.config.get( 'wgFormattedNamespaces' )[ this.namespace ].replace( / /g, '_' ) + ':' );
-               },
-
-               /**
-                * Get the page name without extension or namespace prefix
-                *
-                * Example: "Example_image" for "File:Example_image.svg".
-                *
-                * For the page title (full page name without namespace prefix), see #getMain.
-                *
-                * @return {string}
-                */
-               getName: function () {
-                       if ( $.inArray( this.namespace, mw.config.get( 'wgCaseSensitiveNamespaces' ) ) !== -1 ) {
-                               return this.title;
-                       } else {
-                               return $.ucFirst( this.title );
-                       }
-               },
-
-               /**
-                * Get the page name (transformed by #text)
-                *
-                * Example: "Example image" for "File:Example_image.svg".
-                *
-                * For the page title (full page name without namespace prefix), see #getMainText.
-                *
-                * @return {string}
-                */
-               getNameText: function () {
-                       return text( this.getName() );
-               },
-
-               /**
-                * Get the extension of the page name (if any)
-                *
-                * @return {string|null} Name extension or null if there is none
-                */
-               getExtension: function () {
-                       return this.ext;
-               },
-
-               /**
-                * Shortcut for appendable string to form the main page name.
-                *
-                * Returns a string like ".json", or "" if no extension.
-                *
-                * @return {string}
-                */
-               getDotExtension: function () {
-                       return this.ext === null ? '' : '.' + this.ext;
-               },
-
-               /**
-                * Get the main page name (transformed by #text)
-                *
-                * Example: "Example_image.svg" for "File:Example_image.svg".
-                *
-                * @return {string}
-                */
-               getMain: function () {
-                       return this.getName() + this.getDotExtension();
-               },
-
-               /**
-                * Get the main page name (transformed by #text)
-                *
-                * Example: "Example image.svg" for "File:Example_image.svg".
-                *
-                * @return {string}
-                */
-               getMainText: function () {
-                       return text( this.getMain() );
-               },
-
-               /**
-                * Get the full page name
-                *
-                * Eaxample: "File:Example_image.svg".
-                * Most useful for API calls, anything that must identify the "title".
-                *
-                * @return {string}
-                */
-               getPrefixedDb: function () {
-                       return this.getNamespacePrefix() + this.getMain();
-               },
-
-               /**
-                * Get the full page name (transformed by #text)
-                *
-                * Example: "File:Example image.svg" for "File:Example_image.svg".
-                *
-                * @return {string}
-                */
-               getPrefixedText: function () {
-                       return text( this.getPrefixedDb() );
-               },
-
-               /**
-                * Get the fragment (if any).
-                *
-                * Note that this method (by design) does not include the hash character and
-                * the value is not url encoded.
-                *
-                * @return {string|null}
-                */
-               getFragment: function () {
-                       return this.fragment;
-               },
-
-               /**
-                * Get the URL to this title
-                *
-                * @see mw.util#getUrl
-                * @param {Object} [params] A mapping of query parameter names to values,
-                *     e.g. `{ action: 'edit' }`.
-                * @return {string}
-                */
-               getUrl: function ( params ) {
-                       return mw.util.getUrl( this.toString(), params );
-               },
-
-               /**
-                * Whether this title exists on the wiki.
-                *
-                * @see #static-method-exists
-                * @return {boolean|null} Boolean if the information is available, otherwise null
-                */
-               exists: function () {
-                       return Title.exists( this );
-               }
-       };
-
-       /**
-        * @alias #getPrefixedDb
-        * @method
-        */
-       Title.prototype.toString = Title.prototype.getPrefixedDb;
-
-       /**
-        * @alias #getPrefixedText
-        * @method
-        */
-       Title.prototype.toText = Title.prototype.getPrefixedText;
-
-       // Expose
-       mw.Title = Title;
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.Uri.js b/resources/mediawiki/mediawiki.Uri.js
deleted file mode 100644 (file)
index 5566312..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-/**
- * Library for simple URI parsing and manipulation.
- *
- * Intended to be minimal, but featureful; do not expect full RFC 3986 compliance. The use cases we
- * have in mind are constructing 'next page' or 'previous page' URLs, detecting whether we need to
- * use cross-domain proxies for an API, constructing simple URL-based API calls, etc. Parsing here
- * is regex-based, so may not work on all URIs, but is good enough for most.
- *
- * You can modify the properties directly, then use the #toString method to extract the full URI
- * string again. Example:
- *
- *     var uri = new mw.Uri( 'http://example.com/mysite/mypage.php?quux=2' );
- *
- *     if ( uri.host == 'example.com' ) {
- *         uri.host = 'foo.example.com';
- *         uri.extend( { bar: 1 } );
- *
- *         $( 'a#id1' ).attr( 'href', uri );
- *         // anchor with id 'id1' now links to http://foo.example.com/mysite/mypage.php?bar=1&quux=2
- *
- *         $( 'a#id2' ).attr( 'href', uri.clone().extend( { bar: 3, pif: 'paf' } ) );
- *         // anchor with id 'id2' now links to http://foo.example.com/mysite/mypage.php?bar=3&quux=2&pif=paf
- *     }
- *
- * Given a URI like
- * `http://usr:pwd@www.example.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=&test3=value+%28escaped%29&r=1&r=2#top`
- * the returned object will have the following properties:
- *
- *     protocol  'http'
- *     user      'usr'
- *     password  'pwd'
- *     host      'www.example.com'
- *     port      '81'
- *     path      '/dir/dir.2/index.htm'
- *     query     {
- *                   q1: '0',
- *                   test1: null,
- *                   test2: '',
- *                   test3: 'value (escaped)'
- *                   r: ['1', '2']
- *               }
- *     fragment  'top'
- *
- * (N.b., 'password' is technically not allowed for HTTP URIs, but it is possible with other kinds
- * of URIs.)
- *
- * Parsing based on parseUri 1.2.2 (c) Steven Levithan <http://stevenlevithan.com>, MIT License.
- * <http://stevenlevithan.com/demo/parseuri/js/>
- *
- * @class mw.Uri
- */
-
-( function ( mw, $ ) {
-       /**
-        * Function that's useful when constructing the URI string -- we frequently encounter the pattern
-        * of having to add something to the URI as we go, but only if it's present, and to include a
-        * character before or after if so.
-        *
-        * @private
-        * @static
-        * @param {string|undefined} pre To prepend
-        * @param {string} val To include
-        * @param {string} post To append
-        * @param {boolean} raw If true, val will not be encoded
-        * @return {string} Result
-        */
-       function cat( pre, val, post, raw ) {
-               if ( val === undefined || val === null || val === '' ) {
-                       return '';
-               }
-               return pre + ( raw ? val : mw.Uri.encode( val ) ) + post;
-       }
-
-       /**
-        * Regular expressions to parse many common URIs.
-        *
-        * @private
-        * @static
-        * @property {Object} parser
-        */
-       var parser = {
-               strict: /^(?:([^:\/?#]+):)?(?:\/\/(?:(?:([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?([^:\/?#]*)(?::(\d*))?)?((?:[^?#\/]*\/)*[^?#]*)(?:\?([^#]*))?(?:#(.*))?/,
-               loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?(?:(?:([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?([^:\/?#]*)(?::(\d*))?((?:\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?[^?#\/]*)(?:\?([^#]*))?(?:#(.*))?/
-       },
-
-       /**
-        * The order here matches the order of captured matches in the `parser` property regexes.
-        *
-        * @private
-        * @static
-        * @property {Array} properties
-        */
-       properties = [
-               'protocol',
-               'user',
-               'password',
-               'host',
-               'port',
-               'path',
-               'query',
-               'fragment'
-       ];
-
-       /**
-        * @property {string} protocol For example `http` (always present)
-        */
-       /**
-        * @property {string|undefined} user For example `usr`
-        */
-       /**
-        * @property {string|undefined} password For example `pwd`
-        */
-       /**
-        * @property {string} host For example `www.example.com` (always present)
-        */
-       /**
-        * @property {string|undefined} port For example `81`
-        */
-       /**
-        * @property {string} path For example `/dir/dir.2/index.htm` (always present)
-        */
-       /**
-        * @property {Object} query For example `{ a: '0', b: '', c: 'value' }` (always present)
-        */
-       /**
-        * @property {string|undefined} fragment For example `top`
-        */
-
-       /**
-        * A factory method to create a variation of mw.Uri with a different default location (for
-        * relative URLs, including protocol-relative URLs). Used so the library is still testable &
-        * purely functional.
-        *
-        * @method
-        * @member mw
-        */
-       mw.UriRelative = function ( documentLocation ) {
-               var defaultUri;
-
-               /**
-                * @class mw.Uri
-                * @constructor
-                *
-                * Construct a new URI object. Throws error if arguments are illegal/impossible, or
-                * otherwise don't parse.
-                *
-                * @param {Object|string} [uri] URI string, or an Object with appropriate properties (especially
-                *  another URI object to clone). Object must have non-blank `protocol`, `host`, and `path`
-                *  properties. If omitted (or set to `undefined`, `null` or empty string), then an object
-                *  will be created for the default `uri` of this constructor (`document.location` for
-                *  mw.Uri, other values for other instances -- see mw.UriRelative for details).
-                * @param {Object|boolean} [options] Object with options, or (backwards compatibility) a boolean
-                *  for strictMode
-                * @param {boolean} [options.strictMode=false] Trigger strict mode parsing of the url.
-                * @param {boolean} [options.overrideKeys=false] Whether to let duplicate query parameters
-                *  override each other (`true`) or automagically convert them to an array (`false`).
-                */
-               function Uri( uri, options ) {
-                       options = typeof options === 'object' ? options : { strictMode: !!options };
-                       options = $.extend( {
-                               strictMode: false,
-                               overrideKeys: false
-                       }, options );
-
-                       if ( uri !== undefined && uri !== null && uri !== '' ) {
-                               if ( typeof uri === 'string' ) {
-                                       this.parse( uri, options );
-                               } else if ( typeof uri === 'object' ) {
-                                       // Copy data over from existing URI object
-                                       for ( var prop in uri ) {
-                                               // Only copy direct properties, not inherited ones
-                                               if ( uri.hasOwnProperty( prop ) ) {
-                                                       // Deep copy object properties
-                                                       if ( $.isArray( uri[prop] ) || $.isPlainObject( uri[prop] ) ) {
-                                                               this[prop] = $.extend( true, {}, uri[prop] );
-                                                       } else {
-                                                               this[prop] = uri[prop];
-                                                       }
-                                               }
-                                       }
-                                       if ( !this.query ) {
-                                               this.query = {};
-                                       }
-                               }
-                       } else {
-                               // If we didn't get a URI in the constructor, use the default one.
-                               return defaultUri.clone();
-                       }
-
-                       // protocol-relative URLs
-                       if ( !this.protocol ) {
-                               this.protocol = defaultUri.protocol;
-                       }
-                       // No host given:
-                       if ( !this.host ) {
-                               this.host = defaultUri.host;
-                               // port ?
-                               if ( !this.port ) {
-                                       this.port = defaultUri.port;
-                               }
-                       }
-                       if ( this.path && this.path.charAt( 0 ) !== '/' ) {
-                               // A real relative URL, relative to defaultUri.path. We can't really handle that since we cannot
-                               // figure out whether the last path component of defaultUri.path is a directory or a file.
-                               throw new Error( 'Bad constructor arguments' );
-                       }
-                       if ( !( this.protocol && this.host && this.path ) ) {
-                               throw new Error( 'Bad constructor arguments' );
-                       }
-               }
-
-               /**
-                * Encode a value for inclusion in a url.
-                *
-                * Standard encodeURIComponent, with extra stuff to make all browsers work similarly and more
-                * compliant with RFC 3986. Similar to rawurlencode from PHP and our JS library
-                * mw.util.rawurlencode, except this also replaces spaces with `+`.
-                *
-                * @static
-                * @param {string} s String to encode
-                * @return {string} Encoded string for URI
-                */
-               Uri.encode = function ( s ) {
-                       return encodeURIComponent( s )
-                               .replace( /!/g, '%21' ).replace( /'/g, '%27' ).replace( /\(/g, '%28' )
-                               .replace( /\)/g, '%29' ).replace( /\*/g, '%2A' )
-                               .replace( /%20/g, '+' );
-               };
-
-               /**
-                * Decode a url encoded value.
-                *
-                * Reversed #encode. Standard decodeURIComponent, with addition of replacing
-                * `+` with a space.
-                *
-                * @static
-                * @param {string} s String to decode
-                * @return {string} Decoded string
-                */
-               Uri.decode = function ( s ) {
-                       return decodeURIComponent( s.replace( /\+/g, '%20' ) );
-               };
-
-               Uri.prototype = {
-
-                       /**
-                        * Parse a string and set our properties accordingly.
-                        *
-                        * @private
-                        * @param {string} str URI, see constructor.
-                        * @param {Object} options See constructor.
-                        */
-                       parse: function ( str, options ) {
-                               var q, matches,
-                                       uri = this;
-
-                               // Apply parser regex and set all properties based on the result
-                               matches = parser[ options.strictMode ? 'strict' : 'loose' ].exec( str );
-                               $.each( properties, function ( i, property ) {
-                                       uri[ property ] = matches[ i + 1 ];
-                               } );
-
-                               // uri.query starts out as the query string; we will parse it into key-val pairs then make
-                               // that object the "query" property.
-                               // we overwrite query in uri way to make cloning easier, it can use the same list of properties.
-                               q = {};
-                               // using replace to iterate over a string
-                               if ( uri.query ) {
-                                       uri.query.replace( /(?:^|&)([^&=]*)(?:(=)([^&]*))?/g, function ( $0, $1, $2, $3 ) {
-                                               var k, v;
-                                               if ( $1 ) {
-                                                       k = Uri.decode( $1 );
-                                                       v = ( $2 === '' || $2 === undefined ) ? null : Uri.decode( $3 );
-
-                                                       // If overrideKeys, always (re)set top level value.
-                                                       // If not overrideKeys but this key wasn't set before, then we set it as well.
-                                                       if ( options.overrideKeys || q[ k ] === undefined ) {
-                                                               q[ k ] = v;
-
-                                                       // Use arrays if overrideKeys is false and key was already seen before
-                                                       } else {
-                                                               // Once before, still a string, turn into an array
-                                                               if ( typeof q[ k ] === 'string' ) {
-                                                                       q[ k ] = [ q[ k ] ];
-                                                               }
-                                                               // Add to the array
-                                                               if ( $.isArray( q[ k ] ) ) {
-                                                                       q[ k ].push( v );
-                                                               }
-                                                       }
-                                               }
-                                       } );
-                               }
-                               uri.query = q;
-                       },
-
-                       /**
-                        * Get user and password section of a URI.
-                        *
-                        * @return {string}
-                        */
-                       getUserInfo: function () {
-                               return cat( '', this.user, cat( ':', this.password, '' ) );
-                       },
-
-                       /**
-                        * Get host and port section of a URI.
-                        *
-                        * @return {string}
-                        */
-                       getHostPort: function () {
-                               return this.host + cat( ':', this.port, '' );
-                       },
-
-                       /**
-                        * Get the userInfo, host and port section of the URI.
-                        *
-                        * In most real-world URLs this is simply the hostname, but the definition of 'authority' section is more general.
-                        *
-                        * @return {string}
-                        */
-                       getAuthority: function () {
-                               return cat( '', this.getUserInfo(), '@' ) + this.getHostPort();
-                       },
-
-                       /**
-                        * Get the query arguments of the URL, encoded into a string.
-                        *
-                        * Does not preserve the original order of arguments passed in the URI. Does handle escaping.
-                        *
-                        * @return {string}
-                        */
-                       getQueryString: function () {
-                               var args = [];
-                               $.each( this.query, function ( key, val ) {
-                                       var k = Uri.encode( key ),
-                                               vals = $.isArray( val ) ? val : [ val ];
-                                       $.each( vals, function ( i, v ) {
-                                               if ( v === null ) {
-                                                       args.push( k );
-                                               } else if ( k === 'title' ) {
-                                                       args.push( k + '=' + mw.util.wikiUrlencode( v ) );
-                                               } else {
-                                                       args.push( k + '=' + Uri.encode( v ) );
-                                               }
-                                       } );
-                               } );
-                               return args.join( '&' );
-                       },
-
-                       /**
-                        * Get everything after the authority section of the URI.
-                        *
-                        * @return {string}
-                        */
-                       getRelativePath: function () {
-                               return this.path + cat( '?', this.getQueryString(), '', true ) + cat( '#', this.fragment, '' );
-                       },
-
-                       /**
-                        * Get the entire URI string.
-                        *
-                        * May not be precisely the same as input due to order of query arguments.
-                        *
-                        * @return {string} The URI string
-                        */
-                       toString: function () {
-                               return this.protocol + '://' + this.getAuthority() + this.getRelativePath();
-                       },
-
-                       /**
-                        * Clone this URI
-                        *
-                        * @return {Object} New URI object with same properties
-                        */
-                       clone: function () {
-                               return new Uri( this );
-                       },
-
-                       /**
-                        * Extend the query section of the URI with new parameters.
-                        *
-                        * @param {Object} parameters Query parameters to add to ours (or to override ours with) as an
-                        *  object
-                        * @return {Object} This URI object
-                        */
-                       extend: function ( parameters ) {
-                               $.extend( this.query, parameters );
-                               return this;
-                       }
-               };
-
-               defaultUri = new Uri( documentLocation );
-
-               return Uri;
-       };
-
-       // If we are running in a browser, inject the current document location (for relative URLs).
-       if ( document && document.location && document.location.href ) {
-               mw.Uri = mw.UriRelative( document.location.href );
-       }
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.debug.init.js b/resources/mediawiki/mediawiki.debug.init.js
deleted file mode 100644 (file)
index 0f85e80..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-jQuery( function () {
-       mediaWiki.Debug.init();
-} );
diff --git a/resources/mediawiki/mediawiki.debug.js b/resources/mediawiki/mediawiki.debug.js
deleted file mode 100644 (file)
index f56f0d9..0000000
+++ /dev/null
@@ -1,388 +0,0 @@
-( function ( mw, $ ) {
-       'use strict';
-
-       var debug,
-               hovzer = $.getFootHovzer();
-
-       /**
-        * Debug toolbar.
-        *
-        * Enabled server-side through `$wgDebugToolbar`.
-        *
-        * @class mw.Debug
-        * @singleton
-        * @author John Du Hart
-        * @since 1.19
-        */
-       debug = mw.Debug = {
-               /**
-                * Toolbar container element
-                *
-                * @property {jQuery}
-                */
-               $container: null,
-
-               /**
-                * Object containing data for the debug toolbar
-                *
-                * @property {Object}
-                */
-               data: {},
-
-               /**
-                * Initialize the debugging pane
-                *
-                * Shouldn't be called before the document is ready
-                * (since it binds to elements on the page).
-                *
-                * @param {Object} [data] Defaults to 'debugInfo' from mw.config
-                */
-               init: function ( data ) {
-
-                       this.data = data || mw.config.get( 'debugInfo' );
-                       this.buildHtml();
-
-                       // Insert the container into the DOM
-                       hovzer.$.append( this.$container );
-                       hovzer.update();
-
-                       $( '.mw-debug-panelink' ).click( this.switchPane );
-               },
-
-               /**
-                * Switch between panes
-                *
-                * Should be called with an HTMLElement as its thisArg,
-                * because it's meant to be an event handler.
-                *
-                * TODO: Store cookie for last pane open.
-                *
-                * @param {jQuery.Event} e
-                */
-               switchPane: function ( e ) {
-                       var currentPaneId = debug.$container.data( 'currentPane' ),
-                               requestedPaneId = $( this ).prop( 'id' ).substr( 9 ),
-                               $currentPane = $( '#mw-debug-pane-' + currentPaneId ),
-                               $requestedPane = $( '#mw-debug-pane-' + requestedPaneId ),
-                               hovDone = false;
-
-                       function updateHov() {
-                               if ( !hovDone ) {
-                                       hovzer.update();
-                                       hovDone = true;
-                               }
-                       }
-
-                       // Skip hash fragment handling. Prevents screen from jumping.
-                       e.preventDefault();
-
-                       $( this ).addClass( 'current ' );
-                       $( '.mw-debug-panelink' ).not( this ).removeClass( 'current ' );
-
-                       // Hide the current pane
-                       if ( requestedPaneId === currentPaneId ) {
-                               $currentPane.slideUp( updateHov );
-                               debug.$container.data( 'currentPane', null );
-                               return;
-                       }
-
-                       debug.$container.data( 'currentPane', requestedPaneId );
-
-                       if ( currentPaneId === undefined || currentPaneId === null ) {
-                               $requestedPane.slideDown( updateHov );
-                       } else {
-                               $currentPane.hide();
-                               $requestedPane.show();
-                               updateHov();
-                       }
-               },
-
-               /**
-                * Construct the HTML for the debugging toolbar
-                */
-               buildHtml: function () {
-                       var $container, $bits, panes, id, gitInfo;
-
-                       $container = $( '<div id="mw-debug-toolbar" class="mw-debug" lang="en" dir="ltr"></div>' );
-
-                       $bits = $( '<div class="mw-debug-bits"></div>' );
-
-                       /**
-                        * Returns a jQuery element for a debug-bit div
-                        *
-                        * @ignore
-                        * @param {string} id
-                        * @return {jQuery}
-                        */
-                       function bitDiv( id ) {
-                               return $( '<div>' ).prop( {
-                                       id: 'mw-debug-' + id,
-                                       className: 'mw-debug-bit'
-                               } )
-                               .appendTo( $bits );
-                       }
-
-                       /**
-                        * Returns a jQuery element for a pane link
-                        *
-                        * @ignore
-                        * @param {string} id
-                        * @param {string} text
-                        * @return {jQuery}
-                        */
-                       function paneLabel( id, text ) {
-                               return $( '<a>' )
-                                       .prop( {
-                                               className: 'mw-debug-panelabel',
-                                               href: '#mw-debug-pane-' + id
-                                       } )
-                                       .text( text );
-                       }
-
-                       /**
-                        * Returns a jQuery element for a debug-bit div with a for a pane link
-                        *
-                        * @ignore
-                        * @param {string} id CSS id snippet. Will be prefixed with 'mw-debug-'
-                        * @param {string} text Text to show
-                        * @param {string} count Optional count to show
-                        * @return {jQuery}
-                        */
-                       function paneTriggerBitDiv( id, text, count ) {
-                               if ( count ) {
-                                       text = text + ' (' + count + ')';
-                               }
-                               return $( '<div>' ).prop( {
-                                       id: 'mw-debug-' + id,
-                                       className: 'mw-debug-bit mw-debug-panelink'
-                               } )
-                               .append( paneLabel( id, text ) )
-                               .appendTo( $bits );
-                       }
-
-                       paneTriggerBitDiv( 'console', 'Console', this.data.log.length );
-
-                       paneTriggerBitDiv( 'querylist', 'Queries', this.data.queries.length );
-
-                       paneTriggerBitDiv( 'debuglog', 'Debug log', this.data.debugLog.length );
-
-                       paneTriggerBitDiv( 'request', 'Request' );
-
-                       paneTriggerBitDiv( 'includes', 'PHP includes', this.data.includes.length );
-
-                       paneTriggerBitDiv( 'profile', 'Profile', this.data.profile.length );
-
-                       gitInfo = '';
-                       if ( this.data.gitRevision !== false ) {
-                               gitInfo = '(' + this.data.gitRevision.substring( 0, 7 ) + ')';
-                               if ( this.data.gitViewUrl !== false ) {
-                                       gitInfo = $( '<a>' )
-                                               .attr( 'href', this.data.gitViewUrl )
-                                               .text( gitInfo );
-                               }
-                       }
-
-                       bitDiv( 'mwversion' )
-                               .append( $( '<a href="//www.mediawiki.org/">MediaWiki</a>' ) )
-                               .append( document.createTextNode( ': ' + this.data.mwVersion + ' ' ) )
-                               .append( gitInfo );
-
-                       if ( this.data.gitBranch !== false ) {
-                               bitDiv( 'gitbranch' ).text( 'Git branch: ' + this.data.gitBranch );
-                       }
-
-                       bitDiv( 'phpversion' )
-                               .append( $( '<a href="//www.php.net/"></a>' ).text( 'PHP' ) )
-                               .append( ': ' + this.data.phpVersion );
-
-                       bitDiv( 'time' )
-                               .text( 'Time: ' + this.data.time.toFixed( 5 ) );
-
-                       bitDiv( 'memory' )
-                               .text( 'Memory: ' + this.data.memory + ' (Peak: ' + this.data.memoryPeak + ')' );
-
-                       $bits.appendTo( $container );
-
-                       panes = {
-                               console: this.buildConsoleTable(),
-                               querylist: this.buildQueryTable(),
-                               debuglog: this.buildDebugLogTable(),
-                               request: this.buildRequestPane(),
-                               includes: this.buildIncludesPane(),
-                               profile: this.buildProfilePane()
-                       };
-
-                       for ( id in panes ) {
-                               if ( !panes.hasOwnProperty( id ) ) {
-                                       continue;
-                               }
-
-                               $( '<div>' )
-                                       .prop( {
-                                               className: 'mw-debug-pane',
-                                               id: 'mw-debug-pane-' + id
-                                       } )
-                                       .append( panes[id] )
-                                       .appendTo( $container );
-                       }
-
-                       this.$container = $container;
-               },
-
-               /**
-                * Build the console panel
-                */
-               buildConsoleTable: function () {
-                       var $table, entryTypeText, i, length, entry;
-
-                       $table = $( '<table id="mw-debug-console">' );
-
-                       $( '<colgroup>' ).css( 'width', /* padding = */ 20 + ( 10 * /* fontSize = */ 11 ) ).appendTo( $table );
-                       $( '<colgroup>' ).appendTo( $table );
-                       $( '<colgroup>' ).css( 'width', 350 ).appendTo( $table );
-
-                       entryTypeText = function ( entryType ) {
-                               switch ( entryType ) {
-                                       case 'log':
-                                               return 'Log';
-                                       case 'warn':
-                                               return 'Warning';
-                                       case 'deprecated':
-                                               return 'Deprecated';
-                                       default:
-                                               return 'Unknown';
-                               }
-                       };
-
-                       for ( i = 0, length = this.data.log.length; i < length; i += 1 ) {
-                               entry = this.data.log[i];
-                               entry.typeText = entryTypeText( entry.type );
-
-                               $( '<tr>' )
-                                       .append( $( '<td>' )
-                                               .text( entry.typeText )
-                                               .addClass( 'mw-debug-console-' + entry.type )
-                                       )
-                                       .append( $( '<td>' ).html( entry.msg ) )
-                                       .append( $( '<td>' ).text( entry.caller ) )
-                                       .appendTo( $table );
-                       }
-
-                       return $table;
-               },
-
-               /**
-                * Build query list pane
-                *
-                * @return {jQuery}
-                */
-               buildQueryTable: function () {
-                       var $table, i, length, query;
-
-                       $table = $( '<table id="mw-debug-querylist"></table>' );
-
-                       $( '<tr>' )
-                               .append( $( '<th>#</th>' ).css( 'width', '4em' )    )
-                               .append( $( '<th>SQL</th>' ) )
-                               .append( $( '<th>Time</th>' ).css( 'width', '8em'  ) )
-                               .append( $( '<th>Call</th>' ).css( 'width', '18em' ) )
-                       .appendTo( $table );
-
-                       for ( i = 0, length = this.data.queries.length; i < length; i += 1 ) {
-                               query = this.data.queries[i];
-
-                               $( '<tr>' )
-                                       .append( $( '<td>' ).text( i + 1 ) )
-                                       .append( $( '<td>' ).text( query.sql ) )
-                                       .append( $( '<td class="stats">' ).text( ( query.time * 1000 ).toFixed( 4 ) + 'ms' ) )
-                                       .append( $( '<td>' ).text( query['function'] ) )
-                               .appendTo( $table );
-                       }
-
-                       return $table;
-               },
-
-               /**
-                * Build legacy debug log pane
-                *
-                * @return {jQuery}
-                */
-               buildDebugLogTable: function () {
-                       var $list, i, length, line;
-                       $list = $( '<ul>' );
-
-                       for ( i = 0, length = this.data.debugLog.length; i < length; i += 1 ) {
-                               line = this.data.debugLog[i];
-                               $( '<li>' )
-                                       .html( mw.html.escape( line ).replace( /\n/g, '<br />\n' ) )
-                                       .appendTo( $list );
-                       }
-
-                       return $list;
-               },
-
-               /**
-                * Build request information pane
-                *
-                * @return {jQuery}
-                */
-               buildRequestPane: function () {
-
-                       function buildTable( title, data ) {
-                               var $unit, $table, key;
-
-                               $unit = $( '<div>' ).append( $( '<h2>' ).text( title ) );
-
-                               $table = $( '<table>' ).appendTo( $unit );
-
-                               $( '<tr>' )
-                                       .html( '<th>Key</th><th>Value</th>' )
-                                       .appendTo( $table );
-
-                               for ( key in data ) {
-                                       if ( !data.hasOwnProperty( key ) ) {
-                                               continue;
-                                       }
-
-                                       $( '<tr>' )
-                                               .append( $( '<th>' ).text( key ) )
-                                               .append( $( '<td>' ).text( data[key] ) )
-                                               .appendTo( $table );
-                               }
-
-                               return $unit;
-                       }
-
-                       return $( '<div>' )
-                               .text( this.data.request.method + ' ' + this.data.request.url )
-                               .append( buildTable( 'Headers', this.data.request.headers ) )
-                               .append( buildTable( 'Parameters', this.data.request.params ) );
-               },
-
-               /**
-                * Build included files pane
-                *
-                * @return {jQuery}
-                */
-               buildIncludesPane: function () {
-                       var $table, i, length, file;
-
-                       $table = $( '<table>' );
-
-                       for ( i = 0, length = this.data.includes.length; i < length; i += 1 ) {
-                               file = this.data.includes[i];
-                               $( '<tr>' )
-                                       .append( $( '<td>' ).text( file.name ) )
-                                       .append( $( '<td class="nr">' ).text( file.size ) )
-                                       .appendTo( $table );
-                       }
-
-                       return $table;
-               },
-
-               buildProfilePane: function () {
-                       return mw.Debug.profile.init();
-               }
-       };
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.debug.less b/resources/mediawiki/mediawiki.debug.less
deleted file mode 100644 (file)
index 949c558..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-.mw-debug {
-       width: 100%;
-       background-color: #eee;
-       border-top: 1px solid #aaa;
-
-       pre {
-               font-size: 11px;
-               padding: 0;
-               margin: 0;
-               background: none;
-               border: none;
-       }
-
-       table {
-               border-spacing: 0;
-               width: 100%;
-               table-layout: fixed;
-
-               td,
-               th {
-                       padding: 4px 10px;
-               }
-
-               td {
-                       border-bottom: 1px solid #eee;
-                       word-wrap: break-word;
-
-                       &.nr {
-                               text-align: right;
-                       }
-
-                       span.stats {
-                               color: #808080;
-                       }
-               }
-
-               tr {
-                       background-color: #fff;
-
-                       &:nth-child(even) {
-                               background-color: #f9f9f9;
-                       }
-               }
-       }
-
-       ul {
-               margin: 0;
-               list-style: none;
-       }
-
-       li {
-               padding: 4px 0;
-               width: 100%;
-       }
-}
-
-.mw-debug-bits {
-       text-align: center;
-       border-bottom: 1px solid #aaa;
-}
-
-.mw-debug-bit {
-       display: inline-block;
-       padding: 10px 5px;
-       font-size: 13px;
-       /* IE-hack for display: inline-block */
-       zoom: 1;
-       *display:inline;
-}
-
-.mw-debug-panelink {
-       background-color: #eee;
-       border-right: 1px solid #ccc;
-
-       &:first-child {
-               border-left: 1px solid #ccc;
-       }
-
-       &:hover {
-               background-color: #fefefe;
-               cursor: pointer;
-       }
-
-       &.current {
-               background-color: #dedede;
-       }
-}
-
-a.mw-debug-panelabel,
-a.mw-debug-panelabel:visited {
-       color: #000;
-}
-
-.mw-debug-pane {
-       height: 300px;
-       overflow: scroll;
-       display: none;
-       font-size: 11px;
-       background-color: #e1eff2;
-       box-sizing: border-box;
-}
-
-#mw-debug-pane-debuglog,
-#mw-debug-pane-request {
-       padding: 20px;
-}
-
-#mw-debug-pane-request {
-       table {
-               width: 100%;
-               margin: 10px 0 30px;
-       }
-
-       tr,
-       th,
-       td,
-       table {
-               border: 1px solid #D0DBB3;
-               border-collapse: collapse;
-               margin: 0;
-       }
-
-       th,
-       td {
-               font-size: 12px;
-               padding: 8px 10px;
-       }
-
-       th {
-               background-color: #F1F7E2;
-               font-weight: bold;
-       }
-
-       td {
-               background-color: white;
-       }
-}
-
-#mw-debug-console tr td {
-       &:first-child {
-               font-weight: bold;
-               vertical-align: top;
-       }
-
-       &:last-child {
-               vertical-align: top;
-       }
-}
-
-.mw-debug-backtrace {
-       padding: 5px 10px;
-       margin: 5px;
-       background-color: #dedede;
-
-       span {
-               font-weight: bold;
-               color: #111;
-       }
-
-       ul {
-               padding-left: 10px;
-       }
-
-       li {
-               width: auto;
-               padding: 0;
-               color: #333;
-               font-size: 10px;
-               margin-bottom: 0;
-               line-height: 1em;
-       }
-}
-
-.mw-debug-console-log {
-       background-color: #add8e6;
-}
-
-.mw-debug-console-warn {
-       background-color: #ffa07a;
-}
-
-.mw-debug-console-deprecated {
-       background-color: #ffb6c1;
-}
-
-/* Cheapo hack to hide the first 3 lines of the backtrace */
-.mw-debug-backtrace li:nth-child(-n+3) {
-       display: none;
-}
diff --git a/resources/mediawiki/mediawiki.debug.profile.css b/resources/mediawiki/mediawiki.debug.profile.css
deleted file mode 100644 (file)
index bf49d1a..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-
-.mw-debug-profile-tipsy .tipsy-inner {
-       /* undo max-width from vector on .tipsy-inner */
-       max-width: none;
-       /* needed for some browsers to provide space for the scrollbar without wrapping text */
-       min-width: 100%;
-       max-height: 150px;
-       overflow-y: auto;
-}
-
-.mw-debug-profile-underline {
-       stroke-width: 1;
-       stroke: #dfdfdf;
-}
-
-.mw-debug-profile-period {
-       fill: red;
-}
-
-/* connecting line between endpoints on long events */
-.mw-debug-profile-period line {
-       stroke: red;
-       stroke-width: 2;
-}
-
-.mw-debug-profile-tipsy,
-.mw-debug-profile-timeline text {
-       color: #444;
-       fill: #444;
-       /* using em's causes the two locations to have different sizes */
-       font-size: 12px;
-       font-family: sans-serif;
-}
-
-.mw-debug-profile-meta,
-.mw-debug-profile-timeline tspan {
-       /* using em's causes the two locations to have different sizes */
-       font-size: 10px;
-}
-
-.mw-debug-profile-no-data {
-       text-align: center;
-       padding-top: 5em;
-       font-weight: bold;
-       font-size: 1.2em;
-}
diff --git a/resources/mediawiki/mediawiki.debug.profile.js b/resources/mediawiki/mediawiki.debug.profile.js
deleted file mode 100644 (file)
index f6bc81d..0000000
+++ /dev/null
@@ -1,546 +0,0 @@
-/*!
- * JavaScript for the debug toolbar profiler, enabled through $wgDebugToolbar
- * and StartProfiler.php.
- *
- * @author Erik Bernhardson
- * @since 1.23
- */
-
-( function ( mw, $ ) {
-       'use strict';
-
-       /**
-        * @singleton
-        * @class mw.Debug.profile
-        */
-       var profile = mw.Debug.profile = {
-               /**
-                * Object containing data for the debug toolbar
-                *
-                * @property ProfileData
-                */
-               data: null,
-
-               /**
-                * @property DOMElement
-                */
-               container: null,
-
-               /**
-                * Initializes the profiling pane.
-                */
-               init: function ( data, width, mergeThresholdPx, dropThresholdPx ) {
-                       data = data || mw.config.get( 'debugInfo' ).profile;
-                       profile.width = width || $(window).width() - 20;
-                       // merge events from same pixel(some events are very granular)
-                       mergeThresholdPx = mergeThresholdPx || 2;
-                       // only drop events if requested
-                       dropThresholdPx = dropThresholdPx || 0;
-
-                       if ( !Array.prototype.map || !Array.prototype.reduce || !Array.prototype.filter ) {
-                               profile.container = profile.buildRequiresES5();
-                       } else if ( data.length === 0 ) {
-                               profile.container = profile.buildNoData();
-                       } else {
-                               // generate a flyout
-                               profile.data = new ProfileData( data, profile.width, mergeThresholdPx, dropThresholdPx );
-                               // draw it
-                               profile.container = profile.buildSvg( profile.container );
-                               profile.attachFlyout();
-                       }
-
-                       return profile.container;
-               },
-
-               buildRequiresES5: function () {
-                       return $( '<div>' )
-                               .text( 'An ES5 compatible javascript engine is required for the profile visualization.' )
-                               .get( 0 );
-               },
-
-               buildNoData: function () {
-                       return $( '<div>' ).addClass( 'mw-debug-profile-no-data' )
-                               .text( 'No events recorded, ensure profiling is enabled in StartProfiler.php.' )
-                               .get( 0 );
-               },
-
-               /**
-                * Creates DOM nodes appropriately namespaced for SVG.
-                *
-                * @param string tag to create
-                * @return DOMElement
-                */
-               createSvgElement: document.createElementNS.bind( document, 'http://www.w3.org/2000/svg' ),
-
-               /**
-                * @param DOMElement|undefined
-                */
-               buildSvg: function ( node ) {
-                       var container, group, i, g,
-                               timespan = profile.data.timespan,
-                               gapPerEvent = 38,
-                               space = 10.5,
-                               currentHeight = space,
-                               totalHeight = 0;
-
-                       profile.ratio = ( profile.width - space * 2 ) / ( timespan.end - timespan.start );
-                       totalHeight += gapPerEvent * profile.data.groups.length;
-
-                       if ( node ) {
-                               $( node ).empty();
-                       } else {
-                               node = profile.createSvgElement( 'svg' );
-                               node.setAttribute( 'version', '1.2' );
-                               node.setAttribute( 'baseProfile', 'tiny' );
-                       }
-                       node.style.height = totalHeight;
-                       node.style.width = profile.width;
-
-                       // use a container that can be transformed
-                       container = profile.createSvgElement( 'g' );
-                       node.appendChild( container );
-
-                       for ( i = 0; i < profile.data.groups.length; i++ ) {
-                               group = profile.data.groups[i];
-                               g = profile.buildTimeline( group );
-
-                               g.setAttribute( 'transform', 'translate( 0 ' + currentHeight + ' )' );
-                               container.appendChild( g );
-
-                               currentHeight += gapPerEvent;
-                       }
-
-                       return node;
-               },
-
-               /**
-                * @param Object group of periods to transform into graphics
-                */
-               buildTimeline: function ( group ) {
-                       var text, tspan, line, i,
-                               sum = group.timespan.sum,
-                               ms = ' ~ ' + ( sum < 1 ? sum.toFixed( 2 ) : sum.toFixed( 0 ) ) + ' ms',
-                               timeline = profile.createSvgElement( 'g' );
-
-                       timeline.setAttribute( 'class', 'mw-debug-profile-timeline' );
-
-                       // draw label
-                       text = profile.createSvgElement( 'text' );
-                       text.setAttribute( 'x', profile.xCoord( group.timespan.start ) );
-                       text.setAttribute( 'y', 0 );
-                       text.textContent = group.name;
-                       timeline.appendChild( text );
-
-                       // draw metadata
-                       tspan = profile.createSvgElement( 'tspan' );
-                       tspan.textContent = ms;
-                       text.appendChild( tspan );
-
-                       // draw timeline periods
-                       for ( i = 0; i < group.periods.length; i++ ) {
-                               timeline.appendChild( profile.buildPeriod( group.periods[i] ) );
-                       }
-
-                       // full-width line under each timeline
-                       line = profile.createSvgElement( 'line' );
-                       line.setAttribute( 'class', 'mw-debug-profile-underline' );
-                       line.setAttribute( 'x1', 0 );
-                       line.setAttribute( 'y1', 28 );
-                       line.setAttribute( 'x2', profile.width );
-                       line.setAttribute( 'y2', 28 );
-                       timeline.appendChild( line );
-
-                       return timeline;
-               },
-
-               /**
-                * @param Object period to transform into graphics
-                */
-               buildPeriod: function ( period ) {
-                       var node,
-                               head = profile.xCoord( period.start ),
-                               tail = profile.xCoord( period.end ),
-                               g = profile.createSvgElement( 'g' );
-
-                       g.setAttribute( 'class', 'mw-debug-profile-period' );
-                       $( g ).data( 'period', period );
-
-                       if ( head + 16 > tail ) {
-                               node = profile.createSvgElement( 'rect' );
-                               node.setAttribute( 'x', head );
-                               node.setAttribute( 'y', 8 );
-                               node.setAttribute( 'width', 2 );
-                               node.setAttribute( 'height', 9 );
-                               g.appendChild( node );
-
-                               node = profile.createSvgElement( 'rect' );
-                               node.setAttribute( 'x', head );
-                               node.setAttribute( 'y', 8 );
-                               node.setAttribute( 'width', ( period.end - period.start ) * profile.ratio || 2 );
-                               node.setAttribute( 'height', 6 );
-                               g.appendChild( node );
-                       } else {
-                               node = profile.createSvgElement( 'polygon' );
-                               node.setAttribute( 'points', pointList( [
-                                       [ head, 8 ],
-                                       [ head, 19 ],
-                                       [ head + 8, 8 ],
-                                       [ head, 8]
-                               ] ) );
-                               g.appendChild( node );
-
-                               node = profile.createSvgElement( 'polygon' );
-                               node.setAttribute( 'points', pointList( [
-                                       [ tail, 8 ],
-                                       [ tail, 19 ],
-                                       [ tail - 8, 8 ],
-                                       [ tail, 8 ],
-                               ] ) );
-                               g.appendChild( node );
-
-                               node = profile.createSvgElement( 'line' );
-                               node.setAttribute( 'x1', head );
-                               node.setAttribute( 'y1', 9 );
-                               node.setAttribute( 'x2', tail );
-                               node.setAttribute( 'y2', 9 );
-                               g.appendChild( node );
-                       }
-
-                       return g;
-               },
-
-               /**
-                * @param Object
-                */
-               buildFlyout: function ( period ) {
-                       var contained, sum, ms, mem, i,
-                               node = $( '<div>' );
-
-                       for ( i = 0; i < period.contained.length; i++ ) {
-                               contained = period.contained[i];
-                               sum = contained.end - contained.start;
-                               ms = '' + ( sum < 1 ? sum.toFixed( 2 ) : sum.toFixed( 0 ) ) + ' ms';
-                               mem = formatBytes( contained.memory );
-
-                               $( '<div>' ).text( contained.source.name )
-                                       .append( $( '<span>' ).text( ' ~ ' + ms + ' / ' + mem ).addClass( 'mw-debug-profile-meta' ) )
-                                       .appendTo( node );
-                       }
-
-                       return node;
-               },
-
-               /**
-                * Attach a hover flyout to all .mw-debug-profile-period groups.
-                */
-               attachFlyout: function () {
-                       // for some reason addClass and removeClass from jQuery
-                       // arn't working on svg elements in chrome <= 33.0 (possibly more)
-                       var $container = $( profile.container ),
-                               addClass = function ( node, value ) {
-                                       var current = node.getAttribute( 'class' ),
-                                               list = current ? current.split( ' ' ) : false,
-                                               idx = list ? list.indexOf( value ) : -1;
-
-                                       if ( idx === -1 ) {
-                                               node.setAttribute( 'class', current ? ( current + ' ' + value ) : value );
-                                       }
-                               },
-                               removeClass = function ( node, value ) {
-                                       var current = node.getAttribute( 'class' ),
-                                               list = current ? current.split( ' ' ) : false,
-                                               idx = list ? list.indexOf( value ) : -1;
-
-                                       if ( idx !== -1 ) {
-                                               list.splice( idx, 1 );
-                                               node.setAttribute( 'class', list.join( ' ' ) );
-                                       }
-                               },
-                               // hide all tipsy flyouts
-                               hide = function () {
-                                       $container.find( '.mw-debug-profile-period.tipsy-visible' )
-                                               .each( function () {
-                                                       removeClass( this, 'tipsy-visible' );
-                                                       $( this ).tipsy( 'hide' );
-                                               } );
-                               };
-
-                       $container.find( '.mw-debug-profile-period' ).tipsy( {
-                               fade: true,
-                               gravity: function () {
-                                       return $.fn.tipsy.autoNS.call( this )
-                                               + $.fn.tipsy.autoWE.call( this );
-                               },
-                               className: 'mw-debug-profile-tipsy',
-                               center: false,
-                               html: true,
-                               trigger: 'manual',
-                               title: function () {
-                                       return profile.buildFlyout( $( this ).data( 'period' ) ).html();
-                               },
-                       } ).on( 'mouseenter', function () {
-                               hide();
-                               addClass( this, 'tipsy-visible' );
-                               $( this ).tipsy( 'show' );
-                       } );
-
-                       $container.on( 'mouseleave', function ( event ) {
-                               var $from = $( event.relatedTarget ),
-                                       $to = $( event.target );
-                               // only close the tipsy if we are not
-                               if ( $from.closest( '.tipsy' ).length === 0 &&
-                                       $to.closest( '.tipsy' ).length === 0 &&
-                                       $to.get( 0 ).namespaceURI !== 'http://www.w4.org/2000/svg'
-                               ) {
-                                       hide();
-                               }
-                       } ).on( 'click', function () {
-                               // convenience method for closing
-                               hide();
-                       } );
-               },
-
-               /**
-                * @return number the x co-ordinate for the specified timestamp
-                */
-               xCoord: function ( msTimestamp ) {
-                       return ( msTimestamp - profile.data.timespan.start ) * profile.ratio;
-               },
-       };
-
-       function ProfileData( data, width, mergeThresholdPx, dropThresholdPx ) {
-               // validate input data
-               this.data = data.map( function ( event ) {
-                       event.periods = event.periods.filter( function ( period ) {
-                               return period.start && period.end
-                                       && period.start < period.end
-                                       // period start must be a reasonable ms timestamp
-                                       && period.start > 1000000;
-                       } );
-                       return event;
-               } ).filter( function ( event ) {
-                       return event.name && event.periods.length > 0;
-               } );
-
-               // start and end time of the data
-               this.timespan = this.data.reduce( function ( result, event ) {
-                       return event.periods.reduce( periodMinMax, result );
-               }, periodMinMax.initial() );
-
-               // transform input data
-               this.groups = this.collate( width, mergeThresholdPx, dropThresholdPx );
-
-               return this;
-       }
-
-       /**
-        * There are too many unique events to display a line for each,
-        * so this does a basic grouping.
-        */
-       ProfileData.groupOf = function ( label ) {
-               var pos, prefix = 'Profile section ended by close(): ';
-               if ( label.indexOf( prefix ) === 0 ) {
-                       label = label.substring( prefix.length );
-               }
-
-               pos = [ '::', ':', '-' ].reduce( function ( result, separator ) {
-                       var pos = label.indexOf( separator );
-                       if ( pos === -1 ) {
-                               return result;
-                       } else if ( result === -1 ) {
-                               return pos;
-                       } else {
-                               return Math.min( result, pos );
-                       }
-               }, -1 );
-
-               if ( pos === -1 ) {
-                       return label;
-               } else {
-                       return label.substring( 0, pos );
-               }
-       };
-
-       /**
-        * @return Array list of objects with `name` and `events` keys
-        */
-       ProfileData.groupEvents = function ( events ) {
-               var group, i,
-                       groups = {};
-
-               // Group events together
-               for ( i = events.length - 1; i >= 0; i-- ) {
-                       group = ProfileData.groupOf( events[i].name );
-                       if ( groups[group] ) {
-                               groups[group].push( events[i] );
-                       } else {
-                               groups[group] = [events[i]];
-                       }
-               }
-
-               // Return an array of groups
-               return Object.keys( groups ).map( function ( group ) {
-                       return {
-                               name: group,
-                               events: groups[group],
-                       };
-               } );
-       };
-
-       ProfileData.periodSorter = function ( a, b ) {
-               if ( a.start === b.start ) {
-                       return a.end - b.end;
-               }
-               return a.start - b.start;
-       };
-
-       ProfileData.genMergePeriodReducer = function ( mergeThresholdMs ) {
-               return function ( result, period ) {
-                       if ( result.length === 0 ) {
-                               // period is first result
-                               return [{
-                                       start: period.start,
-                                       end: period.end,
-                                       contained: [period],
-                               }];
-                       }
-                       var last = result[result.length - 1];
-                       if ( period.end < last.end ) {
-                               // end is contained within previous
-                               result[result.length - 1].contained.push( period );
-                       } else if ( period.start - mergeThresholdMs < last.end ) {
-                               // neighbors within merging distance
-                               result[result.length - 1].end = period.end;
-                               result[result.length - 1].contained.push( period );
-                       } else {
-                               // period is next result
-                               result.push({
-                                       start: period.start,
-                                       end: period.end,
-                                       contained: [period],
-                               });
-                       }
-                       return result;
-               };
-       };
-
-       /**
-        * Collect all periods from the grouped events and apply merge and
-        * drop transformations
-        */
-       ProfileData.extractPeriods = function ( events, mergeThresholdMs, dropThresholdMs ) {
-               // collect the periods from all events
-               return events.reduce( function ( result, event ) {
-                               if ( !event.periods.length ) {
-                                       return result;
-                               }
-                               result.push.apply( result, event.periods.map( function ( period ) {
-                                       // maintain link from period to event
-                                       period.source = event;
-                                       return period;
-                               } ) );
-                               return result;
-                       }, [] )
-                       // sort combined periods
-                       .sort( ProfileData.periodSorter )
-                       // Apply merge threshold. Original periods
-                       // are maintained in the `contained` property
-                       .reduce( ProfileData.genMergePeriodReducer( mergeThresholdMs ), [] )
-                       // Apply drop threshold
-                       .filter( function ( period ) {
-                               return period.end - period.start > dropThresholdMs;
-                       } );
-       };
-
-       /**
-        * runs a callback on all periods in the group.  Only valid after
-        * groups.periods[0..n].contained are populated. This runs against
-        * un-transformed data and is better suited to summing or other
-        * stat collection
-        */
-       ProfileData.reducePeriods = function ( group, callback, result ) {
-               return group.periods.reduce( function ( result, period ) {
-                       return period.contained.reduce( callback, result );
-               }, result );
-       };
-
-       /**
-        * Transforms this.data grouping by labels, merging neighboring
-        * events in the groups, and drops events and groups below the
-        * display threshold. Groups are returned sorted by starting time.
-        */
-       ProfileData.prototype.collate = function ( width, mergeThresholdPx, dropThresholdPx ) {
-               // ms to pixel ratio
-               var ratio = ( this.timespan.end - this.timespan.start ) / width,
-                       // transform thresholds to ms
-                       mergeThresholdMs = mergeThresholdPx * ratio,
-                       dropThresholdMs = dropThresholdPx * ratio;
-
-               return ProfileData.groupEvents( this.data )
-                       // generate data about the grouped events
-                       .map( function ( group ) {
-                               // Cleaned periods from all events
-                               group.periods = ProfileData.extractPeriods( group.events, mergeThresholdMs, dropThresholdMs );
-                               // min and max timestamp per group
-                               group.timespan = ProfileData.reducePeriods( group, periodMinMax, periodMinMax.initial() );
-                               // ms from first call to end of last call
-                               group.timespan.length = group.timespan.end - group.timespan.start;
-                               // collect the un-transformed periods
-                               group.timespan.sum = ProfileData.reducePeriods( group, function ( result, period ) {
-                                               result.push( period );
-                                               return result;
-                                       }, [] )
-                                       // sort by start time
-                                       .sort( ProfileData.periodSorter )
-                                       // merge overlapping
-                                       .reduce( ProfileData.genMergePeriodReducer( 0 ), [] )
-                                       // sum
-                                       .reduce( function ( result, period ) {
-                                               return result + period.end - period.start;
-                                       }, 0 );
-
-                               return group;
-                       }, this )
-                       // remove groups that have had all their periods filtered
-                       .filter( function ( group ) {
-                               return group.periods.length > 0;
-                       } )
-                       // sort events by first start
-                       .sort( function ( a, b ) {
-                               return ProfileData.periodSorter( a.timespan, b.timespan );
-                       } );
-       };
-
-       // reducer to find edges of period array
-       function periodMinMax( result, period ) {
-               if ( period.start < result.start ) {
-                       result.start = period.start;
-               }
-               if ( period.end > result.end ) {
-                       result.end = period.end;
-               }
-               return result;
-       }
-
-       periodMinMax.initial = function () {
-               return { start: Number.POSITIVE_INFINITY, end: Number.NEGATIVE_INFINITY };
-       };
-
-       function formatBytes( bytes ) {
-               var i, sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
-               if ( bytes === 0 ) {
-                       return '0 Bytes';
-               }
-               i = parseInt( Math.floor( Math.log( bytes ) / Math.log( 1024 ) ), 10 );
-               return Math.round( bytes / Math.pow( 1024, i ), 2 ) + ' ' + sizes[i];
-       }
-
-       // turns a 2d array into a point list for svg
-       // polygon points attribute
-       // ex: [[1,2],[3,4],[4,2]] = '1,2 3,4 4,2'
-       function pointList( pairs ) {
-               return pairs.map( function ( pair ) {
-                       return pair.join( ',' );
-               } ).join( ' ' );
-       }
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.feedback.css b/resources/mediawiki/mediawiki.feedback.css
deleted file mode 100644 (file)
index 6bd47bb..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-.feedback-spinner {
-       display: inline-block;
-       zoom: 1;
-       *display: inline; /* IE7 and below */
-       /* @embed */
-       background: url(mediawiki.feedback.spinner.gif);
-       width: 18px;
-       height: 18px;
-}
diff --git a/resources/mediawiki/mediawiki.feedback.js b/resources/mediawiki/mediawiki.feedback.js
deleted file mode 100644 (file)
index 90a6425..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-/*!
- * mediawiki.feedback
- *
- * @author Ryan Kaldari, 2010
- * @author Neil Kandalgaonkar, 2010-11
- * @since 1.19
- */
-( function ( mw, $ ) {
-       /**
-        * This is a way of getting simple feedback from users. It's useful
-        * for testing new features -- users can give you feedback without
-        * the difficulty of opening a whole new talk page. For this reason,
-        * it also tends to collect a wider range of both positive and negative
-        * comments. However you do need to tend to the feedback page. It will
-        * get long relatively quickly, and you often get multiple messages
-        * reporting the same issue.
-        *
-        * It takes the form of thing on your page which, when clicked, opens a small
-        * dialog box. Submitting that dialog box appends its contents to a
-        * wiki page that you specify, as a new section.
-        *
-        * Not compatible with LiquidThreads.
-        *
-        * Minimal example in how to use it:
-        *
-        *     var feedback = new mw.Feedback();
-        *     $( '#myButton' ).click( function () { feedback.launch(); } );
-        *
-        * You can also launch the feedback form with a prefilled subject and body.
-        * See the docs for the #launch() method.
-        *
-        * @class
-        * @constructor
-        * @param {Object} [options]
-        * @param {mw.Api} [options.api] if omitted, will just create a standard API
-        * @param {mw.Title} [options.title="Feedback"] The title of the page where you collect
-        * feedback.
-        * @param {string} [options.dialogTitleMessageKey="feedback-submit"] Message key for the
-        * title of the dialog box
-        * @param {string} [options.bugsLink="//bugzilla.wikimedia.org/enter_bug.cgi"] URL where
-        * bugs can be posted
-        * @param {mw.Uri|string} [options.bugsListLink="//bugzilla.wikimedia.org/query.cgi"]
-        * URL where bugs can be listed
-        */
-       mw.Feedback = function ( options ) {
-               if ( options === undefined ) {
-                       options = {};
-               }
-
-               if ( options.api === undefined ) {
-                       options.api = new mw.Api();
-               }
-
-               if ( options.title === undefined ) {
-                       options.title = new mw.Title( 'Feedback' );
-               }
-
-               if ( options.dialogTitleMessageKey === undefined ) {
-                       options.dialogTitleMessageKey = 'feedback-submit';
-               }
-
-               if ( options.bugsLink === undefined ) {
-                       options.bugsLink = '//bugzilla.wikimedia.org/enter_bug.cgi';
-               }
-
-               if ( options.bugsListLink === undefined ) {
-                       options.bugsListLink = '//bugzilla.wikimedia.org/query.cgi';
-               }
-
-               $.extend( this, options );
-               this.setup();
-       };
-
-       mw.Feedback.prototype = {
-               /**
-                * Sets up interface
-                */
-               setup: function () {
-                       var $feedbackPageLink,
-                               $bugNoteLink,
-                               $bugsListLink,
-                               fb = this;
-
-                       $feedbackPageLink = $( '<a>' )
-                               .attr( {
-                                       href: fb.title.getUrl(),
-                                       target: '_blank'
-                               } )
-                               .css( {
-                                       whiteSpace: 'nowrap'
-                               } );
-
-                       $bugNoteLink = $( '<a>' ).attr( { href: '#' } ).click( function () {
-                               fb.displayBugs();
-                       } );
-
-                       $bugsListLink = $( '<a>' ).attr( {
-                               href: fb.bugsListLink,
-                               target: '_blank'
-                       } );
-
-                       // TODO: Use a stylesheet instead of these inline styles
-                       this.$dialog =
-                               $( '<div style="position: relative;"></div>' ).append(
-                                       $( '<div class="feedback-mode feedback-form"></div>' ).append(
-                                               $( '<small>' ).append(
-                                                       $( '<p>' ).msg(
-                                                               'feedback-bugornote',
-                                                               $bugNoteLink,
-                                                               fb.title.getNameText(),
-                                                               $feedbackPageLink.clone()
-                                                       )
-                                               ),
-                                               $( '<div style="margin-top: 1em;"></div>' ).append(
-                                                       mw.msg( 'feedback-subject' ),
-                                                       $( '<br>' ),
-                                                       $( '<input type="text" class="feedback-subject" name="subject" maxlength="60" style="width: 100%; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;"/>' )
-                                               ),
-                                               $( '<div style="margin-top: 0.4em;"></div>' ).append(
-                                                       mw.msg( 'feedback-message' ),
-                                                       $( '<br>' ),
-                                                       $( '<textarea name="message" class="feedback-message" rows="5" cols="60"></textarea>' )
-                                               )
-                                       ),
-                                       $( '<div class="feedback-mode feedback-bugs"></div>' ).append(
-                                               $( '<p>' ).msg( 'feedback-bugcheck', $bugsListLink )
-                                       ),
-                                       $( '<div class="feedback-mode feedback-submitting" style="text-align: center; margin: 3em 0;"></div>' ).append(
-                                               mw.msg( 'feedback-adding' ),
-                                               $( '<br>' ),
-                                               $( '<span class="feedback-spinner"></span>' )
-                                       ),
-                                       $( '<div class="feedback-mode feedback-thanks" style="text-align: center; margin:1em"></div>' ).msg(
-                                               'feedback-thanks', fb.title.getNameText(), $feedbackPageLink.clone()
-                                       ),
-                                       $( '<div class="feedback-mode feedback-error" style="position: relative;"></div>' ).append(
-                                               $( '<div class="feedback-error-msg style="color: #990000; margin-top: 0.4em;"></div>' )
-                                       )
-                               );
-
-                               // undo some damage from dialog css
-                               this.$dialog.find( 'a' ).css( {
-                                       color: '#0645ad'
-                               } );
-
-                               this.$dialog.dialog({
-                                       width: 500,
-                                       autoOpen: false,
-                                       title: mw.msg( this.dialogTitleMessageKey ),
-                                       modal: true,
-                                       buttons: fb.buttons
-                               });
-
-                       this.subjectInput = this.$dialog.find( 'input.feedback-subject' ).get(0);
-                       this.messageInput = this.$dialog.find( 'textarea.feedback-message' ).get(0);
-
-               },
-
-               /**
-                * Displays a section of the dialog.
-                *
-                * @param {"form"|"bugs"|"submitting"|"thanks"|"error"} s
-                * The section of the dialog to show.
-                */
-               display: function ( s ) {
-                       // Hide the buttons
-                       this.$dialog.dialog( { buttons: {} } );
-                       // Hide everything
-                       this.$dialog.find( '.feedback-mode' ).hide();
-                       // Show the desired div
-                       this.$dialog.find( '.feedback-' + s ).show();
-               },
-
-               /**
-                * Display the submitting section.
-                */
-               displaySubmitting: function () {
-                       this.display( 'submitting' );
-               },
-
-               /**
-                * Display the bugs section.
-                */
-               displayBugs: function () {
-                       var fb = this,
-                               bugsButtons = {};
-                       this.display( 'bugs' );
-                       bugsButtons[ mw.msg( 'feedback-bugnew' ) ] = function () {
-                               window.open( fb.bugsLink, '_blank' );
-                       };
-                       bugsButtons[ mw.msg( 'feedback-cancel' ) ] = function () {
-                               fb.cancel();
-                       };
-                       this.$dialog.dialog( {
-                               buttons: bugsButtons
-                       } );
-               },
-
-               /**
-                * Display the thanks section.
-                */
-               displayThanks: function () {
-                       var fb = this,
-                               closeButton = {};
-                       this.display( 'thanks' );
-                       closeButton[ mw.msg( 'feedback-close' ) ] = function () {
-                               fb.$dialog.dialog( 'close' );
-                       };
-                       this.$dialog.dialog( {
-                               buttons: closeButton
-                       } );
-               },
-
-               /**
-                * Display the feedback form
-                * @param {Object} [contents] Prefilled contents for the feedback form.
-                * @param {string} [contents.subject] The subject of the feedback
-                * @param {string} [contents.message] The content of the feedback
-                */
-               displayForm: function ( contents ) {
-                       var fb = this,
-                               formButtons = {};
-                       this.subjectInput.value = ( contents && contents.subject ) ? contents.subject : '';
-                       this.messageInput.value = ( contents && contents.message ) ? contents.message : '';
-
-                       this.display( 'form' );
-
-                       // Set up buttons for dialog box. We have to do it the hard way since the json keys are localized
-                       formButtons[ mw.msg( 'feedback-submit' ) ] = function () {
-                               fb.submit();
-                       };
-                       formButtons[ mw.msg( 'feedback-cancel' ) ] = function () {
-                               fb.cancel();
-                       };
-                       this.$dialog.dialog( { buttons: formButtons } ); // put the buttons back
-               },
-
-               /**
-                * Display an error on the form.
-                *
-                * @param {string} message Should be a valid message key.
-                */
-               displayError: function ( message ) {
-                       var fb = this,
-                               closeButton = {};
-                       this.display( 'error' );
-                       this.$dialog.find( '.feedback-error-msg' ).msg( message );
-                       closeButton[ mw.msg( 'feedback-close' ) ] = function () {
-                               fb.$dialog.dialog( 'close' );
-                       };
-                       this.$dialog.dialog( { buttons: closeButton } );
-               },
-
-               /**
-                * Close the feedback form.
-                */
-               cancel: function () {
-                       this.$dialog.dialog( 'close' );
-               },
-
-               /**
-                * Submit the feedback form.
-                */
-               submit: function () {
-                       var subject, message,
-                               fb = this;
-
-                       function ok( result ) {
-                               if ( result.edit !== undefined ) {
-                                       if ( result.edit.result === 'Success' ) {
-                                               fb.displayThanks();
-                                       } else {
-                                               // unknown API result
-                                               fb.displayError( 'feedback-error1' );
-                                       }
-                               } else {
-                                       // edit failed
-                                       fb.displayError( 'feedback-error2' );
-                               }
-                       }
-
-                       function err() {
-                               // ajax request failed
-                               fb.displayError( 'feedback-error3' );
-                       }
-
-                       // Get the values to submit.
-                       subject = this.subjectInput.value;
-
-                       // We used to include "mw.html.escape( navigator.userAgent )" but there are legal issues
-                       // with posting this without their explicit consent
-                       message = this.messageInput.value;
-                       if ( message.indexOf( '~~~' ) === -1 ) {
-                               message += ' ~~~~';
-                       }
-
-                       this.displaySubmitting();
-
-                       this.api.newSection( this.title, subject, message, ok, err );
-               },
-
-               /**
-                * Modify the display form, and then open it, focusing interface on the subject.
-                * @param {Object} [contents] Prefilled contents for the feedback form.
-                * @param {string} [contents.subject] The subject of the feedback
-                * @param {string} [contents.message] The content of the feedback
-                */
-               launch: function ( contents ) {
-                       this.displayForm( contents );
-                       this.$dialog.dialog( 'open' );
-                       this.subjectInput.focus();
-               }
-
-       };
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.feedback.spinner.gif b/resources/mediawiki/mediawiki.feedback.spinner.gif
deleted file mode 100644 (file)
index aed0ea4..0000000
Binary files a/resources/mediawiki/mediawiki.feedback.spinner.gif and /dev/null differ
diff --git a/resources/mediawiki/mediawiki.hidpi.js b/resources/mediawiki/mediawiki.hidpi.js
deleted file mode 100644 (file)
index ecee450..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-jQuery( function ( $ ) {
-       // Apply hidpi images on DOM-ready
-       // Some may have already partly preloaded at low resolution.
-       $( 'body' ).hidpi();
-} );
diff --git a/resources/mediawiki/mediawiki.hlist.css b/resources/mediawiki/mediawiki.hlist.css
deleted file mode 100644 (file)
index adcb810..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*!
- * Stylesheet for mediawiki.hlist module
- * @author [[User:Edokter]]
- */
-.hlist dl,
-.hlist ol,
-.hlist ul {
-       margin: 0;
-       padding: 0;
-}
-/* Display list items inline */
-.hlist dd,
-.hlist dt,
-.hlist li {
-       margin: 0;
-       display: inline;
-}
-/* Display nested lists inline */
-.hlist dl dl, .hlist dl ol, .hlist dl ul,
-.hlist ol dl, .hlist ol ol, .hlist ol ul,
-.hlist ul dl, .hlist ul ol, .hlist ul ul {
-       display: inline;
-}
-/* Generate interpuncts */
-.hlist dt:after {
-       content: ":";
-}
-.hlist dd:after,
-.hlist li:after {
-       content: " ·";
-       font-weight: bold;
-}
-.hlist dd:last-child:after,
-.hlist dt:last-child:after,
-.hlist li:last-child:after {
-       content: none;
-}
-/* For IE8 */
-.hlist dd.hlist-last-child:after,
-.hlist dt.hlist-last-child:after,
-.hlist li.hlist-last-child:after {
-       content: none;
-}
-/* Add parentheses around nested lists */
-.hlist dd dd:first-child:before, .hlist dd dt:first-child:before, .hlist dd li:first-child:before,
-.hlist dt dd:first-child:before, .hlist dt dt:first-child:before, .hlist dt li:first-child:before,
-.hlist li dd:first-child:before, .hlist li dt:first-child:before, .hlist li li:first-child:before {
-       content: "(";
-       font-weight: normal;
-}
-.hlist dd dd:last-child:after, .hlist dd dt:last-child:after, .hlist dd li:last-child:after,
-.hlist dt dd:last-child:after, .hlist dt dt:last-child:after, .hlist dt li:last-child:after,
-.hlist li dd:last-child:after, .hlist li dt:last-child:after, .hlist li li:last-child:after {
-       content: ")";
-       font-weight: normal;
-}
-/* For IE8 */
-.hlist dd dd.hlist-last-child:after, .hlist dd dt.hlist-last-child:after, .hlist dd li.hlist-last-child:after,
-.hlist dt dd.hlist-last-child:after, .hlist dt dt.hlist-last-child:after, .hlist dt li.hlist-last-child:after,
-.hlist li dd.hlist-last-child:after, .hlist li dt.hlist-last-child:after, .hlist li li.hlist-last-child:after {
-       content: ")";
-       font-weight: normal;
-}
-/* Put ordinals in front of ordered list items */
-.hlist ol {
-       counter-reset: list-item;
-}
-.hlist ol > li {
-       counter-increment: list-item;
-}
-.hlist ol > li:before {
-       content: counter(list-item) " ";
-}
-.hlist dd ol > li:first-child:before,
-.hlist dt ol > li:first-child:before,
-.hlist li ol > li:first-child:before {
-       content: "(" counter(list-item) " ";
-}
diff --git a/resources/mediawiki/mediawiki.hlist.js b/resources/mediawiki/mediawiki.hlist.js
deleted file mode 100644 (file)
index 0bbf8fa..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*!
- * .hlist fallbacks for IE 6, 7 and 8.
- * @author [[User:Edokter]]
- */
-( function ( mw, $ ) {
-       var profile = $.client.profile();
-
-       if ( profile.name === 'msie' ) {
-               if ( profile.versionNumber === 8 ) {
-                       /* IE 8: Add pseudo-selector class to last-child list items */
-                       mw.hook( 'wikipage.content' ).add( function ( $content ) {
-                               $content.find( '.hlist' ).find( 'dd:last-child, dt:last-child, li:last-child' )
-                                       .addClass( 'hlist-last-child' );
-                       } );
-               }
-               else if ( profile.versionNumber <= 7 ) {
-                       /* IE 7 and below: Generate interpuncts and parentheses */
-                       mw.hook( 'wikipage.content' ).add( function ( $content ) {
-                               var $hlists = $content.find( '.hlist' );
-                               $hlists.find( 'dt:not(:last-child)' )
-                                       .append( ': ' );
-                               $hlists.find( 'dd:not(:last-child)' )
-                                       .append( '<b>·</b> ' );
-                               $hlists.find( 'li:not(:last-child)' )
-                                       .append( '<b>·</b> ' );
-                               $hlists.find( 'dl dl, dl ol, dl ul, ol dl, ol ol, ol ul, ul dl, ul ol, ul ul' )
-                                       .prepend( '( ' ).append( ') ' );
-                       } );
-               }
-       }
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.htmlform.js b/resources/mediawiki/mediawiki.htmlform.js
deleted file mode 100644 (file)
index 5ba1a54..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * Utility functions for jazzing up HTMLForm elements.
- *
- * @class jQuery.plugin.htmlform
- */
-( function ( mw, $ ) {
-
-       /**
-        * jQuery plugin to fade or snap to visible state.
-        *
-        * @param {boolean} [instantToggle=false]
-        * @return {jQuery}
-        * @chainable
-        */
-       $.fn.goIn = function ( instantToggle ) {
-               if ( instantToggle === true ) {
-                       return $( this ).show();
-               }
-               return $( this ).stop( true, true ).fadeIn();
-       };
-
-       /**
-        * jQuery plugin to fade or snap to hiding state.
-        *
-        * @param {boolean} [instantToggle=false]
-        * @return jQuery
-        * @chainable
-        */
-       $.fn.goOut = function ( instantToggle ) {
-               if ( instantToggle === true ) {
-                       return $( this ).hide();
-               }
-               return $( this ).stop( true, true ).fadeOut();
-       };
-
-       /**
-        * Bind a function to the jQuery object via live(), and also immediately trigger
-        * the function on the objects with an 'instant' parameter set to true.
-        * @param {Function} callback
-        * @param {boolean|jQuery.Event} callback.immediate True when the event is called immediately,
-        *  an event object when triggered from an event.
-        */
-       $.fn.liveAndTestAtStart = function ( callback ) {
-               $( this )
-                       .live( 'change', callback )
-                       .each( function () {
-                               callback.call( this, true );
-                       } );
-       };
-
-       $( function () {
-
-               // Animate the SelectOrOther fields, to only show the text field when
-               // 'other' is selected.
-               $( '.mw-htmlform-select-or-other' ).liveAndTestAtStart( function ( instant ) {
-                       var $other = $( '#' + $( this ).attr( 'id' ) + '-other' );
-                       $other = $other.add( $other.siblings( 'br' ) );
-                       if ( $( this ).val() === 'other' ) {
-                               $other.goIn( instant );
-                       } else {
-                               $other.goOut( instant );
-                       }
-               } );
-
-       } );
-
-       function addMulti( $oldContainer, $container ) {
-               var name = $oldContainer.find( 'input:first-child' ).attr( 'name' ),
-                       oldClass = ( ' ' + $oldContainer.attr( 'class' ) + ' ' ).replace( /(mw-htmlform-field-HTMLMultiSelectField|mw-chosen)/g, '' ),
-                       $select = $( '<select>' ),
-                       dataPlaceholder = mw.message( 'htmlform-chosen-placeholder' );
-               oldClass = $.trim( oldClass );
-               $select.attr( {
-                       name: name,
-                       multiple: 'multiple',
-                       'data-placeholder': dataPlaceholder.plain(),
-                       'class': 'htmlform-chzn-select mw-input ' + oldClass
-               } );
-               $oldContainer.find( 'input' ).each( function () {
-                       var $oldInput = $( this ),
-                       checked = $oldInput.prop( 'checked' ),
-                       $option = $( '<option>' );
-                       $option.prop( 'value', $oldInput.prop( 'value' ) );
-                       if ( checked ) {
-                               $option.prop( 'selected', true );
-                       }
-                       $option.text( $oldInput.prop( 'value' ) );
-                       $select.append( $option );
-               } );
-               $container.append( $select );
-       }
-
-       function convertCheckboxesToMulti( $oldContainer, type ) {
-               var $fieldLabel = $( '<td>' ),
-               $td = $( '<td>' ),
-               $fieldLabelText = $( '<label>' ),
-               $container;
-               if ( type === 'tr' ) {
-                       addMulti( $oldContainer, $td );
-                       $container = $( '<tr>' );
-                       $container.append( $td );
-               } else if ( type === 'div' ) {
-                       $fieldLabel = $( '<div>' );
-                       $container = $( '<div>' );
-                       addMulti( $oldContainer, $container );
-               }
-               $fieldLabel.attr( 'class', 'mw-label' );
-               $fieldLabelText.text( $oldContainer.find( '.mw-label label' ).text() );
-               $fieldLabel.append( $fieldLabelText );
-               $container.prepend( $fieldLabel );
-               $oldContainer.replaceWith( $container );
-               return $container;
-       }
-
-       if ( $( '.mw-chosen' ).length ) {
-               mw.loader.using( 'jquery.chosen', function () {
-                       $( '.mw-chosen' ).each( function () {
-                               var type = this.nodeName.toLowerCase(),
-                                       $converted = convertCheckboxesToMulti( $( this ), type );
-                               $converted.find( '.htmlform-chzn-select' ).chosen( { width: 'auto' } );
-                       } );
-               } );
-       }
-
-       $( function () {
-               var $matrixTooltips = $( '.mw-htmlform-matrix .mw-htmlform-tooltip' );
-               if ( $matrixTooltips.length ) {
-                       mw.loader.using( 'jquery.tipsy', function () {
-                               $matrixTooltips.tipsy( { gravity: 's' } );
-                       } );
-               }
-       } );
-
-       /**
-        * @class jQuery
-        * @mixins jQuery.plugin.htmlform
-        */
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.icon.less b/resources/mediawiki/mediawiki.icon.less
deleted file mode 100644 (file)
index 49f0f70..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* General-purpose icons via CSS. Classes here should be named "mw-icon-*". */
-
-@import "mediawiki.mixins";
-
-/* For the collapsed and expanded arrows, we also provide selectors to make it
- * easy to use them with jquery.makeCollapsible. */
-.mw-icon-arrow-collapsed,
-.mw-collapsible-arrow.mw-collapsible-toggle-collapsed {
-       .background-image-svg('images/arrow-collapsed-ltr.svg', 'images/arrow-collapsed-ltr.png');
-       background-repeat: no-repeat;
-       background-position: left bottom;
-}
-
-.mw-icon-arrow-expanded,
-.mw-collapsible-arrow.mw-collapsible-toggle-expanded {
-       .background-image-svg('images/arrow-expanded.svg', 'images/arrow-expanded.png');
-       background-repeat: no-repeat;
-       background-position: left bottom;
-}
diff --git a/resources/mediawiki/mediawiki.inspect.js b/resources/mediawiki/mediawiki.inspect.js
deleted file mode 100644 (file)
index 62fa410..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/*!
- * Tools for inspecting page composition and performance.
- *
- * @author Ori Livneh
- * @since 1.22
- */
-/*jshint devel:true */
-( function ( mw, $ ) {
-
-       function sortByProperty( array, prop, descending ) {
-               var order = descending ? -1 : 1;
-               return array.sort( function ( a, b ) {
-                       return a[prop] > b[prop] ? order : a[prop] < b[prop] ? -order : 0;
-               } );
-       }
-
-       function humanSize( bytes ) {
-               if ( !$.isNumeric( bytes ) || bytes === 0 ) { return bytes; }
-               var i = 0, units = [ '', ' kB', ' MB', ' GB', ' TB', ' PB' ];
-               for ( ; bytes >= 1024; bytes /= 1024 ) { i++; }
-               return bytes.toFixed( 1 ) + units[i];
-       }
-
-       /**
-        * @class mw.inspect
-        * @singleton
-        */
-       var inspect = {
-
-               /**
-                * Return a map of all dependency relationships between loaded modules.
-                *
-                * @return {Object} Maps module names to objects. Each sub-object has
-                *  two properties, 'requires' and 'requiredBy'.
-                */
-               getDependencyGraph: function () {
-                       var modules = inspect.getLoadedModules(), graph = {};
-
-                       $.each( modules, function ( moduleIndex, moduleName ) {
-                               var dependencies = mw.loader.moduleRegistry[moduleName].dependencies || [];
-
-                               graph[moduleName] = graph[moduleName] || { requiredBy: [] };
-                               graph[moduleName].requires = dependencies;
-
-                               $.each( dependencies, function ( depIndex, depName ) {
-                                       graph[depName] = graph[depName] || { requiredBy: [] };
-                                       graph[depName].requiredBy.push( moduleName );
-                               } );
-                       } );
-                       return graph;
-               },
-
-               /**
-                * Calculate the byte size of a ResourceLoader module.
-                *
-                * @param {string} moduleName The name of the module
-                * @return {number|null} Module size in bytes or null
-                */
-               getModuleSize: function ( moduleName ) {
-                       var module = mw.loader.moduleRegistry[ moduleName ],
-                               payload = 0;
-
-                       if ( mw.loader.getState( moduleName ) !== 'ready' ) {
-                               return null;
-                       }
-
-                       if ( !module.style && !module.script ) {
-                               return null;
-                       }
-
-                       // Tally CSS
-                       if ( module.style && $.isArray( module.style.css ) ) {
-                               $.each( module.style.css, function ( i, stylesheet ) {
-                                       payload += $.byteLength( stylesheet );
-                               } );
-                       }
-
-                       // Tally JavaScript
-                       if ( $.isFunction( module.script ) ) {
-                               payload += $.byteLength( module.script.toString() );
-                       }
-
-                       return payload;
-               },
-
-               /**
-                * Given CSS source, count both the total number of selectors it
-                * contains and the number which match some element in the current
-                * document.
-                *
-                * @param {string} css CSS source
-                * @return Selector counts
-                * @return {number} return.selectors Total number of selectors
-                * @return {number} return.matched Number of matched selectors
-                */
-               auditSelectors: function ( css ) {
-                       var selectors = { total: 0, matched: 0 },
-                               style = document.createElement( 'style' ),
-                               sheet, rules;
-
-                       style.textContent = css;
-                       document.body.appendChild( style );
-                       // Standards-compliant browsers use .sheet.cssRules, IE8 uses .styleSheet.rules…
-                       sheet = style.sheet || style.styleSheet;
-                       rules = sheet.cssRules || sheet.rules;
-                       $.each( rules, function ( index, rule ) {
-                               selectors.total++;
-                               if ( document.querySelector( rule.selectorText ) !== null ) {
-                                       selectors.matched++;
-                               }
-                       } );
-                       document.body.removeChild( style );
-                       return selectors;
-               },
-
-               /**
-                * Get a list of all loaded ResourceLoader modules.
-                *
-                * @return {Array} List of module names
-                */
-               getLoadedModules: function () {
-                       return $.grep( mw.loader.getModuleNames(), function ( module ) {
-                               return mw.loader.getState( module ) === 'ready';
-                       } );
-               },
-
-               /**
-                * Print tabular data to the console, using console.table, console.log,
-                * or mw.log (in declining order of preference).
-                *
-                * @param {Array} data Tabular data represented as an array of objects
-                *  with common properties.
-                */
-               dumpTable: function ( data ) {
-                       try {
-                               // Bartosz made me put this here.
-                               if ( window.opera ) { throw window.opera; }
-                               // Use Function.prototype#call to force an exception on Firefox,
-                               // which doesn't define console#table but doesn't complain if you
-                               // try to invoke it.
-                               console.table.call( console, data );
-                               return;
-                       } catch ( e ) {}
-                       try {
-                               console.log( $.toJSON( data, null, 2 ) );
-                               return;
-                       } catch ( e ) {}
-                       mw.log( data );
-               },
-
-               /**
-                * Generate and print one more reports. When invoked with no arguments,
-                * print all reports.
-                *
-                * @param {string...} [reports] Report names to run, or unset to print
-                *  all available reports.
-                */
-               runReports: function () {
-                       var reports = arguments.length > 0 ?
-                               Array.prototype.slice.call( arguments ) :
-                               $.map( inspect.reports, function ( v, k ) { return k; } );
-
-                       $.each( reports, function ( index, name ) {
-                               inspect.dumpTable( inspect.reports[name]() );
-                       } );
-               },
-
-               /**
-                * @class mw.inspect.reports
-                * @singleton
-                */
-               reports: {
-                       /**
-                        * Generate a breakdown of all loaded modules and their size in
-                        * kilobytes. Modules are ordered from largest to smallest.
-                        */
-                       size: function () {
-                               // Map each module to a descriptor object.
-                               var modules = $.map( inspect.getLoadedModules(), function ( module ) {
-                                       return {
-                                               name: module,
-                                               size: inspect.getModuleSize( module )
-                                       };
-                               } );
-
-                               // Sort module descriptors by size, largest first.
-                               sortByProperty( modules, 'size', true );
-
-                               // Convert size to human-readable string.
-                               $.each( modules, function ( i, module ) {
-                                       module.size = humanSize( module.size );
-                               } );
-
-                               return modules;
-                       },
-
-                       /**
-                        * For each module with styles, count the number of selectors, and
-                        * count how many match against some element currently in the DOM.
-                        */
-                       css: function () {
-                               var modules = [];
-
-                               $.each( inspect.getLoadedModules(), function ( index, name ) {
-                                       var css, stats, module = mw.loader.moduleRegistry[name];
-
-                                       try {
-                                               css = module.style.css.join();
-                                       } catch ( e ) { return; } // skip
-
-                                       stats = inspect.auditSelectors( css );
-                                       modules.push( {
-                                               module: name,
-                                               allSelectors: stats.total,
-                                               matchedSelectors: stats.matched,
-                                               percentMatched: stats.total !== 0 ?
-                                                       ( stats.matched / stats.total * 100 ).toFixed( 2 )  + '%' : null
-                                       } );
-                               } );
-                               sortByProperty( modules, 'allSelectors', true );
-                               return modules;
-                       },
-
-                       /**
-                        * Report stats on mw.loader.store: the number of localStorage
-                        * cache hits and misses, the number of items purged from the
-                        * cache, and the total size of the module blob in localStorage.
-                        */
-                       store: function () {
-                               var raw, stats = { enabled: mw.loader.store.enabled };
-                               if ( stats.enabled ) {
-                                       $.extend( stats, mw.loader.store.stats );
-                                       try {
-                                               raw = localStorage.getItem( mw.loader.store.getStoreKey() );
-                                               stats.totalSize = humanSize( $.byteLength( raw ) );
-                                       } catch ( e ) {}
-                               }
-                               return [stats];
-                       }
-               },
-
-               /**
-                * Perform a substring search across the JavaScript and CSS source code
-                * of all loaded modules and return an array of the names of the
-                * modules that matched.
-                *
-                * @param {string|RegExp} pattern String or regexp to match.
-                * @return {Array} Array of the names of modules that matched.
-                */
-               grep: function ( pattern ) {
-                       if ( typeof pattern.test !== 'function' ) {
-                               // Based on Y.Escape.regex from YUI v3.15.0
-                               pattern = new RegExp( pattern.replace( /[\-$\^*()+\[\]{}|\\,.?\s]/g, '\\$&' ), 'g' );
-                       }
-
-                       return $.grep( inspect.getLoadedModules(), function ( moduleName ) {
-                               var module = mw.loader.moduleRegistry[moduleName];
-
-                               // Grep module's JavaScript
-                               if ( $.isFunction( module.script ) && pattern.test( module.script.toString() ) ) {
-                                       return true;
-                               }
-
-                               // Grep module's CSS
-                               if (
-                                       $.isPlainObject( module.style ) && $.isArray( module.style.css )
-                                       && pattern.test( module.style.css.join( '' ) )
-                               ) {
-                                       // Module's CSS source matches
-                                       return true;
-                               }
-
-                               return false;
-                       } );
-               }
-       };
-
-       if ( mw.config.get( 'debug' ) ) {
-               mw.log( 'mw.inspect: reports are not available in debug mode.' );
-       }
-
-       mw.inspect = inspect;
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.jqueryMsg.js b/resources/mediawiki/mediawiki.jqueryMsg.js
deleted file mode 100644 (file)
index 3a6869e..0000000
+++ /dev/null
@@ -1,1237 +0,0 @@
-/*!
-* Experimental advanced wikitext parser-emitter.
-* See: https://www.mediawiki.org/wiki/Extension:UploadWizard/MessageParser for docs
-*
-* @author neilk@wikimedia.org
-* @author mflaschen@wikimedia.org
-*/
-( function ( mw, $ ) {
-       /**
-        * @class mw.jqueryMsg
-        * @singleton
-        */
-
-       var oldParser,
-               slice = Array.prototype.slice,
-               parserDefaults = {
-                       magic: {
-                               'SITENAME': mw.config.get( 'wgSiteName' )
-                       },
-                       // This is a whitelist based on, but simpler than, Sanitizer.php.
-                       // Self-closing tags are not currently supported.
-                       allowedHtmlElements: [
-                               'b',
-                               'i'
-                       ],
-                       // Key tag name, value allowed attributes for that tag.
-                       // See Sanitizer::setupAttributeWhitelist
-                       allowedHtmlCommonAttributes: [
-                               // HTML
-                               'id',
-                               'class',
-                               'style',
-                               'lang',
-                               'dir',
-                               'title',
-
-                               // WAI-ARIA
-                               'role'
-                       ],
-
-                       // Attributes allowed for specific elements.
-                       // Key is element name in lower case
-                       // Value is array of allowed attributes for that element
-                       allowedHtmlAttributesByElement: {},
-                       messages: mw.messages,
-                       language: mw.language,
-
-                       // Same meaning as in mediawiki.js.
-                       //
-                       // Only 'text', 'parse', and 'escaped' are supported, and the
-                       // actual escaping for 'escaped' is done by other code (generally
-                       // through mediawiki.js).
-                       //
-                       // However, note that this default only
-                       // applies to direct calls to jqueryMsg. The default for mediawiki.js itself
-                       // is 'text', including when it uses jqueryMsg.
-                       format: 'parse'
-
-               };
-
-       /**
-        * Wrapper around jQuery append that converts all non-objects to TextNode so append will not
-        * convert what it detects as an htmlString to an element.
-        *
-        * Object elements of children (jQuery, HTMLElement, TextNode, etc.) will be left as is.
-        *
-        * @private
-        * @param {jQuery} $parent Parent node wrapped by jQuery
-        * @param {Object|string|Array} children What to append, with the same possible types as jQuery
-        * @return {jQuery} $parent
-        */
-       function appendWithoutParsing( $parent, children ) {
-               var i, len;
-
-               if ( !$.isArray( children ) ) {
-                       children = [children];
-               }
-
-               for ( i = 0, len = children.length; i < len; i++ ) {
-                       if ( typeof children[i] !== 'object' ) {
-                               children[i] = document.createTextNode( children[i] );
-                       }
-               }
-
-               return $parent.append( children );
-       }
-
-       /**
-        * Decodes the main HTML entities, those encoded by mw.html.escape.
-        *
-        * @private
-        * @param {string} encoded Encoded string
-        * @return {string} String with those entities decoded
-        */
-       function decodePrimaryHtmlEntities( encoded ) {
-               return encoded
-                       .replace( /&#039;/g, '\'' )
-                       .replace( /&quot;/g, '"' )
-                       .replace( /&lt;/g, '<' )
-                       .replace( /&gt;/g, '>' )
-                       .replace( /&amp;/g, '&' );
-       }
-
-       /**
-        * Given parser options, return a function that parses a key and replacements, returning jQuery object
-        *
-        * Try to parse a key and optional replacements, returning a jQuery object that may be a tree of jQuery nodes.
-        * If there was an error parsing, return the key and the error message (wrapped in jQuery). This should put the error right into
-        * the interface, without causing the page to halt script execution, and it hopefully should be clearer how to fix it.
-        * @private
-        * @param {Object} options Parser options
-        * @return {Function}
-        * @return {Array} return.args First element is the key, replacements may be in array in 2nd element, or remaining elements.
-        * @return {jQuery} return.return
-        */
-       function getFailableParserFn( options ) {
-               var parser = new mw.jqueryMsg.parser( options );
-
-               return function ( args ) {
-                       var key = args[0],
-                               argsArray = $.isArray( args[1] ) ? args[1] : slice.call( args, 1 );
-                       try {
-                               return parser.parse( key, argsArray );
-                       } catch ( e ) {
-                               return $( '<span>' ).text( key + ': ' + e.message );
-                       }
-               };
-       }
-
-       mw.jqueryMsg = {};
-
-       /**
-        * Returns a function suitable for use as a global, to construct strings from the message key (and optional replacements).
-        * e.g.
-        *
-        *       window.gM = mediaWiki.parser.getMessageFunction( options );
-        *       $( 'p#headline' ).html( gM( 'hello-user', username ) );
-        *
-        * Like the old gM() function this returns only strings, so it destroys any bindings. If you want to preserve bindings use the
-        * jQuery plugin version instead. This is only included for backwards compatibility with gM().
-        *
-        * N.B. replacements are variadic arguments or an array in second parameter. In other words:
-        *    somefunction( a, b, c, d )
-        * is equivalent to
-        *    somefunction( a, [b, c, d] )
-        *
-        * @param {Object} options parser options
-        * @return {Function} Function suitable for assigning to window.gM
-        * @return {string} return.key Message key.
-        * @return {Array|Mixed} return.replacements Optional variable replacements (variadically or an array).
-        * @return {string} return.return Rendered HTML.
-        */
-       mw.jqueryMsg.getMessageFunction = function ( options ) {
-               var failableParserFn = getFailableParserFn( options ),
-                       format;
-
-               if ( options && options.format !== undefined ) {
-                       format = options.format;
-               } else {
-                       format = parserDefaults.format;
-               }
-
-               return function () {
-                       var failableResult = failableParserFn( arguments );
-                       if ( format === 'text' || format === 'escaped' ) {
-                               return failableResult.text();
-                       } else {
-                               return failableResult.html();
-                       }
-               };
-       };
-
-       /**
-        * Returns a jQuery plugin which parses the message in the message key, doing replacements optionally, and appends the nodes to
-        * the current selector. Bindings to passed-in jquery elements are preserved. Functions become click handlers for [$1 linktext] links.
-        * e.g.
-        *
-        *        $.fn.msg = mediaWiki.parser.getJqueryPlugin( options );
-        *        var userlink = $( '<a>' ).click( function () { alert( "hello!!" ) } );
-        *        $( 'p#headline' ).msg( 'hello-user', userlink );
-        *
-        * N.B. replacements are variadic arguments or an array in second parameter. In other words:
-        *    somefunction( a, b, c, d )
-        * is equivalent to
-        *    somefunction( a, [b, c, d] )
-        *
-        * We append to 'this', which in a jQuery plugin context will be the selected elements.
-        *
-        * @param {Object} options Parser options
-        * @return {Function} Function suitable for assigning to jQuery plugin, such as jQuery#msg
-        * @return {string} return.key Message key.
-        * @return {Array|Mixed} return.replacements Optional variable replacements (variadically or an array).
-        * @return {jQuery} return.return
-        */
-       mw.jqueryMsg.getPlugin = function ( options ) {
-               var failableParserFn = getFailableParserFn( options );
-
-               return function () {
-                       var $target = this.empty();
-                       // TODO: Simply appendWithoutParsing( $target, failableParserFn( arguments ).contents() )
-                       // or Simply appendWithoutParsing( $target, failableParserFn( arguments ) )
-                       $.each( failableParserFn( arguments ).contents(), function ( i, node ) {
-                               appendWithoutParsing( $target, node );
-                       } );
-                       return $target;
-               };
-       };
-
-       /**
-        * The parser itself.
-        * Describes an object, whose primary duty is to .parse() message keys.
-        *
-        * @class
-        * @private
-        * @param {Object} options
-        */
-       mw.jqueryMsg.parser = function ( options ) {
-               this.settings = $.extend( {}, parserDefaults, options );
-               this.settings.onlyCurlyBraceTransform = ( this.settings.format === 'text' || this.settings.format === 'escaped' );
-
-               this.emitter = new mw.jqueryMsg.htmlEmitter( this.settings.language, this.settings.magic );
-       };
-
-       mw.jqueryMsg.parser.prototype = {
-               /**
-                * Cache mapping MediaWiki message keys and the value onlyCurlyBraceTransform, to the AST of the message.
-                *
-                * In most cases, the message is a string so this is identical.
-                * (This is why we would like to move this functionality server-side).
-                *
-                * The two parts of the key are separated by colon.  For example:
-                *
-                *     "message-key:true": ast
-                *
-                * if they key is "message-key" and onlyCurlyBraceTransform is true.
-                *
-                * This cache is shared by all instances of mw.jqueryMsg.parser.
-                *
-                * NOTE: We promise, it's static - when you create this empty object
-                * in the prototype, each new instance of the class gets a reference
-                * to the same object.
-                *
-                * @static
-                * @property {Object}
-                */
-               astCache: {},
-
-               /**
-                * Where the magic happens.
-                * Parses a message from the key, and swaps in replacements as necessary, wraps in jQuery
-                * If an error is thrown, returns original key, and logs the error
-                * @param {string} key Message key.
-                * @param {Array} replacements Variable replacements for $1, $2... $n
-                * @return {jQuery}
-                */
-               parse: function ( key, replacements ) {
-                       return this.emitter.emit( this.getAst( key ), replacements );
-               },
-
-               /**
-                * Fetch the message string associated with a key, return parsed structure. Memoized.
-                * Note that we pass '[' + key + ']' back for a missing message here.
-                * @param {string} key
-                * @return {string|Array} string of '[key]' if message missing, simple string if possible, array of arrays if needs parsing
-                */
-               getAst: function ( key ) {
-                       var cacheKey = [key, this.settings.onlyCurlyBraceTransform].join( ':' ), wikiText;
-
-                       if ( this.astCache[ cacheKey ] === undefined ) {
-                               wikiText = this.settings.messages.get( key );
-                               if ( typeof wikiText !== 'string' ) {
-                                       wikiText = '\\[' + key + '\\]';
-                               }
-                               this.astCache[ cacheKey ] = this.wikiTextToAst( wikiText );
-                       }
-                       return this.astCache[ cacheKey ];
-               },
-
-               /**
-                * Parses the input wikiText into an abstract syntax tree, essentially an s-expression.
-                *
-                * CAVEAT: This does not parse all wikitext. It could be more efficient, but it's pretty good already.
-                * n.b. We want to move this functionality to the server. Nothing here is required to be on the client.
-                *
-                * @param {string} input Message string wikitext
-                * @throws Error
-                * @return {Mixed} abstract syntax tree
-                */
-               wikiTextToAst: function ( input ) {
-                       var pos, settings = this.settings, concat = Array.prototype.concat,
-                               regularLiteral, regularLiteralWithoutBar, regularLiteralWithoutSpace, regularLiteralWithSquareBrackets,
-                               doubleQuote, singleQuote, backslash, anyCharacter, asciiAlphabetLiteral,
-                               escapedOrLiteralWithoutSpace, escapedOrLiteralWithoutBar, escapedOrRegularLiteral,
-                               whitespace, dollar, digits, htmlDoubleQuoteAttributeValue, htmlSingleQuoteAttributeValue,
-                               htmlAttributeEquals, openHtmlStartTag, optionalForwardSlash, openHtmlEndTag, closeHtmlTag,
-                               openExtlink, closeExtlink, wikilinkPage, wikilinkContents, openWikilink, closeWikilink, templateName, pipe, colon,
-                               templateContents, openTemplate, closeTemplate,
-                               nonWhitespaceExpression, paramExpression, expression, curlyBraceTransformExpression, result;
-
-                       // Indicates current position in input as we parse through it.
-                       // Shared among all parsing functions below.
-                       pos = 0;
-
-                       // =========================================================
-                       // parsing combinators - could be a library on its own
-                       // =========================================================
-
-                       /**
-                        * Try parsers until one works, if none work return null
-                        * @private
-                        * @param {Function[]} ps
-                        * @return {string|null}
-                        */
-                       function choice( ps ) {
-                               return function () {
-                                       var i, result;
-                                       for ( i = 0; i < ps.length; i++ ) {
-                                               result = ps[i]();
-                                               if ( result !== null ) {
-                                                        return result;
-                                               }
-                                       }
-                                       return null;
-                               };
-                       }
-
-                       /**
-                        * Try several ps in a row, all must succeed or return null.
-                        * This is the only eager one.
-                        * @private
-                        * @param {Function[]} ps
-                        * @return {string|null}
-                        */
-                       function sequence( ps ) {
-                               var i, res,
-                                       originalPos = pos,
-                                       result = [];
-                               for ( i = 0; i < ps.length; i++ ) {
-                                       res = ps[i]();
-                                       if ( res === null ) {
-                                               pos = originalPos;
-                                               return null;
-                                       }
-                                       result.push( res );
-                               }
-                               return result;
-                       }
-
-                       /**
-                        * Run the same parser over and over until it fails.
-                        * Must succeed a minimum of n times or return null.
-                        * @private
-                        * @param {number} n
-                        * @param {Function} p
-                        * @return {string|null}
-                        */
-                       function nOrMore( n, p ) {
-                               return function () {
-                                       var originalPos = pos,
-                                               result = [],
-                                               parsed = p();
-                                       while ( parsed !== null ) {
-                                               result.push( parsed );
-                                               parsed = p();
-                                       }
-                                       if ( result.length < n ) {
-                                               pos = originalPos;
-                                               return null;
-                                       }
-                                       return result;
-                               };
-                       }
-
-                       /**
-                        * There is a general pattern -- parse a thing, if that worked, apply transform, otherwise return null.
-                        *
-                        * TODO: But using this as a combinator seems to cause problems when combined with #nOrMore().
-                        * May be some scoping issue
-                        *
-                        * @private
-                        * @param {Function} p
-                        * @param {Function} fn
-                        * @return {string|null}
-                        */
-                       function transform( p, fn ) {
-                               return function () {
-                                       var result = p();
-                                       return result === null ? null : fn( result );
-                               };
-                       }
-
-                       /**
-                        * Just make parsers out of simpler JS builtin types
-                        * @private
-                        * @param {string} s
-                        * @return {Function}
-                        * @return {string} return.return
-                        */
-                       function makeStringParser( s ) {
-                               var len = s.length;
-                               return function () {
-                                       var result = null;
-                                       if ( input.substr( pos, len ) === s ) {
-                                                result = s;
-                                                pos += len;
-                                       }
-                                       return result;
-                               };
-                       }
-
-                       /**
-                        * Makes a regex parser, given a RegExp object.
-                        * The regex being passed in should start with a ^ to anchor it to the start
-                        * of the string.
-                        *
-                        * @private
-                        * @param {RegExp} regex anchored regex
-                        * @return {Function} function to parse input based on the regex
-                        */
-                       function makeRegexParser( regex ) {
-                               return function () {
-                                       var matches = input.substr( pos ).match( regex );
-                                       if ( matches === null ) {
-                                               return null;
-                                       }
-                                       pos += matches[0].length;
-                                       return matches[0];
-                               };
-                       }
-
-                       // ===================================================================
-                       // General patterns above this line -- wikitext specific parsers below
-                       // ===================================================================
-
-                       // Parsing functions follow. All parsing functions work like this:
-                       // They don't accept any arguments.
-                       // Instead, they just operate non destructively on the string 'input'
-                       // As they can consume parts of the string, they advance the shared variable pos,
-                       // and return tokens (or whatever else they want to return).
-                       // some things are defined as closures and other things as ordinary functions
-                       // converting everything to a closure makes it a lot harder to debug... errors pop up
-                       // but some debuggers can't tell you exactly where they come from. Also the mutually
-                       // recursive functions seem not to work in all browsers then. (Tested IE6-7, Opera, Safari, FF)
-                       // This may be because, to save code, memoization was removed
-
-                       regularLiteral = makeRegexParser( /^[^{}\[\]$<\\]/ );
-                       regularLiteralWithoutBar = makeRegexParser( /^[^{}\[\]$\\|]/ );
-                       regularLiteralWithoutSpace = makeRegexParser( /^[^{}\[\]$\s]/ );
-                       regularLiteralWithSquareBrackets = makeRegexParser( /^[^{}$\\]/ );
-
-                       backslash = makeStringParser( '\\' );
-                       doubleQuote = makeStringParser( '"' );
-                       singleQuote = makeStringParser( '\'' );
-                       anyCharacter = makeRegexParser( /^./ );
-
-                       openHtmlStartTag = makeStringParser( '<' );
-                       optionalForwardSlash = makeRegexParser( /^\/?/ );
-                       openHtmlEndTag = makeStringParser( '</' );
-                       htmlAttributeEquals = makeRegexParser( /^\s*=\s*/ );
-                       closeHtmlTag = makeRegexParser( /^\s*>/ );
-
-                       function escapedLiteral() {
-                               var result = sequence( [
-                                       backslash,
-                                       anyCharacter
-                               ] );
-                               return result === null ? null : result[1];
-                       }
-                       escapedOrLiteralWithoutSpace = choice( [
-                               escapedLiteral,
-                               regularLiteralWithoutSpace
-                       ] );
-                       escapedOrLiteralWithoutBar = choice( [
-                               escapedLiteral,
-                               regularLiteralWithoutBar
-                       ] );
-                       escapedOrRegularLiteral = choice( [
-                               escapedLiteral,
-                               regularLiteral
-                       ] );
-                       // Used to define "literals" without spaces, in space-delimited situations
-                       function literalWithoutSpace() {
-                               var result = nOrMore( 1, escapedOrLiteralWithoutSpace )();
-                               return result === null ? null : result.join( '' );
-                       }
-                       // Used to define "literals" within template parameters. The pipe character is the parameter delimeter, so by default
-                       // it is not a literal in the parameter
-                       function literalWithoutBar() {
-                               var result = nOrMore( 1, escapedOrLiteralWithoutBar )();
-                               return result === null ? null : result.join( '' );
-                       }
-
-                       // Used for wikilink page names.  Like literalWithoutBar, but
-                       // without allowing escapes.
-                       function unescapedLiteralWithoutBar() {
-                               var result = nOrMore( 1, regularLiteralWithoutBar )();
-                               return result === null ? null : result.join( '' );
-                       }
-
-                       function literal() {
-                               var result = nOrMore( 1, escapedOrRegularLiteral )();
-                               return result === null ? null : result.join( '' );
-                       }
-
-                       function curlyBraceTransformExpressionLiteral() {
-                               var result = nOrMore( 1, regularLiteralWithSquareBrackets )();
-                               return result === null ? null : result.join( '' );
-                       }
-
-                       asciiAlphabetLiteral = makeRegexParser( /[A-Za-z]+/ );
-                       htmlDoubleQuoteAttributeValue = makeRegexParser( /^[^"]*/ );
-                       htmlSingleQuoteAttributeValue = makeRegexParser( /^[^']*/ );
-
-                       whitespace = makeRegexParser( /^\s+/ );
-                       dollar = makeStringParser( '$' );
-                       digits = makeRegexParser( /^\d+/ );
-
-                       function replacement() {
-                               var result = sequence( [
-                                       dollar,
-                                       digits
-                               ] );
-                               if ( result === null ) {
-                                       return null;
-                               }
-                               return [ 'REPLACE', parseInt( result[1], 10 ) - 1 ];
-                       }
-                       openExtlink = makeStringParser( '[' );
-                       closeExtlink = makeStringParser( ']' );
-                       // this extlink MUST have inner contents, e.g. [foo] not allowed; [foo bar] [foo <i>bar</i>], etc. are allowed
-                       function extlink() {
-                               var result, parsedResult;
-                               result = null;
-                               parsedResult = sequence( [
-                                       openExtlink,
-                                       nonWhitespaceExpression,
-                                       whitespace,
-                                       nOrMore( 1, expression ),
-                                       closeExtlink
-                               ] );
-                               if ( parsedResult !== null ) {
-                                       result = [ 'EXTLINK', parsedResult[1] ];
-                                       // TODO (mattflaschen, 2013-03-22): Clean this up if possible.
-                                       // It's avoiding CONCAT for single nodes, so they at least doesn't get the htmlEmitter span.
-                                       if ( parsedResult[3].length === 1 ) {
-                                               result.push( parsedResult[3][0] );
-                                       } else {
-                                               result.push( ['CONCAT'].concat( parsedResult[3] ) );
-                                       }
-                               }
-                               return result;
-                       }
-                       // this is the same as the above extlink, except that the url is being passed on as a parameter
-                       function extLinkParam() {
-                               var result = sequence( [
-                                       openExtlink,
-                                       dollar,
-                                       digits,
-                                       whitespace,
-                                       expression,
-                                       closeExtlink
-                               ] );
-                               if ( result === null ) {
-                                       return null;
-                               }
-                               return [ 'EXTLINKPARAM', parseInt( result[2], 10 ) - 1, result[4] ];
-                       }
-                       openWikilink = makeStringParser( '[[' );
-                       closeWikilink = makeStringParser( ']]' );
-                       pipe = makeStringParser( '|' );
-
-                       function template() {
-                               var result = sequence( [
-                                       openTemplate,
-                                       templateContents,
-                                       closeTemplate
-                               ] );
-                               return result === null ? null : result[1];
-                       }
-
-                       wikilinkPage = choice( [
-                               unescapedLiteralWithoutBar,
-                               template
-                       ] );
-
-                       function pipedWikilink() {
-                               var result = sequence( [
-                                       wikilinkPage,
-                                       pipe,
-                                       expression
-                               ] );
-                               return result === null ? null : [ result[0], result[2] ];
-                       }
-
-                       wikilinkContents = choice( [
-                               pipedWikilink,
-                               wikilinkPage // unpiped link
-                       ] );
-
-                       function wikilink() {
-                               var result, parsedResult, parsedLinkContents;
-                               result = null;
-
-                               parsedResult = sequence( [
-                                       openWikilink,
-                                       wikilinkContents,
-                                       closeWikilink
-                               ] );
-                               if ( parsedResult !== null ) {
-                                       parsedLinkContents = parsedResult[1];
-                                       result = [ 'WIKILINK' ].concat( parsedLinkContents );
-                               }
-                               return result;
-                       }
-
-                       // TODO: Support data- if appropriate
-                       function doubleQuotedHtmlAttributeValue() {
-                               var parsedResult = sequence( [
-                                       doubleQuote,
-                                       htmlDoubleQuoteAttributeValue,
-                                       doubleQuote
-                               ] );
-                               return parsedResult === null ? null : parsedResult[1];
-                       }
-
-                       function singleQuotedHtmlAttributeValue() {
-                               var parsedResult = sequence( [
-                                       singleQuote,
-                                       htmlSingleQuoteAttributeValue,
-                                       singleQuote
-                               ] );
-                               return parsedResult === null ? null : parsedResult[1];
-                       }
-
-                       function htmlAttribute() {
-                               var parsedResult = sequence( [
-                                       whitespace,
-                                       asciiAlphabetLiteral,
-                                       htmlAttributeEquals,
-                                       choice( [
-                                               doubleQuotedHtmlAttributeValue,
-                                               singleQuotedHtmlAttributeValue
-                                       ] )
-                               ] );
-                               return parsedResult === null ? null : [parsedResult[1], parsedResult[3]];
-                       }
-
-                       /**
-                        * Checks if HTML is allowed
-                        *
-                        * @param {string} startTagName HTML start tag name
-                        * @param {string} endTagName HTML start tag name
-                        * @param {Object} attributes array of consecutive key value pairs,
-                        *  with index 2 * n being a name and 2 * n + 1 the associated value
-                        * @return {boolean} true if this is HTML is allowed, false otherwise
-                        */
-                       function isAllowedHtml( startTagName, endTagName, attributes ) {
-                               var i, len, attributeName;
-
-                               startTagName = startTagName.toLowerCase();
-                               endTagName = endTagName.toLowerCase();
-                               if ( startTagName !== endTagName || $.inArray( startTagName, settings.allowedHtmlElements ) === -1 ) {
-                                       return false;
-                               }
-
-                               for ( i = 0, len = attributes.length; i < len; i += 2 ) {
-                                       attributeName = attributes[i];
-                                       if ( $.inArray( attributeName, settings.allowedHtmlCommonAttributes ) === -1 &&
-                                            $.inArray( attributeName, settings.allowedHtmlAttributesByElement[startTagName] || [] ) === -1 ) {
-                                               return false;
-                                       }
-                               }
-
-                               return true;
-                       }
-
-                       function htmlAttributes() {
-                               var parsedResult = nOrMore( 0, htmlAttribute )();
-                               // Un-nest attributes array due to structure of jQueryMsg operations (see emit).
-                               return concat.apply( ['HTMLATTRIBUTES'], parsedResult );
-                       }
-
-                       // Subset of allowed HTML markup.
-                       // Most elements and many attributes allowed on the server are not supported yet.
-                       function html() {
-                               var result = null, parsedOpenTagResult, parsedHtmlContents,
-                                       parsedCloseTagResult, wrappedAttributes, attributes,
-                                       startTagName, endTagName, startOpenTagPos, startCloseTagPos,
-                                       endOpenTagPos, endCloseTagPos;
-
-                               // Break into three sequence calls.  That should allow accurate reconstruction of the original HTML, and requiring an exact tag name match.
-                               // 1. open through closeHtmlTag
-                               // 2. expression
-                               // 3. openHtmlEnd through close
-                               // This will allow recording the positions to reconstruct if HTML is to be treated as text.
-
-                               startOpenTagPos = pos;
-                               parsedOpenTagResult = sequence( [
-                                       openHtmlStartTag,
-                                       asciiAlphabetLiteral,
-                                       htmlAttributes,
-                                       optionalForwardSlash,
-                                       closeHtmlTag
-                               ] );
-
-                               if ( parsedOpenTagResult === null ) {
-                                       return null;
-                               }
-
-                               endOpenTagPos = pos;
-                               startTagName = parsedOpenTagResult[1];
-
-                               parsedHtmlContents = nOrMore( 0, expression )();
-
-                               startCloseTagPos = pos;
-                               parsedCloseTagResult = sequence( [
-                                       openHtmlEndTag,
-                                       asciiAlphabetLiteral,
-                                       closeHtmlTag
-                               ] );
-
-                               if ( parsedCloseTagResult === null ) {
-                                       // Closing tag failed.  Return the start tag and contents.
-                                       return [ 'CONCAT', input.substring( startOpenTagPos, endOpenTagPos ) ]
-                                               .concat( parsedHtmlContents );
-                               }
-
-                               endCloseTagPos = pos;
-                               endTagName = parsedCloseTagResult[1];
-                               wrappedAttributes = parsedOpenTagResult[2];
-                               attributes = wrappedAttributes.slice( 1 );
-                               if ( isAllowedHtml( startTagName, endTagName, attributes ) ) {
-                                       result = [ 'HTMLELEMENT', startTagName, wrappedAttributes ]
-                                               .concat( parsedHtmlContents );
-                               } else {
-                                       // HTML is not allowed, so contents will remain how
-                                       // it was, while HTML markup at this level will be
-                                       // treated as text
-                                       // E.g. assuming script tags are not allowed:
-                                       //
-                                       // <script>[[Foo|bar]]</script>
-                                       //
-                                       // results in '&lt;script&gt;' and '&lt;/script&gt;'
-                                       // (not treated as an HTML tag), surrounding a fully
-                                       // parsed HTML link.
-                                       //
-                                       // Concatenate everything from the tag, flattening the contents.
-                                       result = [ 'CONCAT', input.substring( startOpenTagPos, endOpenTagPos ) ]
-                                               .concat( parsedHtmlContents, input.substring( startCloseTagPos, endCloseTagPos ) );
-                               }
-
-                               return result;
-                       }
-
-                       templateName = transform(
-                               // see $wgLegalTitleChars
-                               // not allowing : due to the need to catch "PLURAL:$1"
-                               makeRegexParser( /^[ !"$&'()*,.\/0-9;=?@A-Z\^_`a-z~\x80-\xFF+\-]+/ ),
-                               function ( result ) { return result.toString(); }
-                       );
-                       function templateParam() {
-                               var expr, result;
-                               result = sequence( [
-                                       pipe,
-                                       nOrMore( 0, paramExpression )
-                               ] );
-                               if ( result === null ) {
-                                       return null;
-                               }
-                               expr = result[1];
-                               // use a CONCAT operator if there are multiple nodes, otherwise return the first node, raw.
-                               return expr.length > 1 ? [ 'CONCAT' ].concat( expr ) : expr[0];
-                       }
-
-                       function templateWithReplacement() {
-                               var result = sequence( [
-                                       templateName,
-                                       colon,
-                                       replacement
-                               ] );
-                               return result === null ? null : [ result[0], result[2] ];
-                       }
-                       function templateWithOutReplacement() {
-                               var result = sequence( [
-                                       templateName,
-                                       colon,
-                                       paramExpression
-                               ] );
-                               return result === null ? null : [ result[0], result[2] ];
-                       }
-                       function templateWithOutFirstParameter() {
-                               var result = sequence( [
-                                       templateName,
-                                       colon
-                               ] );
-                               return result === null ? null : [ result[0], '' ];
-                       }
-                       colon = makeStringParser( ':' );
-                       templateContents = choice( [
-                               function () {
-                                       var res = sequence( [
-                                               // templates can have placeholders for dynamic replacement eg: {{PLURAL:$1|one car|$1 cars}}
-                                               // or no placeholders eg: {{GRAMMAR:genitive|{{SITENAME}}}
-                                               choice( [ templateWithReplacement, templateWithOutReplacement, templateWithOutFirstParameter ] ),
-                                               nOrMore( 0, templateParam )
-                                       ] );
-                                       return res === null ? null : res[0].concat( res[1] );
-                               },
-                               function () {
-                                       var res = sequence( [
-                                               templateName,
-                                               nOrMore( 0, templateParam )
-                                       ] );
-                                       if ( res === null ) {
-                                               return null;
-                                       }
-                                       return [ res[0] ].concat( res[1] );
-                               }
-                       ] );
-                       openTemplate = makeStringParser( '{{' );
-                       closeTemplate = makeStringParser( '}}' );
-                       nonWhitespaceExpression = choice( [
-                               template,
-                               wikilink,
-                               extLinkParam,
-                               extlink,
-                               replacement,
-                               literalWithoutSpace
-                       ] );
-                       paramExpression = choice( [
-                               template,
-                               wikilink,
-                               extLinkParam,
-                               extlink,
-                               replacement,
-                               literalWithoutBar
-                       ] );
-
-                       expression = choice( [
-                               template,
-                               wikilink,
-                               extLinkParam,
-                               extlink,
-                               replacement,
-                               html,
-                               literal
-                       ] );
-
-                       // Used when only {{-transformation is wanted, for 'text'
-                       // or 'escaped' formats
-                       curlyBraceTransformExpression = choice( [
-                               template,
-                               replacement,
-                               curlyBraceTransformExpressionLiteral
-                       ] );
-
-                       /**
-                        * Starts the parse
-                        *
-                        * @param {Function} rootExpression root parse function
-                        */
-                       function start( rootExpression ) {
-                               var result = nOrMore( 0, rootExpression )();
-                               if ( result === null ) {
-                                       return null;
-                               }
-                               return [ 'CONCAT' ].concat( result );
-                       }
-                       // everything above this point is supposed to be stateless/static, but
-                       // I am deferring the work of turning it into prototypes & objects. It's quite fast enough
-                       // finally let's do some actual work...
-
-                       // If you add another possible rootExpression, you must update the astCache key scheme.
-                       result = start( this.settings.onlyCurlyBraceTransform ? curlyBraceTransformExpression : expression );
-
-                       /*
-                        * For success, the p must have gotten to the end of the input
-                        * and returned a non-null.
-                        * n.b. This is part of language infrastructure, so we do not throw an internationalizable message.
-                        */
-                       if ( result === null || pos !== input.length ) {
-                               throw new Error( 'Parse error at position ' + pos.toString() + ' in input: ' + input );
-                       }
-                       return result;
-               }
-
-       };
-
-       /**
-        * htmlEmitter - object which primarily exists to emit HTML from parser ASTs
-        */
-       mw.jqueryMsg.htmlEmitter = function ( language, magic ) {
-               this.language = language;
-               var jmsg = this;
-               $.each( magic, function ( key, val ) {
-                       jmsg[ key.toLowerCase() ] = function () {
-                               return val;
-                       };
-               } );
-
-               /**
-                * (We put this method definition here, and not in prototype, to make sure it's not overwritten by any magic.)
-                * Walk entire node structure, applying replacements and template functions when appropriate
-                * @param {Mixed} node Abstract syntax tree (top node or subnode)
-                * @param {Array} replacements for $1, $2, ... $n
-                * @return {Mixed} single-string node or array of nodes suitable for jQuery appending
-                */
-               this.emit = function ( node, replacements ) {
-                       var ret, subnodes, operation,
-                               jmsg = this;
-                       switch ( typeof node ) {
-                               case 'string':
-                               case 'number':
-                                       ret = node;
-                                       break;
-                               // typeof returns object for arrays
-                               case 'object':
-                                       // node is an array of nodes
-                                       subnodes = $.map( node.slice( 1 ), function ( n ) {
-                                               return jmsg.emit( n, replacements );
-                                       } );
-                                       operation = node[0].toLowerCase();
-                                       if ( typeof jmsg[operation] === 'function' ) {
-                                               ret = jmsg[ operation ]( subnodes, replacements );
-                                       } else {
-                                               throw new Error( 'Unknown operation "' + operation + '"' );
-                                       }
-                                       break;
-                               case 'undefined':
-                                       // Parsing the empty string (as an entire expression, or as a paramExpression in a template) results in undefined
-                                       // Perhaps a more clever parser can detect this, and return the empty string? Or is that useful information?
-                                       // The logical thing is probably to return the empty string here when we encounter undefined.
-                                       ret = '';
-                                       break;
-                               default:
-                                       throw new Error( 'Unexpected type in AST: ' + typeof node );
-                       }
-                       return ret;
-               };
-       };
-
-       // For everything in input that follows double-open-curly braces, there should be an equivalent parser
-       // function. For instance {{PLURAL ... }} will be processed by 'plural'.
-       // If you have 'magic words' then configure the parser to have them upon creation.
-       //
-       // An emitter method takes the parent node, the array of subnodes and the array of replacements (the values that $1, $2... should translate to).
-       // Note: all such functions must be pure, with the exception of referring to other pure functions via this.language (convertPlural and so on)
-       mw.jqueryMsg.htmlEmitter.prototype = {
-               /**
-                * Parsing has been applied depth-first we can assume that all nodes here are single nodes
-                * Must return a single node to parents -- a jQuery with synthetic span
-                * However, unwrap any other synthetic spans in our children and pass them upwards
-                * @param {Mixed[]} nodes Some single nodes, some arrays of nodes
-                * @return {jQuery}
-                */
-               concat: function ( nodes ) {
-                       var $span = $( '<span>' ).addClass( 'mediaWiki_htmlEmitter' );
-                       $.each( nodes, function ( i, node ) {
-                               if ( node instanceof jQuery && node.hasClass( 'mediaWiki_htmlEmitter' ) ) {
-                                       $.each( node.contents(), function ( j, childNode ) {
-                                               appendWithoutParsing( $span, childNode );
-                                       } );
-                               } else {
-                                       // Let jQuery append nodes, arrays of nodes and jQuery objects
-                                       // other things (strings, numbers, ..) are appended as text nodes (not as HTML strings)
-                                       appendWithoutParsing( $span, node );
-                               }
-                       } );
-                       return $span;
-               },
-
-               /**
-                * Return escaped replacement of correct index, or string if unavailable.
-                * Note that we expect the parsed parameter to be zero-based. i.e. $1 should have become [ 0 ].
-                * if the specified parameter is not found return the same string
-                * (e.g. "$99" -> parameter 98 -> not found -> return "$99" )
-                *
-                * TODO: Throw error if nodes.length > 1 ?
-                *
-                * @param {Array} nodes List of one element, integer, n >= 0
-                * @param {Array} replacements List of at least n strings
-                * @return {String} replacement
-                */
-               replace: function ( nodes, replacements ) {
-                       var index = parseInt( nodes[0], 10 );
-
-                       if ( index < replacements.length ) {
-                               return replacements[index];
-                       } else {
-                               // index not found, fallback to displaying variable
-                               return '$' + ( index + 1 );
-                       }
-               },
-
-               /**
-                * Transform wiki-link
-                *
-                * TODO:
-                * It only handles basic cases, either no pipe, or a pipe with an explicit
-                * anchor.
-                *
-                * It does not attempt to handle features like the pipe trick.
-                * However, the pipe trick should usually not be present in wikitext retrieved
-                * from the server, since the replacement is done at save time.
-                * It may, though, if the wikitext appears in extension-controlled content.
-                *
-                * @param nodes
-                */
-               wikilink: function ( nodes ) {
-                       var page, anchor, url;
-
-                       page = nodes[0];
-                       url = mw.util.getUrl( page );
-
-                       // [[Some Page]] or [[Namespace:Some Page]]
-                       if ( nodes.length === 1 ) {
-                               anchor = page;
-                       }
-
-                       /*
-                        * [[Some Page|anchor text]] or
-                        * [[Namespace:Some Page|anchor]
-                        */
-                       else {
-                               anchor = nodes[1];
-                       }
-
-                       return $( '<a>' ).attr( {
-                               title: page,
-                               href: url
-                       } ).text( anchor );
-               },
-
-               /**
-                * Converts array of HTML element key value pairs to object
-                *
-                * @param {Array} nodes Array of consecutive key value pairs, with index 2 * n being a
-                *  name and 2 * n + 1 the associated value
-                * @return {Object} Object mapping attribute name to attribute value
-                */
-               htmlattributes: function ( nodes ) {
-                       var i, len, mapping = {};
-                       for ( i = 0, len = nodes.length; i < len; i += 2 ) {
-                               mapping[nodes[i]] = decodePrimaryHtmlEntities( nodes[i + 1] );
-                       }
-                       return mapping;
-               },
-
-               /**
-                * Handles an (already-validated) HTML element.
-                *
-                * @param {Array} nodes Nodes to process when creating element
-                * @return {jQuery|Array} jQuery node for valid HTML or array for disallowed element
-                */
-               htmlelement: function ( nodes ) {
-                       var tagName, attributes, contents, $element;
-
-                       tagName = nodes.shift();
-                       attributes = nodes.shift();
-                       contents = nodes;
-                       $element = $( document.createElement( tagName ) ).attr( attributes );
-                       return appendWithoutParsing( $element, contents );
-               },
-
-               /**
-                * Transform parsed structure into external link
-                * If the href is a jQuery object, treat it as "enclosing" the link text.
-                *
-                * - ... function, treat it as the click handler.
-                * - ... string, treat it as a URI.
-                *
-                * TODO: throw an error if nodes.length > 2 ?
-                *
-                * @param {Array} nodes List of two elements, {jQuery|Function|String} and {String}
-                * @return {jQuery}
-                */
-               extlink: function ( nodes ) {
-                       var $el,
-                               arg = nodes[0],
-                               contents = nodes[1];
-                       if ( arg instanceof jQuery ) {
-                               $el = arg;
-                       } else {
-                               $el = $( '<a>' );
-                               if ( typeof arg === 'function' ) {
-                                       $el.click( arg ).attr( 'href', '#' );
-                               } else {
-                                       $el.attr( 'href', arg.toString() );
-                               }
-                       }
-                       return appendWithoutParsing( $el, contents );
-               },
-
-               /**
-                * This is basically use a combination of replace + external link (link with parameter
-                * as url), but we don't want to run the regular replace here-on: inserting a
-                * url as href-attribute of a link will automatically escape it already, so
-                * we don't want replace to (manually) escape it as well.
-                *
-                * TODO: throw error if nodes.length > 1 ?
-                *
-                * @param {Array} nodes List of one element, integer, n >= 0
-                * @param {Array} replacements List of at least n strings
-                * @return {string} replacement
-                */
-               extlinkparam: function ( nodes, replacements ) {
-                       var replacement,
-                               index = parseInt( nodes[0], 10 );
-                       if ( index < replacements.length ) {
-                               replacement = replacements[index];
-                       } else {
-                               replacement = '$' + ( index + 1 );
-                       }
-                       return this.extlink( [ replacement, nodes[1] ] );
-               },
-
-               /**
-                * Transform parsed structure into pluralization
-                * n.b. The first node may be a non-integer (for instance, a string representing an Arabic number).
-                * So convert it back with the current language's convertNumber.
-                * @param {Array} nodes List of nodes, [ {string|number}, {string}, {string} ... ]
-                * @return {string} selected pluralized form according to current language
-                */
-               plural: function ( nodes ) {
-                       var forms, count;
-                       count = parseFloat( this.language.convertNumber( nodes[0], true ) );
-                       forms = nodes.slice( 1 );
-                       return forms.length ? this.language.convertPlural( count, forms ) : '';
-               },
-
-               /**
-                * Transform parsed structure according to gender.
-                *
-                * Usage: {{gender:[ mw.user object | '' | 'male' | 'female' | 'unknown' ] | masculine form | feminine form | neutral form}}.
-                *
-                * The first node must be one of:
-                * - the mw.user object (or a compatible one)
-                * - an empty string - indicating the current user, same effect as passing the mw.user object
-                * - a gender string ('male', 'female' or 'unknown')
-                *
-                * @param {Array} nodes List of nodes, [ {string|mw.user}, {string}, {string}, {string} ]
-                * @return {string} Selected gender form according to current language
-                */
-               gender: function ( nodes ) {
-                       var gender,
-                               maybeUser = nodes[0],
-                               forms = nodes.slice( 1 );
-
-                       if ( maybeUser === '' ) {
-                               maybeUser = mw.user;
-                       }
-
-                       // If we are passed a mw.user-like object, check their gender.
-                       // Otherwise, assume the gender string itself was passed .
-                       if ( maybeUser && maybeUser.options instanceof mw.Map ) {
-                               gender = maybeUser.options.get( 'gender' );
-                       } else {
-                               gender = maybeUser;
-                       }
-
-                       return this.language.gender( gender, forms );
-               },
-
-               /**
-                * Transform parsed structure into grammar conversion.
-                * Invoked by putting `{{grammar:form|word}}` in a message
-                * @param {Array} nodes List of nodes [{Grammar case eg: genitive}, {string word}]
-                * @return {string} selected grammatical form according to current language
-                */
-               grammar: function ( nodes ) {
-                       var form = nodes[0],
-                               word = nodes[1];
-                       return word && form && this.language.convertGrammar( word, form );
-               },
-
-               /**
-                * Tranform parsed structure into a int: (interface language) message include
-                * Invoked by putting `{{int:othermessage}}` into a message
-                * @param {Array} nodes List of nodes
-                * @return {string} Other message
-                */
-               int: function ( nodes ) {
-                       return mw.jqueryMsg.getMessageFunction()( nodes[0].toLowerCase() );
-               },
-
-               /**
-                * Takes an unformatted number (arab, no group separators and . as decimal separator)
-                * and outputs it in the localized digit script and formatted with decimal
-                * separator, according to the current language.
-                * @param {Array} nodes List of nodes
-                * @return {number|string} Formatted number
-                */
-               formatnum: function ( nodes ) {
-                       var isInteger = ( nodes[1] && nodes[1] === 'R' ) ? true : false,
-                               number = nodes[0];
-
-                       return this.language.convertNumber( number, isInteger );
-               }
-       };
-
-       // Deprecated! don't rely on gM existing.
-       // The window.gM ought not to be required - or if required, not required here.
-       // But moving it to extensions breaks it (?!)
-       // Need to fix plugin so it could do attributes as well, then will be okay to remove this.
-       // @deprecated since 1.23
-       mw.log.deprecate( window, 'gM', mw.jqueryMsg.getMessageFunction(), 'Use mw.message( ... ).parse() instead' );
-
-       /**
-        * @method
-        * @member jQuery
-        * @see mw.jqueryMsg#getPlugin
-        */
-       $.fn.msg = mw.jqueryMsg.getPlugin();
-
-       // Replace the default message parser with jqueryMsg
-       oldParser = mw.Message.prototype.parser;
-       mw.Message.prototype.parser = function () {
-               var messageFunction;
-
-               // TODO: should we cache the message function so we don't create a new one every time? Benchmark this maybe?
-               // Caching is somewhat problematic, because we do need different message functions for different maps, so
-               // we'd have to cache the parser as a member of this.map, which sounds a bit ugly.
-               // Do not use mw.jqueryMsg unless required
-               if ( this.format === 'plain' || !/\{\{|[\[<>]/.test( this.map.get( this.key ) ) ) {
-                       // Fall back to mw.msg's simple parser
-                       return oldParser.apply( this );
-               }
-
-               messageFunction = mw.jqueryMsg.getMessageFunction( {
-                       'messages': this.map,
-                       // For format 'escaped', escaping part is handled by mediawiki.js
-                       'format': this.format
-               } );
-               return messageFunction( this.key, this.parameters );
-       };
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.jqueryMsg.peg b/resources/mediawiki/mediawiki.jqueryMsg.peg
deleted file mode 100644 (file)
index 716c326..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* PEG grammar for a subset of wikitext, useful in the MediaWiki frontend */
-
-start
-  = e:expression* { return e.length > 1 ? [ "CONCAT" ].concat(e) : e[0]; }
-
-expression
-  = template
-  / link
-  / extlink
-  / replacement
-  / literal
-
-paramExpression
-  = template
-  / link
-  / extlink
-  / replacement
-  / literalWithoutBar
-
-template
-  = "{{" t:templateContents "}}" { return t; }
-
-templateContents
-  = twr:templateWithReplacement p:templateParam* { return twr.concat(p) }
-  / twr:templateWithOutReplacement p:templateParam* { return twr.concat(p) }
-  / twr:templateWithOutFirstParameter p:templateParam* { return twr.concat(p) }
-  / t:templateName p:templateParam* { return p.length ? [ t, p ] : [ t ] }
-
-templateWithReplacement
-  = t:templateName ":" r:replacement { return [ t, r ] }
-
-templateWithOutReplacement
-  = t:templateName ":" p:paramExpression { return [ t, p ] }
-
-templateWithOutFirstParameter
-  = t:templateName ":" { return [ t, "" ] }
-
-templateParam
-  = "|" e:paramExpression* { return e.length > 1 ? [ "CONCAT" ].concat(e) : e[0]; }
-
-templateName
-  = tn:[A-Za-z_]+ { return tn.join('').toUpperCase() }
-
-/* TODO: Update to reflect separate piped and unpiped handling */
-link
-  = "[[" w:expression "]]" { return [ 'WLINK', w ]; }
-
-extlink
-  = "[" url:url whitespace text:expression "]" { return [ 'LINK', url, text ] }
-
-url
-  = url:[^ ]+ { return url.join(''); }
-
-whitespace
-  = [ ]+
-
-replacement
-  = '$' digits:digits { return [ 'REPLACE', parseInt( digits, 10 ) - 1 ] }
-
-digits
-  = [0-9]+
-
-literal
-  = lit:escapedOrRegularLiteral+ { return lit.join(''); }
-
-literalWithoutBar
-  = lit:escapedOrLiteralWithoutBar+ { return lit.join(''); }
-
-escapedOrRegularLiteral
-  = escapedLiteral
-  / regularLiteral
-
-escapedOrLiteralWithoutBar
-  = escapedLiteral
-  / regularLiteralWithoutBar
-
-escapedLiteral
-  = "\\" escaped:. { return escaped; }
-
-regularLiteral
-  = [^{}\[\]$\\]
-
-regularLiteralWithoutBar
-  = [^{}\[\]$\\|]
-
diff --git a/resources/mediawiki/mediawiki.js b/resources/mediawiki/mediawiki.js
deleted file mode 100644 (file)
index d8a17f6..0000000
+++ /dev/null
@@ -1,2413 +0,0 @@
-/**
- * Base library for MediaWiki.
- *
- * Exposed as globally as `mediaWiki` with `mw` as shortcut.
- *
- * @class mw
- * @alternateClassName mediaWiki
- * @singleton
- */
-
-var mw = ( function ( $, undefined ) {
-       'use strict';
-
-       /* Private Members */
-
-       var hasOwn = Object.prototype.hasOwnProperty,
-               slice = Array.prototype.slice,
-               trackCallbacks = $.Callbacks( 'memory' ),
-               trackQueue = [];
-
-       /**
-        * Log a message to window.console, if possible. Useful to force logging of some
-        * errors that are otherwise hard to detect (I.e., this logs also in production mode).
-        * Gets console references in each invocation, so that delayed debugging tools work
-        * fine. No need for optimization here, which would only result in losing logs.
-        *
-        * @private
-        * @method log_
-        * @param {string} msg text for the log entry.
-        * @param {Error} [e]
-        */
-       function log( msg, e ) {
-               var console = window.console;
-               if ( console && console.log ) {
-                       console.log( msg );
-                       // If we have an exception object, log it through .error() to trigger
-                       // proper stacktraces in browsers that support it. There are no (known)
-                       // browsers that don't support .error(), that do support .log() and
-                       // have useful exception handling through .log().
-                       if ( e && console.error ) {
-                               console.error( String( e ), e );
-                       }
-               }
-       }
-
-       /* Object constructors */
-
-       /**
-        * Creates an object that can be read from or written to from prototype functions
-        * that allow both single and multiple variables at once.
-        *
-        *     @example
-        *
-        *     var addies, wanted, results;
-        *
-        *     // Create your address book
-        *     addies = new mw.Map();
-        *
-        *     // This data could be coming from an external source (eg. API/AJAX)
-        *     addies.set( {
-        *         'John Doe' : '10 Wall Street, New York, USA',
-        *         'Jane Jackson' : '21 Oxford St, London, UK',
-        *         'Dominique van Halen' : 'Kalverstraat 7, Amsterdam, NL'
-        *     } );
-        *
-        *     wanted = ['Dominique van Halen', 'George Johnson', 'Jane Jackson'];
-        *
-        *     // You can detect missing keys first
-        *     if ( !addies.exists( wanted ) ) {
-        *         // One or more are missing (in this case: "George Johnson")
-        *         mw.log( 'One or more names were not found in your address book' );
-        *     }
-        *
-        *     // Or just let it give you what it can
-        *     results = addies.get( wanted, 'Middle of Nowhere, Alaska, US' );
-        *     mw.log( results['Jane Jackson'] ); // "21 Oxford St, London, UK"
-        *     mw.log( results['George Johnson'] ); // "Middle of Nowhere, Alaska, US"
-        *
-        * @class mw.Map
-        *
-        * @constructor
-        * @param {Object|boolean} [values] Value-bearing object to map, or boolean
-        *  true to map over the global object. Defaults to an empty object.
-        */
-       function Map( values ) {
-               this.values = values === true ? window : ( values || {} );
-               return this;
-       }
-
-       Map.prototype = {
-               /**
-                * Get the value of one or multiple a keys.
-                *
-                * If called with no arguments, all values will be returned.
-                *
-                * @param {string|Array} selection String key or array of keys to get values for.
-                * @param {Mixed} [fallback] Value to use in case key(s) do not exist.
-                * @return mixed If selection was a string returns the value or null,
-                *  If selection was an array, returns an object of key/values (value is null if not found),
-                *  If selection was not passed or invalid, will return the 'values' object member (be careful as
-                *  objects are always passed by reference in JavaScript!).
-                * @return {string|Object|null} Values as a string or object, null if invalid/inexistant.
-                */
-               get: function ( selection, fallback ) {
-                       var results, i;
-                       // If we only do this in the `return` block, it'll fail for the
-                       // call to get() from the mutli-selection block.
-                       fallback = arguments.length > 1 ? fallback : null;
-
-                       if ( $.isArray( selection ) ) {
-                               selection = slice.call( selection );
-                               results = {};
-                               for ( i = 0; i < selection.length; i++ ) {
-                                       results[selection[i]] = this.get( selection[i], fallback );
-                               }
-                               return results;
-                       }
-
-                       if ( typeof selection === 'string' ) {
-                               if ( !hasOwn.call( this.values, selection ) ) {
-                                       return fallback;
-                               }
-                               return this.values[selection];
-                       }
-
-                       if ( selection === undefined ) {
-                               return this.values;
-                       }
-
-                       // invalid selection key
-                       return null;
-               },
-
-               /**
-                * Sets one or multiple key/value pairs.
-                *
-                * @param {string|Object} selection String key to set value for, or object mapping keys to values.
-                * @param {Mixed} [value] Value to set (optional, only in use when key is a string)
-                * @return {Boolean} This returns true on success, false on failure.
-                */
-               set: function ( selection, value ) {
-                       var s;
-
-                       if ( $.isPlainObject( selection ) ) {
-                               for ( s in selection ) {
-                                       this.values[s] = selection[s];
-                               }
-                               return true;
-                       }
-                       if ( typeof selection === 'string' && arguments.length > 1 ) {
-                               this.values[selection] = value;
-                               return true;
-                       }
-                       return false;
-               },
-
-               /**
-                * Checks if one or multiple keys exist.
-                *
-                * @param {Mixed} selection String key or array of keys to check
-                * @return {boolean} Existence of key(s)
-                */
-               exists: function ( selection ) {
-                       var s;
-
-                       if ( $.isArray( selection ) ) {
-                               for ( s = 0; s < selection.length; s++ ) {
-                                       if ( typeof selection[s] !== 'string' || !hasOwn.call( this.values, selection[s] ) ) {
-                                               return false;
-                                       }
-                               }
-                               return true;
-                       }
-                       return typeof selection === 'string' && hasOwn.call( this.values, selection );
-               }
-       };
-
-       /**
-        * Object constructor for messages.
-        *
-        * Similar to the Message class in MediaWiki PHP.
-        *
-        * Format defaults to 'text'.
-        *
-        *     @example
-        *
-        *     var obj, str;
-        *     mw.messages.set( {
-        *         'hello': 'Hello world',
-        *         'hello-user': 'Hello, $1!',
-        *         'welcome-user': 'Welcome back to $2, $1! Last visit by $1: $3'
-        *     } );
-        *
-        *     obj = new mw.Message( mw.messages, 'hello' );
-        *     mw.log( obj.text() );
-        *     // Hello world
-        *
-        *     obj = new mw.Message( mw.messages, 'hello-user', [ 'John Doe' ] );
-        *     mw.log( obj.text() );
-        *     // Hello, John Doe!
-        *
-        *     obj = new mw.Message( mw.messages, 'welcome-user', [ 'John Doe', 'Wikipedia', '2 hours ago' ] );
-        *     mw.log( obj.text() );
-        *     // Welcome back to Wikipedia, John Doe! Last visit by John Doe: 2 hours ago
-        *
-        *     // Using mw.message shortcut
-        *     obj = mw.message( 'hello-user', 'John Doe' );
-        *     mw.log( obj.text() );
-        *     // Hello, John Doe!
-        *
-        *     // Using mw.msg shortcut
-        *     str = mw.msg( 'hello-user', 'John Doe' );
-        *     mw.log( str );
-        *     // Hello, John Doe!
-        *
-        *     // Different formats
-        *     obj = new mw.Message( mw.messages, 'hello-user', [ 'John "Wiki" <3 Doe' ] );
-        *
-        *     obj.format = 'text';
-        *     str = obj.toString();
-        *     // Same as:
-        *     str = obj.text();
-        *
-        *     mw.log( str );
-        *     // Hello, John "Wiki" <3 Doe!
-        *
-        *     mw.log( obj.escaped() );
-        *     // Hello, John &quot;Wiki&quot; &lt;3 Doe!
-        *
-        * @class mw.Message
-        *
-        * @constructor
-        * @param {mw.Map} map Message storage
-        * @param {string} key
-        * @param {Array} [parameters]
-        */
-       function Message( map, key, parameters ) {
-               this.format = 'text';
-               this.map = map;
-               this.key = key;
-               this.parameters = parameters === undefined ? [] : slice.call( parameters );
-               return this;
-       }
-
-       Message.prototype = {
-               /**
-                * Simple message parser, does $N replacement and nothing else.
-                *
-                * This may be overridden to provide a more complex message parser.
-                *
-                * The primary override is in mediawiki.jqueryMsg.
-                *
-                * This function will not be called for nonexistent messages.
-                */
-               parser: function () {
-                       var parameters = this.parameters;
-                       return this.map.get( this.key ).replace( /\$(\d+)/g, function ( str, match ) {
-                               var index = parseInt( match, 10 ) - 1;
-                               return parameters[index] !== undefined ? parameters[index] : '$' + match;
-                       } );
-               },
-
-               /**
-                * Appends (does not replace) parameters for replacement to the .parameters property.
-                *
-                * @param {Array} parameters
-                * @chainable
-                */
-               params: function ( parameters ) {
-                       var i;
-                       for ( i = 0; i < parameters.length; i += 1 ) {
-                               this.parameters.push( parameters[i] );
-                       }
-                       return this;
-               },
-
-               /**
-                * Converts message object to its string form based on the state of format.
-                *
-                * @return {string} Message as a string in the current form or `<key>` if key does not exist.
-                */
-               toString: function () {
-                       var text;
-
-                       if ( !this.exists() ) {
-                               // Use <key> as text if key does not exist
-                               if ( this.format === 'escaped' || this.format === 'parse' ) {
-                                       // format 'escaped' and 'parse' need to have the brackets and key html escaped
-                                       return mw.html.escape( '<' + this.key + '>' );
-                               }
-                               return '<' + this.key + '>';
-                       }
-
-                       if ( this.format === 'plain' || this.format === 'text' || this.format === 'parse' ) {
-                               text = this.parser();
-                       }
-
-                       if ( this.format === 'escaped' ) {
-                               text = this.parser();
-                               text = mw.html.escape( text );
-                       }
-
-                       return text;
-               },
-
-               /**
-                * Changes format to 'parse' and converts message to string
-                *
-                * If jqueryMsg is loaded, this parses the message text from wikitext
-                * (where supported) to HTML
-                *
-                * Otherwise, it is equivalent to plain.
-                *
-                * @return {string} String form of parsed message
-                */
-               parse: function () {
-                       this.format = 'parse';
-                       return this.toString();
-               },
-
-               /**
-                * Changes format to 'plain' and converts message to string
-                *
-                * This substitutes parameters, but otherwise does not change the
-                * message text.
-                *
-                * @return {string} String form of plain message
-                */
-               plain: function () {
-                       this.format = 'plain';
-                       return this.toString();
-               },
-
-               /**
-                * Changes format to 'text' and converts message to string
-                *
-                * If jqueryMsg is loaded, {{-transformation is done where supported
-                * (such as {{plural:}}, {{gender:}}, {{int:}}).
-                *
-                * Otherwise, it is equivalent to plain.
-                */
-               text: function () {
-                       this.format = 'text';
-                       return this.toString();
-               },
-
-               /**
-                * Changes the format to 'escaped' and converts message to string
-                *
-                * This is equivalent to using the 'text' format (see text method), then
-                * HTML-escaping the output.
-                *
-                * @return {string} String form of html escaped message
-                */
-               escaped: function () {
-                       this.format = 'escaped';
-                       return this.toString();
-               },
-
-               /**
-                * Checks if message exists
-                *
-                * @see mw.Map#exists
-                * @return {boolean}
-                */
-               exists: function () {
-                       return this.map.exists( this.key );
-               }
-       };
-
-       /**
-        * @class mw
-        */
-       return {
-               /* Public Members */
-
-               /**
-                * Get the current time, measured in milliseconds since January 1, 1970 (UTC).
-                *
-                * On browsers that implement the Navigation Timing API, this function will produce floating-point
-                * values with microsecond precision that are guaranteed to be monotonic. On all other browsers,
-                * it will fall back to using `Date`.
-                *
-                * @return {number} Current time
-                */
-               now: ( function () {
-                       var perf = window.performance,
-                               navStart = perf && perf.timing && perf.timing.navigationStart;
-                       return navStart && typeof perf.now === 'function' ?
-                               function () { return navStart + perf.now(); } :
-                               function () { return +new Date(); };
-               }() ),
-
-               /**
-                * Track an analytic event.
-                *
-                * This method provides a generic means for MediaWiki JavaScript code to capture state
-                * information for analysis. Each logged event specifies a string topic name that describes
-                * the kind of event that it is. Topic names consist of dot-separated path components,
-                * arranged from most general to most specific. Each path component should have a clear and
-                * well-defined purpose.
-                *
-                * Data handlers are registered via `mw.trackSubscribe`, and receive the full set of
-                * events that match their subcription, including those that fired before the handler was
-                * bound.
-                *
-                * @param {string} topic Topic name
-                * @param {Object} [data] Data describing the event, encoded as an object
-                */
-               track: function ( topic, data ) {
-                       trackQueue.push( { topic: topic, timeStamp: mw.now(), data: data } );
-                       trackCallbacks.fire( trackQueue );
-               },
-
-               /**
-                * Register a handler for subset of analytic events, specified by topic
-                *
-                * Handlers will be called once for each tracked event, including any events that fired before the
-                * handler was registered; 'this' is set to a plain object with a 'timeStamp' property indicating
-                * the exact time at which the event fired, a string 'topic' property naming the event, and a
-                * 'data' property which is an object of event-specific data. The event topic and event data are
-                * also passed to the callback as the first and second arguments, respectively.
-                *
-                * @param {string} topic Handle events whose name starts with this string prefix
-                * @param {Function} callback Handler to call for each matching tracked event
-                */
-               trackSubscribe: function ( topic, callback ) {
-                       var seen = 0;
-
-                       trackCallbacks.add( function ( trackQueue ) {
-                               var event;
-                               for ( ; seen < trackQueue.length; seen++ ) {
-                                       event = trackQueue[ seen ];
-                                       if ( event.topic.indexOf( topic ) === 0 ) {
-                                               callback.call( event, event.topic, event.data );
-                                       }
-                               }
-                       } );
-               },
-
-               // Make the Map constructor publicly available.
-               Map: Map,
-
-               // Make the Message constructor publicly available.
-               Message: Message,
-
-               /**
-                * Map of configuration values
-                *
-                * Check out [the complete list of configuration values](https://www.mediawiki.org/wiki/Manual:Interface/JavaScript#mw.config)
-                * on mediawiki.org.
-                *
-                * If `$wgLegacyJavaScriptGlobals` is true, this Map will add its values to the
-                * global `window` object.
-                *
-                * @property {mw.Map} config
-                */
-               // Dummy placeholder. Re-assigned in ResourceLoaderStartupModule to an instance of `mw.Map`.
-               config: null,
-
-               /**
-                * Empty object that plugins can be installed in.
-                * @property
-                */
-               libs: {},
-
-               /**
-                * Access container for deprecated functionality that can be moved from
-                * from their legacy location and attached to this object (e.g. a global
-                * function that is deprecated and as stop-gap can be exposed through here).
-                *
-                * This was reserved for future use but never ended up being used.
-                *
-                * @deprecated since 1.22: Let deprecated identifiers keep their original name
-                *  and use mw.log#deprecate to create an access container for tracking.
-                * @property
-                */
-               legacy: {},
-
-               /**
-                * Localization system
-                * @property {mw.Map}
-                */
-               messages: new Map(),
-
-               /* Public Methods */
-
-               /**
-                * Get a message object.
-                *
-                * Shorcut for `new mw.Message( mw.messages, key, parameters )`.
-                *
-                * @see mw.Message
-                * @param {string} key Key of message to get
-                * @param {Mixed...} parameters Parameters for the $N replacements in messages.
-                * @return {mw.Message}
-                */
-               message: function ( key ) {
-                       // Variadic arguments
-                       var parameters = slice.call( arguments, 1 );
-                       return new Message( mw.messages, key, parameters );
-               },
-
-               /**
-                * Get a message string using the (default) 'text' format.
-                *
-                * Shortcut for `mw.message( key, parameters... ).text()`.
-                *
-                * @see mw.Message
-                * @param {string} key Key of message to get
-                * @param {Mixed...} parameters Parameters for the $N replacements in messages.
-                * @return {string}
-                */
-               msg: function () {
-                       return mw.message.apply( mw.message, arguments ).toString();
-               },
-
-               /**
-                * Dummy placeholder for {@link mw.log}
-                * @method
-                */
-               log: ( function () {
-                       // Also update the restoration of methods in mediawiki.log.js
-                       // when adding or removing methods here.
-                       var log = function () {};
-
-                       /**
-                        * @class mw.log
-                        * @singleton
-                        */
-
-                       /**
-                        * Write a message the console's warning channel.
-                        * Also logs a stacktrace for easier debugging.
-                        * Each action is silently ignored if the browser doesn't support it.
-                        *
-                        * @param {string...} msg Messages to output to console
-                        */
-                       log.warn = function () {
-                               var console = window.console;
-                               if ( console && console.warn ) {
-                                       console.warn.apply( console, arguments );
-                                       if ( console.trace ) {
-                                               console.trace();
-                                       }
-                               }
-                       };
-
-                       /**
-                        * Create a property in a host object that, when accessed, will produce
-                        * a deprecation warning in the console with backtrace.
-                        *
-                        * @param {Object} obj Host object of deprecated property
-                        * @param {string} key Name of property to create in `obj`
-                        * @param {Mixed} val The value this property should return when accessed
-                        * @param {string} [msg] Optional text to include in the deprecation message.
-                        */
-                       log.deprecate = !Object.defineProperty ? function ( obj, key, val ) {
-                               obj[key] = val;
-                       } : function ( obj, key, val, msg ) {
-                               msg = 'Use of "' + key + '" is deprecated.' + ( msg ? ( ' ' + msg ) : '' );
-                               try {
-                                       Object.defineProperty( obj, key, {
-                                               configurable: true,
-                                               enumerable: true,
-                                               get: function () {
-                                                       mw.track( 'mw.deprecate', key );
-                                                       mw.log.warn( msg );
-                                                       return val;
-                                               },
-                                               set: function ( newVal ) {
-                                                       mw.track( 'mw.deprecate', key );
-                                                       mw.log.warn( msg );
-                                                       val = newVal;
-                                               }
-                                       } );
-                               } catch ( err ) {
-                                       // IE8 can throw on Object.defineProperty
-                                       obj[key] = val;
-                               }
-                       };
-
-                       return log;
-               }() ),
-
-               /**
-                * Client-side module loader which integrates with the MediaWiki ResourceLoader
-                * @class mw.loader
-                * @singleton
-                */
-               loader: ( function () {
-
-                       /* Private Members */
-
-                       /**
-                        * Mapping of registered modules
-                        *
-                        * The jquery module is pre-registered, because it must have already
-                        * been provided for this object to have been built, and in debug mode
-                        * jquery would have been provided through a unique loader request,
-                        * making it impossible to hold back registration of jquery until after
-                        * mediawiki.
-                        *
-                        * For exact details on support for script, style and messages, look at
-                        * mw.loader.implement.
-                        *
-                        * Format:
-                        *     {
-                        *         'moduleName': {
-                        *             'version': ############## (unix timestamp),
-                        *             'dependencies': ['required.foo', 'bar.also', ...], (or) function () {}
-                        *             'group': 'somegroup', (or) null,
-                        *             'source': 'local', 'someforeignwiki', (or) null
-                        *             'state': 'registered', 'loaded', 'loading', 'ready', 'error' or 'missing'
-                        *             'script': ...,
-                        *             'style': ...,
-                        *             'messages': { 'key': 'value' },
-                        *         }
-                        *     }
-                        *
-                        * @property
-                        * @private
-                        */
-                       var registry = {},
-                               //
-                               // Mapping of sources, keyed by source-id, values are objects.
-                               // Format:
-                               //      {
-                               //              'sourceId': {
-                               //                      'loadScript': 'http://foo.bar/w/load.php'
-                               //              }
-                               //      }
-                               //
-                               sources = {},
-                               // List of modules which will be loaded as when ready
-                               batch = [],
-                               // List of modules to be loaded
-                               queue = [],
-                               // List of callback functions waiting for modules to be ready to be called
-                               jobs = [],
-                               // Selector cache for the marker element. Use getMarker() to get/use the marker!
-                               $marker = null,
-                               // Buffer for addEmbeddedCSS.
-                               cssBuffer = '',
-                               // Callbacks for addEmbeddedCSS.
-                               cssCallbacks = $.Callbacks();
-
-                       /* Private methods */
-
-                       function getMarker() {
-                               // Cached ?
-                               if ( $marker ) {
-                                       return $marker;
-                               }
-
-                               $marker = $( 'meta[name="ResourceLoaderDynamicStyles"]' );
-                               if ( $marker.length ) {
-                                       return $marker;
-                               }
-                               mw.log( 'getMarker> No <meta name="ResourceLoaderDynamicStyles"> found, inserting dynamically.' );
-                               $marker = $( '<meta>' ).attr( 'name', 'ResourceLoaderDynamicStyles' ).appendTo( 'head' );
-
-                               return $marker;
-                       }
-
-                       /**
-                        * Create a new style tag and add it to the DOM.
-                        *
-                        * @private
-                        * @param {string} text CSS text
-                        * @param {HTMLElement|jQuery} [nextnode=document.head] The element where the style tag should be
-                        *  inserted before. Otherwise it will be appended to `<head>`.
-                        * @return {HTMLElement} Reference to the created `<style>` element.
-                        */
-                       function newStyleTag( text, nextnode ) {
-                               var s = document.createElement( 'style' );
-                               // Insert into document before setting cssText (bug 33305)
-                               if ( nextnode ) {
-                                       // Must be inserted with native insertBefore, not $.fn.before.
-                                       // When using jQuery to insert it, like $nextnode.before( s ),
-                                       // then IE6 will throw "Access is denied" when trying to append
-                                       // to .cssText later. Some kind of weird security measure.
-                                       // http://stackoverflow.com/q/12586482/319266
-                                       // Works: jsfiddle.net/zJzMy/1
-                                       // Fails: jsfiddle.net/uJTQz
-                                       // Works again: http://jsfiddle.net/Azr4w/ (diff: the next 3 lines)
-                                       if ( nextnode.jquery ) {
-                                               nextnode = nextnode.get( 0 );
-                                       }
-                                       nextnode.parentNode.insertBefore( s, nextnode );
-                               } else {
-                                       document.getElementsByTagName( 'head' )[0].appendChild( s );
-                               }
-                               if ( s.styleSheet ) {
-                                       // IE
-                                       s.styleSheet.cssText = text;
-                               } else {
-                                       // Other browsers.
-                                       // (Safari sometimes borks on non-string values,
-                                       // play safe by casting to a string, just in case.)
-                                       s.appendChild( document.createTextNode( String( text ) ) );
-                               }
-                               return s;
-                       }
-
-                       /**
-                        * Checks whether it is safe to add this css to a stylesheet.
-                        *
-                        * @private
-                        * @param {string} cssText
-                        * @return {boolean} False if a new one must be created.
-                        */
-                       function canExpandStylesheetWith( cssText ) {
-                               // Makes sure that cssText containing `@import`
-                               // rules will end up in a new stylesheet (as those only work when
-                               // placed at the start of a stylesheet; bug 35562).
-                               return cssText.indexOf( '@import' ) === -1;
-                       }
-
-                       /**
-                        * Add a bit of CSS text to the current browser page.
-                        *
-                        * The CSS will be appended to an existing ResourceLoader-created `<style>` tag
-                        * or create a new one based on whether the given `cssText` is safe for extension.
-                        *
-                        * @param {string} [cssText=cssBuffer] If called without cssText,
-                        *  the internal buffer will be inserted instead.
-                        * @param {Function} [callback]
-                        */
-                       function addEmbeddedCSS( cssText, callback ) {
-                               var $style, styleEl;
-
-                               if ( callback ) {
-                                       cssCallbacks.add( callback );
-                               }
-
-                               // Yield once before inserting the <style> tag. There are likely
-                               // more calls coming up which we can combine this way.
-                               // Appending a stylesheet and waiting for the browser to repaint
-                               // is fairly expensive, this reduces it (bug 45810)
-                               if ( cssText ) {
-                                       // Be careful not to extend the buffer with css that needs a new stylesheet
-                                       if ( !cssBuffer || canExpandStylesheetWith( cssText ) ) {
-                                               // Linebreak for somewhat distinguishable sections
-                                               // (the rl-cachekey comment separating each)
-                                               cssBuffer += '\n' + cssText;
-                                               // TODO: Use requestAnimationFrame in the future which will
-                                               // perform even better by not injecting styles while the browser
-                                               // is paiting.
-                                               setTimeout( function () {
-                                                       // Can't pass addEmbeddedCSS to setTimeout directly because Firefox
-                                                       // (below version 13) has the non-standard behaviour of passing a
-                                                       // numerical "lateness" value as first argument to this callback
-                                                       // http://benalman.com/news/2009/07/the-mysterious-firefox-settime/
-                                                       addEmbeddedCSS();
-                                               } );
-                                               return;
-                                       }
-
-                               // This is a delayed call and we got a buffer still
-                               } else if ( cssBuffer ) {
-                                       cssText = cssBuffer;
-                                       cssBuffer = '';
-                               } else {
-                                       // This is a delayed call, but buffer is already cleared by
-                                       // another delayed call.
-                                       return;
-                               }
-
-                               // By default, always create a new <style>. Appending text to a <style>
-                               // tag is bad as it means the contents have to be re-parsed (bug 45810).
-                               //
-                               // Except, of course, in IE 9 and below. In there we default to re-using and
-                               // appending to a <style> tag due to the IE stylesheet limit (bug 31676).
-                               if ( 'documentMode' in document && document.documentMode <= 9 ) {
-
-                                       $style = getMarker().prev();
-                                       // Verify that the the element before Marker actually is a
-                                       // <style> tag and one that came from ResourceLoader
-                                       // (not some other style tag or even a `<meta>` or `<script>`).
-                                       if ( $style.data( 'ResourceLoaderDynamicStyleTag' ) === true ) {
-                                               // There's already a dynamic <style> tag present and
-                                               // canExpandStylesheetWith() gave a green light to append more to it.
-                                               styleEl = $style.get( 0 );
-                                               if ( styleEl.styleSheet ) {
-                                                       try {
-                                                               styleEl.styleSheet.cssText += cssText; // IE
-                                                       } catch ( e ) {
-                                                               log( 'addEmbeddedCSS fail', e );
-                                                       }
-                                               } else {
-                                                       styleEl.appendChild( document.createTextNode( String( cssText ) ) );
-                                               }
-                                               cssCallbacks.fire().empty();
-                                               return;
-                                       }
-                               }
-
-                               $( newStyleTag( cssText, getMarker() ) ).data( 'ResourceLoaderDynamicStyleTag', true );
-
-                               cssCallbacks.fire().empty();
-                       }
-
-                       /**
-                        * Generates an ISO8601 "basic" string from a UNIX timestamp
-                        * @private
-                        */
-                       function formatVersionNumber( timestamp ) {
-                               var     d = new Date();
-                               function pad( a, b, c ) {
-                                       return [a < 10 ? '0' + a : a, b < 10 ? '0' + b : b, c < 10 ? '0' + c : c].join( '' );
-                               }
-                               d.setTime( timestamp * 1000 );
-                               return [
-                                       pad( d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate() ), 'T',
-                                       pad( d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds() ), 'Z'
-                               ].join( '' );
-                       }
-
-                       /**
-                        * Resolves dependencies and detects circular references.
-                        *
-                        * @private
-                        * @param {string} module Name of the top-level module whose dependencies shall be
-                        *   resolved and sorted.
-                        * @param {Array} resolved Returns a topological sort of the given module and its
-                        *   dependencies, such that later modules depend on earlier modules. The array
-                        *   contains the module names. If the array contains already some module names,
-                        *   this function appends its result to the pre-existing array.
-                        * @param {Object} [unresolved] Hash used to track the current dependency
-                        *   chain; used to report loops in the dependency graph.
-                        * @throws {Error} If any unregistered module or a dependency loop is encountered
-                        */
-                       function sortDependencies( module, resolved, unresolved ) {
-                               var n, deps, len;
-
-                               if ( registry[module] === undefined ) {
-                                       throw new Error( 'Unknown dependency: ' + module );
-                               }
-                               // Resolves dynamic loader function and replaces it with its own results
-                               if ( $.isFunction( registry[module].dependencies ) ) {
-                                       registry[module].dependencies = registry[module].dependencies();
-                                       // Ensures the module's dependencies are always in an array
-                                       if ( typeof registry[module].dependencies !== 'object' ) {
-                                               registry[module].dependencies = [registry[module].dependencies];
-                                       }
-                               }
-                               if ( $.inArray( module, resolved ) !== -1 ) {
-                                       // Module already resolved; nothing to do.
-                                       return;
-                               }
-                               // unresolved is optional, supply it if not passed in
-                               if ( !unresolved ) {
-                                       unresolved = {};
-                               }
-                               // Tracks down dependencies
-                               deps = registry[module].dependencies;
-                               len = deps.length;
-                               for ( n = 0; n < len; n += 1 ) {
-                                       if ( $.inArray( deps[n], resolved ) === -1 ) {
-                                               if ( unresolved[deps[n]] ) {
-                                                       throw new Error(
-                                                               'Circular reference detected: ' + module +
-                                                               ' -> ' + deps[n]
-                                                       );
-                                               }
-
-                                               // Add to unresolved
-                                               unresolved[module] = true;
-                                               sortDependencies( deps[n], resolved, unresolved );
-                                               delete unresolved[module];
-                                       }
-                               }
-                               resolved[resolved.length] = module;
-                       }
-
-                       /**
-                        * Gets a list of module names that a module depends on in their proper dependency
-                        * order.
-                        *
-                        * @private
-                        * @param {string} module Module name or array of string module names
-                        * @return {Array} list of dependencies, including 'module'.
-                        * @throws {Error} If circular reference is detected
-                        */
-                       function resolve( module ) {
-                               var m, resolved;
-
-                               // Allow calling with an array of module names
-                               if ( $.isArray( module ) ) {
-                                       resolved = [];
-                                       for ( m = 0; m < module.length; m += 1 ) {
-                                               sortDependencies( module[m], resolved );
-                                       }
-                                       return resolved;
-                               }
-
-                               if ( typeof module === 'string' ) {
-                                       resolved = [];
-                                       sortDependencies( module, resolved );
-                                       return resolved;
-                               }
-
-                               throw new Error( 'Invalid module argument: ' + module );
-                       }
-
-                       /**
-                        * Narrows a list of module names down to those matching a specific
-                        * state (see comment on top of this scope for a list of valid states).
-                        * One can also filter for 'unregistered', which will return the
-                        * modules names that don't have a registry entry.
-                        *
-                        * @private
-                        * @param {string|string[]} states Module states to filter by
-                        * @param {Array} [modules] List of module names to filter (optional, by default the entire
-                        * registry is used)
-                        * @return {Array} List of filtered module names
-                        */
-                       function filter( states, modules ) {
-                               var list, module, s, m;
-
-                               // Allow states to be given as a string
-                               if ( typeof states === 'string' ) {
-                                       states = [states];
-                               }
-                               // If called without a list of modules, build and use a list of all modules
-                               list = [];
-                               if ( modules === undefined ) {
-                                       modules = [];
-                                       for ( module in registry ) {
-                                               modules[modules.length] = module;
-                                       }
-                               }
-                               // Build a list of modules which are in one of the specified states
-                               for ( s = 0; s < states.length; s += 1 ) {
-                                       for ( m = 0; m < modules.length; m += 1 ) {
-                                               if ( registry[modules[m]] === undefined ) {
-                                                       // Module does not exist
-                                                       if ( states[s] === 'unregistered' ) {
-                                                               // OK, undefined
-                                                               list[list.length] = modules[m];
-                                                       }
-                                               } else {
-                                                       // Module exists, check state
-                                                       if ( registry[modules[m]].state === states[s] ) {
-                                                               // OK, correct state
-                                                               list[list.length] = modules[m];
-                                                       }
-                                               }
-                                       }
-                               }
-                               return list;
-                       }
-
-                       /**
-                        * Determine whether all dependencies are in state 'ready', which means we may
-                        * execute the module or job now.
-                        *
-                        * @private
-                        * @param {Array} dependencies Dependencies (module names) to be checked.
-                        * @return {boolean} True if all dependencies are in state 'ready', false otherwise
-                        */
-                       function allReady( dependencies ) {
-                               return filter( 'ready', dependencies ).length === dependencies.length;
-                       }
-
-                       /**
-                        * A module has entered state 'ready', 'error', or 'missing'. Automatically update pending jobs
-                        * and modules that depend upon this module. if the given module failed, propagate the 'error'
-                        * state up the dependency tree; otherwise, execute all jobs/modules that now have all their
-                        * dependencies satisfied. On jobs depending on a failed module, run the error callback, if any.
-                        *
-                        * @private
-                        * @param {string} module Name of module that entered one of the states 'ready', 'error', or 'missing'.
-                        */
-                       function handlePending( module ) {
-                               var j, job, hasErrors, m, stateChange;
-
-                               // Modules.
-                               if ( $.inArray( registry[module].state, ['error', 'missing'] ) !== -1 ) {
-                                       // If the current module failed, mark all dependent modules also as failed.
-                                       // Iterate until steady-state to propagate the error state upwards in the
-                                       // dependency tree.
-                                       do {
-                                               stateChange = false;
-                                               for ( m in registry ) {
-                                                       if ( $.inArray( registry[m].state, ['error', 'missing'] ) === -1 ) {
-                                                               if ( filter( ['error', 'missing'], registry[m].dependencies ).length > 0 ) {
-                                                                       registry[m].state = 'error';
-                                                                       stateChange = true;
-                                                               }
-                                                       }
-                                               }
-                                       } while ( stateChange );
-                               }
-
-                               // Execute all jobs whose dependencies are either all satisfied or contain at least one failed module.
-                               for ( j = 0; j < jobs.length; j += 1 ) {
-                                       hasErrors = filter( ['error', 'missing'], jobs[j].dependencies ).length > 0;
-                                       if ( hasErrors || allReady( jobs[j].dependencies ) ) {
-                                               // All dependencies satisfied, or some have errors
-                                               job = jobs[j];
-                                               jobs.splice( j, 1 );
-                                               j -= 1;
-                                               try {
-                                                       if ( hasErrors ) {
-                                                               if ( $.isFunction( job.error ) ) {
-                                                                       job.error( new Error( 'Module ' + module + ' has failed dependencies' ), [module] );
-                                                               }
-                                                       } else {
-                                                               if ( $.isFunction( job.ready ) ) {
-                                                                       job.ready();
-                                                               }
-                                                       }
-                                               } catch ( e ) {
-                                                       // A user-defined callback raised an exception.
-                                                       // Swallow it to protect our state machine!
-                                                       log( 'Exception thrown by job.error', e );
-                                               }
-                                       }
-                               }
-
-                               if ( registry[module].state === 'ready' ) {
-                                       // The current module became 'ready'. Set it in the module store, and recursively execute all
-                                       // dependent modules that are loaded and now have all dependencies satisfied.
-                                       mw.loader.store.set( module, registry[module] );
-                                       for ( m in registry ) {
-                                               if ( registry[m].state === 'loaded' && allReady( registry[m].dependencies ) ) {
-                                                       execute( m );
-                                               }
-                                       }
-                               }
-                       }
-
-                       /**
-                        * Adds a script tag to the DOM, either using document.write or low-level DOM manipulation,
-                        * depending on whether document-ready has occurred yet and whether we are in async mode.
-                        *
-                        * @private
-                        * @param {string} src URL to script, will be used as the src attribute in the script tag
-                        * @param {Function} [callback] Callback which will be run when the script is done
-                        * @param {boolean} [async=false] Whether to load modules asynchronously.
-                        *  Ignored (and defaulted to `true`) if the document-ready event has already occurred.
-                        */
-                       function addScript( src, callback, async ) {
-                               /*jshint evil:true */
-                               var script, head, done;
-
-                               // Using isReady directly instead of storing it locally from
-                               // a $.fn.ready callback (bug 31895).
-                               if ( $.isReady || async ) {
-                                       // Can't use jQuery.getScript because that only uses <script> for cross-domain,
-                                       // it uses XHR and eval for same-domain scripts, which we don't want because it
-                                       // messes up line numbers.
-                                       // The below is based on jQuery ([jquery@1.9.1]/src/ajax/script.js)
-
-                                       // IE-safe way of getting an append target. In old IE document.head isn't supported
-                                       // and its getElementsByTagName can't find <head> until </head> is parsed.
-                                       done = false;
-                                       head = document.head || document.getElementsByTagName( 'head' )[0] || document.documentElement;
-
-                                       script = document.createElement( 'script' );
-                                       script.async = true;
-                                       script.src = src;
-                                       if ( $.isFunction( callback ) ) {
-                                               script.onload = script.onreadystatechange = function () {
-                                                       if (
-                                                               !done
-                                                               && (
-                                                                       !script.readyState
-                                                                       || /loaded|complete/.test( script.readyState )
-                                                               )
-                                                       ) {
-                                                               done = true;
-
-                                                               // Handle memory leak in IE
-                                                               script.onload = script.onreadystatechange = null;
-
-                                                               // Detach the element from the document
-                                                               if ( script.parentNode ) {
-                                                                       script.parentNode.removeChild( script );
-                                                               }
-
-                                                               // Dereference the element from javascript
-                                                               script = undefined;
-
-                                                               callback();
-                                                       }
-                                               };
-                                       }
-
-                                       if ( window.opera ) {
-                                               // Appending to the <head> blocks rendering completely in Opera,
-                                               // so append to the <body> after document ready. This means the
-                                               // scripts only start loading after the document has been rendered,
-                                               // but so be it. Opera users don't deserve faster web pages if their
-                                               // browser makes it impossible.
-                                               $( function () {
-                                                       document.body.appendChild( script );
-                                               } );
-                                       } else {
-                                               // Circumvent IE6 bugs with base elements (jqbug.com/2709, jqbug.com/4378)
-                                               // by prepending instead of appending.
-                                               head.insertBefore( script, head.firstChild );
-                                       }
-                               } else {
-                                       document.write( mw.html.element( 'script', { 'src': src }, '' ) );
-                                       if ( $.isFunction( callback ) ) {
-                                               // Document.write is synchronous, so this is called when it's done
-                                               // FIXME: that's a lie. doc.write isn't actually synchronous
-                                               callback();
-                                       }
-                               }
-                       }
-
-                       /**
-                        * Executes a loaded module, making it ready to use
-                        *
-                        * @private
-                        * @param {string} module Module name to execute
-                        */
-                       function execute( module ) {
-                               var key, value, media, i, urls, cssHandle, checkCssHandles,
-                                       cssHandlesRegistered = false;
-
-                               if ( registry[module] === undefined ) {
-                                       throw new Error( 'Module has not been registered yet: ' + module );
-                               } else if ( registry[module].state === 'registered' ) {
-                                       throw new Error( 'Module has not been requested from the server yet: ' + module );
-                               } else if ( registry[module].state === 'loading' ) {
-                                       throw new Error( 'Module has not completed loading yet: ' + module );
-                               } else if ( registry[module].state === 'ready' ) {
-                                       throw new Error( 'Module has already been executed: ' + module );
-                               }
-
-                               /**
-                                * Define loop-function here for efficiency
-                                * and to avoid re-using badly scoped variables.
-                                * @ignore
-                                */
-                               function addLink( media, url ) {
-                                       var el = document.createElement( 'link' );
-                                       // For IE: Insert in document *before* setting href
-                                       getMarker().before( el );
-                                       el.rel = 'stylesheet';
-                                       if ( media && media !== 'all' ) {
-                                               el.media = media;
-                                       }
-                                       // If you end up here from an IE exception "SCRIPT: Invalid property value.",
-                                       // see #addEmbeddedCSS, bug 31676, and bug 47277 for details.
-                                       el.href = url;
-                               }
-
-                               function runScript() {
-                                       var script, markModuleReady, nestedAddScript;
-                                       try {
-                                               script = registry[module].script;
-                                               markModuleReady = function () {
-                                                       registry[module].state = 'ready';
-                                                       handlePending( module );
-                                               };
-                                               nestedAddScript = function ( arr, callback, async, i ) {
-                                                       // Recursively call addScript() in its own callback
-                                                       // for each element of arr.
-                                                       if ( i >= arr.length ) {
-                                                               // We're at the end of the array
-                                                               callback();
-                                                               return;
-                                                       }
-
-                                                       addScript( arr[i], function () {
-                                                               nestedAddScript( arr, callback, async, i + 1 );
-                                                       }, async );
-                                               };
-
-                                               if ( $.isArray( script ) ) {
-                                                       nestedAddScript( script, markModuleReady, registry[module].async, 0 );
-                                               } else if ( $.isFunction( script ) ) {
-                                                       registry[module].state = 'ready';
-                                                       // Pass jQuery twice so that the signature of the closure which wraps
-                                                       // the script can bind both '$' and 'jQuery'.
-                                                       script( $, $ );
-                                                       handlePending( module );
-                                               }
-                                       } catch ( e ) {
-                                               // This needs to NOT use mw.log because these errors are common in production mode
-                                               // and not in debug mode, such as when a symbol that should be global isn't exported
-                                               log( 'Exception thrown by ' + module, e );
-                                               registry[module].state = 'error';
-                                               handlePending( module );
-                                       }
-                               }
-
-                               // This used to be inside runScript, but since that is now fired asychronously
-                               // (after CSS is loaded) we need to set it here right away. It is crucial that
-                               // when execute() is called this is set synchronously, otherwise modules will get
-                               // executed multiple times as the registry will state that it isn't loading yet.
-                               registry[module].state = 'loading';
-
-                               // Add localizations to message system
-                               if ( $.isPlainObject( registry[module].messages ) ) {
-                                       mw.messages.set( registry[module].messages );
-                               }
-
-                               if ( $.isReady || registry[module].async ) {
-                                       // Make sure we don't run the scripts until all (potentially asynchronous)
-                                       // stylesheet insertions have completed.
-                                       ( function () {
-                                               var pending = 0;
-                                               checkCssHandles = function () {
-                                                       // cssHandlesRegistered ensures we don't take off too soon, e.g. when
-                                                       // one of the cssHandles is fired while we're still creating more handles.
-                                                       if ( cssHandlesRegistered && pending === 0 && runScript ) {
-                                                               runScript();
-                                                               runScript = undefined; // Revoke
-                                                       }
-                                               };
-                                               cssHandle = function () {
-                                                       var check = checkCssHandles;
-                                                       pending++;
-                                                       return function () {
-                                                               if (check) {
-                                                                       pending--;
-                                                                       check();
-                                                                       check = undefined; // Revoke
-                                                               }
-                                                       };
-                                               };
-                                       }() );
-                               } else {
-                                       // We are in blocking mode, and so we can't afford to wait for CSS
-                                       cssHandle = function () {};
-                                       // Run immediately
-                                       checkCssHandles = runScript;
-                               }
-
-                               // Process styles (see also mw.loader.implement)
-                               // * back-compat: { <media>: css }
-                               // * back-compat: { <media>: [url, ..] }
-                               // * { "css": [css, ..] }
-                               // * { "url": { <media>: [url, ..] } }
-                               if ( $.isPlainObject( registry[module].style ) ) {
-                                       for ( key in registry[module].style ) {
-                                               value = registry[module].style[key];
-                                               media = undefined;
-
-                                               if ( key !== 'url' && key !== 'css' ) {
-                                                       // Backwards compatibility, key is a media-type
-                                                       if ( typeof value === 'string' ) {
-                                                               // back-compat: { <media>: css }
-                                                               // Ignore 'media' because it isn't supported (nor was it used).
-                                                               // Strings are pre-wrapped in "@media". The media-type was just ""
-                                                               // (because it had to be set to something).
-                                                               // This is one of the reasons why this format is no longer used.
-                                                               addEmbeddedCSS( value, cssHandle() );
-                                                       } else {
-                                                               // back-compat: { <media>: [url, ..] }
-                                                               media = key;
-                                                               key = 'bc-url';
-                                                       }
-                                               }
-
-                                               // Array of css strings in key 'css',
-                                               // or back-compat array of urls from media-type
-                                               if ( $.isArray( value ) ) {
-                                                       for ( i = 0; i < value.length; i += 1 ) {
-                                                               if ( key === 'bc-url' ) {
-                                                                       // back-compat: { <media>: [url, ..] }
-                                                                       addLink( media, value[i] );
-                                                               } else if ( key === 'css' ) {
-                                                                       // { "css": [css, ..] }
-                                                                       addEmbeddedCSS( value[i], cssHandle() );
-                                                               }
-                                                       }
-                                               // Not an array, but a regular object
-                                               // Array of urls inside media-type key
-                                               } else if ( typeof value === 'object' ) {
-                                                       // { "url": { <media>: [url, ..] } }
-                                                       for ( media in value ) {
-                                                               urls = value[media];
-                                                               for ( i = 0; i < urls.length; i += 1 ) {
-                                                                       addLink( media, urls[i] );
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-
-                               // Kick off.
-                               cssHandlesRegistered = true;
-                               checkCssHandles();
-                       }
-
-                       /**
-                        * Adds a dependencies to the queue with optional callbacks to be run
-                        * when the dependencies are ready or fail
-                        *
-                        * @private
-                        * @param {string|string[]} dependencies Module name or array of string module names
-                        * @param {Function} [ready] Callback to execute when all dependencies are ready
-                        * @param {Function} [error] Callback to execute when any dependency fails
-                        * @param {boolean} [async=false] Whether to load modules asynchronously.
-                        *  Ignored (and defaulted to `true`) if the document-ready event has already occurred.
-                        */
-                       function request( dependencies, ready, error, async ) {
-                               var n;
-
-                               // Allow calling by single module name
-                               if ( typeof dependencies === 'string' ) {
-                                       dependencies = [dependencies];
-                               }
-
-                               // Add ready and error callbacks if they were given
-                               if ( ready !== undefined || error !== undefined ) {
-                                       jobs[jobs.length] = {
-                                               'dependencies': filter(
-                                                       ['registered', 'loading', 'loaded'],
-                                                       dependencies
-                                               ),
-                                               'ready': ready,
-                                               'error': error
-                                       };
-                               }
-
-                               // Queue up any dependencies that are registered
-                               dependencies = filter( ['registered'], dependencies );
-                               for ( n = 0; n < dependencies.length; n += 1 ) {
-                                       if ( $.inArray( dependencies[n], queue ) === -1 ) {
-                                               queue[queue.length] = dependencies[n];
-                                               if ( async ) {
-                                                       // Mark this module as async in the registry
-                                                       registry[dependencies[n]].async = true;
-                                               }
-                                       }
-                               }
-
-                               // Work the queue
-                               mw.loader.work();
-                       }
-
-                       function sortQuery( o ) {
-                               var sorted = {}, key, a = [];
-                               for ( key in o ) {
-                                       if ( hasOwn.call( o, key ) ) {
-                                               a.push( key );
-                                       }
-                               }
-                               a.sort();
-                               for ( key = 0; key < a.length; key += 1 ) {
-                                       sorted[a[key]] = o[a[key]];
-                               }
-                               return sorted;
-                       }
-
-                       /**
-                        * Converts a module map of the form { foo: [ 'bar', 'baz' ], bar: [ 'baz, 'quux' ] }
-                        * to a query string of the form foo.bar,baz|bar.baz,quux
-                        * @private
-                        */
-                       function buildModulesString( moduleMap ) {
-                               var arr = [], p, prefix;
-                               for ( prefix in moduleMap ) {
-                                       p = prefix === '' ? '' : prefix + '.';
-                                       arr.push( p + moduleMap[prefix].join( ',' ) );
-                               }
-                               return arr.join( '|' );
-                       }
-
-                       /**
-                        * Asynchronously append a script tag to the end of the body
-                        * that invokes load.php
-                        * @private
-                        * @param {Object} moduleMap Module map, see #buildModulesString
-                        * @param {Object} currReqBase Object with other parameters (other than 'modules') to use in the request
-                        * @param {string} sourceLoadScript URL of load.php
-                        * @param {boolean} async Whether to load modules asynchronously.
-                        *  Ignored (and defaulted to `true`) if the document-ready event has already occurred.
-                        */
-                       function doRequest( moduleMap, currReqBase, sourceLoadScript, async ) {
-                               var request = $.extend(
-                                       { modules: buildModulesString( moduleMap ) },
-                                       currReqBase
-                               );
-                               request = sortQuery( request );
-                               // Append &* to avoid triggering the IE6 extension check
-                               addScript( sourceLoadScript + '?' + $.param( request ) + '&*', null, async );
-                       }
-
-                       /* Public Members */
-                       return {
-                               /**
-                                * The module registry is exposed as an aid for debugging and inspecting page
-                                * state; it is not a public interface for modifying the registry.
-                                *
-                                * @see #registry
-                                * @property
-                                * @private
-                                */
-                               moduleRegistry: registry,
-
-                               /**
-                                * @inheritdoc #newStyleTag
-                                * @method
-                                */
-                               addStyleTag: newStyleTag,
-
-                               /**
-                                * Batch-request queued dependencies from the server.
-                                */
-                               work: function () {
-                                       var     reqBase, splits, maxQueryLength, q, b, bSource, bGroup, bSourceGroup,
-                                               source, concatSource, origBatch, group, g, i, modules, maxVersion, sourceLoadScript,
-                                               currReqBase, currReqBaseLength, moduleMap, l,
-                                               lastDotIndex, prefix, suffix, bytesAdded, async;
-
-                                       // Build a list of request parameters common to all requests.
-                                       reqBase = {
-                                               skin: mw.config.get( 'skin' ),
-                                               lang: mw.config.get( 'wgUserLanguage' ),
-                                               debug: mw.config.get( 'debug' )
-                                       };
-                                       // Split module batch by source and by group.
-                                       splits = {};
-                                       maxQueryLength = mw.config.get( 'wgResourceLoaderMaxQueryLength', -1 );
-
-                                       // Appends a list of modules from the queue to the batch
-                                       for ( q = 0; q < queue.length; q += 1 ) {
-                                               // Only request modules which are registered
-                                               if ( registry[queue[q]] !== undefined && registry[queue[q]].state === 'registered' ) {
-                                                       // Prevent duplicate entries
-                                                       if ( $.inArray( queue[q], batch ) === -1 ) {
-                                                               batch[batch.length] = queue[q];
-                                                               // Mark registered modules as loading
-                                                               registry[queue[q]].state = 'loading';
-                                                       }
-                                               }
-                                       }
-
-                                       mw.loader.store.init();
-                                       if ( mw.loader.store.enabled ) {
-                                               concatSource = [];
-                                               origBatch = batch;
-                                               batch = $.grep( batch, function ( module ) {
-                                                       var source = mw.loader.store.get( module );
-                                                       if ( source ) {
-                                                               concatSource.push( source );
-                                                               return false;
-                                                       }
-                                                       return true;
-                                               } );
-                                               try {
-                                                       $.globalEval( concatSource.join( ';' ) );
-                                               } catch ( err ) {
-                                                       // Not good, the cached mw.loader.implement calls failed! This should
-                                                       // never happen, barring ResourceLoader bugs, browser bugs and PEBKACs.
-                                                       // Depending on how corrupt the string is, it is likely that some
-                                                       // modules' implement() succeeded while the ones after the error will
-                                                       // never run and leave their modules in the 'loading' state forever.
-
-                                                       // Since this is an error not caused by an individual module but by
-                                                       // something that infected the implement call itself, don't take any
-                                                       // risks and clear everything in this cache.
-                                                       mw.loader.store.clear();
-                                                       // Re-add the ones still pending back to the batch and let the server
-                                                       // repopulate these modules to the cache.
-                                                       // This means that at most one module will be useless (the one that had
-                                                       // the error) instead of all of them.
-                                                       log( 'Error while evaluating data from mw.loader.store', err );
-                                                       origBatch = $.grep( origBatch, function ( module ) {
-                                                               return registry[module].state === 'loading';
-                                                       } );
-                                                       batch = batch.concat( origBatch );
-                                               }
-                                       }
-
-                                       // Early exit if there's nothing to load...
-                                       if ( !batch.length ) {
-                                               return;
-                                       }
-
-                                       // The queue has been processed into the batch, clear up the queue.
-                                       queue = [];
-
-                                       // Always order modules alphabetically to help reduce cache
-                                       // misses for otherwise identical content.
-                                       batch.sort();
-
-                                       // Split batch by source and by group.
-                                       for ( b = 0; b < batch.length; b += 1 ) {
-                                               bSource = registry[batch[b]].source;
-                                               bGroup = registry[batch[b]].group;
-                                               if ( splits[bSource] === undefined ) {
-                                                       splits[bSource] = {};
-                                               }
-                                               if ( splits[bSource][bGroup] === undefined ) {
-                                                       splits[bSource][bGroup] = [];
-                                               }
-                                               bSourceGroup = splits[bSource][bGroup];
-                                               bSourceGroup[bSourceGroup.length] = batch[b];
-                                       }
-
-                                       // Clear the batch - this MUST happen before we append any
-                                       // script elements to the body or it's possible that a script
-                                       // will be locally cached, instantly load, and work the batch
-                                       // again, all before we've cleared it causing each request to
-                                       // include modules which are already loaded.
-                                       batch = [];
-
-                                       for ( source in splits ) {
-
-                                               sourceLoadScript = sources[source].loadScript;
-
-                                               for ( group in splits[source] ) {
-
-                                                       // Cache access to currently selected list of
-                                                       // modules for this group from this source.
-                                                       modules = splits[source][group];
-
-                                                       // Calculate the highest timestamp
-                                                       maxVersion = 0;
-                                                       for ( g = 0; g < modules.length; g += 1 ) {
-                                                               if ( registry[modules[g]].version > maxVersion ) {
-                                                                       maxVersion = registry[modules[g]].version;
-                                                               }
-                                                       }
-
-                                                       currReqBase = $.extend( { version: formatVersionNumber( maxVersion ) }, reqBase );
-                                                       // For user modules append a user name to the request.
-                                                       if ( group === 'user' && mw.config.get( 'wgUserName' ) !== null ) {
-                                                               currReqBase.user = mw.config.get( 'wgUserName' );
-                                                       }
-                                                       currReqBaseLength = $.param( currReqBase ).length;
-                                                       async = true;
-                                                       // We may need to split up the request to honor the query string length limit,
-                                                       // so build it piece by piece.
-                                                       l = currReqBaseLength + 9; // '&modules='.length == 9
-
-                                                       moduleMap = {}; // { prefix: [ suffixes ] }
-
-                                                       for ( i = 0; i < modules.length; i += 1 ) {
-                                                               // Determine how many bytes this module would add to the query string
-                                                               lastDotIndex = modules[i].lastIndexOf( '.' );
-                                                               // Note that these substr() calls work even if lastDotIndex == -1
-                                                               prefix = modules[i].substr( 0, lastDotIndex );
-                                                               suffix = modules[i].substr( lastDotIndex + 1 );
-                                                               bytesAdded = moduleMap[prefix] !== undefined
-                                                                       ? suffix.length + 3 // '%2C'.length == 3
-                                                                       : modules[i].length + 3; // '%7C'.length == 3
-
-                                                               // If the request would become too long, create a new one,
-                                                               // but don't create empty requests
-                                                               if ( maxQueryLength > 0 && !$.isEmptyObject( moduleMap ) && l + bytesAdded > maxQueryLength ) {
-                                                                       // This request would become too long, create a new one
-                                                                       // and fire off the old one
-                                                                       doRequest( moduleMap, currReqBase, sourceLoadScript, async );
-                                                                       moduleMap = {};
-                                                                       async = true;
-                                                                       l = currReqBaseLength + 9;
-                                                               }
-                                                               if ( moduleMap[prefix] === undefined ) {
-                                                                       moduleMap[prefix] = [];
-                                                               }
-                                                               moduleMap[prefix].push( suffix );
-                                                               if ( !registry[modules[i]].async ) {
-                                                                       // If this module is blocking, make the entire request blocking
-                                                                       // This is slightly suboptimal, but in practice mixing of blocking
-                                                                       // and async modules will only occur in debug mode.
-                                                                       async = false;
-                                                               }
-                                                               l += bytesAdded;
-                                                       }
-                                                       // If there's anything left in moduleMap, request that too
-                                                       if ( !$.isEmptyObject( moduleMap ) ) {
-                                                               doRequest( moduleMap, currReqBase, sourceLoadScript, async );
-                                                       }
-                                               }
-                                       }
-                               },
-
-                               /**
-                                * Register a source.
-                                *
-                                * The #work method will use this information to split up requests by source.
-                                *
-                                *     mw.loader.addSource( 'mediawikiwiki', { loadScript: '//www.mediawiki.org/w/load.php' } );
-                                *
-                                * @param {string} id Short string representing a source wiki, used internally for
-                                *  registered modules to indicate where they should be loaded from (usually lowercase a-z).
-                                * @param {Object} props
-                                * @param {string} props.loadScript Url to the load.php entry point of the source wiki.
-                                * @return {boolean}
-                                */
-                               addSource: function ( id, props ) {
-                                       var source;
-                                       // Allow multiple additions
-                                       if ( typeof id === 'object' ) {
-                                               for ( source in id ) {
-                                                       mw.loader.addSource( source, id[source] );
-                                               }
-                                               return true;
-                                       }
-
-                                       if ( sources[id] !== undefined ) {
-                                               throw new Error( 'source already registered: ' + id );
-                                       }
-
-                                       sources[id] = props;
-
-                                       return true;
-                               },
-
-                               /**
-                                * Register a module, letting the system know about it and its
-                                * properties. Startup modules contain calls to this function.
-                                *
-                                * @param {string} module Module name
-                                * @param {number} version Module version number as a timestamp (falls backs to 0)
-                                * @param {string|Array|Function} dependencies One string or array of strings of module
-                                *  names on which this module depends, or a function that returns that array.
-                                * @param {string} [group=null] Group which the module is in
-                                * @param {string} [source='local'] Name of the source
-                                */
-                               register: function ( module, version, dependencies, group, source ) {
-                                       var m;
-                                       // Allow multiple registration
-                                       if ( typeof module === 'object' ) {
-                                               for ( m = 0; m < module.length; m += 1 ) {
-                                                       // module is an array of module names
-                                                       if ( typeof module[m] === 'string' ) {
-                                                               mw.loader.register( module[m] );
-                                                       // module is an array of arrays
-                                                       } else if ( typeof module[m] === 'object' ) {
-                                                               mw.loader.register.apply( mw.loader, module[m] );
-                                                       }
-                                               }
-                                               return;
-                                       }
-                                       // Validate input
-                                       if ( typeof module !== 'string' ) {
-                                               throw new Error( 'module must be a string, not a ' + typeof module );
-                                       }
-                                       if ( registry[module] !== undefined ) {
-                                               throw new Error( 'module already registered: ' + module );
-                                       }
-                                       // List the module as registered
-                                       registry[module] = {
-                                               version: version !== undefined ? parseInt( version, 10 ) : 0,
-                                               dependencies: [],
-                                               group: typeof group === 'string' ? group : null,
-                                               source: typeof source === 'string' ? source: 'local',
-                                               state: 'registered'
-                                       };
-                                       if ( typeof dependencies === 'string' ) {
-                                               // Allow dependencies to be given as a single module name
-                                               registry[module].dependencies = [ dependencies ];
-                                       } else if ( typeof dependencies === 'object' || $.isFunction( dependencies ) ) {
-                                               // Allow dependencies to be given as an array of module names
-                                               // or a function which returns an array
-                                               registry[module].dependencies = dependencies;
-                                       }
-                               },
-
-                               /**
-                                * Implement a module given the components that make up the module.
-                                *
-                                * When #load or #using requests one or more modules, the server
-                                * response contain calls to this function.
-                                *
-                                * All arguments are required.
-                                *
-                                * @param {string} module Name of module
-                                * @param {Function|Array} script Function with module code or Array of URLs to
-                                *  be used as the src attribute of a new `<script>` tag.
-                                * @param {Object} style Should follow one of the following patterns:
-                                *
-                                *     { "css": [css, ..] }
-                                *     { "url": { <media>: [url, ..] } }
-                                *
-                                * And for backwards compatibility (needs to be supported forever due to caching):
-                                *
-                                *     { <media>: css }
-                                *     { <media>: [url, ..] }
-                                *
-                                * The reason css strings are not concatenated anymore is bug 31676. We now check
-                                * whether it's safe to extend the stylesheet (see #canExpandStylesheetWith).
-                                *
-                                * @param {Object} msgs List of key/value pairs to be added to mw#messages.
-                                */
-                               implement: function ( module, script, style, msgs ) {
-                                       // Validate input
-                                       if ( typeof module !== 'string' ) {
-                                               throw new Error( 'module must be a string, not a ' + typeof module );
-                                       }
-                                       if ( !$.isFunction( script ) && !$.isArray( script ) ) {
-                                               throw new Error( 'script must be a function or an array, not a ' + typeof script );
-                                       }
-                                       if ( !$.isPlainObject( style ) ) {
-                                               throw new Error( 'style must be an object, not a ' + typeof style );
-                                       }
-                                       if ( !$.isPlainObject( msgs ) ) {
-                                               throw new Error( 'msgs must be an object, not a ' + typeof msgs );
-                                       }
-                                       // Automatically register module
-                                       if ( registry[module] === undefined ) {
-                                               mw.loader.register( module );
-                                       }
-                                       // Check for duplicate implementation
-                                       if ( registry[module] !== undefined && registry[module].script !== undefined ) {
-                                               throw new Error( 'module already implemented: ' + module );
-                                       }
-                                       // Attach components
-                                       registry[module].script = script;
-                                       registry[module].style = style;
-                                       registry[module].messages = msgs;
-                                       // The module may already have been marked as erroneous
-                                       if ( $.inArray( registry[module].state, ['error', 'missing'] ) === -1 ) {
-                                               registry[module].state = 'loaded';
-                                               if ( allReady( registry[module].dependencies ) ) {
-                                                       execute( module );
-                                               }
-                                       }
-                               },
-
-                               /**
-                                * Execute a function as soon as one or more required modules are ready.
-                                *
-                                * Example of inline dependency on OOjs:
-                                *
-                                *     mw.loader.using( 'oojs', function () {
-                                *         OO.compare( [ 1 ], [ 1 ] );
-                                *     } );
-                                *
-                                * @param {string|Array} dependencies Module name or array of modules names the callback
-                                *  dependends on to be ready before executing
-                                * @param {Function} [ready] Callback to execute when all dependencies are ready
-                                * @param {Function} [error] Callback to execute if one or more dependencies failed
-                                * @return {jQuery.Promise}
-                                */
-                               using: function ( dependencies, ready, error ) {
-                                       var deferred = $.Deferred();
-
-                                       // Allow calling with a single dependency as a string
-                                       if ( typeof dependencies === 'string' ) {
-                                               dependencies = [ dependencies ];
-                                       } else if ( !$.isArray( dependencies ) ) {
-                                               // Invalid input
-                                               throw new Error( 'Dependencies must be a string or an array' );
-                                       }
-
-                                       if ( ready ) {
-                                               deferred.done( ready );
-                                       }
-                                       if ( error ) {
-                                               deferred.fail( error );
-                                       }
-
-                                       // Resolve entire dependency map
-                                       dependencies = resolve( dependencies );
-                                       if ( allReady( dependencies ) ) {
-                                               // Run ready immediately
-                                               deferred.resolve();
-                                       } else if ( filter( ['error', 'missing'], dependencies ).length ) {
-                                               // Execute error immediately if any dependencies have errors
-                                               deferred.reject(
-                                                       new Error( 'One or more dependencies failed to load' ),
-                                                       dependencies
-                                               );
-                                       } else {
-                                               // Not all dependencies are ready: queue up a request
-                                               request( dependencies, deferred.resolve, deferred.reject );
-                                       }
-
-                                       return deferred.promise();
-                               },
-
-                               /**
-                                * Load an external script or one or more modules.
-                                *
-                                * @param {string|Array} modules Either the name of a module, array of modules,
-                                *  or a URL of an external script or style
-                                * @param {string} [type='text/javascript'] mime-type to use if calling with a URL of an
-                                *  external script or style; acceptable values are "text/css" and
-                                *  "text/javascript"; if no type is provided, text/javascript is assumed.
-                                * @param {boolean} [async] Whether to load modules asynchronously.
-                                *  Ignored (and defaulted to `true`) if the document-ready event has already occurred.
-                                *  Defaults to `true` if loading a URL, `false` otherwise.
-                                */
-                               load: function ( modules, type, async ) {
-                                       var filtered, m, module, l;
-
-                                       // Validate input
-                                       if ( typeof modules !== 'object' && typeof modules !== 'string' ) {
-                                               throw new Error( 'modules must be a string or an array, not a ' + typeof modules );
-                                       }
-                                       // Allow calling with an external url or single dependency as a string
-                                       if ( typeof modules === 'string' ) {
-                                               // Support adding arbitrary external scripts
-                                               if ( /^(https?:)?\/\//.test( modules ) ) {
-                                                       if ( async === undefined ) {
-                                                               // Assume async for bug 34542
-                                                               async = true;
-                                                       }
-                                                       if ( type === 'text/css' ) {
-                                                               // IE7-8 throws security warnings when inserting a <link> tag
-                                                               // with a protocol-relative URL set though attributes (instead of
-                                                               // properties) - when on HTTPS. See also bug 41331.
-                                                               l = document.createElement( 'link' );
-                                                               l.rel = 'stylesheet';
-                                                               l.href = modules;
-                                                               $( 'head' ).append( l );
-                                                               return;
-                                                       }
-                                                       if ( type === 'text/javascript' || type === undefined ) {
-                                                               addScript( modules, null, async );
-                                                               return;
-                                                       }
-                                                       // Unknown type
-                                                       throw new Error( 'invalid type for external url, must be text/css or text/javascript. not ' + type );
-                                               }
-                                               // Called with single module
-                                               modules = [ modules ];
-                                       }
-
-                                       // Filter out undefined modules, otherwise resolve() will throw
-                                       // an exception for trying to load an undefined module.
-                                       // Undefined modules are acceptable here in load(), because load() takes
-                                       // an array of unrelated modules, whereas the modules passed to
-                                       // using() are related and must all be loaded.
-                                       for ( filtered = [], m = 0; m < modules.length; m += 1 ) {
-                                               module = registry[modules[m]];
-                                               if ( module !== undefined ) {
-                                                       if ( $.inArray( module.state, ['error', 'missing'] ) === -1 ) {
-                                                               filtered[filtered.length] = modules[m];
-                                                       }
-                                               }
-                                       }
-
-                                       if ( filtered.length === 0 ) {
-                                               return;
-                                       }
-                                       // Resolve entire dependency map
-                                       filtered = resolve( filtered );
-                                       // If all modules are ready, nothing to be done
-                                       if ( allReady( filtered ) ) {
-                                               return;
-                                       }
-                                       // If any modules have errors: also quit.
-                                       if ( filter( ['error', 'missing'], filtered ).length ) {
-                                               return;
-                                       }
-                                       // Since some modules are not yet ready, queue up a request.
-                                       request( filtered, undefined, undefined, async );
-                               },
-
-                               /**
-                                * Change the state of one or more modules.
-                                *
-                                * @param {string|Object} module Module name or object of module name/state pairs
-                                * @param {string} state State name
-                                */
-                               state: function ( module, state ) {
-                                       var m;
-
-                                       if ( typeof module === 'object' ) {
-                                               for ( m in module ) {
-                                                       mw.loader.state( m, module[m] );
-                                               }
-                                               return;
-                                       }
-                                       if ( registry[module] === undefined ) {
-                                               mw.loader.register( module );
-                                       }
-                                       if ( $.inArray( state, ['ready', 'error', 'missing'] ) !== -1
-                                               && registry[module].state !== state ) {
-                                               // Make sure pending modules depending on this one get executed if their
-                                               // dependencies are now fulfilled!
-                                               registry[module].state = state;
-                                               handlePending( module );
-                                       } else {
-                                               registry[module].state = state;
-                                       }
-                               },
-
-                               /**
-                                * Get the version of a module.
-                                *
-                                * @param {string} module Name of module to get version for
-                                * @return {string|null} The version, or null if the module (or its version) is not
-                                *  in the registry.
-                                */
-                               getVersion: function ( module ) {
-                                       if ( registry[module] !== undefined && registry[module].version !== undefined ) {
-                                               return formatVersionNumber( registry[module].version );
-                                       }
-                                       return null;
-                               },
-
-                               /**
-                                * Get the state of a module.
-                                *
-                                * @param {string} module Name of module to get state for
-                                */
-                               getState: function ( module ) {
-                                       if ( registry[module] !== undefined && registry[module].state !== undefined ) {
-                                               return registry[module].state;
-                                       }
-                                       return null;
-                               },
-
-                               /**
-                                * Get the names of all registered modules.
-                                *
-                                * @return {Array}
-                                */
-                               getModuleNames: function () {
-                                       return $.map( registry, function ( i, key ) {
-                                               return key;
-                                       } );
-                               },
-
-                               /**
-                                * @inheritdoc mw.inspect#runReports
-                                * @method
-                                */
-                               inspect: function () {
-                                       var args = slice.call( arguments );
-                                       mw.loader.using( 'mediawiki.inspect', function () {
-                                               mw.inspect.runReports.apply( mw.inspect, args );
-                                       } );
-                               },
-
-                               /**
-                                * On browsers that implement the localStorage API, the module store serves as a
-                                * smart complement to the browser cache. Unlike the browser cache, the module store
-                                * can slice a concatenated response from ResourceLoader into its constituent
-                                * modules and cache each of them separately, using each module's versioning scheme
-                                * to determine when the cache should be invalidated.
-                                *
-                                * @singleton
-                                * @class mw.loader.store
-                                */
-                               store: {
-                                       // Whether the store is in use on this page.
-                                       enabled: null,
-
-                                       // The contents of the store, mapping '[module name]@[version]' keys
-                                       // to module implementations.
-                                       items: {},
-
-                                       // Cache hit stats
-                                       stats: { hits: 0, misses: 0, expired: 0 },
-
-                                       /**
-                                        * Construct a JSON-serializable object representing the content of the store.
-                                        * @return {Object} Module store contents.
-                                        */
-                                       toJSON: function () {
-                                               return { items: mw.loader.store.items, vary: mw.loader.store.getVary() };
-                                       },
-
-                                       /**
-                                        * Get the localStorage key for the entire module store. The key references
-                                        * $wgDBname to prevent clashes between wikis which share a common host.
-                                        *
-                                        * @return {string} localStorage item key
-                                        */
-                                       getStoreKey: function () {
-                                               return 'MediaWikiModuleStore:' + mw.config.get( 'wgDBname' );
-                                       },
-
-                                       /**
-                                        * Get a string key on which to vary the module cache.
-                                        * @return {string} String of concatenated vary conditions.
-                                        */
-                                       getVary: function () {
-                                               return [
-                                                       mw.config.get( 'skin' ),
-                                                       mw.config.get( 'wgResourceLoaderStorageVersion' ),
-                                                       mw.config.get( 'wgUserLanguage' )
-                                               ].join( ':' );
-                                       },
-
-                                       /**
-                                        * Get a string key for a specific module. The key format is '[name]@[version]'.
-                                        *
-                                        * @param {string} module Module name
-                                        * @return {string|null} Module key or null if module does not exist
-                                        */
-                                       getModuleKey: function ( module ) {
-                                               return typeof registry[module] === 'object' ?
-                                                       ( module + '@' + registry[module].version ) : null;
-                                       },
-
-                                       /**
-                                        * Initialize the store.
-                                        *
-                                        * Retrieves store from localStorage and (if successfully retrieved) decoding
-                                        * the stored JSON value to a plain object.
-                                        *
-                                        * The try / catch block is used for JSON & localStorage feature detection.
-                                        * See the in-line documentation for Modernizr's localStorage feature detection
-                                        * code for a full account of why we need a try / catch:
-                                        * <https://github.com/Modernizr/Modernizr/blob/v2.7.1/modernizr.js#L771-L796>.
-                                        */
-                                       init: function () {
-                                               var raw, data;
-
-                                               if ( mw.loader.store.enabled !== null ) {
-                                                       // Init already ran
-                                                       return;
-                                               }
-
-                                               if ( !mw.config.get( 'wgResourceLoaderStorageEnabled' ) || mw.config.get( 'debug' ) ) {
-                                                       // Disabled by configuration, or because debug mode is set
-                                                       mw.loader.store.enabled = false;
-                                                       return;
-                                               }
-
-                                               try {
-                                                       raw = localStorage.getItem( mw.loader.store.getStoreKey() );
-                                                       // If we get here, localStorage is available; mark enabled
-                                                       mw.loader.store.enabled = true;
-                                                       data = JSON.parse( raw );
-                                                       if ( data && typeof data.items === 'object' && data.vary === mw.loader.store.getVary() ) {
-                                                               mw.loader.store.items = data.items;
-                                                               return;
-                                                       }
-                                               } catch ( e ) {}
-
-                                               if ( raw === undefined ) {
-                                                       // localStorage failed; disable store
-                                                       mw.loader.store.enabled = false;
-                                               } else {
-                                                       mw.loader.store.update();
-                                               }
-                                       },
-
-                                       /**
-                                        * Retrieve a module from the store and update cache hit stats.
-                                        *
-                                        * @param {string} module Module name
-                                        * @return {string|boolean} Module implementation or false if unavailable
-                                        */
-                                       get: function ( module ) {
-                                               var key;
-
-                                               if ( !mw.loader.store.enabled ) {
-                                                       return false;
-                                               }
-
-                                               key = mw.loader.store.getModuleKey( module );
-                                               if ( key in mw.loader.store.items ) {
-                                                       mw.loader.store.stats.hits++;
-                                                       return mw.loader.store.items[key];
-                                               }
-                                               mw.loader.store.stats.misses++;
-                                               return false;
-                                       },
-
-                                       /**
-                                        * Stringify a module and queue it for storage.
-                                        *
-                                        * @param {string} module Module name
-                                        * @param {Object} descriptor The module's descriptor as set in the registry
-                                        */
-                                       set: function ( module, descriptor ) {
-                                               var args, key;
-
-                                               if ( !mw.loader.store.enabled ) {
-                                                       return false;
-                                               }
-
-                                               key = mw.loader.store.getModuleKey( module );
-
-                                               if (
-                                                       // Already stored a copy of this exact version
-                                                       key in mw.loader.store.items ||
-                                                       // Module failed to load
-                                                       descriptor.state !== 'ready' ||
-                                                       // Unversioned, private, or site-/user-specific
-                                                       ( !descriptor.version || $.inArray( descriptor.group, [ 'private', 'user', 'site' ] ) !== -1 ) ||
-                                                       // Partial descriptor
-                                                       $.inArray( undefined, [ descriptor.script, descriptor.style, descriptor.messages ] ) !== -1
-                                               ) {
-                                                       // Decline to store
-                                                       return false;
-                                               }
-
-                                               try {
-                                                       args = [
-                                                               JSON.stringify( module ),
-                                                               typeof descriptor.script === 'function' ?
-                                                                       String( descriptor.script ) :
-                                                                       JSON.stringify( descriptor.script ),
-                                                               JSON.stringify( descriptor.style ),
-                                                               JSON.stringify( descriptor.messages )
-                                                       ];
-                                                       // Attempted workaround for a possible Opera bug (bug 57567).
-                                                       // This regex should never match under sane conditions.
-                                                       if ( /^\s*\(/.test( args[1] ) ) {
-                                                               args[1] = 'function' + args[1];
-                                                               log( 'Detected malformed function stringification (bug 57567)' );
-                                                       }
-                                               } catch ( e ) {
-                                                       return;
-                                               }
-
-                                               mw.loader.store.items[key] = 'mw.loader.implement(' + args.join( ',' ) + ');';
-                                               mw.loader.store.update();
-                                       },
-
-                                       /**
-                                        * Iterate through the module store, removing any item that does not correspond
-                                        * (in name and version) to an item in the module registry.
-                                        */
-                                       prune: function () {
-                                               var key, module;
-
-                                               if ( !mw.loader.store.enabled ) {
-                                                       return false;
-                                               }
-
-                                               for ( key in mw.loader.store.items ) {
-                                                       module = key.substring( 0, key.indexOf( '@' ) );
-                                                       if ( mw.loader.store.getModuleKey( module ) !== key ) {
-                                                               mw.loader.store.stats.expired++;
-                                                               delete mw.loader.store.items[key];
-                                                       }
-                                               }
-                                       },
-
-                                       /**
-                                        * Clear the entire module store right now.
-                                        */
-                                       clear: function () {
-                                               mw.loader.store.items = {};
-                                               localStorage.removeItem( mw.loader.store.getStoreKey() );
-                                       },
-
-                                       /**
-                                        * Sync modules to localStorage.
-                                        *
-                                        * This function debounces localStorage updates. When called multiple times in
-                                        * quick succession, the calls are coalesced into a single update operation.
-                                        * This allows us to call #update without having to consider the module load
-                                        * queue; the call to localStorage.setItem will be naturally deferred until the
-                                        * page is quiescent.
-                                        *
-                                        * Because localStorage is shared by all pages with the same origin, if multiple
-                                        * pages are loaded with different module sets, the possibility exists that
-                                        * modules saved by one page will be clobbered by another. But the impact would
-                                        * be minor and the problem would be corrected by subsequent page views.
-                                        *
-                                        * @method
-                                        */
-                                       update: ( function () {
-                                               var timer;
-
-                                               function flush() {
-                                                       var data,
-                                                               key = mw.loader.store.getStoreKey();
-
-                                                       if ( !mw.loader.store.enabled ) {
-                                                               return false;
-                                                       }
-                                                       mw.loader.store.prune();
-                                                       try {
-                                                               // Replacing the content of the module store might fail if the new
-                                                               // contents would exceed the browser's localStorage size limit. To
-                                                               // avoid clogging the browser with stale data, always remove the old
-                                                               // value before attempting to set the new one.
-                                                               localStorage.removeItem( key );
-                                                               data = JSON.stringify( mw.loader.store );
-                                                               localStorage.setItem( key, data );
-                                                       } catch ( e ) {}
-                                               }
-
-                                               return function () {
-                                                       clearTimeout( timer );
-                                                       timer = setTimeout( flush, 2000 );
-                                               };
-                                       }() )
-                               }
-                       };
-               }() ),
-
-               /**
-                * HTML construction helper functions
-                *
-                *     @example
-                *
-                *     var Html, output;
-                *
-                *     Html = mw.html;
-                *     output = Html.element( 'div', {}, new Html.Raw(
-                *         Html.element( 'img', { src: '<' } )
-                *     ) );
-                *     mw.log( output ); // <div><img src="&lt;"/></div>
-                *
-                * @class mw.html
-                * @singleton
-                */
-               html: ( function () {
-                       function escapeCallback( s ) {
-                               switch ( s ) {
-                                       case '\'':
-                                               return '&#039;';
-                                       case '"':
-                                               return '&quot;';
-                                       case '<':
-                                               return '&lt;';
-                                       case '>':
-                                               return '&gt;';
-                                       case '&':
-                                               return '&amp;';
-                               }
-                       }
-
-                       return {
-                               /**
-                                * Escape a string for HTML. Converts special characters to HTML entities.
-                                *
-                                *     mw.html.escape( '< > \' & "' );
-                                *     // Returns &lt; &gt; &#039; &amp; &quot;
-                                *
-                                * @param {string} s The string to escape
-                                */
-                               escape: function ( s ) {
-                                       return s.replace( /['"<>&]/g, escapeCallback );
-                               },
-
-                               /**
-                                * Create an HTML element string, with safe escaping.
-                                *
-                                * @param {string} name The tag name.
-                                * @param {Object} attrs An object with members mapping element names to values
-                                * @param {Mixed} contents The contents of the element. May be either:
-                                *
-                                *  - string: The string is escaped.
-                                *  - null or undefined: The short closing form is used, e.g. `<br/>`.
-                                *  - this.Raw: The value attribute is included without escaping.
-                                *  - this.Cdata: The value attribute is included, and an exception is
-                                *   thrown if it contains an illegal ETAGO delimiter.
-                                *   See <http://www.w3.org/TR/1999/REC-html401-19991224/appendix/notes.html#h-B.3.2>.
-                                */
-                               element: function ( name, attrs, contents ) {
-                                       var v, attrName, s = '<' + name;
-
-                                       for ( attrName in attrs ) {
-                                               v = attrs[attrName];
-                                               // Convert name=true, to name=name
-                                               if ( v === true ) {
-                                                       v = attrName;
-                                               // Skip name=false
-                                               } else if ( v === false ) {
-                                                       continue;
-                                               }
-                                               s += ' ' + attrName + '="' + this.escape( String( v ) ) + '"';
-                                       }
-                                       if ( contents === undefined || contents === null ) {
-                                               // Self close tag
-                                               s += '/>';
-                                               return s;
-                                       }
-                                       // Regular open tag
-                                       s += '>';
-                                       switch ( typeof contents ) {
-                                               case 'string':
-                                                       // Escaped
-                                                       s += this.escape( contents );
-                                                       break;
-                                               case 'number':
-                                               case 'boolean':
-                                                       // Convert to string
-                                                       s += String( contents );
-                                                       break;
-                                               default:
-                                                       if ( contents instanceof this.Raw ) {
-                                                               // Raw HTML inclusion
-                                                               s += contents.value;
-                                                       } else if ( contents instanceof this.Cdata ) {
-                                                               // CDATA
-                                                               if ( /<\/[a-zA-z]/.test( contents.value ) ) {
-                                                                       throw new Error( 'mw.html.element: Illegal end tag found in CDATA' );
-                                                               }
-                                                               s += contents.value;
-                                                       } else {
-                                                               throw new Error( 'mw.html.element: Invalid type of contents' );
-                                                       }
-                                       }
-                                       s += '</' + name + '>';
-                                       return s;
-                               },
-
-                               /**
-                                * Wrapper object for raw HTML passed to mw.html.element().
-                                * @class mw.html.Raw
-                                */
-                               Raw: function ( value ) {
-                                       this.value = value;
-                               },
-
-                               /**
-                                * Wrapper object for CDATA element contents passed to mw.html.element()
-                                * @class mw.html.Cdata
-                                */
-                               Cdata: function ( value ) {
-                                       this.value = value;
-                               }
-                       };
-               }() ),
-
-               // Skeleton user object. mediawiki.user.js extends this
-               user: {
-                       options: new Map(),
-                       tokens: new Map()
-               },
-
-               /**
-                * Registry and firing of events.
-                *
-                * MediaWiki has various interface components that are extended, enhanced
-                * or manipulated in some other way by extensions, gadgets and even
-                * in core itself.
-                *
-                * This framework helps streamlining the timing of when these other
-                * code paths fire their plugins (instead of using document-ready,
-                * which can and should be limited to firing only once).
-                *
-                * Features like navigating to other wiki pages, previewing an edit
-                * and editing itself – without a refresh – can then retrigger these
-                * hooks accordingly to ensure everything still works as expected.
-                *
-                * Example usage:
-                *
-                *     mw.hook( 'wikipage.content' ).add( fn ).remove( fn );
-                *     mw.hook( 'wikipage.content' ).fire( $content );
-                *
-                * Handlers can be added and fired for arbitrary event names at any time. The same
-                * event can be fired multiple times. The last run of an event is memorized
-                * (similar to `$(document).ready` and `$.Deferred().done`).
-                * This means if an event is fired, and a handler added afterwards, the added
-                * function will be fired right away with the last given event data.
-                *
-                * Like Deferreds and Promises, the mw.hook object is both detachable and chainable.
-                * Thus allowing flexible use and optimal maintainability and authority control.
-                * You can pass around the `add` and/or `fire` method to another piece of code
-                * without it having to know the event name (or `mw.hook` for that matter).
-                *
-                *     var h = mw.hook( 'bar.ready' );
-                *     new mw.Foo( .. ).fetch( { callback: h.fire } );
-                *
-                * Note: Events are documented with an underscore instead of a dot in the event
-                * name due to jsduck not supporting dots in that position.
-                *
-                * @class mw.hook
-                */
-               hook: ( function () {
-                       var lists = {};
-
-                       /**
-                        * Create an instance of mw.hook.
-                        *
-                        * @method hook
-                        * @member mw
-                        * @param {string} name Name of hook.
-                        * @return {mw.hook}
-                        */
-                       return function ( name ) {
-                               var list = lists[name] || ( lists[name] = $.Callbacks( 'memory' ) );
-
-                               return {
-                                       /**
-                                        * Register a hook handler
-                                        * @param {Function...} handler Function to bind.
-                                        * @chainable
-                                        */
-                                       add: list.add,
-
-                                       /**
-                                        * Unregister a hook handler
-                                        * @param {Function...} handler Function to unbind.
-                                        * @chainable
-                                        */
-                                       remove: list.remove,
-
-                                       /**
-                                        * Run a hook.
-                                        * @param {Mixed...} data
-                                        * @chainable
-                                        */
-                                       fire: function () {
-                                               return list.fireWith( null, slice.call( arguments ) );
-                                       }
-                               };
-                       };
-               }() )
-       };
-
-}( jQuery ) );
-
-// Alias $j to jQuery for backwards compatibility
-// @deprecated since 1.23 Use $ or jQuery instead
-mw.log.deprecate( window, '$j', jQuery, 'Use $ or jQuery instead.' );
-
-// Attach to window and globally alias
-window.mw = window.mediaWiki = mw;
-
-// Auto-register from pre-loaded startup scripts
-if ( jQuery.isFunction( window.startUp ) ) {
-       window.startUp();
-       window.startUp = undefined;
-}
diff --git a/resources/mediawiki/mediawiki.log.js b/resources/mediawiki/mediawiki.log.js
deleted file mode 100644 (file)
index 2ca0bbd..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*!
- * Logger for MediaWiki javascript.
- * Implements the stub left by the main 'mediawiki' module.
- *
- * @author Michael Dale <mdale@wikimedia.org>
- * @author Trevor Parscal <tparscal@wikimedia.org>
- */
-
-( function ( mw, $ ) {
-
-       // Reference to dummy
-       // We don't need the dummy, but it has other methods on it
-       // that we need to restore afterwards.
-       var original = mw.log,
-               slice = Array.prototype.slice;
-
-       /**
-        * Logs a message to the console in debug mode.
-        *
-        * In the case the browser does not have a console API, a console is created on-the-fly by appending
-        * a `<div id="mw-log-console">` element to the bottom of the body and then appending this and future
-        * messages to that, instead of the console.
-        *
-        * @member mw.log
-        * @param {string...} msg Messages to output to console.
-        */
-       mw.log = function () {
-               // Turn arguments into an array
-               var args = slice.call( arguments ),
-                       // Allow log messages to use a configured prefix to identify the source window (ie. frame)
-                       prefix = mw.config.exists( 'mw.log.prefix' ) ? mw.config.get( 'mw.log.prefix' ) + '> ' : '';
-
-               // Try to use an existing console
-               // Generally we can cache this, but in this case we want to re-evaluate this as a
-               // global property live so that things like Firebug Lite can take precedence.
-               if ( window.console && window.console.log && window.console.log.apply ) {
-                       args.unshift( prefix );
-                       window.console.log.apply( window.console, args );
-                       return;
-               }
-
-               // If there is no console, use our own log box
-               mw.loader.using( 'jquery.footHovzer', function () {
-
-                       var     hovzer,
-                               d = new Date(),
-                               // Create HH:MM:SS.MIL timestamp
-                               time = ( d.getHours() < 10 ? '0' + d.getHours() : d.getHours() ) +
-                                ':' + ( d.getMinutes() < 10 ? '0' + d.getMinutes() : d.getMinutes() ) +
-                                ':' + ( d.getSeconds() < 10 ? '0' + d.getSeconds() : d.getSeconds() ) +
-                                '.' + ( d.getMilliseconds() < 10 ? '00' + d.getMilliseconds() : ( d.getMilliseconds() < 100 ? '0' + d.getMilliseconds() : d.getMilliseconds() ) ),
-                                $log = $( '#mw-log-console' );
-
-                       if ( !$log.length ) {
-                               $log = $( '<div id="mw-log-console"></div>' ).css( {
-                                               overflow: 'auto',
-                                               height: '150px',
-                                               backgroundColor: 'white',
-                                               borderTop: 'solid 2px #ADADAD'
-                                       } );
-                               hovzer = $.getFootHovzer();
-                               hovzer.$.append( $log );
-                               hovzer.update();
-                       }
-                       $log.append(
-                               $( '<div>' )
-                                       .css( {
-                                               borderBottom: 'solid 1px #DDDDDD',
-                                               fontSize: 'small',
-                                               fontFamily: 'monospace',
-                                               whiteSpace: 'pre-wrap',
-                                               padding: '0.125em 0.25em'
-                                       } )
-                                       .text( prefix + args.join( ', ' ) )
-                                       .prepend( '<span style="float: right;">[' + time + ']</span>' )
-                       );
-               } );
-       };
-
-       // Restore original methods
-       mw.log.warn = original.warn;
-       mw.log.deprecate = original.deprecate;
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.notification.css b/resources/mediawiki/mediawiki.notification.css
deleted file mode 100644 (file)
index 0c8152e..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-.mw-notification-area {
-       position: absolute;
-       top: 0;
-       right: 0;
-       padding: 1em 1em 0 0;
-       width: 20em;
-       line-height: 1.35;
-       z-index: 10000;
-}
-
-.mw-notification-area-floating {
-       position: fixed;
-}
-
-* html .mw-notification-area-floating {
-       /* Make it at least 'absolute' in IE6 since 'fixed' is not supported */
-       position: absolute;
-}
-
-.mw-notification {
-       padding: 0.25em 1em;
-       margin-bottom: 0.5em;
-       border: solid 1px #ddd;
-       background-color: #fcfcfc;
-       /* Message hides on-click */
-       /* See also mediawiki.notification.js */
-       cursor: pointer;
-}
-
-.mw-notification-title {
-       font-weight: bold;
-}
diff --git a/resources/mediawiki/mediawiki.notification.hideForPrint.css b/resources/mediawiki/mediawiki.notification.hideForPrint.css
deleted file mode 100644 (file)
index 4f9162e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.mw-notification-area {
-       display: none;
-}
diff --git a/resources/mediawiki/mediawiki.notification.js b/resources/mediawiki/mediawiki.notification.js
deleted file mode 100644 (file)
index b5fd69c..0000000
+++ /dev/null
@@ -1,522 +0,0 @@
-( function ( mw, $ ) {
-       'use strict';
-
-       var notification,
-               // The #mw-notification-area div that all notifications are contained inside.
-               $area,
-               // Number of open notification boxes at any time
-               openNotificationCount = 0,
-               isPageReady = false,
-               preReadyNotifQueue = [];
-
-       /**
-        * A Notification object for 1 message.
-        *
-        * The "_" in the name is to avoid a bug (http://github.com/senchalabs/jsduck/issues/304).
-        * It is not part of the actual class name.
-        *
-        * @class mw.Notification_
-        * @alternateClassName mw.Notification
-        *
-        * @constructor The constructor is not publicly accessible; use mw.notification#notify instead.
-        *  This does not insert anything into the document (see #start).
-        * @private
-        */
-       function Notification( message, options ) {
-               var $notification, $notificationTitle, $notificationContent;
-
-               $notification = $( '<div class="mw-notification"></div>' )
-                       .data( 'mw.notification', this )
-                       .addClass( options.autoHide ? 'mw-notification-autohide' : 'mw-notification-noautohide' );
-
-               if ( options.tag ) {
-                       // Sanitize options.tag before it is used by any code. (Including Notification class methods)
-                       options.tag = options.tag.replace( /[ _\-]+/g, '-' ).replace( /[^\-a-z0-9]+/ig, '' );
-                       if ( options.tag ) {
-                               $notification.addClass( 'mw-notification-tag-' + options.tag );
-                       } else {
-                               delete options.tag;
-                       }
-               }
-
-               if ( options.title ) {
-                       $notificationTitle = $( '<div class="mw-notification-title"></div>' )
-                               .text( options.title )
-                               .appendTo( $notification );
-               }
-
-               $notificationContent = $( '<div class="mw-notification-content"></div>' );
-
-               if ( typeof message === 'object' ) {
-                       // Handle mw.Message objects separately from DOM nodes and jQuery objects
-                       if ( message instanceof mw.Message ) {
-                               $notificationContent.html( message.parse() );
-                       } else {
-                               $notificationContent.append( message );
-                       }
-               } else {
-                       $notificationContent.text( message );
-               }
-
-               $notificationContent.appendTo( $notification );
-
-               // Private state parameters, meant for internal use only
-               // isOpen: Set to true after .start() is called to avoid double calls.
-               //         Set back to false after .close() to avoid duplicating the close animation.
-               // isPaused: false after .resume(), true after .pause(). Avoids duplicating or breaking the hide timeouts.
-               //           Set to true initially so .start() can call .resume().
-               // message: The message passed to the notification. Unused now but may be used in the future
-               //          to stop replacement of a tagged notification with another notification using the same message.
-               // options: The options passed to the notification with a little sanitization. Used by various methods.
-               // $notification: jQuery object containing the notification DOM node.
-               this.isOpen = false;
-               this.isPaused = true;
-               this.message = message;
-               this.options = options;
-               this.$notification = $notification;
-       }
-
-       /**
-        * Start the notification. Called automatically by mw.notification#notify
-        * (possibly asynchronously on document-ready).
-        *
-        * This inserts the notification into the page, closes any matching tagged notifications,
-        * handles the fadeIn animations and replacement transitions, and starts autoHide timers.
-        *
-        * @private
-        */
-       Notification.prototype.start = function () {
-               var
-                       // Local references
-                       $notification, options,
-                       // Original opacity so that we can animate back to it later
-                       opacity,
-                       // Other notification elements matching the same tag
-                       $tagMatches,
-                       outerHeight,
-                       placeholderHeight,
-                       autohideCount,
-                       notif;
-
-               $area.show();
-
-               if ( this.isOpen ) {
-                       return;
-               }
-
-               this.isOpen = true;
-               openNotificationCount++;
-
-               options = this.options;
-               $notification = this.$notification;
-
-               opacity = this.$notification.css( 'opacity' );
-
-               // Set the opacity to 0 so we can fade in later.
-               $notification.css( 'opacity', 0 );
-
-               if ( options.tag ) {
-                       // Check to see if there are any tagged notifications with the same tag as the new one
-                       $tagMatches = $area.find( '.mw-notification-tag-' + options.tag );
-               }
-
-               // If we found a tagged notification use the replacement pattern instead of the new
-               // notification fade-in pattern.
-               if ( options.tag && $tagMatches.length ) {
-
-                       // Iterate over the tag matches to find the outerHeight we should use
-                       // for the placeholder.
-                       outerHeight = 0;
-                       $tagMatches.each( function () {
-                               var notif = $( this ).data( 'mw.notification' );
-                               if ( notif ) {
-                                       // Use the notification's height + padding + border + margins
-                                       // as the placeholder height.
-                                       outerHeight = notif.$notification.outerHeight( true );
-                                       if ( notif.$replacementPlaceholder ) {
-                                               // Grab the height of a placeholder that has not finished animating.
-                                               placeholderHeight = notif.$replacementPlaceholder.height();
-                                               // Remove any placeholders added by a previous tagged
-                                               // notification that was in the middle of replacing another.
-                                               // This also makes sure that we only grab the placeholderHeight
-                                               // for the most recent notification.
-                                               notif.$replacementPlaceholder.remove();
-                                               delete notif.$replacementPlaceholder;
-                                       }
-                                       // Close the previous tagged notification
-                                       // Since we're replacing it do this with a fast speed and don't output a placeholder
-                                       // since we're taking care of that transition ourselves.
-                                       notif.close( { speed: 'fast', placeholder: false } );
-                               }
-                       } );
-                       if ( placeholderHeight !== undefined ) {
-                               // If the other tagged notification was in the middle of replacing another
-                               // tagged notification, continue from the placeholder's height instead of
-                               // using the outerHeight of the notification.
-                               outerHeight = placeholderHeight;
-                       }
-
-                       $notification
-                               // Insert the new notification before the tagged notification(s)
-                               .insertBefore( $tagMatches.first() )
-                               .css( {
-                                       // Use an absolute position so that we can use a placeholder to gracefully push other notifications
-                                       // into the right spot.
-                                       position: 'absolute',
-                                       width: $notification.width()
-                               } )
-                               // Fade-in the notification
-                               .animate( { opacity: opacity },
-                                       {
-                                               duration: 'slow',
-                                               complete: function () {
-                                                       // After we've faded in clear the opacity and let css take over
-                                                       $( this ).css( { opacity: '' } );
-                                               }
-                                       } );
-
-                       notif = this;
-
-                       // Create a clear placeholder we can use to make the notifications around the notification that is being
-                       // replaced expand or contract gracefully to fit the height of the new notification.
-                       notif.$replacementPlaceholder = $( '<div>' )
-                               // Set the height to the space the previous notification or placeholder took
-                               .css( 'height', outerHeight )
-                               // Make sure that this placeholder is at the very end of this tagged notification group
-                               .insertAfter( $tagMatches.eq( -1 ) )
-                               // Animate the placeholder height to the space that this new notification will take up
-                               .animate( { height: $notification.outerHeight( true ) },
-                                       {
-                                               // Do space animations fast
-                                               speed: 'fast',
-                                               complete: function () {
-                                                       // Reset the notification position after we've finished the space animation
-                                                       // However do not do it if the placeholder was removed because another tagged
-                                                       // notification went and closed this one.
-                                                       if ( notif.$replacementPlaceholder ) {
-                                                               $notification.css( 'position', '' );
-                                                       }
-                                                       // Finally, remove the placeholder from the DOM
-                                                       $( this ).remove();
-                                               }
-                                       } );
-               } else {
-                       // Append to the notification area and fade in to the original opacity.
-                       $notification
-                               .appendTo( $area )
-                               .animate( { opacity: opacity },
-                                       {
-                                               duration: 'fast',
-                                               complete: function () {
-                                                       // After we've faded in clear the opacity and let css take over
-                                                       $( this ).css( 'opacity', '' );
-                                               }
-                                       }
-                               );
-               }
-
-               // By default a notification is paused.
-               // If this notification is within the first {autoHideLimit} notifications then
-               // start the auto-hide timer as soon as it's created.
-               autohideCount = $area.find( '.mw-notification-autohide' ).length;
-               if ( autohideCount <= notification.autoHideLimit ) {
-                       this.resume();
-               }
-       };
-
-       /**
-        * Pause any running auto-hide timer for this notification
-        */
-       Notification.prototype.pause = function () {
-               if ( this.isPaused ) {
-                       return;
-               }
-               this.isPaused = true;
-
-               if ( this.timeout ) {
-                       clearTimeout( this.timeout );
-                       delete this.timeout;
-               }
-       };
-
-       /**
-        * Start autoHide timer if not already started.
-        * Does nothing if autoHide is disabled.
-        * Either to resume from pause or to make the first start.
-        */
-       Notification.prototype.resume = function () {
-               var notif = this;
-               if ( !notif.isPaused ) {
-                       return;
-               }
-               // Start any autoHide timeouts
-               if ( notif.options.autoHide ) {
-                       notif.isPaused = false;
-                       notif.timeout = setTimeout( function () {
-                               // Already finished, so don't try to re-clear it
-                               delete notif.timeout;
-                               notif.close();
-                       }, notification.autoHideSeconds * 1000 );
-               }
-       };
-
-       /**
-        * Close/hide the notification.
-        *
-        * @param {Object} options An object containing options for the closing of the notification.
-        *
-        *  - speed: Use a close speed different than the default 'slow'.
-        *  - placeholder: Set to false to disable the placeholder transition.
-        */
-       Notification.prototype.close = function ( options ) {
-               if ( !this.isOpen ) {
-                       return;
-               }
-               this.isOpen = false;
-               openNotificationCount--;
-               // Clear any remaining timeout on close
-               this.pause();
-
-               options = $.extend( {
-                       speed: 'slow',
-                       placeholder: true
-               }, options );
-
-               // Remove the mw-notification-autohide class from the notification to avoid
-               // having a half-closed notification counted as a notification to resume
-               // when handling {autoHideLimit}.
-               this.$notification.removeClass( 'mw-notification-autohide' );
-
-               // Now that a notification is being closed. Start auto-hide timers for any
-               // notification that has now become one of the first {autoHideLimit} notifications.
-               notification.resume();
-
-               this.$notification
-                       .css( {
-                               // Don't trigger any mouse events while fading out, just in case the cursor
-                               // happens to be right above us when we transition upwards.
-                               pointerEvents: 'none',
-                               // Set an absolute position so we can move upwards in the animation.
-                               // Notification replacement doesn't look right unless we use an animation like this.
-                               position: 'absolute',
-                               // We must fix the width to avoid it shrinking horizontally.
-                               width: this.$notification.width()
-                       } )
-                       // Fix the top/left position to the current computed position from which we
-                       // can animate upwards.
-                       .css( this.$notification.position() );
-
-               // This needs to be done *after* notification's position has been made absolute.
-               if ( options.placeholder ) {
-                       // Insert a placeholder with a height equal to the height of the
-                       // notification plus it's vertical margins in place of the notification
-                       var $placeholder = $( '<div>' )
-                               .css( 'height', this.$notification.outerHeight( true ) )
-                               .insertBefore( this.$notification );
-               }
-
-               // Animate opacity and top to create fade upwards animation for notification closing
-               this.$notification
-                       .animate( {
-                               opacity: 0,
-                               top: '-=35'
-                       }, {
-                               duration: options.speed,
-                               complete: function () {
-                                       // Remove the notification
-                                       $( this ).remove();
-                                       // Hide the area manually after closing the last notification, since it has padding,
-                                       // causing it to obscure whatever is behind it in spite of being invisible (bug 52659).
-                                       // It's okay to do this before getting rid of the placeholder, as it's invisible as well.
-                                       if ( openNotificationCount === 0 ) {
-                                               $area.hide();
-                                       }
-                                       if ( options.placeholder ) {
-                                               // Use a fast slide up animation after closing to make it look like the notifications
-                                               // below slide up into place when the notification disappears
-                                               $placeholder.slideUp( 'fast', function () {
-                                                       // Remove the placeholder
-                                                       $( this ).remove();
-                                               } );
-                                       }
-                               }
-                       } );
-       };
-
-       /**
-        * Helper function, take a list of notification divs and call
-        * a function on the Notification instance attached to them.
-        *
-        * @private
-        * @static
-        * @param {jQuery} $notifications A jQuery object containing notification divs
-        * @param {string} fn The name of the function to call on the Notification instance
-        */
-       function callEachNotification( $notifications, fn ) {
-               $notifications.each( function () {
-                       var notif = $( this ).data( 'mw.notification' );
-                       if ( notif ) {
-                               notif[fn]();
-                       }
-               } );
-       }
-
-       /**
-        * Initialisation.
-        * Must only be called once, and not before the document is ready.
-        * @ignore
-        */
-       function init() {
-               var offset, $window = $( window );
-
-               $area = $( '<div id="mw-notification-area" class="mw-notification-area mw-notification-area-layout"></div>' )
-                       // Pause auto-hide timers when the mouse is in the notification area.
-                       .on( {
-                               mouseenter: notification.pause,
-                               mouseleave: notification.resume
-                       } )
-                       // When clicking on a notification close it.
-                       .on( 'click', '.mw-notification', function () {
-                               var notif = $( this ).data( 'mw.notification' );
-                               if ( notif ) {
-                                       notif.close();
-                               }
-                       } )
-                       // Stop click events from <a> tags from propogating to prevent clicking.
-                       // on links from hiding a notification.
-                       .on( 'click', 'a', function ( e ) {
-                               e.stopPropagation();
-                       } );
-
-               // Prepend the notification area to the content area and save it's object.
-               mw.util.$content.prepend( $area );
-               offset = $area.offset();
-
-               function updateAreaMode() {
-                       var isFloating = $window.scrollTop() > offset.top;
-                       $area
-                               .toggleClass( 'mw-notification-area-floating', isFloating )
-                               .toggleClass( 'mw-notification-area-layout', !isFloating );
-               }
-
-               $window.on( 'scroll', updateAreaMode );
-
-               // Initial mode
-               updateAreaMode();
-       }
-
-       /**
-        * @class mw.notification
-        * @singleton
-        */
-       notification = {
-               /**
-                * Pause auto-hide timers for all notifications.
-                * Notifications will not auto-hide until resume is called.
-                * @see mw.Notification#pause
-                */
-               pause: function () {
-                       callEachNotification(
-                               $area.children( '.mw-notification' ),
-                               'pause'
-                       );
-               },
-
-               /**
-                * Resume any paused auto-hide timers from the beginning.
-                * Only the first #autoHideLimit timers will be resumed.
-                */
-               resume: function () {
-                       callEachNotification(
-                               // Only call resume on the first #autoHideLimit notifications.
-                               // Exclude noautohide notifications to avoid bugs where #autoHideLimit
-                               // `{ autoHide: false }` notifications are at the start preventing any
-                               // auto-hide notifications from being autohidden.
-                               $area.children( '.mw-notification-autohide' ).slice( 0, notification.autoHideLimit ),
-                               'resume'
-                       );
-               },
-
-               /**
-                * Display a notification message to the user.
-                *
-                * @param {HTMLElement|jQuery|mw.Message|string} message
-                * @param {Object} options The options to use for the notification.
-                *  See #defaults for details.
-                * @return {mw.Notification} Notification object
-                */
-               notify: function ( message, options ) {
-                       var notif;
-                       options = $.extend( {}, notification.defaults, options );
-
-                       notif = new Notification( message, options );
-
-                       if ( isPageReady ) {
-                               notif.start();
-                       } else {
-                               preReadyNotifQueue.push( notif );
-                       }
-
-                       return notif;
-               },
-
-               /**
-                * @property {Object}
-                * The defaults for #notify options parameter.
-                *
-                * - autoHide:
-                *   A boolean indicating whether the notifification should automatically
-                *   be hidden after shown. Or if it should persist.
-                *
-                * - tag:
-                *   An optional string. When a notification is tagged only one message
-                *   with that tag will be displayed. Trying to display a new notification
-                *   with the same tag as one already being displayed will cause the other
-                *   notification to be closed and this new notification to open up inside
-                *   the same place as the previous notification.
-                *
-                * - title:
-                *   An optional title for the notification. Will be displayed above the
-                *   content. Usually in bold.
-                */
-               defaults: {
-                       autoHide: true,
-                       tag: false,
-                       title: undefined
-               },
-
-               /**
-                * @property {number}
-                * Number of seconds to wait before auto-hiding notifications.
-                */
-               autoHideSeconds: 5,
-
-               /**
-                * @property {number}
-                * Maximum number of notifications to count down auto-hide timers for.
-                * Only the first #autoHideLimit notifications being displayed will
-                * auto-hide. Any notifications further down in the list will only start
-                * counting down to auto-hide after the first few messages have closed.
-                *
-                * This basically represents the number of notifications the user should
-                * be able to process in #autoHideSeconds time.
-                */
-               autoHideLimit: 3
-       };
-
-       $( function () {
-               var notif;
-
-               init();
-
-               // Handle pre-ready queue.
-               isPageReady = true;
-               while ( preReadyNotifQueue.length ) {
-                       notif = preReadyNotifQueue.shift();
-                       notif.start();
-               }
-       } );
-
-       mw.notification = notification;
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.notify.js b/resources/mediawiki/mediawiki.notify.js
deleted file mode 100644 (file)
index 743d651..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * @class mw.plugin.notify
- */
-( function ( mw, $ ) {
-       'use strict';
-
-       /**
-        * @see mw.notification#notify
-        * @param message
-        * @param options
-        * @return {jQuery.Promise}
-        */
-       mw.notify = function ( message, options ) {
-               var d = $.Deferred();
-               // Don't bother loading the whole notification system if we never use it.
-               mw.loader.using( 'mediawiki.notification', function () {
-                       // Call notify with the notification the user requested of us.
-                       d.resolve( mw.notification.notify( message, options ) );
-               }, d.reject );
-               return d.promise();
-       };
-
-       /**
-        * @class mw
-        * @mixins mw.plugin.notify
-        */
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.searchSuggest.css b/resources/mediawiki/mediawiki.searchSuggest.css
deleted file mode 100644 (file)
index 0fb862b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Make sure the links are not underlined or colored, ever. */
-/* There is already a :focus / :hover indication on the <div>. */
-.suggestions a.mw-searchSuggest-link,
-.suggestions a.mw-searchSuggest-link:hover,
-.suggestions a.mw-searchSuggest-link:active,
-.suggestions a.mw-searchSuggest-link:focus {
-       text-decoration: none;
-       color: black;
-}
-
-.suggestions-result-current a.mw-searchSuggest-link,
-.suggestions-result-current a.mw-searchSuggest-link:hover,
-.suggestions-result-current a.mw-searchSuggest-link:active,
-.suggestions-result-current a.mw-searchSuggest-link:focus {
-       color: white;
-}
diff --git a/resources/mediawiki/mediawiki.searchSuggest.js b/resources/mediawiki/mediawiki.searchSuggest.js
deleted file mode 100644 (file)
index 6999610..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*!
- * Add search suggestions to the search form.
- */
-( function ( mw, $ ) {
-       $( function () {
-               var map, resultRenderCache, searchboxesSelectors,
-                       // Region where the suggestions box will appear directly below
-                       // (using the same width). Can be a container element or the input
-                       // itself, depending on what suits best in the environment.
-                       // For Vector the suggestion box should align with the simpleSearch
-                       // container's borders, in other skins it should align with the input
-                       // element (not the search form, as that would leave the buttons
-                       // vertically between the input and the suggestions).
-                       $searchRegion = $( '#simpleSearch, #searchInput' ).first(),
-                       $searchInput = $( '#searchInput' );
-
-               // Compatibility map
-               map = {
-                       // SimpleSearch is broken in Opera < 9.6
-                       opera: [['>=', 9.6]],
-                       // Older Konquerors are unable to position the suggestions correctly (bug 50805)
-                       konqueror: [['>=', '4.11']],
-                       docomo: false,
-                       blackberry: false,
-                       ipod: false,
-                       iphone: false
-               };
-
-               if ( !$.client.test( map ) ) {
-                       return;
-               }
-
-               // Compute form data for search suggestions functionality.
-               function computeResultRenderCache( context ) {
-                       var $form, baseHref, linkParams;
-
-                       // Compute common parameters for links' hrefs
-                       $form = context.config.$region.closest( 'form' );
-
-                       baseHref = $form.attr( 'action' );
-                       baseHref += baseHref.indexOf( '?' ) > -1 ? '&' : '?';
-
-                       linkParams = {};
-                       $.each( $form.serializeArray(), function ( idx, obj ) {
-                               linkParams[ obj.name ] = obj.value;
-                       } );
-
-                       return {
-                               textParam: context.data.$textbox.attr( 'name' ),
-                               linkParams: linkParams,
-                               baseHref: baseHref
-                       };
-               }
-
-               // The function used to render the suggestions.
-               function renderFunction( text, context ) {
-                       if ( !resultRenderCache ) {
-                               resultRenderCache = computeResultRenderCache( context );
-                       }
-
-                       // linkParams object is modified and reused
-                       resultRenderCache.linkParams[ resultRenderCache.textParam ] = text;
-
-                       // this is the container <div>, jQueryfied
-                       this
-                               .append(
-                                       // the <span> is needed for $.autoEllipsis to work
-                                       $( '<span>' )
-                                               .css( 'whiteSpace', 'nowrap' )
-                                               .text( text )
-                               )
-                               .wrap(
-                                       $( '<a>' )
-                                               .attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) )
-                                               .addClass( 'mw-searchSuggest-link' )
-                               );
-               }
-
-               function specialRenderFunction( query, context ) {
-                       var $el = this;
-
-                       if ( !resultRenderCache ) {
-                               resultRenderCache = computeResultRenderCache( context );
-                       }
-
-                       // linkParams object is modified and reused
-                       resultRenderCache.linkParams[ resultRenderCache.textParam ] = query;
-
-                       if ( $el.children().length === 0 ) {
-                               $el
-                                       .append(
-                                               $( '<div>' )
-                                                       .addClass( 'special-label' )
-                                                       .text( mw.msg( 'searchsuggest-containing' ) ),
-                                               $( '<div>' )
-                                                       .addClass( 'special-query' )
-                                                       .text( query )
-                                                       .autoEllipsis()
-                                       )
-                                       .show();
-                       } else {
-                               $el.find( '.special-query' )
-                                       .text( query )
-                                       .autoEllipsis();
-                       }
-
-                       if ( $el.parent().hasClass( 'mw-searchSuggest-link' ) ) {
-                               $el.parent().attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) + '&fulltext=1' );
-                       } else {
-                               $el.wrap(
-                                       $( '<a>' )
-                                               .attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) + '&fulltext=1' )
-                                               .addClass( 'mw-searchSuggest-link' )
-                               );
-                       }
-               }
-
-               // General suggestions functionality for all search boxes
-               searchboxesSelectors = [
-                       // Primary searchbox on every page in standard skins
-                       '#searchInput',
-                       // Special:Search
-                       '#powerSearchText',
-                       '#searchText',
-                       // Generic selector for skins with multiple searchboxes (used by CologneBlue)
-                       '.mw-searchInput'
-               ];
-               $( searchboxesSelectors.join( ', ' ) )
-                       .suggestions( {
-                               fetch: function ( query ) {
-                                       var $el;
-
-                                       if ( query.length !== 0 ) {
-                                               $el = $( this );
-                                               $el.data( 'request', ( new mw.Api() ).get( {
-                                                       action: 'opensearch',
-                                                       search: query,
-                                                       namespace: 0,
-                                                       suggest: ''
-                                               } ).done( function ( data ) {
-                                                       $el.suggestions( 'suggestions', data[1] );
-                                               } ) );
-                                       }
-                               },
-                               cancel: function () {
-                                       var apiPromise = $( this ).data( 'request' );
-                                       // If the delay setting has caused the fetch to have not even happened
-                                       // yet, the apiPromise object will have never been set.
-                                       if ( apiPromise && $.isFunction( apiPromise.abort ) ) {
-                                               apiPromise.abort();
-                                               $( this ).removeData( 'request' );
-                                       }
-                               },
-                               result: {
-                                       render: renderFunction,
-                                       select: function () {
-                                               return true; // allow the form to be submitted
-                                       }
-                               },
-                               delay: 120,
-                               highlightInput: true
-                       } )
-                       .bind( 'paste cut drop', function () {
-                               // make sure paste and cut events from the mouse and drag&drop events
-                               // trigger the keypress handler and cause the suggestions to update
-                               $( this ).trigger( 'keypress' );
-                       } );
-
-               // Ensure that the thing is actually present!
-               if ( $searchRegion.length === 0 ) {
-                       // Don't try to set anything up if simpleSearch is disabled sitewide.
-                       // The loader code loads us if the option is present, even if we're
-                       // not actually enabled (anymore).
-                       return;
-               }
-
-               // Special suggestions functionality for skin-provided search box
-               $searchInput.suggestions( {
-                       result: {
-                               render: renderFunction,
-                               select: function () {
-                                       return true; // allow the form to be submitted
-                               }
-                       },
-                       special: {
-                               render: specialRenderFunction,
-                               select: function ( $input ) {
-                                       $input.closest( 'form' )
-                                               .append( $( '<input type="hidden" name="fulltext" value="1"/>' ) );
-                                       return true; // allow the form to be submitted
-                               }
-                       },
-                       $region: $searchRegion
-               } );
-
-               // If the form includes any fallback fulltext search buttons, remove them
-               $searchInput.closest( 'form' ).find( '.mw-fallbackSearchButton' ).remove();
-
-               // In most skins (at least Monobook and Vector), the font-size is messed up in <body>.
-               // (they use 2 elements to get a sane font-height). So, instead of making exceptions for
-               // each skin or adding more stylesheets, just copy it from the active element so auto-fit.
-               $searchInput
-                       .data( 'suggestions-context' )
-                       .data.$container
-                               .css( 'fontSize', $searchInput.css( 'fontSize' ) );
-
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.toc.js b/resources/mediawiki/mediawiki.toc.js
deleted file mode 100644 (file)
index 6eb8552..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * @private
- * @singleton
- * @class mw.toc
- */
-( function ( mw, $ ) {
-       'use strict';
-
-       // Table of contents toggle
-       mw.hook( 'wikipage.content' ).add( function ( $content ) {
-
-               /**
-                * Hide/show the table of contents element
-                *
-                * @param {jQuery} $toggleLink A jQuery object of the toggle link.
-                */
-               function toggleToc( $toggleLink ) {
-                       var $tocList = $content.find( '#toc ul:first' );
-
-                       // This function shouldn't be called if there's no TOC,
-                       // but just in case...
-                       if ( $tocList.length ) {
-                               if ( $tocList.is( ':hidden' ) ) {
-                                       $tocList.slideDown( 'fast' );
-                                       $toggleLink.text( mw.msg( 'hidetoc' ) );
-                                       $content.find( '#toc' ).removeClass( 'tochidden' );
-                                       $.cookie( 'mw_hidetoc', null, {
-                                               expires: 30,
-                                               path: '/'
-                                       } );
-                               } else {
-                                       $tocList.slideUp( 'fast' );
-                                       $toggleLink.text( mw.msg( 'showtoc' ) );
-                                       $content.find( '#toc' ).addClass( 'tochidden' );
-                                       $.cookie( 'mw_hidetoc', '1', {
-                                               expires: 30,
-                                               path: '/'
-                                       } );
-                               }
-                       }
-               }
-
-               var $tocTitle, $tocToggleLink, hideTocCookie;
-               $tocTitle = $content.find( '#toctitle' );
-               $tocToggleLink = $content.find( '#togglelink' );
-               // Only add it if there is a TOC and there is no toggle added already
-               if ( $content.find( '#toc' ).length && $tocTitle.length && !$tocToggleLink.length ) {
-                       hideTocCookie = $.cookie( 'mw_hidetoc' );
-                       $tocToggleLink = $( '<a href="#" class="internal" id="togglelink"></a>' )
-                               .text( mw.msg( 'hidetoc' ) )
-                               .click( function ( e ) {
-                                       e.preventDefault();
-                                       toggleToc( $( this ) );
-                               } );
-                       $tocTitle.append(
-                               $tocToggleLink
-                                       .wrap( '<span class="toctoggle"></span>' )
-                                       .parent()
-                                               .prepend( '&nbsp;[' )
-                                               .append( ']&nbsp;' )
-                       );
-
-                       if ( hideTocCookie === '1' ) {
-                               toggleToc( $tocToggleLink );
-                       }
-               }
-       } );
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.user.js b/resources/mediawiki/mediawiki.user.js
deleted file mode 100644 (file)
index 8344111..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/**
- * @class mw.user
- * @singleton
- */
-( function ( mw, $ ) {
-       var user,
-               deferreds = {},
-               // Extend the skeleton mw.user from mediawiki.js
-               // This is kind of ugly but we're stuck with this for b/c reasons
-               options = mw.user.options || new mw.Map(),
-               tokens = mw.user.tokens || new mw.Map();
-
-       /**
-        * Get the current user's groups or rights
-        *
-        * @private
-        * @param {string} info One of 'groups' or 'rights'
-        * @param {Function} [callback]
-        * @return {jQuery.Promise}
-        */
-       function getUserInfo( info, callback ) {
-               var api;
-               if ( !deferreds[info] ) {
-
-                       deferreds.rights = $.Deferred();
-                       deferreds.groups = $.Deferred();
-
-                       api = new mw.Api();
-                       api.get( {
-                               action: 'query',
-                               meta: 'userinfo',
-                               uiprop: 'rights|groups'
-                       } ).always( function ( data ) {
-                               var rights, groups;
-                               if ( data.query && data.query.userinfo ) {
-                                       rights = data.query.userinfo.rights;
-                                       groups = data.query.userinfo.groups;
-                               }
-                               deferreds.rights.resolve( rights || [] );
-                               deferreds.groups.resolve( groups || [] );
-                       } );
-
-               }
-
-               return deferreds[info].done( callback ).promise();
-       }
-
-       mw.user = user = {
-               options: options,
-               tokens: tokens,
-
-               /**
-                * Generate a random user session ID (32 alpha-numeric characters)
-                *
-                * This information would potentially be stored in a cookie to identify a user during a
-                * session or series of sessions. Its uniqueness should not be depended on.
-                *
-                * @return {string} Random set of 32 alpha-numeric characters
-                */
-               generateRandomSessionId: function () {
-                       var i, r,
-                               id = '',
-                               seed = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
-                       for ( i = 0; i < 32; i++ ) {
-                               r = Math.floor( Math.random() * seed.length );
-                               id += seed.substring( r, r + 1 );
-                       }
-                       return id;
-               },
-
-               /**
-                * Get the current user's database id
-                *
-                * Not to be confused with #id.
-                *
-                * @return {number} Current user's id, or 0 if user is anonymous
-                */
-               getId: function () {
-                       return mw.config.get( 'wgUserId', 0 );
-               },
-
-               /**
-                * Get the current user's name
-                *
-                * @return {string|null} User name string or null if user is anonymous
-                */
-               getName: function () {
-                       return mw.config.get( 'wgUserName' );
-               },
-
-               /**
-                * @inheritdoc #getName
-                * @deprecated since 1.20 use #getName instead
-                */
-               name: function () {
-                       return user.getName();
-               },
-
-               /**
-                * Get date user registered, if available
-                *
-                * @return {Date|boolean|null} Date user registered, or false for anonymous users, or
-                *  null when data is not available
-                */
-               getRegistration: function () {
-                       var registration = mw.config.get( 'wgUserRegistration' );
-                       if ( user.isAnon() ) {
-                               return false;
-                       } else if ( registration === null ) {
-                               // Information may not be available if they signed up before
-                               // MW began storing this.
-                               return null;
-                       } else {
-                               return new Date( registration );
-                       }
-               },
-
-               /**
-                * Whether the current user is anonymous
-                *
-                * @return {boolean}
-                */
-               isAnon: function () {
-                       return user.getName() === null;
-               },
-
-               /**
-                * @inheritdoc #isAnon
-                * @deprecated since 1.20 use #isAnon instead
-                */
-               anonymous: function () {
-                       return user.isAnon();
-               },
-
-               /**
-                * Get an automatically generated random ID (stored in a session cookie)
-                *
-                * This ID is ephemeral for everyone, staying in their browser only until they close
-                * their browser.
-                *
-                * @return {string} Random session ID
-                */
-               sessionId: function () {
-                       var sessionId = $.cookie( 'mediaWiki.user.sessionId' );
-                       if ( sessionId === undefined || sessionId === null ) {
-                               sessionId = user.generateRandomSessionId();
-                               $.cookie( 'mediaWiki.user.sessionId', sessionId, { expires: null, path: '/' } );
-                       }
-                       return sessionId;
-               },
-
-               /**
-                * Get the current user's name or the session ID
-                *
-                * Not to be confused with #getId.
-                *
-                * @return {string} User name or random session ID
-                */
-               id: function () {
-                       return user.getName() || user.sessionId();
-               },
-
-               /**
-                * Get the user's bucket (place them in one if not done already)
-                *
-                *     mw.user.bucket( 'test', {
-                *         buckets: { ignored: 50, control: 25, test: 25 },
-                *         version: 1,
-                *         expires: 7
-                *     } );
-                *
-                * @deprecated since 1.23
-                * @param {string} key Name of bucket
-                * @param {Object} options Bucket configuration options
-                * @param {Object} options.buckets List of bucket-name/relative-probability pairs (required,
-                *  must have at least one pair)
-                * @param {number} [options.version=0] Version of bucket test, changing this forces
-                *  rebucketing
-                * @param {number} [options.expires=30] Length of time (in days) until the user gets
-                *  rebucketed
-                * @return {string} Bucket name - the randomly chosen key of the `options.buckets` object
-                */
-               bucket: function ( key, options ) {
-                       var cookie, parts, version, bucket,
-                               range, k, rand, total;
-
-                       options = $.extend( {
-                               buckets: {},
-                               version: 0,
-                               expires: 30
-                       }, options || {} );
-
-                       cookie = $.cookie( 'mediaWiki.user.bucket:' + key );
-
-                       // Bucket information is stored as 2 integers, together as version:bucket like: "1:2"
-                       if ( typeof cookie === 'string' && cookie.length > 2 && cookie.indexOf( ':' ) !== -1 ) {
-                               parts = cookie.split( ':' );
-                               if ( parts.length > 1 && Number( parts[0] ) === options.version ) {
-                                       version = Number( parts[0] );
-                                       bucket = String( parts[1] );
-                               }
-                       }
-
-                       if ( bucket === undefined ) {
-                               if ( !$.isPlainObject( options.buckets ) ) {
-                                       throw new Error( 'Invalid bucket. Object expected for options.buckets.' );
-                               }
-
-                               version = Number( options.version );
-
-                               // Find range
-                               range = 0;
-                               for ( k in options.buckets ) {
-                                       range += options.buckets[k];
-                               }
-
-                               // Select random value within range
-                               rand = Math.random() * range;
-
-                               // Determine which bucket the value landed in
-                               total = 0;
-                               for ( k in options.buckets ) {
-                                       bucket = k;
-                                       total += options.buckets[k];
-                                       if ( total >= rand ) {
-                                               break;
-                                       }
-                               }
-
-                               $.cookie(
-                                       'mediaWiki.user.bucket:' + key,
-                                       version + ':' + bucket,
-                                       { path: '/', expires: Number( options.expires ) }
-                               );
-                       }
-
-                       return bucket;
-               },
-
-               /**
-                * Get the current user's groups
-                *
-                * @param {Function} [callback]
-                * @return {jQuery.Promise}
-                */
-               getGroups: function ( callback ) {
-                       return getUserInfo( 'groups', callback );
-               },
-
-               /**
-                * Get the current user's rights
-                *
-                * @param {Function} [callback]
-                * @return {jQuery.Promise}
-                */
-               getRights: function ( callback ) {
-                       return getUserInfo( 'rights', callback );
-               }
-       };
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/mediawiki/mediawiki.util.js b/resources/mediawiki/mediawiki.util.js
deleted file mode 100644 (file)
index ffafd33..0000000
+++ /dev/null
@@ -1,595 +0,0 @@
-( function ( mw, $ ) {
-       'use strict';
-
-       /**
-        * Utility library
-        * @class mw.util
-        * @singleton
-        */
-       var util = {
-
-               /**
-                * Initialisation
-                * (don't call before document ready)
-                */
-               init: function () {
-                       var profile;
-
-                       /* Set tooltipAccessKeyPrefix */
-                       profile = $.client.profile();
-
-                       // Opera on any platform
-                       if ( profile.name === 'opera' ) {
-                               util.tooltipAccessKeyPrefix = 'shift-esc-';
-
-                       // Chrome on any platform
-                       } else if ( profile.name === 'chrome' ) {
-
-                               util.tooltipAccessKeyPrefix = (
-                                       profile.platform === 'mac'
-                                               // Chrome on Mac
-                                               ? 'ctrl-option-'
-                                               // Chrome on Windows or Linux
-                                               // (both alt- and alt-shift work, but alt with E, D, F etc does not
-                                               // work since they are browser shortcuts)
-                                               : 'alt-shift-'
-                               );
-
-                       // Non-Windows Safari with webkit_version > 526
-                       } else if ( profile.platform !== 'win'
-                               && profile.name === 'safari'
-                               && profile.layoutVersion > 526 ) {
-                               util.tooltipAccessKeyPrefix = 'ctrl-alt-';
-                       // Firefox 14+ on Mac
-                       } else if ( profile.platform === 'mac'
-                               && profile.name === 'firefox'
-                               && profile.versionNumber >= 14 ) {
-                               util.tooltipAccessKeyPrefix = 'ctrl-option-';
-                       // Safari/Konqueror on any platform, or any browser on Mac
-                       // (but not Safari on Windows)
-                       } else if ( !( profile.platform === 'win' && profile.name === 'safari' )
-                                                       && ( profile.name === 'safari'
-                                                       || profile.platform === 'mac'
-                                                       || profile.name === 'konqueror' ) ) {
-                               util.tooltipAccessKeyPrefix = 'ctrl-';
-
-                       // Firefox/Iceweasel 2.x and later
-                       } else if ( ( profile.name === 'firefox' || profile.name === 'iceweasel' )
-                               && profile.versionBase > '1' ) {
-                               util.tooltipAccessKeyPrefix = 'alt-shift-';
-                       }
-
-                       /* Fill $content var */
-                       util.$content = ( function () {
-                               var i, l, $content, selectors;
-                               selectors = [
-                                       // The preferred standard for setting $content (class="mw-body")
-                                       // You may also use (class="mw-body mw-body-primary") if you use
-                                       // mw-body in multiple locations.
-                                       // Or class="mw-body-primary" if you want $content to be deeper
-                                       // in the dom than mw-body
-                                       '.mw-body-primary',
-                                       '.mw-body',
-
-                                       /* Legacy fallbacks for setting the content */
-                                       // Vector, Monobook, Chick, etc... based skins
-                                       '#bodyContent',
-
-                                       // Modern based skins
-                                       '#mw_contentholder',
-
-                                       // Standard, CologneBlue
-                                       '#article',
-
-                                       // #content is present on almost all if not all skins. Most skins (the above cases)
-                                       // have #content too, but as an outer wrapper instead of the article text container.
-                                       // The skins that don't have an outer wrapper do have #content for everything
-                                       // so it's a good fallback
-                                       '#content',
-
-                                       // If nothing better is found fall back to our bodytext div that is guaranteed to be here
-                                       '#mw-content-text',
-
-                                       // Should never happen... well, it could if someone is not finished writing a skin and has
-                                       // not inserted bodytext yet. But in any case <body> should always exist
-                                       'body'
-                               ];
-                               for ( i = 0, l = selectors.length; i < l; i++ ) {
-                                       $content = $( selectors[i] ).first();
-                                       if ( $content.length ) {
-                                               return $content;
-                                       }
-                               }
-
-                               // Make sure we don't unset util.$content if it was preset and we don't find anything
-                               return util.$content;
-                       } )();
-               },
-
-               /* Main body */
-
-               /**
-                * Encode the string like PHP's rawurlencode
-                *
-                * @param {string} str String to be encoded.
-                */
-               rawurlencode: function ( str ) {
-                       str = String( str );
-                       return encodeURIComponent( str )
-                               .replace( /!/g, '%21' ).replace( /'/g, '%27' ).replace( /\(/g, '%28' )
-                               .replace( /\)/g, '%29' ).replace( /\*/g, '%2A' ).replace( /~/g, '%7E' );
-               },
-
-               /**
-                * Encode page titles for use in a URL
-                * We want / and : to be included as literal characters in our title URLs
-                * as they otherwise fatally break the title
-                *
-                * @param {string} str String to be encoded.
-                */
-               wikiUrlencode: function ( str ) {
-                       return util.rawurlencode( str )
-                               .replace( /%20/g, '_' ).replace( /%3A/g, ':' ).replace( /%2F/g, '/' );
-               },
-
-               /**
-                * Get the link to a page name (relative to `wgServer`),
-                *
-                * @param {string} str Page name
-                * @param {Object} [params] A mapping of query parameter names to values,
-                *  e.g. `{ action: 'edit' }`
-                * @return {string} Url of the page with name of `str`
-                */
-               getUrl: function ( str, params ) {
-                       var url = mw.config.get( 'wgArticlePath' ).replace(
-                               '$1',
-                               util.wikiUrlencode( typeof str === 'string' ? str : mw.config.get( 'wgPageName' ) )
-                       );
-
-                       if ( params && !$.isEmptyObject( params ) ) {
-                               url += ( url.indexOf( '?' ) !== -1 ? '&' : '?' ) + $.param( params );
-                       }
-
-                       return url;
-               },
-
-               /**
-                * Get address to a script in the wiki root.
-                * For index.php use `mw.config.get( 'wgScript' )`.
-                *
-                * @since 1.18
-                * @param str string Name of script (eg. 'api'), defaults to 'index'
-                * @return string Address to script (eg. '/w/api.php' )
-                */
-               wikiScript: function ( str ) {
-                       str = str || 'index';
-                       if ( str === 'index' ) {
-                               return mw.config.get( 'wgScript' );
-                       } else if ( str === 'load' ) {
-                               return mw.config.get( 'wgLoadScript' );
-                       } else {
-                               return mw.config.get( 'wgScriptPath' ) + '/' + str +
-                                       mw.config.get( 'wgScriptExtension' );
-                       }
-               },
-
-               /**
-                * Append a new style block to the head and return the CSSStyleSheet object.
-                * Use .ownerNode to access the `<style>` element, or use mw.loader#addStyleTag.
-                * This function returns the styleSheet object for convience (due to cross-browsers
-                * difference as to where it is located).
-                *
-                *     var sheet = mw.util.addCSS( '.foobar { display: none; }' );
-                *     $( foo ).click( function () {
-                *         // Toggle the sheet on and off
-                *         sheet.disabled = !sheet.disabled;
-                *     } );
-                *
-                * @param {string} text CSS to be appended
-                * @return {CSSStyleSheet} Use .ownerNode to get to the `<style>` element.
-                */
-               addCSS: function ( text ) {
-                       var s = mw.loader.addStyleTag( text );
-                       return s.sheet || s.styleSheet || s;
-               },
-
-               /**
-                * Hide/show the table of contents element
-                *
-                * @param {jQuery} $toggleLink A jQuery object of the toggle link.
-                * @param {Function} [callback] Function to be called after the toggle is
-                *  completed (including the animation).
-                * @return {Mixed} Boolean visibility of the toc (true if it's visible)
-                * or Null if there was no table of contents.
-                * @deprecated since 1.23 Use jQuery
-                */
-               toggleToc: function ( $toggleLink, callback ) {
-                       var ret, $tocList = $( '#toc ul:first' );
-
-                       // This function shouldn't be called if there's no TOC,
-                       // but just in case...
-                       if ( !$tocList.length ) {
-                               return null;
-                       }
-                       ret = $tocList.is( ':hidden' );
-                       $toggleLink.click();
-                       $tocList.promise().done( callback );
-                       return ret;
-               },
-
-               /**
-                * Grab the URL parameter value for the given parameter.
-                * Returns null if not found.
-                *
-                * @param {string} param The parameter name.
-                * @param {string} [url=document.location.href] URL to search through, defaulting to the current document's URL.
-                * @return {Mixed} Parameter value or null.
-                */
-               getParamValue: function ( param, url ) {
-                       if ( url === undefined ) {
-                               url = document.location.href;
-                       }
-                       // Get last match, stop at hash
-                       var     re = new RegExp( '^[^#]*[&?]' + $.escapeRE( param ) + '=([^&#]*)' ),
-                               m = re.exec( url );
-                       if ( m ) {
-                               // Beware that decodeURIComponent is not required to understand '+'
-                               // by spec, as encodeURIComponent does not produce it.
-                               return decodeURIComponent( m[1].replace( /\+/g, '%20' ) );
-                       }
-                       return null;
-               },
-
-               /**
-                * @property {string}
-                * Access key prefix. Will be re-defined based on browser/operating system
-                * detection in mw.util#init.
-                */
-               tooltipAccessKeyPrefix: 'alt-',
-
-               /**
-                * @property {RegExp}
-                * Regex to match accesskey tooltips.
-                *
-                * Should match:
-                *
-                * - "ctrl-option-"
-                * - "alt-shift-"
-                * - "ctrl-alt-"
-                * - "ctrl-"
-                *
-                * The accesskey is matched in group $6.
-                */
-               tooltipAccessKeyRegexp: /\[(ctrl-)?(option-)?(alt-)?(shift-)?(esc-)?(.)\]$/,
-
-               /**
-                * Add the appropriate prefix to the accesskey shown in the tooltip.
-                *
-                * If the `$nodes` parameter is given, only those nodes are updated;
-                * otherwise, depending on browser support, we update either all elements
-                * with accesskeys on the page or a bunch of elements which are likely to
-                * have them on core skins.
-                *
-                * @param {Array|jQuery} [$nodes] A jQuery object, or array of nodes to update.
-                */
-               updateTooltipAccessKeys: function ( $nodes ) {
-                       if ( !$nodes ) {
-                               if ( document.querySelectorAll ) {
-                                       // If we're running on a browser where we can do this efficiently,
-                                       // just find all elements that have accesskeys. We can't use jQuery's
-                                       // polyfill for the selector since looping over all elements on page
-                                       // load might be too slow.
-                                       $nodes = $( document.querySelectorAll( '[accesskey]' ) );
-                               } else {
-                                       // Otherwise go through some elements likely to have accesskeys rather
-                                       // than looping over all of them. Unfortunately this will not fully
-                                       // work for custom skins with different HTML structures. Input, label
-                                       // and button should be rare enough that no optimizations are needed.
-                                       $nodes = $( '#column-one a, #mw-head a, #mw-panel a, #p-logo a, input, label, button' );
-                               }
-                       } else if ( !( $nodes instanceof $ ) ) {
-                               $nodes = $( $nodes );
-                       }
-
-                       $nodes.attr( 'title', function ( i, val ) {
-                               if ( val && util.tooltipAccessKeyRegexp.test( val ) ) {
-                                       return val.replace( util.tooltipAccessKeyRegexp,
-                                               '[' + util.tooltipAccessKeyPrefix + '$6]' );
-                               }
-                               return val;
-                       } );
-               },
-
-               /*
-                * @property {jQuery}
-                * A jQuery object that refers to the content area element.
-                * Populated by #init.
-                */
-               $content: null,
-
-               /**
-                * Add a link to a portlet menu on the page, such as:
-                *
-                * p-cactions (Content actions), p-personal (Personal tools),
-                * p-navigation (Navigation), p-tb (Toolbox)
-                *
-                * The first three paramters are required, the others are optional and
-                * may be null. Though providing an id and tooltip is recommended.
-                *
-                * By default the new link will be added to the end of the list. To
-                * add the link before a given existing item, pass the DOM node
-                * (e.g. `document.getElementById( 'foobar' )`) or a jQuery-selector
-                * (e.g. `'#foobar'`) for that item.
-                *
-                *     mw.util.addPortletLink(
-                *         'p-tb', 'http://mediawiki.org/',
-                *         'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org ', 'm', '#t-print'
-                *     );
-                *
-                * @param {string} portlet ID of the target portlet ( 'p-cactions' or 'p-personal' etc.)
-                * @param {string} href Link URL
-                * @param {string} text Link text
-                * @param {string} [id] ID of the new item, should be unique and preferably have
-                *  the appropriate prefix ( 'ca-', 'pt-', 'n-' or 't-' )
-                * @param {string} [tooltip] Text to show when hovering over the link, without accesskey suffix
-                * @param {string} [accesskey] Access key to activate this link (one character, try
-                *  to avoid conflicts. Use `$( '[accesskey=x]' ).get()` in the console to
-                *  see if 'x' is already used.
-                * @param {HTMLElement|jQuery|string} [nextnode] Element or jQuery-selector string to the item that
-                *  the new item should be added before, should be another item in the same
-                *  list, it will be ignored otherwise
-                *
-                * @return {HTMLElement|null} The added element (a ListItem or Anchor element,
-                * depending on the skin) or null if no element was added to the document.
-                */
-               addPortletLink: function ( portlet, href, text, id, tooltip, accesskey, nextnode ) {
-                       var $item, $link, $portlet, $ul;
-
-                       // Check if there's atleast 3 arguments to prevent a TypeError
-                       if ( arguments.length < 3 ) {
-                               return null;
-                       }
-                       // Setup the anchor tag
-                       $link = $( '<a>' ).attr( 'href', href ).text( text );
-                       if ( tooltip ) {
-                               $link.attr( 'title', tooltip );
-                       }
-
-                       // Select the specified portlet
-                       $portlet = $( '#' + portlet );
-                       if ( $portlet.length === 0 ) {
-                               return null;
-                       }
-                       // Select the first (most likely only) unordered list inside the portlet
-                       $ul = $portlet.find( 'ul' ).eq( 0 );
-
-                       // If it didn't have an unordered list yet, create it
-                       if ( $ul.length === 0 ) {
-
-                               $ul = $( '<ul>' );
-
-                               // If there's no <div> inside, append it to the portlet directly
-                               if ( $portlet.find( 'div:first' ).length === 0 ) {
-                                       $portlet.append( $ul );
-                               } else {
-                                       // otherwise if there's a div (such as div.body or div.pBody)
-                                       // append the <ul> to last (most likely only) div
-                                       $portlet.find( 'div' ).eq( -1 ).append( $ul );
-                               }
-                       }
-                       // Just in case..
-                       if ( $ul.length === 0 ) {
-                               return null;
-                       }
-
-                       // Unhide portlet if it was hidden before
-                       $portlet.removeClass( 'emptyPortlet' );
-
-                       // Wrap the anchor tag in a list item (and a span if $portlet is a Vector tab)
-                       // and back up the selector to the list item
-                       if ( $portlet.hasClass( 'vectorTabs' ) ) {
-                               $item = $link.wrap( '<li><span></span></li>' ).parent().parent();
-                       } else {
-                               $item = $link.wrap( '<li></li>' ).parent();
-                       }
-
-                       // Implement the properties passed to the function
-                       if ( id ) {
-                               $item.attr( 'id', id );
-                       }
-
-                       if ( tooltip ) {
-                               // Trim any existing accesskey hint and the trailing space
-                               tooltip = $.trim( tooltip.replace( util.tooltipAccessKeyRegexp, '' ) );
-                               if ( accesskey ) {
-                                       tooltip += ' [' + accesskey + ']';
-                               }
-                               $link.attr( 'title', tooltip );
-                               if ( accesskey ) {
-                                       util.updateTooltipAccessKeys( $link );
-                               }
-                       }
-
-                       if ( accesskey ) {
-                               $link.attr( 'accesskey', accesskey );
-                       }
-
-                       if ( nextnode ) {
-                               if ( nextnode.nodeType || typeof nextnode === 'string' ) {
-                                       // nextnode is a DOM element (was the only option before MW 1.17, in wikibits.js)
-                                       // or nextnode is a CSS selector for jQuery
-                                       nextnode = $ul.find( nextnode );
-                               } else if ( !nextnode.jquery || ( nextnode.length && nextnode[0].parentNode !== $ul[0] ) ) {
-                                       // Fallback
-                                       $ul.append( $item );
-                                       return $item[0];
-                               }
-                               if ( nextnode.length === 1 ) {
-                                       // nextnode is a jQuery object that represents exactly one element
-                                       nextnode.before( $item );
-                                       return $item[0];
-                               }
-                       }
-
-                       // Fallback (this is the default behavior)
-                       $ul.append( $item );
-                       return $item[0];
-
-               },
-
-               /**
-                * Add a little box at the top of the screen to inform the user of
-                * something, replacing any previous message.
-                * Calling with no arguments, with an empty string or null will hide the message
-                *
-                * @param {Mixed} message The DOM-element, jQuery object or HTML-string to be put inside the message box.
-                * to allow CSS/JS to hide different boxes. null = no class used.
-                * @deprecated since 1.20 Use mw#notify
-                */
-               jsMessage: function ( message ) {
-                       if ( !arguments.length || message === '' || message === null ) {
-                               return true;
-                       }
-                       if ( typeof message !== 'object' ) {
-                               message = $.parseHTML( message );
-                       }
-                       mw.notify( message, { autoHide: true, tag: 'legacy' } );
-                       return true;
-               },
-
-               /**
-                * Validate a string as representing a valid e-mail address
-                * according to HTML5 specification. Please note the specification
-                * does not validate a domain with one character.
-                *
-                * FIXME: should be moved to or replaced by a validation module.
-                *
-                * @param {string} mailtxt E-mail address to be validated.
-                * @return {boolean|null} Null if `mailtxt` was an empty string, otherwise true/false
-                * as determined by validation.
-                */
-               validateEmail: function ( mailtxt ) {
-                       var rfc5322Atext, rfc1034LdhStr, html5EmailRegexp;
-
-                       if ( mailtxt === '' ) {
-                               return null;
-                       }
-
-                       // HTML5 defines a string as valid e-mail address if it matches
-                       // the ABNF:
-                       //      1 * ( atext / "." ) "@" ldh-str 1*( "." ldh-str )
-                       // With:
-                       // - atext   : defined in RFC 5322 section 3.2.3
-                       // - ldh-str : defined in RFC 1034 section 3.5
-                       //
-                       // (see STD 68 / RFC 5234 http://tools.ietf.org/html/std68)
-                       // First, define the RFC 5322 'atext' which is pretty easy:
-                       // atext = ALPHA / DIGIT / ; Printable US-ASCII
-                       //     "!" / "#" /    ; characters not including
-                       //     "$" / "%" /    ; specials. Used for atoms.
-                       //     "&" / "'" /
-                       //     "*" / "+" /
-                       //     "-" / "/" /
-                       //     "=" / "?" /
-                       //     "^" / "_" /
-                       //     "`" / "{" /
-                       //     "|" / "}" /
-                       //     "~"
-                       rfc5322Atext = 'a-z0-9!#$%&\'*+\\-/=?^_`{|}~';
-
-                       // Next define the RFC 1034 'ldh-str'
-                       //      <domain> ::= <subdomain> | " "
-                       //      <subdomain> ::= <label> | <subdomain> "." <label>
-                       //      <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
-                       //      <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
-                       //      <let-dig-hyp> ::= <let-dig> | "-"
-                       //      <let-dig> ::= <letter> | <digit>
-                       rfc1034LdhStr = 'a-z0-9\\-';
-
-                       html5EmailRegexp = new RegExp(
-                               // start of string
-                               '^'
-                               +
-                               // User part which is liberal :p
-                               '[' + rfc5322Atext + '\\.]+'
-                               +
-                               // 'at'
-                               '@'
-                               +
-                               // Domain first part
-                               '[' + rfc1034LdhStr + ']+'
-                               +
-                               // Optional second part and following are separated by a dot
-                               '(?:\\.[' + rfc1034LdhStr + ']+)*'
-                               +
-                               // End of string
-                               '$',
-                               // RegExp is case insensitive
-                               'i'
-                       );
-                       return ( null !== mailtxt.match( html5EmailRegexp ) );
-               },
-
-               /**
-                * Note: borrows from IP::isIPv4
-                *
-                * @param {string} address
-                * @param {boolean} allowBlock
-                * @return {boolean}
-                */
-               isIPv4Address: function ( address, allowBlock ) {
-                       if ( typeof address !== 'string' ) {
-                               return false;
-                       }
-
-                       var     block = allowBlock ? '(?:\\/(?:3[0-2]|[12]?\\d))?' : '',
-                               RE_IP_BYTE = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])',
-                               RE_IP_ADD = '(?:' + RE_IP_BYTE + '\\.){3}' + RE_IP_BYTE;
-
-                       return address.search( new RegExp( '^' + RE_IP_ADD + block + '$' ) ) !== -1;
-               },
-
-               /**
-                * Note: borrows from IP::isIPv6
-                *
-                * @param {string} address
-                * @param {boolean} allowBlock
-                * @return {boolean}
-                */
-               isIPv6Address: function ( address, allowBlock ) {
-                       if ( typeof address !== 'string' ) {
-                               return false;
-                       }
-
-                       var     block = allowBlock ? '(?:\\/(?:12[0-8]|1[01][0-9]|[1-9]?\\d))?' : '',
-                               RE_IPV6_ADD =
-                       '(?:' + // starts with "::" (including "::")
-                       ':(?::|(?::' + '[0-9A-Fa-f]{1,4}' + '){1,7})' +
-                       '|' + // ends with "::" (except "::")
-                       '[0-9A-Fa-f]{1,4}' + '(?::' + '[0-9A-Fa-f]{1,4}' + '){0,6}::' +
-                       '|' + // contains no "::"
-                       '[0-9A-Fa-f]{1,4}' + '(?::' + '[0-9A-Fa-f]{1,4}' + '){7}' +
-                       ')';
-
-                       if ( address.search( new RegExp( '^' + RE_IPV6_ADD + block + '$' ) ) !== -1 ) {
-                               return true;
-                       }
-
-                       RE_IPV6_ADD = // contains one "::" in the middle (single '::' check below)
-                               '[0-9A-Fa-f]{1,4}' + '(?:::?' + '[0-9A-Fa-f]{1,4}' + '){1,6}';
-
-                       return address.search( new RegExp( '^' + RE_IPV6_ADD + block + '$' ) ) !== -1
-                               && address.search( /::/ ) !== -1 && address.search( /::.*::/ ) === -1;
-               }
-       };
-
-       /**
-        * @method wikiGetlink
-        * @inheritdoc #getUrl
-        * @deprecated since 1.23 Use #getUrl instead.
-        */
-       mw.log.deprecate( util, 'wikiGetlink', util.getUrl, 'Use mw.util.getUrl instead.' );
-
-       mw.util = util;
-
-}( mediaWiki, jQuery ) );
diff --git a/resources/moment/LICENSE b/resources/moment/LICENSE
deleted file mode 100644 (file)
index b44e3a6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-Copyright (c) 2011-2013 Tim Wood, Iskren Chernev, Moment.js contributors
-
-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/resources/moment/lang/ar-ma.js b/resources/moment/lang/ar-ma.js
deleted file mode 100644 (file)
index 1c159f1..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// moment.js language configuration
-// language : Moroccan Arabic (ar-ma)
-// author : ElFadili Yassine : https://github.com/ElFadiliY
-// author : Abdel Said : https://github.com/abdelsaid
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ar-ma', {
-        months : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),
-        monthsShort : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),
-        weekdays : "الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
-        weekdaysShort : "احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),
-        weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[اليوم على الساعة] LT",
-            nextDay: '[غدا على الساعة] LT',
-            nextWeek: 'dddd [على الساعة] LT',
-            lastDay: '[أمس على الساعة] LT',
-            lastWeek: 'dddd [على الساعة] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "في %s",
-            past : "منذ %s",
-            s : "ثوان",
-            m : "دقيقة",
-            mm : "%d دقائق",
-            h : "ساعة",
-            hh : "%d ساعات",
-            d : "يوم",
-            dd : "%d أيام",
-            M : "شهر",
-            MM : "%d أشهر",
-            y : "سنة",
-            yy : "%d سنوات"
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/ar.js b/resources/moment/lang/ar.js
deleted file mode 100644 (file)
index 6e27d29..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// moment.js language configuration
-// language : Arabic (ar)
-// author : Abdel Said : https://github.com/abdelsaid
-// changes in months, weekdays : Ahmed Elkhatib
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ar', {
-        months : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"),
-        monthsShort : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"),
-        weekdays : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
-        weekdaysShort : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
-        weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[اليوم على الساعة] LT",
-            nextDay: '[غدا على الساعة] LT',
-            nextWeek: 'dddd [على الساعة] LT',
-            lastDay: '[أمس على الساعة] LT',
-            lastWeek: 'dddd [على الساعة] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "في %s",
-            past : "منذ %s",
-            s : "ثوان",
-            m : "دقيقة",
-            mm : "%d دقائق",
-            h : "ساعة",
-            hh : "%d ساعات",
-            d : "يوم",
-            dd : "%d أيام",
-            M : "شهر",
-            MM : "%d أشهر",
-            y : "سنة",
-            yy : "%d سنوات"
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/bg.js b/resources/moment/lang/bg.js
deleted file mode 100644 (file)
index f47ed65..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// moment.js language configuration
-// language : bulgarian (bg)
-// author : Krasen Borisov : https://github.com/kraz
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('bg', {
-        months : "януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),
-        monthsShort : "янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),
-        weekdays : "неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),
-        weekdaysShort : "нед_пон_вто_сря_чет_пет_съб".split("_"),
-        weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "D.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Днес в] LT',
-            nextDay : '[Утре в] LT',
-            nextWeek : 'dddd [в] LT',
-            lastDay : '[Вчера в] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                case 6:
-                    return '[В изминалата] dddd [в] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[В изминалия] dddd [в] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "след %s",
-            past : "преди %s",
-            s : "няколко секунди",
-            m : "минута",
-            mm : "%d минути",
-            h : "час",
-            hh : "%d часа",
-            d : "ден",
-            dd : "%d дни",
-            M : "месец",
-            MM : "%d месеца",
-            y : "година",
-            yy : "%d години"
-        },
-        ordinal : function (number) {
-            var lastDigit = number % 10,
-                last2Digits = number % 100;
-            if (number === 0) {
-                return number + '-ев';
-            } else if (last2Digits === 0) {
-                return number + '-ен';
-            } else if (last2Digits > 10 && last2Digits < 20) {
-                return number + '-ти';
-            } else if (lastDigit === 1) {
-                return number + '-ви';
-            } else if (lastDigit === 2) {
-                return number + '-ри';
-            } else if (lastDigit === 7 || lastDigit === 8) {
-                return number + '-ми';
-            } else {
-                return number + '-ти';
-            }
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/br.js b/resources/moment/lang/br.js
deleted file mode 100644 (file)
index 39c60df..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// moment.js language configuration
-// language : breton (br)
-// author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function relativeTimeWithMutation(number, withoutSuffix, key) {
-        var format = {
-            'mm': "munutenn",
-            'MM': "miz",
-            'dd': "devezh"
-        };
-        return number + ' ' + mutation(format[key], number);
-    }
-
-    function specialMutationForYears(number) {
-        switch (lastNumber(number)) {
-        case 1:
-        case 3:
-        case 4:
-        case 5:
-        case 9:
-            return number + ' bloaz';
-        default:
-            return number + ' vloaz';
-        }
-    }
-
-    function lastNumber(number) {
-        if (number > 9) {
-            return lastNumber(number % 10);
-        }
-        return number;
-    }
-
-    function mutation(text, number) {
-        if (number === 2) {
-            return softMutation(text);
-        }
-        return text;
-    }
-
-    function softMutation(text) {
-        var mutationTable = {
-            'm': 'v',
-            'b': 'v',
-            'd': 'z'
-        };
-        if (mutationTable[text.charAt(0)] === undefined) {
-            return text;
-        }
-        return mutationTable[text.charAt(0)] + text.substring(1);
-    }
-
-    return moment.lang('br', {
-        months : "Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),
-        monthsShort : "Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),
-        weekdays : "Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"),
-        weekdaysShort : "Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),
-        weekdaysMin : "Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),
-        longDateFormat : {
-            LT : "h[e]mm A",
-            L : "DD/MM/YYYY",
-            LL : "D [a viz] MMMM YYYY",
-            LLL : "D [a viz] MMMM YYYY LT",
-            LLLL : "dddd, D [a viz] MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Hiziv da] LT',
-            nextDay : '[Warc\'hoazh da] LT',
-            nextWeek : 'dddd [da] LT',
-            lastDay : '[Dec\'h da] LT',
-            lastWeek : 'dddd [paset da] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "a-benn %s",
-            past : "%s 'zo",
-            s : "un nebeud segondennoù",
-            m : "ur vunutenn",
-            mm : relativeTimeWithMutation,
-            h : "un eur",
-            hh : "%d eur",
-            d : "un devezh",
-            dd : relativeTimeWithMutation,
-            M : "ur miz",
-            MM : relativeTimeWithMutation,
-            y : "ur bloaz",
-            yy : specialMutationForYears
-        },
-        ordinal : function (number) {
-            var output = (number === 1) ? 'añ' : 'vet';
-            return number + output;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/bs.js b/resources/moment/lang/bs.js
deleted file mode 100644 (file)
index 83a9b4c..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-// moment.js language configuration
-// language : bosnian (bs)
-// author : Nedim Cholich : https://github.com/frontyard
-// based on (hr) translation by Bojan Marković
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    function translate(number, withoutSuffix, key) {
-        var result = number + " ";
-        switch (key) {
-        case 'm':
-            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
-        case 'mm':
-            if (number === 1) {
-                result += 'minuta';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'minute';
-            } else {
-                result += 'minuta';
-            }
-            return result;
-        case 'h':
-            return withoutSuffix ? 'jedan sat' : 'jednog sata';
-        case 'hh':
-            if (number === 1) {
-                result += 'sat';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'sata';
-            } else {
-                result += 'sati';
-            }
-            return result;
-        case 'dd':
-            if (number === 1) {
-                result += 'dan';
-            } else {
-                result += 'dana';
-            }
-            return result;
-        case 'MM':
-            if (number === 1) {
-                result += 'mjesec';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'mjeseca';
-            } else {
-                result += 'mjeseci';
-            }
-            return result;
-        case 'yy':
-            if (number === 1) {
-                result += 'godina';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'godine';
-            } else {
-                result += 'godina';
-            }
-            return result;
-        }
-    }
-
-    return moment.lang('bs', {
-               months : "januar_februar_mart_april_maj_juni_juli_avgust_septembar_oktobar_novembar_decembar".split("_"),
-               monthsShort : "jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),
-        weekdays : "nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),
-        weekdaysShort : "ned._pon._uto._sri._čet._pet._sub.".split("_"),
-        weekdaysMin : "ne_po_ut_sr_če_pe_su".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD. MM. YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay  : '[danas u] LT',
-            nextDay  : '[sutra u] LT',
-
-            nextWeek : function () {
-                switch (this.day()) {
-                case 0:
-                    return '[u] [nedjelju] [u] LT';
-                case 3:
-                    return '[u] [srijedu] [u] LT';
-                case 6:
-                    return '[u] [subotu] [u] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[u] dddd [u] LT';
-                }
-            },
-            lastDay  : '[jučer u] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                    return '[prošlu] dddd [u] LT';
-                case 6:
-                    return '[prošle] [subote] [u] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[prošli] dddd [u] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "za %s",
-            past   : "prije %s",
-            s      : "par sekundi",
-            m      : translate,
-            mm     : translate,
-            h      : translate,
-            hh     : translate,
-            d      : "dan",
-            dd     : translate,
-            M      : "mjesec",
-            MM     : translate,
-            y      : "godinu",
-            yy     : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/ca.js b/resources/moment/lang/ca.js
deleted file mode 100644 (file)
index cf47113..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// moment.js language configuration
-// language : catalan (ca)
-// author : Juan G. Hurtado : https://github.com/juanghurtado
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ca', {
-        months : "gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),
-        monthsShort : "gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.".split("_"),
-        weekdays : "diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),
-        weekdaysShort : "dg._dl._dt._dc._dj._dv._ds.".split("_"),
-        weekdaysMin : "Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : function () {
-                return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            nextDay : function () {
-                return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            nextWeek : function () {
-                return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            lastDay : function () {
-                return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            lastWeek : function () {
-                return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "en %s",
-            past : "fa %s",
-            s : "uns segons",
-            m : "un minut",
-            mm : "%d minuts",
-            h : "una hora",
-            hh : "%d hores",
-            d : "un dia",
-            dd : "%d dies",
-            M : "un mes",
-            MM : "%d mesos",
-            y : "un any",
-            yy : "%d anys"
-        },
-        ordinal : '%dº',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/cs.js b/resources/moment/lang/cs.js
deleted file mode 100644 (file)
index c1396cf..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-// moment.js language configuration
-// language : czech (cs)
-// author : petrbela : https://github.com/petrbela
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var months = "leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),
-        monthsShort = "led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_");
-
-    function plural(n) {
-        return (n > 1) && (n < 5) && (~~(n / 10) !== 1);
-    }
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var result = number + " ";
-        switch (key) {
-        case 's':  // a few seconds / in a few seconds / a few seconds ago
-            return (withoutSuffix || isFuture) ? 'pár vteřin' : 'pár vteřinami';
-        case 'm':  // a minute / in a minute / a minute ago
-            return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou');
-        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'minuty' : 'minut');
-            } else {
-                return result + 'minutami';
-            }
-            break;
-        case 'h':  // an hour / in an hour / an hour ago
-            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
-        case 'hh': // 9 hours / in 9 hours / 9 hours ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'hodiny' : 'hodin');
-            } else {
-                return result + 'hodinami';
-            }
-            break;
-        case 'd':  // a day / in a day / a day ago
-            return (withoutSuffix || isFuture) ? 'den' : 'dnem';
-        case 'dd': // 9 days / in 9 days / 9 days ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'dny' : 'dní');
-            } else {
-                return result + 'dny';
-            }
-            break;
-        case 'M':  // a month / in a month / a month ago
-            return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem';
-        case 'MM': // 9 months / in 9 months / 9 months ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'měsíce' : 'měsíců');
-            } else {
-                return result + 'měsíci';
-            }
-            break;
-        case 'y':  // a year / in a year / a year ago
-            return (withoutSuffix || isFuture) ? 'rok' : 'rokem';
-        case 'yy': // 9 years / in 9 years / 9 years ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'roky' : 'let');
-            } else {
-                return result + 'lety';
-            }
-            break;
-        }
-    }
-
-    return moment.lang('cs', {
-        months : months,
-        monthsShort : monthsShort,
-        monthsParse : (function (months, monthsShort) {
-            var i, _monthsParse = [];
-            for (i = 0; i < 12; i++) {
-                // use custom parser to solve problem with July (červenec)
-                _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
-            }
-            return _monthsParse;
-        }(months, monthsShort)),
-        weekdays : "neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),
-        weekdaysShort : "ne_po_út_st_čt_pá_so".split("_"),
-        weekdaysMin : "ne_po_út_st_čt_pá_so".split("_"),
-        longDateFormat : {
-            LT: "H:mm",
-            L : "DD.MM.YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[dnes v] LT",
-            nextDay: '[zítra v] LT',
-            nextWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[v neděli v] LT';
-                case 1:
-                case 2:
-                    return '[v] dddd [v] LT';
-                case 3:
-                    return '[ve středu v] LT';
-                case 4:
-                    return '[ve čtvrtek v] LT';
-                case 5:
-                    return '[v pátek v] LT';
-                case 6:
-                    return '[v sobotu v] LT';
-                }
-            },
-            lastDay: '[včera v] LT',
-            lastWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[minulou neděli v] LT';
-                case 1:
-                case 2:
-                    return '[minulé] dddd [v] LT';
-                case 3:
-                    return '[minulou středu v] LT';
-                case 4:
-                case 5:
-                    return '[minulý] dddd [v] LT';
-                case 6:
-                    return '[minulou sobotu v] LT';
-                }
-            },
-            sameElse: "L"
-        },
-        relativeTime : {
-            future : "za %s",
-            past : "před %s",
-            s : translate,
-            m : translate,
-            mm : translate,
-            h : translate,
-            hh : translate,
-            d : translate,
-            dd : translate,
-            M : translate,
-            MM : translate,
-            y : translate,
-            yy : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/cv.js b/resources/moment/lang/cv.js
deleted file mode 100644 (file)
index a5812de..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// moment.js language configuration
-// language : chuvash (cv)
-// author : Anatoly Mironov : https://github.com/mirontoli
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('cv', {
-        months : "кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"),
-        monthsShort : "кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"),
-        weekdays : "вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"),
-        weekdaysShort : "выр_тун_ытл_юн_кĕç_эрн_шăм".split("_"),
-        weekdaysMin : "вр_тн_ыт_юн_кç_эр_шм".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD-MM-YYYY",
-            LL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ]",
-            LLL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT",
-            LLLL : "dddd, YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT"
-        },
-        calendar : {
-            sameDay: '[Паян] LT [сехетре]',
-            nextDay: '[Ыран] LT [сехетре]',
-            lastDay: '[Ĕнер] LT [сехетре]',
-            nextWeek: '[Çитес] dddd LT [сехетре]',
-            lastWeek: '[Иртнĕ] dddd LT [сехетре]',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : function (output) {
-                var affix = /сехет$/i.exec(output) ? "рен" : /çул$/i.exec(output) ? "тан" : "ран";
-                return output + affix;
-            },
-            past : "%s каялла",
-            s : "пĕр-ик çеккунт",
-            m : "пĕр минут",
-            mm : "%d минут",
-            h : "пĕр сехет",
-            hh : "%d сехет",
-            d : "пĕр кун",
-            dd : "%d кун",
-            M : "пĕр уйăх",
-            MM : "%d уйăх",
-            y : "пĕр çул",
-            yy : "%d çул"
-        },
-        ordinal : '%d-мĕш',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/cy.js b/resources/moment/lang/cy.js
deleted file mode 100644 (file)
index b47d7c2..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// moment.js language configuration
-// language : Welsh (cy)
-// author : Robert Allen
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang("cy", {
-        months: "Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),
-        monthsShort: "Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),
-        weekdays: "Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),
-        weekdaysShort: "Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),
-        weekdaysMin: "Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),
-        // time formats are the same as en-gb
-        longDateFormat: {
-            LT: "HH:mm",
-            L: "DD/MM/YYYY",
-            LL: "D MMMM YYYY",
-            LLL: "D MMMM YYYY LT",
-            LLLL: "dddd, D MMMM YYYY LT"
-        },
-        calendar: {
-            sameDay: '[Heddiw am] LT',
-            nextDay: '[Yfory am] LT',
-            nextWeek: 'dddd [am] LT',
-            lastDay: '[Ddoe am] LT',
-            lastWeek: 'dddd [diwethaf am] LT',
-            sameElse: 'L'
-        },
-        relativeTime: {
-            future: "mewn %s",
-            past: "%s yn àl",
-            s: "ychydig eiliadau",
-            m: "munud",
-            mm: "%d munud",
-            h: "awr",
-            hh: "%d awr",
-            d: "diwrnod",
-            dd: "%d diwrnod",
-            M: "mis",
-            MM: "%d mis",
-            y: "blwyddyn",
-            yy: "%d flynedd"
-        },
-        // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
-        ordinal: function (number) {
-            var b = number,
-                output = '',
-                lookup = [
-                    '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
-                    'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed
-                ];
-
-            if (b > 20) {
-                if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
-                    output = 'fed'; // not 30ain, 70ain or 90ain
-                } else {
-                    output = 'ain';
-                }
-            } else if (b > 0) {
-                output = lookup[b];
-            }
-
-            return number + output;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/da.js b/resources/moment/lang/da.js
deleted file mode 100644 (file)
index 2fa8244..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// moment.js language configuration
-// language : danish (da)
-// author : Ulrik Nielsen : https://github.com/mrbase
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('da', {
-        months : "januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),
-        monthsShort : "jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),
-        weekdays : "søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),
-        weekdaysShort : "søn_man_tir_ons_tor_fre_lør".split("_"),
-        weekdaysMin : "sø_ma_ti_on_to_fr_lø".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D. MMMM, YYYY LT"
-        },
-        calendar : {
-            sameDay : '[I dag kl.] LT',
-            nextDay : '[I morgen kl.] LT',
-            nextWeek : 'dddd [kl.] LT',
-            lastDay : '[I går kl.] LT',
-            lastWeek : '[sidste] dddd [kl] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "om %s",
-            past : "%s siden",
-            s : "få sekunder",
-            m : "et minut",
-            mm : "%d minutter",
-            h : "en time",
-            hh : "%d timer",
-            d : "en dag",
-            dd : "%d dage",
-            M : "en måned",
-            MM : "%d måneder",
-            y : "et år",
-            yy : "%d år"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/de.js b/resources/moment/lang/de.js
deleted file mode 100644 (file)
index 988f328..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// moment.js language configuration
-// language : german (de)
-// author : lluchs : https://github.com/lluchs
-// author: Menelion Elensúle: https://github.com/Oire
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function processRelativeTime(number, withoutSuffix, key, isFuture) {
-        var format = {
-            'm': ['eine Minute', 'einer Minute'],
-            'h': ['eine Stunde', 'einer Stunde'],
-            'd': ['ein Tag', 'einem Tag'],
-            'dd': [number + ' Tage', number + ' Tagen'],
-            'M': ['ein Monat', 'einem Monat'],
-            'MM': [number + ' Monate', number + ' Monaten'],
-            'y': ['ein Jahr', 'einem Jahr'],
-            'yy': [number + ' Jahre', number + ' Jahren']
-        };
-        return withoutSuffix ? format[key][0] : format[key][1];
-    }
-
-    return moment.lang('de', {
-        months : "Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),
-        monthsShort : "Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),
-        weekdays : "Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),
-        weekdaysShort : "So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),
-        weekdaysMin : "So_Mo_Di_Mi_Do_Fr_Sa".split("_"),
-        longDateFormat : {
-            LT: "H:mm [Uhr]",
-            L : "DD.MM.YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[Heute um] LT",
-            sameElse: "L",
-            nextDay: '[Morgen um] LT',
-            nextWeek: 'dddd [um] LT',
-            lastDay: '[Gestern um] LT',
-            lastWeek: '[letzten] dddd [um] LT'
-        },
-        relativeTime : {
-            future : "in %s",
-            past : "vor %s",
-            s : "ein paar Sekunden",
-            m : processRelativeTime,
-            mm : "%d Minuten",
-            h : processRelativeTime,
-            hh : "%d Stunden",
-            d : processRelativeTime,
-            dd : processRelativeTime,
-            M : processRelativeTime,
-            MM : processRelativeTime,
-            y : processRelativeTime,
-            yy : processRelativeTime
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/el.js b/resources/moment/lang/el.js
deleted file mode 100644 (file)
index 9dfea23..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-// moment.js language configuration
-// language : modern greek (el)
-// author : Aggelos Karalias : https://github.com/mehiel
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('el', {
-        monthsNominativeEl : "Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),
-        monthsGenitiveEl : "Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),
-        months : function (momentToFormat, format) {
-            if (/D/.test(format.substring(0, format.indexOf("MMMM")))) { // if there is a day number before 'MMMM'
-                return this._monthsGenitiveEl[momentToFormat.month()];
-            } else {
-                return this._monthsNominativeEl[momentToFormat.month()];
-            }
-        },
-        monthsShort : "Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),
-        weekdays : "Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),
-        weekdaysShort : "Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),
-        weekdaysMin : "Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),
-        meridiem : function (hours, minutes, isLower) {
-            if (hours > 11) {
-                return isLower ? 'μμ' : 'ΜΜ';
-            } else {
-                return isLower ? 'πμ' : 'ΠΜ';
-            }
-        },
-        longDateFormat : {
-            LT : "h:mm A",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendarEl : {
-            sameDay : '[Σήμερα {}] LT',
-            nextDay : '[Αύριο {}] LT',
-            nextWeek : 'dddd [{}] LT',
-            lastDay : '[Χθες {}] LT',
-            lastWeek : '[την προηγούμενη] dddd [{}] LT',
-            sameElse : 'L'
-        },
-        calendar : function (key, mom) {
-            var output = this._calendarEl[key],
-                hours = mom && mom.hours();
-
-            return output.replace("{}", (hours % 12 === 1 ? "στη" : "στις"));
-        },
-        relativeTime : {
-            future : "σε %s",
-            past : "%s πριν",
-            s : "δευτερόλεπτα",
-            m : "ένα λεπτό",
-            mm : "%d λεπτά",
-            h : "μία ώρα",
-            hh : "%d ώρες",
-            d : "μία μέρα",
-            dd : "%d μέρες",
-            M : "ένας μήνας",
-            MM : "%d μήνες",
-            y : "ένας χρόνος",
-            yy : "%d χρόνια"
-        },
-        ordinal : function (number) {
-            return number + 'η';
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/en-au.js b/resources/moment/lang/en-au.js
deleted file mode 100644 (file)
index 4d91e25..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-// moment.js language configuration
-// language : australian english (en-au)
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('en-au', {
-        months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
-        monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
-        weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
-        weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
-        weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
-        longDateFormat : {
-            LT : "h:mm A",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Today at] LT',
-            nextDay : '[Tomorrow at] LT',
-            nextWeek : 'dddd [at] LT',
-            lastDay : '[Yesterday at] LT',
-            lastWeek : '[Last] dddd [at] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "in %s",
-            past : "%s ago",
-            s : "a few seconds",
-            m : "a minute",
-            mm : "%d minutes",
-            h : "an hour",
-            hh : "%d hours",
-            d : "a day",
-            dd : "%d days",
-            M : "a month",
-            MM : "%d months",
-            y : "a year",
-            yy : "%d years"
-        },
-        ordinal : function (number) {
-            var b = number % 10,
-                output = (~~ (number % 100 / 10) === 1) ? 'th' :
-                (b === 1) ? 'st' :
-                (b === 2) ? 'nd' :
-                (b === 3) ? 'rd' : 'th';
-            return number + output;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/en-ca.js b/resources/moment/lang/en-ca.js
deleted file mode 100644 (file)
index a97e9f3..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// moment.js language configuration
-// language : canadian english (en-ca)
-// author : Jonathan Abourbih : https://github.com/jonbca
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('en-ca', {
-        months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
-        monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
-        weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
-        weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
-        weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
-        longDateFormat : {
-            LT : "h:mm A",
-            L : "YYYY-MM-DD",
-            LL : "D MMMM, YYYY",
-            LLL : "D MMMM, YYYY LT",
-            LLLL : "dddd, D MMMM, YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Today at] LT',
-            nextDay : '[Tomorrow at] LT',
-            nextWeek : 'dddd [at] LT',
-            lastDay : '[Yesterday at] LT',
-            lastWeek : '[Last] dddd [at] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "in %s",
-            past : "%s ago",
-            s : "a few seconds",
-            m : "a minute",
-            mm : "%d minutes",
-            h : "an hour",
-            hh : "%d hours",
-            d : "a day",
-            dd : "%d days",
-            M : "a month",
-            MM : "%d months",
-            y : "a year",
-            yy : "%d years"
-        },
-        ordinal : function (number) {
-            var b = number % 10,
-                output = (~~ (number % 100 / 10) === 1) ? 'th' :
-                (b === 1) ? 'st' :
-                (b === 2) ? 'nd' :
-                (b === 3) ? 'rd' : 'th';
-            return number + output;
-        }
-    });
-}));
diff --git a/resources/moment/lang/en-gb.js b/resources/moment/lang/en-gb.js
deleted file mode 100644 (file)
index 3a7907b..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// moment.js language configuration
-// language : great britain english (en-gb)
-// author : Chris Gedrim : https://github.com/chrisgedrim
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('en-gb', {
-        months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
-        monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
-        weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
-        weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
-        weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Today at] LT',
-            nextDay : '[Tomorrow at] LT',
-            nextWeek : 'dddd [at] LT',
-            lastDay : '[Yesterday at] LT',
-            lastWeek : '[Last] dddd [at] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "in %s",
-            past : "%s ago",
-            s : "a few seconds",
-            m : "a minute",
-            mm : "%d minutes",
-            h : "an hour",
-            hh : "%d hours",
-            d : "a day",
-            dd : "%d days",
-            M : "a month",
-            MM : "%d months",
-            y : "a year",
-            yy : "%d years"
-        },
-        ordinal : function (number) {
-            var b = number % 10,
-                output = (~~ (number % 100 / 10) === 1) ? 'th' :
-                (b === 1) ? 'st' :
-                (b === 2) ? 'nd' :
-                (b === 3) ? 'rd' : 'th';
-            return number + output;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/eo.js b/resources/moment/lang/eo.js
deleted file mode 100644 (file)
index 03b1abf..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// moment.js language configuration
-// language : esperanto (eo)
-// author : Colin Dean : https://github.com/colindean
-// komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko.
-//          Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni!
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('eo', {
-        months : "januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro".split("_"),
-        monthsShort : "jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec".split("_"),
-        weekdays : "Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato".split("_"),
-        weekdaysShort : "Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab".split("_"),
-        weekdaysMin : "Di_Lu_Ma_Me_Ĵa_Ve_Sa".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "YYYY-MM-DD",
-            LL : "D[-an de] MMMM, YYYY",
-            LLL : "D[-an de] MMMM, YYYY LT",
-            LLLL : "dddd, [la] D[-an de] MMMM, YYYY LT"
-        },
-        meridiem : function (hours, minutes, isLower) {
-            if (hours > 11) {
-                return isLower ? 'p.t.m.' : 'P.T.M.';
-            } else {
-                return isLower ? 'a.t.m.' : 'A.T.M.';
-            }
-        },
-        calendar : {
-            sameDay : '[Hodiaŭ je] LT',
-            nextDay : '[Morgaŭ je] LT',
-            nextWeek : 'dddd [je] LT',
-            lastDay : '[Hieraŭ je] LT',
-            lastWeek : '[pasinta] dddd [je] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "je %s",
-            past : "antaŭ %s",
-            s : "sekundoj",
-            m : "minuto",
-            mm : "%d minutoj",
-            h : "horo",
-            hh : "%d horoj",
-            d : "tago",//ne 'diurno', ĉar estas uzita por proksimumo
-            dd : "%d tagoj",
-            M : "monato",
-            MM : "%d monatoj",
-            y : "jaro",
-            yy : "%d jaroj"
-        },
-        ordinal : "%da",
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/es.js b/resources/moment/lang/es.js
deleted file mode 100644 (file)
index 0a38396..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// moment.js language configuration
-// language : spanish (es)
-// author : Julio Napurí : https://github.com/julionc
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('es', {
-        months : "enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),
-        monthsShort : "ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),
-        weekdays : "domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),
-        weekdaysShort : "dom._lun._mar._mié._jue._vie._sáb.".split("_"),
-        weekdaysMin : "Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD/MM/YYYY",
-            LL : "D [de] MMMM [de] YYYY",
-            LLL : "D [de] MMMM [de] YYYY LT",
-            LLLL : "dddd, D [de] MMMM [de] YYYY LT"
-        },
-        calendar : {
-            sameDay : function () {
-                return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
-            },
-            nextDay : function () {
-                return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
-            },
-            nextWeek : function () {
-                return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
-            },
-            lastDay : function () {
-                return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
-            },
-            lastWeek : function () {
-                return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "en %s",
-            past : "hace %s",
-            s : "unos segundos",
-            m : "un minuto",
-            mm : "%d minutos",
-            h : "una hora",
-            hh : "%d horas",
-            d : "un día",
-            dd : "%d días",
-            M : "un mes",
-            MM : "%d meses",
-            y : "un año",
-            yy : "%d años"
-        },
-        ordinal : '%dº',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/et.js b/resources/moment/lang/et.js
deleted file mode 100644 (file)
index fb410ef..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// moment.js language configuration
-// language : estonian (et)
-// author : Henry Kehlmann : https://github.com/madhenry
-// improvements : Illimar Tambek : https://github.com/ragulka
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function processRelativeTime(number, withoutSuffix, key, isFuture) {
-        var format = {
-            's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'],
-            'm' : ['ühe minuti', 'üks minut'],
-            'mm': [number + ' minuti', number + ' minutit'],
-            'h' : ['ühe tunni', 'tund aega', 'üks tund'],
-            'hh': [number + ' tunni', number + ' tundi'],
-            'd' : ['ühe päeva', 'üks päev'],
-            'M' : ['kuu aja', 'kuu aega', 'üks kuu'],
-            'MM': [number + ' kuu', number + ' kuud'],
-            'y' : ['ühe aasta', 'aasta', 'üks aasta'],
-            'yy': [number + ' aasta', number + ' aastat']
-        };
-        if (withoutSuffix) {
-            return format[key][2] ? format[key][2] : format[key][1];
-        }
-        return isFuture ? format[key][0] : format[key][1];
-    }
-
-    return moment.lang('et', {
-        months        : "jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),
-        monthsShort   : "jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),
-        weekdays      : "pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"),
-        weekdaysShort : "P_E_T_K_N_R_L".split("_"),
-        weekdaysMin   : "P_E_T_K_N_R_L".split("_"),
-        longDateFormat : {
-            LT   : "H:mm",
-            L    : "DD.MM.YYYY",
-            LL   : "D. MMMM YYYY",
-            LLL  : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay  : '[Täna,] LT',
-            nextDay  : '[Homme,] LT',
-            nextWeek : '[Järgmine] dddd LT',
-            lastDay  : '[Eile,] LT',
-            lastWeek : '[Eelmine] dddd LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s pärast",
-            past   : "%s tagasi",
-            s      : processRelativeTime,
-            m      : processRelativeTime,
-            mm     : processRelativeTime,
-            h      : processRelativeTime,
-            hh     : processRelativeTime,
-            d      : processRelativeTime,
-            dd     : '%d päeva',
-            M      : processRelativeTime,
-            MM     : processRelativeTime,
-            y      : processRelativeTime,
-            yy     : processRelativeTime
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/eu.js b/resources/moment/lang/eu.js
deleted file mode 100644 (file)
index 659b739..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// moment.js language configuration
-// language : euskara (eu)
-// author : Eneko Illarramendi : https://github.com/eillarra
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('eu', {
-        months : "urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),
-        monthsShort : "urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),
-        weekdays : "igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),
-        weekdaysShort : "ig._al._ar._az._og._ol._lr.".split("_"),
-        weekdaysMin : "ig_al_ar_az_og_ol_lr".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "YYYY-MM-DD",
-            LL : "YYYY[ko] MMMM[ren] D[a]",
-            LLL : "YYYY[ko] MMMM[ren] D[a] LT",
-            LLLL : "dddd, YYYY[ko] MMMM[ren] D[a] LT",
-            l : "YYYY-M-D",
-            ll : "YYYY[ko] MMM D[a]",
-            lll : "YYYY[ko] MMM D[a] LT",
-            llll : "ddd, YYYY[ko] MMM D[a] LT"
-        },
-        calendar : {
-            sameDay : '[gaur] LT[etan]',
-            nextDay : '[bihar] LT[etan]',
-            nextWeek : 'dddd LT[etan]',
-            lastDay : '[atzo] LT[etan]',
-            lastWeek : '[aurreko] dddd LT[etan]',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s barru",
-            past : "duela %s",
-            s : "segundo batzuk",
-            m : "minutu bat",
-            mm : "%d minutu",
-            h : "ordu bat",
-            hh : "%d ordu",
-            d : "egun bat",
-            dd : "%d egun",
-            M : "hilabete bat",
-            MM : "%d hilabete",
-            y : "urte bat",
-            yy : "%d urte"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/fa.js b/resources/moment/lang/fa.js
deleted file mode 100644 (file)
index 4a690c4..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-// moment.js language configuration
-// language : Persian Language
-// author : Ebrahim Byagowi : https://github.com/ebraminio
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var symbolMap = {
-        '1': '۱',
-        '2': '۲',
-        '3': '۳',
-        '4': '۴',
-        '5': '۵',
-        '6': '۶',
-        '7': '۷',
-        '8': '۸',
-        '9': '۹',
-        '0': '۰'
-    }, numberMap = {
-        '۱': '1',
-        '۲': '2',
-        '۳': '3',
-        '۴': '4',
-        '۵': '5',
-        '۶': '6',
-        '۷': '7',
-        '۸': '8',
-        '۹': '9',
-        '۰': '0'
-    };
-
-    return moment.lang('fa', {
-        months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
-        monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
-        weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
-        weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
-        weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'),
-        longDateFormat : {
-            LT : 'HH:mm',
-            L : 'DD/MM/YYYY',
-            LL : 'D MMMM YYYY',
-            LLL : 'D MMMM YYYY LT',
-            LLLL : 'dddd, D MMMM YYYY LT'
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 12) {
-                return "قبل از ظهر";
-            } else {
-                return "بعد از ظهر";
-            }
-        },
-        calendar : {
-            sameDay : '[امروز ساعت] LT',
-            nextDay : '[فردا ساعت] LT',
-            nextWeek : 'dddd [ساعت] LT',
-            lastDay : '[دیروز ساعت] LT',
-            lastWeek : 'dddd [پیش] [ساعت] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : 'در %s',
-            past : '%s پیش',
-            s : 'چندین ثانیه',
-            m : 'یک دقیقه',
-            mm : '%d دقیقه',
-            h : 'یک ساعت',
-            hh : '%d ساعت',
-            d : 'یک روز',
-            dd : '%d روز',
-            M : 'یک ماه',
-            MM : '%d ماه',
-            y : 'یک سال',
-            yy : '%d سال'
-        },
-        preparse: function (string) {
-            return string.replace(/[۰-۹]/g, function (match) {
-                return numberMap[match];
-            }).replace(/،/g, ',');
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            }).replace(/,/g, '،');
-        },
-        ordinal : '%dم',
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12 // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/fi.js b/resources/moment/lang/fi.js
deleted file mode 100644 (file)
index 18529c1..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-// moment.js language configuration
-// language : finnish (fi)
-// author : Tarmo Aidantausta : https://github.com/bleadof
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var numbers_past = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '),
-        numbers_future = ['nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden',
-                          numbers_past[7], numbers_past[8], numbers_past[9]];
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var result = "";
-        switch (key) {
-        case 's':
-            return isFuture ? 'muutaman sekunnin' : 'muutama sekunti';
-        case 'm':
-            return isFuture ? 'minuutin' : 'minuutti';
-        case 'mm':
-            result = isFuture ? 'minuutin' : 'minuuttia';
-            break;
-        case 'h':
-            return isFuture ? 'tunnin' : 'tunti';
-        case 'hh':
-            result = isFuture ? 'tunnin' : 'tuntia';
-            break;
-        case 'd':
-            return isFuture ? 'päivän' : 'päivä';
-        case 'dd':
-            result = isFuture ? 'päivän' : 'päivää';
-            break;
-        case 'M':
-            return isFuture ? 'kuukauden' : 'kuukausi';
-        case 'MM':
-            result = isFuture ? 'kuukauden' : 'kuukautta';
-            break;
-        case 'y':
-            return isFuture ? 'vuoden' : 'vuosi';
-        case 'yy':
-            result = isFuture ? 'vuoden' : 'vuotta';
-            break;
-        }
-        result = verbal_number(number, isFuture) + " " + result;
-        return result;
-    }
-
-    function verbal_number(number, isFuture) {
-        return number < 10 ? (isFuture ? numbers_future[number] : numbers_past[number]) : number;
-    }
-
-    return moment.lang('fi', {
-        months : "tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),
-        monthsShort : "tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),
-        weekdays : "sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),
-        weekdaysShort : "su_ma_ti_ke_to_pe_la".split("_"),
-        weekdaysMin : "su_ma_ti_ke_to_pe_la".split("_"),
-        longDateFormat : {
-            LT : "HH.mm",
-            L : "DD.MM.YYYY",
-            LL : "Do MMMM[ta] YYYY",
-            LLL : "Do MMMM[ta] YYYY, [klo] LT",
-            LLLL : "dddd, Do MMMM[ta] YYYY, [klo] LT",
-            l : "D.M.YYYY",
-            ll : "Do MMM YYYY",
-            lll : "Do MMM YYYY, [klo] LT",
-            llll : "ddd, Do MMM YYYY, [klo] LT"
-        },
-        calendar : {
-            sameDay : '[tänään] [klo] LT',
-            nextDay : '[huomenna] [klo] LT',
-            nextWeek : 'dddd [klo] LT',
-            lastDay : '[eilen] [klo] LT',
-            lastWeek : '[viime] dddd[na] [klo] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s päästä",
-            past : "%s sitten",
-            s : translate,
-            m : translate,
-            mm : translate,
-            h : translate,
-            hh : translate,
-            d : translate,
-            dd : translate,
-            M : translate,
-            MM : translate,
-            y : translate,
-            yy : translate
-        },
-        ordinal : "%d.",
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/fo.js b/resources/moment/lang/fo.js
deleted file mode 100644 (file)
index 2f1cbb8..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// moment.js language configuration
-// language : faroese (fo)
-// author : Ragnar Johannesen : https://github.com/ragnar123
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('fo', {
-        months : "januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember".split("_"),
-        monthsShort : "jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),
-        weekdays : "sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur".split("_"),
-        weekdaysShort : "sun_mán_týs_mik_hós_frí_ley".split("_"),
-        weekdaysMin : "su_má_tý_mi_hó_fr_le".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D. MMMM, YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Í dag kl.] LT',
-            nextDay : '[Í morgin kl.] LT',
-            nextWeek : 'dddd [kl.] LT',
-            lastDay : '[Í gjár kl.] LT',
-            lastWeek : '[síðstu] dddd [kl] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "um %s",
-            past : "%s síðani",
-            s : "fá sekund",
-            m : "ein minutt",
-            mm : "%d minuttir",
-            h : "ein tími",
-            hh : "%d tímar",
-            d : "ein dagur",
-            dd : "%d dagar",
-            M : "ein mánaði",
-            MM : "%d mánaðir",
-            y : "eitt ár",
-            yy : "%d ár"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/fr-ca.js b/resources/moment/lang/fr-ca.js
deleted file mode 100644 (file)
index 3280d79..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// moment.js language configuration
-// language : canadian french (fr-ca)
-// author : Jonathan Abourbih : https://github.com/jonbca
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('fr-ca', {
-        months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),
-        monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),
-        weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),
-        weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"),
-        weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "YYYY-MM-DD",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[Aujourd'hui à] LT",
-            nextDay: '[Demain à] LT',
-            nextWeek: 'dddd [à] LT',
-            lastDay: '[Hier à] LT',
-            lastWeek: 'dddd [dernier à] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "dans %s",
-            past : "il y a %s",
-            s : "quelques secondes",
-            m : "une minute",
-            mm : "%d minutes",
-            h : "une heure",
-            hh : "%d heures",
-            d : "un jour",
-            dd : "%d jours",
-            M : "un mois",
-            MM : "%d mois",
-            y : "un an",
-            yy : "%d ans"
-        },
-        ordinal : function (number) {
-            return number + (number === 1 ? 'er' : '');
-        }
-    });
-}));
diff --git a/resources/moment/lang/fr.js b/resources/moment/lang/fr.js
deleted file mode 100644 (file)
index 6b3dc52..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// moment.js language configuration
-// language : french (fr)
-// author : John Fischer : https://github.com/jfroffice
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('fr', {
-        months : "janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),
-        monthsShort : "janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),
-        weekdays : "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),
-        weekdaysShort : "dim._lun._mar._mer._jeu._ven._sam.".split("_"),
-        weekdaysMin : "Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[Aujourd'hui à] LT",
-            nextDay: '[Demain à] LT',
-            nextWeek: 'dddd [à] LT',
-            lastDay: '[Hier à] LT',
-            lastWeek: 'dddd [dernier à] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "dans %s",
-            past : "il y a %s",
-            s : "quelques secondes",
-            m : "une minute",
-            mm : "%d minutes",
-            h : "une heure",
-            hh : "%d heures",
-            d : "un jour",
-            dd : "%d jours",
-            M : "un mois",
-            MM : "%d mois",
-            y : "un an",
-            yy : "%d ans"
-        },
-        ordinal : function (number) {
-            return number + (number === 1 ? 'er' : '');
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/gl.js b/resources/moment/lang/gl.js
deleted file mode 100644 (file)
index 8b14127..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// moment.js language configuration
-// language : galician (gl)
-// author : Juan G. Hurtado : https://github.com/juanghurtado
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('gl', {
-        months : "Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"),
-        monthsShort : "Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),
-        weekdays : "Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),
-        weekdaysShort : "Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),
-        weekdaysMin : "Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : function () {
-                return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
-            },
-            nextDay : function () {
-                return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
-            },
-            nextWeek : function () {
-                return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
-            },
-            lastDay : function () {
-                return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT';
-            },
-            lastWeek : function () {
-                return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : function (str) {
-                if (str === "uns segundos") {
-                    return "nuns segundos";
-                }
-                return "en " + str;
-            },
-            past : "hai %s",
-            s : "uns segundos",
-            m : "un minuto",
-            mm : "%d minutos",
-            h : "unha hora",
-            hh : "%d horas",
-            d : "un día",
-            dd : "%d días",
-            M : "un mes",
-            MM : "%d meses",
-            y : "un ano",
-            yy : "%d anos"
-        },
-        ordinal : '%dº',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/he.js b/resources/moment/lang/he.js
deleted file mode 100644 (file)
index b85dbe8..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// moment.js language configuration
-// language : Hebrew (he)
-// author : Tomer Cohen : https://github.com/tomer
-// author : Moshe Simantov : https://github.com/DevelopmentIL
-// author : Tal Ater : https://github.com/TalAter
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('he', {
-        months : "ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),
-        monthsShort : "ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),
-        weekdays : "ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),
-        weekdaysShort : "א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),
-        weekdaysMin : "א_ב_ג_ד_ה_ו_ש".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D [ב]MMMM YYYY",
-            LLL : "D [ב]MMMM YYYY LT",
-            LLLL : "dddd, D [ב]MMMM YYYY LT",
-            l : "D/M/YYYY",
-            ll : "D MMM YYYY",
-            lll : "D MMM YYYY LT",
-            llll : "ddd, D MMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[היום ב־]LT',
-            nextDay : '[מחר ב־]LT',
-            nextWeek : 'dddd [בשעה] LT',
-            lastDay : '[אתמול ב־]LT',
-            lastWeek : '[ביום] dddd [האחרון בשעה] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "בעוד %s",
-            past : "לפני %s",
-            s : "מספר שניות",
-            m : "דקה",
-            mm : "%d דקות",
-            h : "שעה",
-            hh : function (number) {
-                if (number === 2) {
-                    return "שעתיים";
-                }
-                return number + " שעות";
-            },
-            d : "יום",
-            dd : function (number) {
-                if (number === 2) {
-                    return "יומיים";
-                }
-                return number + " ימים";
-            },
-            M : "חודש",
-            MM : function (number) {
-                if (number === 2) {
-                    return "חודשיים";
-                }
-                return number + " חודשים";
-            },
-            y : "שנה",
-            yy : function (number) {
-                if (number === 2) {
-                    return "שנתיים";
-                }
-                return number + " שנים";
-            }
-        }
-    });
-}));
diff --git a/resources/moment/lang/hi.js b/resources/moment/lang/hi.js
deleted file mode 100644 (file)
index 8e6e99c..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// moment.js language configuration
-// language : hindi (hi)
-// author : Mayank Singhal : https://github.com/mayanksinghal
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var symbolMap = {
-        '1': '१',
-        '2': '२',
-        '3': '३',
-        '4': '४',
-        '5': '५',
-        '6': '६',
-        '7': '७',
-        '8': '८',
-        '9': '९',
-        '0': '०'
-    },
-    numberMap = {
-        '१': '1',
-        '२': '2',
-        '३': '3',
-        '४': '4',
-        '५': '5',
-        '६': '6',
-        '७': '7',
-        '८': '8',
-        '९': '9',
-        '०': '0'
-    };
-
-    return moment.lang('hi', {
-        months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split("_"),
-        monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split("_"),
-        weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split("_"),
-        weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split("_"),
-        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split("_"),
-        longDateFormat : {
-            LT : "A h:mm बजे",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY, LT",
-            LLLL : "dddd, D MMMM YYYY, LT"
-        },
-        calendar : {
-            sameDay : '[आज] LT',
-            nextDay : '[कल] LT',
-            nextWeek : 'dddd, LT',
-            lastDay : '[कल] LT',
-            lastWeek : '[पिछले] dddd, LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s में",
-            past : "%s पहले",
-            s : "कुछ ही क्षण",
-            m : "एक मिनट",
-            mm : "%d मिनट",
-            h : "एक घंटा",
-            hh : "%d घंटे",
-            d : "एक दिन",
-            dd : "%d दिन",
-            M : "एक महीने",
-            MM : "%d महीने",
-            y : "एक वर्ष",
-            yy : "%d वर्ष"
-        },
-        preparse: function (string) {
-            return string.replace(/[१२३४५६७८९०]/g, function (match) {
-                return numberMap[match];
-            });
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            });
-        },
-        // Hindi notation for meridiems are quite fuzzy in practice. While there exists
-        // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi.
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return "रात";
-            } else if (hour < 10) {
-                return "सुबह";
-            } else if (hour < 17) {
-                return "दोपहर";
-            } else if (hour < 20) {
-                return "शाम";
-            } else {
-                return "रात";
-            }
-        },
-        week : {
-            dow : 0, // Sunday is the first day of the week.
-            doy : 6  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/hr.js b/resources/moment/lang/hr.js
deleted file mode 100644 (file)
index 2e3bf11..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-// moment.js language configuration
-// language : hrvatski (hr)
-// author : Bojan Marković : https://github.com/bmarkovic
-
-// based on (sl) translation by Robert Sedovšek
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    function translate(number, withoutSuffix, key) {
-        var result = number + " ";
-        switch (key) {
-        case 'm':
-            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
-        case 'mm':
-            if (number === 1) {
-                result += 'minuta';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'minute';
-            } else {
-                result += 'minuta';
-            }
-            return result;
-        case 'h':
-            return withoutSuffix ? 'jedan sat' : 'jednog sata';
-        case 'hh':
-            if (number === 1) {
-                result += 'sat';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'sata';
-            } else {
-                result += 'sati';
-            }
-            return result;
-        case 'dd':
-            if (number === 1) {
-                result += 'dan';
-            } else {
-                result += 'dana';
-            }
-            return result;
-        case 'MM':
-            if (number === 1) {
-                result += 'mjesec';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'mjeseca';
-            } else {
-                result += 'mjeseci';
-            }
-            return result;
-        case 'yy':
-            if (number === 1) {
-                result += 'godina';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'godine';
-            } else {
-                result += 'godina';
-            }
-            return result;
-        }
-    }
-
-    return moment.lang('hr', {
-        months : "sječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_"),
-        monthsShort : "sje._vel._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),
-        weekdays : "nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),
-        weekdaysShort : "ned._pon._uto._sri._čet._pet._sub.".split("_"),
-        weekdaysMin : "ne_po_ut_sr_če_pe_su".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD. MM. YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay  : '[danas u] LT',
-            nextDay  : '[sutra u] LT',
-
-            nextWeek : function () {
-                switch (this.day()) {
-                case 0:
-                    return '[u] [nedjelju] [u] LT';
-                case 3:
-                    return '[u] [srijedu] [u] LT';
-                case 6:
-                    return '[u] [subotu] [u] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[u] dddd [u] LT';
-                }
-            },
-            lastDay  : '[jučer u] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                    return '[prošlu] dddd [u] LT';
-                case 6:
-                    return '[prošle] [subote] [u] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[prošli] dddd [u] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "za %s",
-            past   : "prije %s",
-            s      : "par sekundi",
-            m      : translate,
-            mm     : translate,
-            h      : translate,
-            hh     : translate,
-            d      : "dan",
-            dd     : translate,
-            M      : "mjesec",
-            MM     : translate,
-            y      : "godinu",
-            yy     : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/hu.js b/resources/moment/lang/hu.js
deleted file mode 100644 (file)
index 4d84ebd..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-// moment.js language configuration
-// language : hungarian (hu)
-// author : Adam Brunner : https://github.com/adambrunner
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' ');
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var num = number,
-            suffix;
-
-        switch (key) {
-        case 's':
-            return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce';
-        case 'm':
-            return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce');
-        case 'mm':
-            return num + (isFuture || withoutSuffix ? ' perc' : ' perce');
-        case 'h':
-            return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája');
-        case 'hh':
-            return num + (isFuture || withoutSuffix ? ' óra' : ' órája');
-        case 'd':
-            return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja');
-        case 'dd':
-            return num + (isFuture || withoutSuffix ? ' nap' : ' napja');
-        case 'M':
-            return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
-        case 'MM':
-            return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
-        case 'y':
-            return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve');
-        case 'yy':
-            return num + (isFuture || withoutSuffix ? ' év' : ' éve');
-        }
-
-        return '';
-    }
-
-    function week(isFuture) {
-        return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]';
-    }
-
-    return moment.lang('hu', {
-        months : "január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),
-        monthsShort : "jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),
-        weekdays : "vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),
-        weekdaysShort : "vas_hét_kedd_sze_csüt_pén_szo".split("_"),
-        weekdaysMin : "v_h_k_sze_cs_p_szo".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "YYYY.MM.DD.",
-            LL : "YYYY. MMMM D.",
-            LLL : "YYYY. MMMM D., LT",
-            LLLL : "YYYY. MMMM D., dddd LT"
-        },
-        calendar : {
-            sameDay : '[ma] LT[-kor]',
-            nextDay : '[holnap] LT[-kor]',
-            nextWeek : function () {
-                return week.call(this, true);
-            },
-            lastDay : '[tegnap] LT[-kor]',
-            lastWeek : function () {
-                return week.call(this, false);
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s múlva",
-            past : "%s",
-            s : translate,
-            m : translate,
-            mm : translate,
-            h : translate,
-            hh : translate,
-            d : translate,
-            dd : translate,
-            M : translate,
-            MM : translate,
-            y : translate,
-            yy : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/hy-am.js b/resources/moment/lang/hy-am.js
deleted file mode 100644 (file)
index 951655b..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-// moment.js language configuration
-// language : Armenian (hy-am)
-// author : Armendarabyan : https://github.com/armendarabyan
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    function monthsCaseReplace(m, format) {
-        var months = {
-            'nominative': 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_'),
-            'accusative': 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_')
-        },
-
-        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return months[nounCase][m.month()];
-    }
-
-    function monthsShortCaseReplace(m, format) {
-        var monthsShort = 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_');
-
-        return monthsShort[m.month()];
-    }
-
-    function weekdaysCaseReplace(m, format) {
-        var weekdays = 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_');
-
-        return weekdays[m.day()];
-    }
-
-    return moment.lang('hy-am', {
-        months : monthsCaseReplace,
-        monthsShort : monthsShortCaseReplace,
-        weekdays : weekdaysCaseReplace,
-        weekdaysShort : "կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),
-        weekdaysMin : "կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY թ.",
-            LLL : "D MMMM YYYY թ., LT",
-            LLLL : "dddd, D MMMM YYYY թ., LT"
-        },
-        calendar : {
-            sameDay: '[այսօր] LT',
-            nextDay: '[վաղը] LT',
-            lastDay: '[երեկ] LT',
-            nextWeek: function () {
-                return 'dddd [օրը ժամը] LT';
-            },
-            lastWeek: function () {
-                return '[անցած] dddd [օրը ժամը] LT';
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "%s հետո",
-            past : "%s առաջ",
-            s : "մի քանի վայրկյան",
-            m : "րոպե",
-            mm : "%d րոպե",
-            h : "ժամ",
-            hh : "%d ժամ",
-            d : "օր",
-            dd : "%d օր",
-            M : "ամիս",
-            MM : "%d ամիս",
-            y : "տարի",
-            yy : "%d տարի"
-        },
-
-        meridiem : function (hour) {
-            if (hour < 4) {
-                return "գիշերվա";
-            } else if (hour < 12) {
-                return "առավոտվա";
-            } else if (hour < 17) {
-                return "ցերեկվա";
-            } else {
-                return "երեկոյան";
-            }
-        },
-
-        ordinal: function (number, period) {
-            switch (period) {
-            case 'DDD':
-            case 'w':
-            case 'W':
-            case 'DDDo':
-                if (number === 1) {
-                    return number + '-ին';
-                }
-                return number + '-րդ';
-            default:
-                return number;
-            }
-        },
-
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/id.js b/resources/moment/lang/id.js
deleted file mode 100644 (file)
index f186280..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-// moment.js language configuration
-// language : Bahasa Indonesia (id)
-// author : Mohammad Satrio Utomo : https://github.com/tyok
-// reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('id', {
-        months : "Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),
-        monthsShort : "Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),
-        weekdays : "Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),
-        weekdaysShort : "Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),
-        weekdaysMin : "Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),
-        longDateFormat : {
-            LT : "HH.mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY [pukul] LT",
-            LLLL : "dddd, D MMMM YYYY [pukul] LT"
-        },
-        meridiem : function (hours, minutes, isLower) {
-            if (hours < 11) {
-                return 'pagi';
-            } else if (hours < 15) {
-                return 'siang';
-            } else if (hours < 19) {
-                return 'sore';
-            } else {
-                return 'malam';
-            }
-        },
-        calendar : {
-            sameDay : '[Hari ini pukul] LT',
-            nextDay : '[Besok pukul] LT',
-            nextWeek : 'dddd [pukul] LT',
-            lastDay : '[Kemarin pukul] LT',
-            lastWeek : 'dddd [lalu pukul] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "dalam %s",
-            past : "%s yang lalu",
-            s : "beberapa detik",
-            m : "semenit",
-            mm : "%d menit",
-            h : "sejam",
-            hh : "%d jam",
-            d : "sehari",
-            dd : "%d hari",
-            M : "sebulan",
-            MM : "%d bulan",
-            y : "setahun",
-            yy : "%d tahun"
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/is.js b/resources/moment/lang/is.js
deleted file mode 100644 (file)
index 5b6b2a8..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-// moment.js language configuration
-// language : icelandic (is)
-// author : Hinrik Örn Sigurðsson : https://github.com/hinrik
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function plural(n) {
-        if (n % 100 === 11) {
-            return true;
-        } else if (n % 10 === 1) {
-            return false;
-        }
-        return true;
-    }
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var result = number + " ";
-        switch (key) {
-        case 's':
-            return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum';
-        case 'm':
-            return withoutSuffix ? 'mínúta' : 'mínútu';
-        case 'mm':
-            if (plural(number)) {
-                return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum');
-            } else if (withoutSuffix) {
-                return result + 'mínúta';
-            }
-            return result + 'mínútu';
-        case 'hh':
-            if (plural(number)) {
-                return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum');
-            }
-            return result + 'klukkustund';
-        case 'd':
-            if (withoutSuffix) {
-                return 'dagur';
-            }
-            return isFuture ? 'dag' : 'degi';
-        case 'dd':
-            if (plural(number)) {
-                if (withoutSuffix) {
-                    return result + 'dagar';
-                }
-                return result + (isFuture ? 'daga' : 'dögum');
-            } else if (withoutSuffix) {
-                return result + 'dagur';
-            }
-            return result + (isFuture ? 'dag' : 'degi');
-        case 'M':
-            if (withoutSuffix) {
-                return 'mánuður';
-            }
-            return isFuture ? 'mánuð' : 'mánuði';
-        case 'MM':
-            if (plural(number)) {
-                if (withoutSuffix) {
-                    return result + 'mánuðir';
-                }
-                return result + (isFuture ? 'mánuði' : 'mánuðum');
-            } else if (withoutSuffix) {
-                return result + 'mánuður';
-            }
-            return result + (isFuture ? 'mánuð' : 'mánuði');
-        case 'y':
-            return withoutSuffix || isFuture ? 'ár' : 'ári';
-        case 'yy':
-            if (plural(number)) {
-                return result + (withoutSuffix || isFuture ? 'ár' : 'árum');
-            }
-            return result + (withoutSuffix || isFuture ? 'ár' : 'ári');
-        }
-    }
-
-    return moment.lang('is', {
-        months : "janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),
-        monthsShort : "jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),
-        weekdays : "sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),
-        weekdaysShort : "sun_mán_þri_mið_fim_fös_lau".split("_"),
-        weekdaysMin : "Su_Má_Þr_Mi_Fi_Fö_La".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD/MM/YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY [kl.] LT",
-            LLLL : "dddd, D. MMMM YYYY [kl.] LT"
-        },
-        calendar : {
-            sameDay : '[í dag kl.] LT',
-            nextDay : '[á morgun kl.] LT',
-            nextWeek : 'dddd [kl.] LT',
-            lastDay : '[í gær kl.] LT',
-            lastWeek : '[síðasta] dddd [kl.] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "eftir %s",
-            past : "fyrir %s síðan",
-            s : translate,
-            m : translate,
-            mm : translate,
-            h : "klukkustund",
-            hh : translate,
-            d : translate,
-            dd : translate,
-            M : translate,
-            MM : translate,
-            y : translate,
-            yy : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/it.js b/resources/moment/lang/it.js
deleted file mode 100644 (file)
index 84b7698..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// moment.js language configuration
-// language : italian (it)
-// author : Lorenzo : https://github.com/aliem
-// author: Mattia Larentis: https://github.com/nostalgiaz
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('it', {
-        months : "Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settembre_Ottobre_Novembre_Dicembre".split("_"),
-        monthsShort : "Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"),
-        weekdays : "Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),
-        weekdaysShort : "Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),
-        weekdaysMin : "D_L_Ma_Me_G_V_S".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: '[Oggi alle] LT',
-            nextDay: '[Domani alle] LT',
-            nextWeek: 'dddd [alle] LT',
-            lastDay: '[Ieri alle] LT',
-            lastWeek: '[lo scorso] dddd [alle] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : function (s) {
-                return ((/^[0-9].+$/).test(s) ? "tra" : "in") + " " + s;
-            },
-            past : "%s fa",
-            s : "alcuni secondi",
-            m : "un minuto",
-            mm : "%d minuti",
-            h : "un'ora",
-            hh : "%d ore",
-            d : "un giorno",
-            dd : "%d giorni",
-            M : "un mese",
-            MM : "%d mesi",
-            y : "un anno",
-            yy : "%d anni"
-        },
-        ordinal: '%dº',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/ja.js b/resources/moment/lang/ja.js
deleted file mode 100644 (file)
index 9cd7e9e..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// moment.js language configuration
-// language : japanese (ja)
-// author : LI Long : https://github.com/baryon
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ja', {
-        months : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
-        monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
-        weekdays : "日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),
-        weekdaysShort : "日_月_火_水_木_金_土".split("_"),
-        weekdaysMin : "日_月_火_水_木_金_土".split("_"),
-        longDateFormat : {
-            LT : "Ah時m分",
-            L : "YYYY/MM/DD",
-            LL : "YYYY年M月D日",
-            LLL : "YYYY年M月D日LT",
-            LLLL : "YYYY年M月D日LT dddd"
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 12) {
-                return "午前";
-            } else {
-                return "午後";
-            }
-        },
-        calendar : {
-            sameDay : '[今日] LT',
-            nextDay : '[明日] LT',
-            nextWeek : '[来週]dddd LT',
-            lastDay : '[昨日] LT',
-            lastWeek : '[前週]dddd LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s後",
-            past : "%s前",
-            s : "数秒",
-            m : "1分",
-            mm : "%d分",
-            h : "1時間",
-            hh : "%d時間",
-            d : "1日",
-            dd : "%d日",
-            M : "1ヶ月",
-            MM : "%dヶ月",
-            y : "1年",
-            yy : "%d年"
-        }
-    });
-}));
diff --git a/resources/moment/lang/ka.js b/resources/moment/lang/ka.js
deleted file mode 100644 (file)
index 0cebdaa..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// moment.js language configuration
-// language : Georgian (ka)
-// author : Irakli Janiashvili : https://github.com/irakli-janiashvili
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    function monthsCaseReplace(m, format) {
-        var months = {
-            'nominative': 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'),
-            'accusative': 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_')
-        },
-
-        nounCase = (/D[oD] *MMMM?/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return months[nounCase][m.month()];
-    }
-
-    function weekdaysCaseReplace(m, format) {
-        var weekdays = {
-            'nominative': 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'),
-            'accusative': 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_')
-        },
-
-        nounCase = (/(წინა|შემდეგ)/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return weekdays[nounCase][m.day()];
-    }
-
-    return moment.lang('ka', {
-        months : monthsCaseReplace,
-        monthsShort : "იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ".split("_"),
-        weekdays : weekdaysCaseReplace,
-        weekdaysShort : "კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ".split("_"),
-        weekdaysMin : "კვ_ორ_სა_ოთ_ხუ_პა_შა".split("_"),
-        longDateFormat : {
-            LT : "h:mm A",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[დღეს] LT[-ზე]',
-            nextDay : '[ხვალ] LT[-ზე]',
-            lastDay : '[გუშინ] LT[-ზე]',
-            nextWeek : '[შემდეგ] dddd LT[-ზე]',
-            lastWeek : '[წინა] dddd LT-ზე',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : function (s) {
-                return (/(წამი|წუთი|საათი|წელი)/).test(s) ?
-                    s.replace(/ი$/, "ში") :
-                    s + "ში";
-            },
-            past : function (s) {
-                if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) {
-                    return s.replace(/(ი|ე)$/, "ის წინ");
-                }
-                if ((/წელი/).test(s)) {
-                    return s.replace(/წელი$/, "წლის წინ");
-                }
-            },
-            s : "რამდენიმე წამი",
-            m : "წუთი",
-            mm : "%d წუთი",
-            h : "საათი",
-            hh : "%d საათი",
-            d : "დღე",
-            dd : "%d დღე",
-            M : "თვე",
-            MM : "%d თვე",
-            y : "წელი",
-            yy : "%d წელი"
-        },
-        ordinal : function (number) {
-            if (number === 0) {
-                return number;
-            }
-
-            if (number === 1) {
-                return number + "-ლი";
-            }
-
-            if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) {
-                return "მე-" + number;
-            }
-
-            return number + "-ე";
-        },
-        week : {
-            dow : 1,
-            doy : 7
-        }
-    });
-}));
diff --git a/resources/moment/lang/ko.js b/resources/moment/lang/ko.js
deleted file mode 100644 (file)
index 3b469df..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// moment.js language configuration
-// language : korean (ko)
-//
-// authors 
-//
-// - Kyungwook, Park : https://github.com/kyungw00k
-// - Jeeeyul Lee <jeeeyul@gmail.com>
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ko', {
-        months : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),
-        monthsShort : "1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),
-        weekdays : "일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),
-        weekdaysShort : "일_월_화_수_목_금_토".split("_"),
-        weekdaysMin : "일_월_화_수_목_금_토".split("_"),
-        longDateFormat : {
-            LT : "A h시 mm분",
-            L : "YYYY.MM.DD",
-            LL : "YYYY년 MMMM D일",
-            LLL : "YYYY년 MMMM D일 LT",
-            LLLL : "YYYY년 MMMM D일 dddd LT"
-        },
-        meridiem : function (hour, minute, isUpper) {
-            return hour < 12 ? '오전' : '오후';
-        },
-        calendar : {
-            sameDay : '오늘 LT',
-            nextDay : '내일 LT',
-            nextWeek : 'dddd LT',
-            lastDay : '어제 LT',
-            lastWeek : '지난주 dddd LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s 후",
-            past : "%s 전",
-            s : "몇초",
-            ss : "%d초",
-            m : "일분",
-            mm : "%d분",
-            h : "한시간",
-            hh : "%d시간",
-            d : "하루",
-            dd : "%d일",
-            M : "한달",
-            MM : "%d달",
-            y : "일년",
-            yy : "%d년"
-        },
-        ordinal : '%d일',
-        meridiemParse : /(오전|오후)/,
-        isPM : function (token) {
-            return token === "오후";
-        }
-    });
-}));
diff --git a/resources/moment/lang/lb.js b/resources/moment/lang/lb.js
deleted file mode 100644 (file)
index 946ba13..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-// moment.js language configuration
-// language : Luxembourgish (lb)
-// author : mweimerskirch : https://github.com/mweimerskirch
-
-// Note: Luxembourgish has a very particular phonological rule ("Eifeler Regel") that causes the
-// deletion of the final "n" in certain contexts. That's what the "eifelerRegelAppliesToWeekday"
-// and "eifelerRegelAppliesToNumber" methods are meant for
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function processRelativeTime(number, withoutSuffix, key, isFuture) {
-        var format = {
-            'm': ['eng Minutt', 'enger Minutt'],
-            'h': ['eng Stonn', 'enger Stonn'],
-            'd': ['een Dag', 'engem Dag'],
-            'dd': [number + ' Deeg', number + ' Deeg'],
-            'M': ['ee Mount', 'engem Mount'],
-            'MM': [number + ' Méint', number + ' Méint'],
-            'y': ['ee Joer', 'engem Joer'],
-            'yy': [number + ' Joer', number + ' Joer']
-        };
-        return withoutSuffix ? format[key][0] : format[key][1];
-    }
-
-    function processFutureTime(string) {
-        var number = string.substr(0, string.indexOf(' '));
-        if (eifelerRegelAppliesToNumber(number)) {
-            return "a " + string;
-        }
-        return "an " + string;
-    }
-
-    function processPastTime(string) {
-        var number = string.substr(0, string.indexOf(' '));
-        if (eifelerRegelAppliesToNumber(number)) {
-            return "viru " + string;
-        }
-        return "virun " + string;
-    }
-
-    function processLastWeek(string1) {
-        var weekday = this.format('d');
-        if (eifelerRegelAppliesToWeekday(weekday)) {
-            return '[Leschte] dddd [um] LT';
-        }
-        return '[Leschten] dddd [um] LT';
-    }
-
-    /**
-     * Returns true if the word before the given week day loses the "-n" ending.
-     * e.g. "Leschten Dënschdeg" but "Leschte Méindeg"
-     *
-     * @param weekday {integer}
-     * @returns {boolean}
-     */
-    function eifelerRegelAppliesToWeekday(weekday) {
-        weekday = parseInt(weekday, 10);
-        switch (weekday) {
-        case 0: // Sonndeg
-        case 1: // Méindeg
-        case 3: // Mëttwoch
-        case 5: // Freideg
-        case 6: // Samschdeg
-            return true;
-        default: // 2 Dënschdeg, 4 Donneschdeg
-            return false;
-        }
-    }
-
-    /**
-     * Returns true if the word before the given number loses the "-n" ending.
-     * e.g. "an 10 Deeg" but "a 5 Deeg"
-     *
-     * @param number {integer}
-     * @returns {boolean}
-     */
-    function eifelerRegelAppliesToNumber(number) {
-        number = parseInt(number, 10);
-        if (isNaN(number)) {
-            return false;
-        }
-        if (number < 0) {
-            // Negative Number --> always true
-            return true;
-        } else if (number < 10) {
-            // Only 1 digit
-            if (4 <= number && number <= 7) {
-                return true;
-            }
-            return false;
-        } else if (number < 100) {
-            // 2 digits
-            var lastDigit = number % 10, firstDigit = number / 10;
-            if (lastDigit === 0) {
-                return eifelerRegelAppliesToNumber(firstDigit);
-            }
-            return eifelerRegelAppliesToNumber(lastDigit);
-        } else if (number < 10000) {
-            // 3 or 4 digits --> recursively check first digit
-            while (number >= 10) {
-                number = number / 10;
-            }
-            return eifelerRegelAppliesToNumber(number);
-        } else {
-            // Anything larger than 4 digits: recursively check first n-3 digits
-            number = number / 1000;
-            return eifelerRegelAppliesToNumber(number);
-        }
-    }
-
-    return moment.lang('lb', {
-        months: "Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),
-        monthsShort: "Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),
-        weekdays: "Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),
-        weekdaysShort: "So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),
-        weekdaysMin: "So_Mé_Dë_Më_Do_Fr_Sa".split("_"),
-        longDateFormat: {
-            LT: "H:mm [Auer]",
-            L: "DD.MM.YYYY",
-            LL: "D. MMMM YYYY",
-            LLL: "D. MMMM YYYY LT",
-            LLLL: "dddd, D. MMMM YYYY LT"
-        },
-        calendar: {
-            sameDay: "[Haut um] LT",
-            sameElse: "L",
-            nextDay: '[Muer um] LT',
-            nextWeek: 'dddd [um] LT',
-            lastDay: '[Gëschter um] LT',
-            lastWeek: processLastWeek
-        },
-        relativeTime: {
-            future: processFutureTime,
-            past: processPastTime,
-            s: "e puer Sekonnen",
-            m: processRelativeTime,
-            mm: "%d Minutten",
-            h: processRelativeTime,
-            hh: "%d Stonnen",
-            d: processRelativeTime,
-            dd: processRelativeTime,
-            M: processRelativeTime,
-            MM: processRelativeTime,
-            y: processRelativeTime,
-            yy: processRelativeTime
-        },
-        ordinal: '%d.',
-        week: {
-            dow: 1, // Monday is the first day of the week.
-            doy: 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/lt.js b/resources/moment/lang/lt.js
deleted file mode 100644 (file)
index 1cf6457..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-// moment.js language configuration
-// language : Lithuanian (lt)
-// author : Mindaugas Mozūras : https://github.com/mmozuras
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var units = {
-        "m" : "minutė_minutės_minutę",
-        "mm": "minutės_minučių_minutes",
-        "h" : "valanda_valandos_valandą",
-        "hh": "valandos_valandų_valandas",
-        "d" : "diena_dienos_dieną",
-        "dd": "dienos_dienų_dienas",
-        "M" : "mėnuo_mėnesio_mėnesį",
-        "MM": "mėnesiai_mėnesių_mėnesius",
-        "y" : "metai_metų_metus",
-        "yy": "metai_metų_metus"
-    },
-    weekDays = "pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis_sekmadienis".split("_");
-
-    function translateSeconds(number, withoutSuffix, key, isFuture) {
-        if (withoutSuffix) {
-            return "kelios sekundės";
-        } else {
-            return isFuture ? "kelių sekundžių" : "kelias sekundes";
-        }
-    }
-
-    function translateSingular(number, withoutSuffix, key, isFuture) {
-        return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]);
-    }
-
-    function special(number) {
-        return number % 10 === 0 || (number > 10 && number < 20);
-    }
-
-    function forms(key) {
-        return units[key].split("_");
-    }
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var result = number + " ";
-        if (number === 1) {
-            return result + translateSingular(number, withoutSuffix, key[0], isFuture);
-        } else if (withoutSuffix) {
-            return result + (special(number) ? forms(key)[1] : forms(key)[0]);
-        } else {
-            if (isFuture) {
-                return result + forms(key)[1];
-            } else {
-                return result + (special(number) ? forms(key)[1] : forms(key)[2]);
-            }
-        }
-    }
-
-    function relativeWeekDay(moment, format) {
-        var nominative = format.indexOf('dddd LT') === -1,
-            weekDay = weekDays[moment.weekday()];
-
-        return nominative ? weekDay : weekDay.substring(0, weekDay.length - 2) + "į";
-    }
-
-    return moment.lang("lt", {
-        months : "sausio_vasario_kovo_balandžio_gegužės_biržėlio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),
-        monthsShort : "sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),
-        weekdays : relativeWeekDay,
-        weekdaysShort : "Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),
-        weekdaysMin : "S_P_A_T_K_Pn_Š".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "YYYY-MM-DD",
-            LL : "YYYY [m.] MMMM D [d.]",
-            LLL : "YYYY [m.] MMMM D [d.], LT [val.]",
-            LLLL : "YYYY [m.] MMMM D [d.], dddd, LT [val.]",
-            l : "YYYY-MM-DD",
-            ll : "YYYY [m.] MMMM D [d.]",
-            lll : "YYYY [m.] MMMM D [d.], LT [val.]",
-            llll : "YYYY [m.] MMMM D [d.], ddd, LT [val.]"
-        },
-        calendar : {
-            sameDay : "[Šiandien] LT",
-            nextDay : "[Rytoj] LT",
-            nextWeek : "dddd LT",
-            lastDay : "[Vakar] LT",
-            lastWeek : "[Praėjusį] dddd LT",
-            sameElse : "L"
-        },
-        relativeTime : {
-            future : "po %s",
-            past : "prieš %s",
-            s : translateSeconds,
-            m : translateSingular,
-            mm : translate,
-            h : translateSingular,
-            hh : translate,
-            d : translateSingular,
-            dd : translate,
-            M : translateSingular,
-            MM : translate,
-            y : translateSingular,
-            yy : translate
-        },
-        ordinal : function (number) {
-            return number + '-oji';
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/lv.js b/resources/moment/lang/lv.js
deleted file mode 100644 (file)
index ffe25cf..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// moment.js language configuration
-// language : latvian (lv)
-// author : Kristaps Karlsons : https://github.com/skakri
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var units = {
-        'mm': 'minūti_minūtes_minūte_minūtes',
-        'hh': 'stundu_stundas_stunda_stundas',
-        'dd': 'dienu_dienas_diena_dienas',
-        'MM': 'mēnesi_mēnešus_mēnesis_mēneši',
-        'yy': 'gadu_gadus_gads_gadi'
-    };
-
-    function format(word, number, withoutSuffix) {
-        var forms = word.split('_');
-        if (withoutSuffix) {
-            return number % 10 === 1 && number !== 11 ? forms[2] : forms[3];
-        } else {
-            return number % 10 === 1 && number !== 11 ? forms[0] : forms[1];
-        }
-    }
-
-    function relativeTimeWithPlural(number, withoutSuffix, key) {
-        return number + ' ' + format(units[key], number, withoutSuffix);
-    }
-
-    return moment.lang('lv', {
-        months : "janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),
-        monthsShort : "jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),
-        weekdays : "svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),
-        weekdaysShort : "Sv_P_O_T_C_Pk_S".split("_"),
-        weekdaysMin : "Sv_P_O_T_C_Pk_S".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "YYYY. [gada] D. MMMM",
-            LLL : "YYYY. [gada] D. MMMM, LT",
-            LLLL : "YYYY. [gada] D. MMMM, dddd, LT"
-        },
-        calendar : {
-            sameDay : '[Šodien pulksten] LT',
-            nextDay : '[Rīt pulksten] LT',
-            nextWeek : 'dddd [pulksten] LT',
-            lastDay : '[Vakar pulksten] LT',
-            lastWeek : '[Pagājušā] dddd [pulksten] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s vēlāk",
-            past : "%s agrāk",
-            s : "dažas sekundes",
-            m : "minūti",
-            mm : relativeTimeWithPlural,
-            h : "stundu",
-            hh : relativeTimeWithPlural,
-            d : "dienu",
-            dd : relativeTimeWithPlural,
-            M : "mēnesi",
-            MM : relativeTimeWithPlural,
-            y : "gadu",
-            yy : relativeTimeWithPlural
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/mk.js b/resources/moment/lang/mk.js
deleted file mode 100644 (file)
index 5f272fa..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// moment.js language configuration
-// language : macedonian (mk)
-// author : Borislav Mickov : https://github.com/B0k0
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('mk', {
-        months : "јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември".split("_"),
-        monthsShort : "јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек".split("_"),
-        weekdays : "недела_понеделник_вторник_среда_четврток_петок_сабота".split("_"),
-        weekdaysShort : "нед_пон_вто_сре_чет_пет_саб".split("_"),
-        weekdaysMin : "нe_пo_вт_ср_че_пе_сa".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "D.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Денес во] LT',
-            nextDay : '[Утре во] LT',
-            nextWeek : 'dddd [во] LT',
-            lastDay : '[Вчера во] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                case 6:
-                    return '[Во изминатата] dddd [во] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[Во изминатиот] dddd [во] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "после %s",
-            past : "пред %s",
-            s : "неколку секунди",
-            m : "минута",
-            mm : "%d минути",
-            h : "час",
-            hh : "%d часа",
-            d : "ден",
-            dd : "%d дена",
-            M : "месец",
-            MM : "%d месеци",
-            y : "година",
-            yy : "%d години"
-        },
-        ordinal : function (number) {
-            var lastDigit = number % 10,
-                last2Digits = number % 100;
-            if (number === 0) {
-                return number + '-ев';
-            } else if (last2Digits === 0) {
-                return number + '-ен';
-            } else if (last2Digits > 10 && last2Digits < 20) {
-                return number + '-ти';
-            } else if (lastDigit === 1) {
-                return number + '-ви';
-            } else if (lastDigit === 2) {
-                return number + '-ри';
-            } else if (lastDigit === 7 || lastDigit === 8) {
-                return number + '-ми';
-            } else {
-                return number + '-ти';
-            }
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/ml.js b/resources/moment/lang/ml.js
deleted file mode 100644 (file)
index cc7db9a..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-// moment.js language configuration
-// language : malayalam (ml)
-// author : Floyd Pink : https://github.com/floydpink
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ml', {
-        months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split("_"),
-        monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split("_"),
-        weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split("_"),
-        weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split("_"),
-        weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split("_"),
-        longDateFormat : {
-            LT : "A h:mm -നു",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY, LT",
-            LLLL : "dddd, D MMMM YYYY, LT"
-        },
-        calendar : {
-            sameDay : '[ഇന്ന്] LT',
-            nextDay : '[നാളെ] LT',
-            nextWeek : 'dddd, LT',
-            lastDay : '[ഇന്നലെ] LT',
-            lastWeek : '[കഴിഞ്ഞ] dddd, LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s കഴിഞ്ഞ്",
-            past : "%s മുൻപ്",
-            s : "അൽപ നിമിഷങ്ങൾ",
-            m : "ഒരു മിനിറ്റ്",
-            mm : "%d മിനിറ്റ്",
-            h : "ഒരു മണിക്കൂർ",
-            hh : "%d മണിക്കൂർ",
-            d : "ഒരു ദിവസം",
-            dd : "%d ദിവസം",
-            M : "ഒരു മാസം",
-            MM : "%d മാസം",
-            y : "ഒരു വർഷം",
-            yy : "%d വർഷം"
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return "രാത്രി";
-            } else if (hour < 12) {
-                return "രാവിലെ";
-            } else if (hour < 17) {
-                return "ഉച്ച കഴിഞ്ഞ്";
-            } else if (hour < 20) {
-                return "വൈകുന്നേരം";
-            } else {
-                return "രാത്രി";
-            }
-        }
-    });
-}));
diff --git a/resources/moment/lang/mr.js b/resources/moment/lang/mr.js
deleted file mode 100644 (file)
index 0d1adfd..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-// moment.js language configuration
-// language : Marathi (mr)
-// author : Harshad Kale : https://github.com/kalehv
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var symbolMap = {
-        '1': '१',
-        '2': '२',
-        '3': '३',
-        '4': '४',
-        '5': '५',
-        '6': '६',
-        '7': '७',
-        '8': '८',
-        '9': '९',
-        '0': '०'
-    },
-    numberMap = {
-        '१': '1',
-        '२': '2',
-        '३': '3',
-        '४': '4',
-        '५': '5',
-        '६': '6',
-        '७': '7',
-        '८': '8',
-        '९': '9',
-        '०': '0'
-    };
-
-    return moment.lang('mr', {
-        months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split("_"),
-        monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split("_"),
-        weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split("_"),
-        weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split("_"),
-        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split("_"),
-        longDateFormat : {
-            LT : "A h:mm वाजता",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY, LT",
-            LLLL : "dddd, D MMMM YYYY, LT"
-        },
-        calendar : {
-            sameDay : '[आज] LT',
-            nextDay : '[उद्या] LT',
-            nextWeek : 'dddd, LT',
-            lastDay : '[काल] LT',
-            lastWeek: '[मागील] dddd, LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s नंतर",
-            past : "%s पूर्वी",
-            s : "सेकंद",
-            m: "एक मिनिट",
-            mm: "%d मिनिटे",
-            h : "एक तास",
-            hh : "%d तास",
-            d : "एक दिवस",
-            dd : "%d दिवस",
-            M : "एक महिना",
-            MM : "%d महिने",
-            y : "एक वर्ष",
-            yy : "%d वर्षे"
-        },
-        preparse: function (string) {
-            return string.replace(/[१२३४५६७८९०]/g, function (match) {
-                return numberMap[match];
-            });
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            });
-        },
-        meridiem: function (hour, minute, isLower)
-        {
-            if (hour < 4) {
-                return "रात्री";
-            } else if (hour < 10) {
-                return "सकाळी";
-            } else if (hour < 17) {
-                return "दुपारी";
-            } else if (hour < 20) {
-                return "सायंकाळी";
-            } else {
-                return "रात्री";
-            }
-        },
-        week : {
-            dow : 0, // Sunday is the first day of the week.
-            doy : 6  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/ms-my.js b/resources/moment/lang/ms-my.js
deleted file mode 100644 (file)
index 501d5aa..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// moment.js language configuration
-// language : Bahasa Malaysia (ms-MY)
-// author : Weldan Jamili : https://github.com/weldan
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('ms-my', {
-        months : "Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),
-        monthsShort : "Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),
-        weekdays : "Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),
-        weekdaysShort : "Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),
-        weekdaysMin : "Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),
-        longDateFormat : {
-            LT : "HH.mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY [pukul] LT",
-            LLLL : "dddd, D MMMM YYYY [pukul] LT"
-        },
-        meridiem : function (hours, minutes, isLower) {
-            if (hours < 11) {
-                return 'pagi';
-            } else if (hours < 15) {
-                return 'tengahari';
-            } else if (hours < 19) {
-                return 'petang';
-            } else {
-                return 'malam';
-            }
-        },
-        calendar : {
-            sameDay : '[Hari ini pukul] LT',
-            nextDay : '[Esok pukul] LT',
-            nextWeek : 'dddd [pukul] LT',
-            lastDay : '[Kelmarin pukul] LT',
-            lastWeek : 'dddd [lepas pukul] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "dalam %s",
-            past : "%s yang lepas",
-            s : "beberapa saat",
-            m : "seminit",
-            mm : "%d minit",
-            h : "sejam",
-            hh : "%d jam",
-            d : "sehari",
-            dd : "%d hari",
-            M : "sebulan",
-            MM : "%d bulan",
-            y : "setahun",
-            yy : "%d tahun"
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/nb.js b/resources/moment/lang/nb.js
deleted file mode 100644 (file)
index 2f652ef..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// moment.js language configuration
-// language : norwegian bokmål (nb)
-// authors : Espen Hovlandsdal : https://github.com/rexxars
-//           Sigurd Gartmann : https://github.com/sigurdga
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('nb', {
-        months : "januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),
-        monthsShort : "jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.".split("_"),
-        weekdays : "søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),
-        weekdaysShort : "sø._ma._ti._on._to._fr._lø.".split("_"),
-        weekdaysMin : "sø_ma_ti_on_to_fr_lø".split("_"),
-        longDateFormat : {
-            LT : "H.mm",
-            L : "DD.MM.YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY [kl.] LT",
-            LLLL : "dddd D. MMMM YYYY [kl.] LT"
-        },
-        calendar : {
-            sameDay: '[i dag kl.] LT',
-            nextDay: '[i morgen kl.] LT',
-            nextWeek: 'dddd [kl.] LT',
-            lastDay: '[i går kl.] LT',
-            lastWeek: '[forrige] dddd [kl.] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "om %s",
-            past : "for %s siden",
-            s : "noen sekunder",
-            m : "ett minutt",
-            mm : "%d minutter",
-            h : "en time",
-            hh : "%d timer",
-            d : "en dag",
-            dd : "%d dager",
-            M : "en måned",
-            MM : "%d måneder",
-            y : "ett år",
-            yy : "%d år"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/ne.js b/resources/moment/lang/ne.js
deleted file mode 100644 (file)
index 1d57b8c..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// moment.js language configuration
-// language : nepali/nepalese
-// author : suvash : https://github.com/suvash
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var symbolMap = {
-        '1': '१',
-        '2': '२',
-        '3': '३',
-        '4': '४',
-        '5': '५',
-        '6': '६',
-        '7': '७',
-        '8': '८',
-        '9': '९',
-        '0': '०'
-    },
-    numberMap = {
-        '१': '1',
-        '२': '2',
-        '३': '3',
-        '४': '4',
-        '५': '5',
-        '६': '6',
-        '७': '7',
-        '८': '8',
-        '९': '9',
-        '०': '0'
-    };
-
-    return moment.lang('ne', {
-        months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split("_"),
-        monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split("_"),
-        weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split("_"),
-        weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split("_"),
-        weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split("_"),
-        longDateFormat : {
-            LT : "Aको h:mm बजे",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY, LT",
-            LLLL : "dddd, D MMMM YYYY, LT"
-        },
-        preparse: function (string) {
-            return string.replace(/[१२३४५६७८९०]/g, function (match) {
-                return numberMap[match];
-            });
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            });
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 3) {
-                return "राती";
-            } else if (hour < 10) {
-                return "बिहान";
-            } else if (hour < 15) {
-                return "दिउँसो";
-            } else if (hour < 18) {
-                return "बेलुका";
-            } else if (hour < 20) {
-                return "साँझ";
-            } else {
-                return "राती";
-            }
-        },
-        calendar : {
-            sameDay : '[आज] LT',
-            nextDay : '[भोली] LT',
-            nextWeek : '[आउँदो] dddd[,] LT',
-            lastDay : '[हिजो] LT',
-            lastWeek : '[गएको] dddd[,] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%sमा",
-            past : "%s अगाडी",
-            s : "केही समय",
-            m : "एक मिनेट",
-            mm : "%d मिनेट",
-            h : "एक घण्टा",
-            hh : "%d घण्टा",
-            d : "एक दिन",
-            dd : "%d दिन",
-            M : "एक महिना",
-            MM : "%d महिना",
-            y : "एक बर्ष",
-            yy : "%d बर्ष"
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/nl.js b/resources/moment/lang/nl.js
deleted file mode 100644 (file)
index ffd454f..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-// moment.js language configuration
-// language : dutch (nl)
-// author : Joris Röling : https://github.com/jjupiter
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var monthsShortWithDots = "jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),
-        monthsShortWithoutDots = "jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_");
-
-    return moment.lang('nl', {
-        months : "januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),
-        monthsShort : function (m, format) {
-            if (/-MMM-/.test(format)) {
-                return monthsShortWithoutDots[m.month()];
-            } else {
-                return monthsShortWithDots[m.month()];
-            }
-        },
-        weekdays : "zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),
-        weekdaysShort : "zo._ma._di._wo._do._vr._za.".split("_"),
-        weekdaysMin : "Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD-MM-YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: '[vandaag om] LT',
-            nextDay: '[morgen om] LT',
-            nextWeek: 'dddd [om] LT',
-            lastDay: '[gisteren om] LT',
-            lastWeek: '[afgelopen] dddd [om] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "over %s",
-            past : "%s geleden",
-            s : "een paar seconden",
-            m : "één minuut",
-            mm : "%d minuten",
-            h : "één uur",
-            hh : "%d uur",
-            d : "één dag",
-            dd : "%d dagen",
-            M : "één maand",
-            MM : "%d maanden",
-            y : "één jaar",
-            yy : "%d jaar"
-        },
-        ordinal : function (number) {
-            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/nn.js b/resources/moment/lang/nn.js
deleted file mode 100644 (file)
index f59c415..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// moment.js language configuration
-// language : norwegian nynorsk (nn)
-// author : https://github.com/mechuwind
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('nn', {
-        months : "januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),
-        monthsShort : "jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),
-        weekdays : "sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),
-        weekdaysShort : "sun_mån_tys_ons_tor_fre_lau".split("_"),
-        weekdaysMin : "su_må_ty_on_to_fr_lø".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: '[I dag klokka] LT',
-            nextDay: '[I morgon klokka] LT',
-            nextWeek: 'dddd [klokka] LT',
-            lastDay: '[I går klokka] LT',
-            lastWeek: '[Føregående] dddd [klokka] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "om %s",
-            past : "for %s siden",
-            s : "noen sekund",
-            m : "ett minutt",
-            mm : "%d minutt",
-            h : "en time",
-            hh : "%d timar",
-            d : "en dag",
-            dd : "%d dagar",
-            M : "en månad",
-            MM : "%d månader",
-            y : "ett år",
-            yy : "%d år"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/pl.js b/resources/moment/lang/pl.js
deleted file mode 100644 (file)
index 97770d2..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-// moment.js language configuration
-// language : polish (pl)
-// author : Rafal Hirsz : https://github.com/evoL
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var monthsNominative = "styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),
-        monthsSubjective = "stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_");
-
-    function plural(n) {
-        return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1);
-    }
-
-    function translate(number, withoutSuffix, key) {
-        var result = number + " ";
-        switch (key) {
-        case 'm':
-            return withoutSuffix ? 'minuta' : 'minutę';
-        case 'mm':
-            return result + (plural(number) ? 'minuty' : 'minut');
-        case 'h':
-            return withoutSuffix  ? 'godzina'  : 'godzinę';
-        case 'hh':
-            return result + (plural(number) ? 'godziny' : 'godzin');
-        case 'MM':
-            return result + (plural(number) ? 'miesiące' : 'miesięcy');
-        case 'yy':
-            return result + (plural(number) ? 'lata' : 'lat');
-        }
-    }
-
-    return moment.lang('pl', {
-        months : function (momentToFormat, format) {
-            if (/D MMMM/.test(format)) {
-                return monthsSubjective[momentToFormat.month()];
-            } else {
-                return monthsNominative[momentToFormat.month()];
-            }
-        },
-        monthsShort : "sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),
-        weekdays : "niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),
-        weekdaysShort : "nie_pon_wt_śr_czw_pt_sb".split("_"),
-        weekdaysMin : "N_Pn_Wt_Śr_Cz_Pt_So".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: '[Dziś o] LT',
-            nextDay: '[Jutro o] LT',
-            nextWeek: '[W] dddd [o] LT',
-            lastDay: '[Wczoraj o] LT',
-            lastWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[W zeszłą niedzielę o] LT';
-                case 3:
-                    return '[W zeszłą środę o] LT';
-                case 6:
-                    return '[W zeszłą sobotę o] LT';
-                default:
-                    return '[W zeszły] dddd [o] LT';
-                }
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "za %s",
-            past : "%s temu",
-            s : "kilka sekund",
-            m : translate,
-            mm : translate,
-            h : translate,
-            hh : translate,
-            d : "1 dzień",
-            dd : '%d dni',
-            M : "miesiąc",
-            MM : translate,
-            y : "rok",
-            yy : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/pt-br.js b/resources/moment/lang/pt-br.js
deleted file mode 100644 (file)
index 5cac19b..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// moment.js language configuration
-// language : brazilian portuguese (pt-br)
-// author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('pt-br', {
-        months : "Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),
-        monthsShort : "Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),
-        weekdays : "Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),
-        weekdaysShort : "Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),
-        weekdaysMin : "Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D [de] MMMM [de] YYYY",
-            LLL : "D [de] MMMM [de] YYYY LT",
-            LLLL : "dddd, D [de] MMMM [de] YYYY LT"
-        },
-        calendar : {
-            sameDay: '[Hoje às] LT',
-            nextDay: '[Amanhã às] LT',
-            nextWeek: 'dddd [às] LT',
-            lastDay: '[Ontem às] LT',
-            lastWeek: function () {
-                return (this.day() === 0 || this.day() === 6) ?
-                    '[Último] dddd [às] LT' : // Saturday + Sunday
-                    '[Última] dddd [às] LT'; // Monday - Friday
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "em %s",
-            past : "%s atrás",
-            s : "segundos",
-            m : "um minuto",
-            mm : "%d minutos",
-            h : "uma hora",
-            hh : "%d horas",
-            d : "um dia",
-            dd : "%d dias",
-            M : "um mês",
-            MM : "%d meses",
-            y : "um ano",
-            yy : "%d anos"
-        },
-        ordinal : '%dº'
-    });
-}));
diff --git a/resources/moment/lang/pt.js b/resources/moment/lang/pt.js
deleted file mode 100644 (file)
index 7c1f2b5..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// moment.js language configuration
-// language : portuguese (pt)
-// author : Jefferson : https://github.com/jalex79
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('pt', {
-        months : "Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),
-        monthsShort : "Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),
-        weekdays : "Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),
-        weekdaysShort : "Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),
-        weekdaysMin : "Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D [de] MMMM [de] YYYY",
-            LLL : "D [de] MMMM [de] YYYY LT",
-            LLLL : "dddd, D [de] MMMM [de] YYYY LT"
-        },
-        calendar : {
-            sameDay: '[Hoje às] LT',
-            nextDay: '[Amanhã às] LT',
-            nextWeek: 'dddd [às] LT',
-            lastDay: '[Ontem às] LT',
-            lastWeek: function () {
-                return (this.day() === 0 || this.day() === 6) ?
-                    '[Último] dddd [às] LT' : // Saturday + Sunday
-                    '[Última] dddd [às] LT'; // Monday - Friday
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "em %s",
-            past : "%s atrás",
-            s : "segundos",
-            m : "um minuto",
-            mm : "%d minutos",
-            h : "uma hora",
-            hh : "%d horas",
-            d : "um dia",
-            dd : "%d dias",
-            M : "um mês",
-            MM : "%d meses",
-            y : "um ano",
-            yy : "%d anos"
-        },
-        ordinal : '%dº',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/ro.js b/resources/moment/lang/ro.js
deleted file mode 100644 (file)
index 77d7355..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// moment.js language configuration
-// language : romanian (ro)
-// author : Vlad Gurdiga : https://github.com/gurdiga
-// author : Valentin Agachi : https://github.com/avaly
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function relativeTimeWithPlural(number, withoutSuffix, key) {
-        var format = {
-            'mm': 'minute',
-            'hh': 'ore',
-            'dd': 'zile',
-            'MM': 'luni',
-            'yy': 'ani'
-        },
-            separator = ' ';
-        if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) {
-            separator = ' de ';
-        }
-
-        return number + separator + format[key];
-    }
-
-    return moment.lang('ro', {
-        months : "ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),
-        monthsShort : "ian_feb_mar_apr_mai_iun_iul_aug_sep_oct_noi_dec".split("_"),
-        weekdays : "duminică_luni_marți_miercuri_joi_vineri_sâmbătă".split("_"),
-        weekdaysShort : "Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),
-        weekdaysMin : "Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY H:mm",
-            LLLL : "dddd, D MMMM YYYY H:mm"
-        },
-        calendar : {
-            sameDay: "[azi la] LT",
-            nextDay: '[mâine la] LT',
-            nextWeek: 'dddd [la] LT',
-            lastDay: '[ieri la] LT',
-            lastWeek: '[fosta] dddd [la] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "peste %s",
-            past : "%s în urmă",
-            s : "câteva secunde",
-            m : "un minut",
-            mm : relativeTimeWithPlural,
-            h : "o oră",
-            hh : relativeTimeWithPlural,
-            d : "o zi",
-            dd : relativeTimeWithPlural,
-            M : "o lună",
-            MM : relativeTimeWithPlural,
-            y : "un an",
-            yy : relativeTimeWithPlural
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/rs.js b/resources/moment/lang/rs.js
deleted file mode 100644 (file)
index 8627553..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-// moment.js language configuration
-// language : serbian (rs)
-// author : Limon Monte : https://github.com/limonte
-// based on (bs) translation by Nedim Cholich
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    function translate(number, withoutSuffix, key) {
-        var result = number + " ";
-        switch (key) {
-        case 'm':
-            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
-        case 'mm':
-            if (number === 1) {
-                result += 'minuta';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'minute';
-            } else {
-                result += 'minuta';
-            }
-            return result;
-        case 'h':
-            return withoutSuffix ? 'jedan sat' : 'jednog sata';
-        case 'hh':
-            if (number === 1) {
-                result += 'sat';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'sata';
-            } else {
-                result += 'sati';
-            }
-            return result;
-        case 'dd':
-            if (number === 1) {
-                result += 'dan';
-            } else {
-                result += 'dana';
-            }
-            return result;
-        case 'MM':
-            if (number === 1) {
-                result += 'mesec';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'meseca';
-            } else {
-                result += 'meseci';
-            }
-            return result;
-        case 'yy':
-            if (number === 1) {
-                result += 'godina';
-            } else if (number === 2 || number === 3 || number === 4) {
-                result += 'godine';
-            } else {
-                result += 'godina';
-            }
-            return result;
-        }
-    }
-
-    return moment.lang('rs', {
-        months : "januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),
-        monthsShort : "jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),
-        weekdays : "nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),
-        weekdaysShort : "ned._pon._uto._sre._čet._pet._sub.".split("_"),
-        weekdaysMin : "ne_po_ut_sr_če_pe_su".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD. MM. YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay  : '[danas u] LT',
-            nextDay  : '[sutra u] LT',
-
-            nextWeek : function () {
-                switch (this.day()) {
-                case 0:
-                    return '[u] [nedelju] [u] LT';
-                case 3:
-                    return '[u] [sredu] [u] LT';
-                case 6:
-                    return '[u] [subotu] [u] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[u] dddd [u] LT';
-                }
-            },
-            lastDay  : '[juče u] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                    return '[prošlu] dddd [u] LT';
-                case 6:
-                    return '[prošle] [subote] [u] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[prošli] dddd [u] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "za %s",
-            past   : "pre %s",
-            s      : "par sekundi",
-            m      : translate,
-            mm     : translate,
-            h      : translate,
-            hh     : translate,
-            d      : "dan",
-            dd     : translate,
-            M      : "mesec",
-            MM     : translate,
-            y      : "godinu",
-            yy     : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/ru.js b/resources/moment/lang/ru.js
deleted file mode 100644 (file)
index 1d1816c..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-// moment.js language configuration
-// language : russian (ru)
-// author : Viktorminator : https://github.com/Viktorminator
-// Author : Menelion Elensúle : https://github.com/Oire
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function plural(word, num) {
-        var forms = word.split('_');
-        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
-    }
-
-    function relativeTimeWithPlural(number, withoutSuffix, key) {
-        var format = {
-            'mm': 'минута_минуты_минут',
-            'hh': 'час_часа_часов',
-            'dd': 'день_дня_дней',
-            'MM': 'месяц_месяца_месяцев',
-            'yy': 'год_года_лет'
-        };
-        if (key === 'm') {
-            return withoutSuffix ? 'минута' : 'минуту';
-        }
-        else {
-            return number + ' ' + plural(format[key], +number);
-        }
-    }
-
-    function monthsCaseReplace(m, format) {
-        var months = {
-            'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'),
-            'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_')
-        },
-
-        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return months[nounCase][m.month()];
-    }
-
-    function monthsShortCaseReplace(m, format) {
-        var monthsShort = {
-            'nominative': 'янв_фев_мар_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'),
-            'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_')
-        },
-
-        nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return monthsShort[nounCase][m.month()];
-    }
-
-    function weekdaysCaseReplace(m, format) {
-        var weekdays = {
-            'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
-            'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_')
-        },
-
-        nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую)? ?\] ?dddd/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return weekdays[nounCase][m.day()];
-    }
-
-    return moment.lang('ru', {
-        months : monthsCaseReplace,
-        monthsShort : monthsShortCaseReplace,
-        weekdays : weekdaysCaseReplace,
-        weekdaysShort : "вс_пн_вт_ср_чт_пт_сб".split("_"),
-        weekdaysMin : "вс_пн_вт_ср_чт_пт_сб".split("_"),
-        monthsParse : [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[й|я]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i],
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY г.",
-            LLL : "D MMMM YYYY г., LT",
-            LLLL : "dddd, D MMMM YYYY г., LT"
-        },
-        calendar : {
-            sameDay: '[Сегодня в] LT',
-            nextDay: '[Завтра в] LT',
-            lastDay: '[Вчера в] LT',
-            nextWeek: function () {
-                return this.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT';
-            },
-            lastWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[В прошлое] dddd [в] LT';
-                case 1:
-                case 2:
-                case 4:
-                    return '[В прошлый] dddd [в] LT';
-                case 3:
-                case 5:
-                case 6:
-                    return '[В прошлую] dddd [в] LT';
-                }
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "через %s",
-            past : "%s назад",
-            s : "несколько секунд",
-            m : relativeTimeWithPlural,
-            mm : relativeTimeWithPlural,
-            h : "час",
-            hh : relativeTimeWithPlural,
-            d : "день",
-            dd : relativeTimeWithPlural,
-            M : "месяц",
-            MM : relativeTimeWithPlural,
-            y : "год",
-            yy : relativeTimeWithPlural
-        },
-
-        // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
-
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return "ночи";
-            } else if (hour < 12) {
-                return "утра";
-            } else if (hour < 17) {
-                return "дня";
-            } else {
-                return "вечера";
-            }
-        },
-
-        ordinal: function (number, period) {
-            switch (period) {
-            case 'M':
-            case 'd':
-            case 'DDD':
-                return number + '-й';
-            case 'D':
-                return number + '-го';
-            case 'w':
-            case 'W':
-                return number + '-я';
-            default:
-                return number;
-            }
-        },
-
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/sk.js b/resources/moment/lang/sk.js
deleted file mode 100644 (file)
index ed8a41d..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-// moment.js language configuration
-// language : slovak (sk)
-// author : Martin Minka : https://github.com/k2s
-// based on work of petrbela : https://github.com/petrbela
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    var months = "január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"),
-        monthsShort = "jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_");
-
-    function plural(n) {
-        return (n > 1) && (n < 5);
-    }
-
-    function translate(number, withoutSuffix, key, isFuture) {
-        var result = number + " ";
-        switch (key) {
-        case 's':  // a few seconds / in a few seconds / a few seconds ago
-            return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami';
-        case 'm':  // a minute / in a minute / a minute ago
-            return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou');
-        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'minúty' : 'minút');
-            } else {
-                return result + 'minútami';
-            }
-            break;
-        case 'h':  // an hour / in an hour / an hour ago
-            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
-        case 'hh': // 9 hours / in 9 hours / 9 hours ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'hodiny' : 'hodín');
-            } else {
-                return result + 'hodinami';
-            }
-            break;
-        case 'd':  // a day / in a day / a day ago
-            return (withoutSuffix || isFuture) ? 'deň' : 'dňom';
-        case 'dd': // 9 days / in 9 days / 9 days ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'dni' : 'dní');
-            } else {
-                return result + 'dňami';
-            }
-            break;
-        case 'M':  // a month / in a month / a month ago
-            return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom';
-        case 'MM': // 9 months / in 9 months / 9 months ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'mesiace' : 'mesiacov');
-            } else {
-                return result + 'mesiacmi';
-            }
-            break;
-        case 'y':  // a year / in a year / a year ago
-            return (withoutSuffix || isFuture) ? 'rok' : 'rokom';
-        case 'yy': // 9 years / in 9 years / 9 years ago
-            if (withoutSuffix || isFuture) {
-                return result + (plural(number) ? 'roky' : 'rokov');
-            } else {
-                return result + 'rokmi';
-            }
-            break;
-        }
-    }
-
-    return moment.lang('sk', {
-        months : months,
-        monthsShort : monthsShort,
-        monthsParse : (function (months, monthsShort) {
-            var i, _monthsParse = [];
-            for (i = 0; i < 12; i++) {
-                // use custom parser to solve problem with July (červenec)
-                _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
-            }
-            return _monthsParse;
-        }(months, monthsShort)),
-        weekdays : "nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"),
-        weekdaysShort : "ne_po_ut_st_št_pi_so".split("_"),
-        weekdaysMin : "ne_po_ut_st_št_pi_so".split("_"),
-        longDateFormat : {
-            LT: "H:mm",
-            L : "DD.MM.YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[dnes o] LT",
-            nextDay: '[zajtra o] LT',
-            nextWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[v nedeľu o] LT';
-                case 1:
-                case 2:
-                    return '[v] dddd [o] LT';
-                case 3:
-                    return '[v stredu o] LT';
-                case 4:
-                    return '[vo štvrtok o] LT';
-                case 5:
-                    return '[v piatok o] LT';
-                case 6:
-                    return '[v sobotu o] LT';
-                }
-            },
-            lastDay: '[včera o] LT',
-            lastWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[minulú nedeľu o] LT';
-                case 1:
-                case 2:
-                    return '[minulý] dddd [o] LT';
-                case 3:
-                    return '[minulú stredu o] LT';
-                case 4:
-                case 5:
-                    return '[minulý] dddd [o] LT';
-                case 6:
-                    return '[minulú sobotu o] LT';
-                }
-            },
-            sameElse: "L"
-        },
-        relativeTime : {
-            future : "za %s",
-            past : "pred %s",
-            s : translate,
-            m : translate,
-            mm : translate,
-            h : translate,
-            hh : translate,
-            d : translate,
-            dd : translate,
-            M : translate,
-            MM : translate,
-            y : translate,
-            yy : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/sl.js b/resources/moment/lang/sl.js
deleted file mode 100644 (file)
index d260f80..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-// moment.js language configuration
-// language : slovenian (sl)
-// author : Robert Sedovšek : https://github.com/sedovsek
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function translate(number, withoutSuffix, key) {
-        var result = number + " ";
-        switch (key) {
-        case 'm':
-            return withoutSuffix ? 'ena minuta' : 'eno minuto';
-        case 'mm':
-            if (number === 1) {
-                result += 'minuta';
-            } else if (number === 2) {
-                result += 'minuti';
-            } else if (number === 3 || number === 4) {
-                result += 'minute';
-            } else {
-                result += 'minut';
-            }
-            return result;
-        case 'h':
-            return withoutSuffix ? 'ena ura' : 'eno uro';
-        case 'hh':
-            if (number === 1) {
-                result += 'ura';
-            } else if (number === 2) {
-                result += 'uri';
-            } else if (number === 3 || number === 4) {
-                result += 'ure';
-            } else {
-                result += 'ur';
-            }
-            return result;
-        case 'dd':
-            if (number === 1) {
-                result += 'dan';
-            } else {
-                result += 'dni';
-            }
-            return result;
-        case 'MM':
-            if (number === 1) {
-                result += 'mesec';
-            } else if (number === 2) {
-                result += 'meseca';
-            } else if (number === 3 || number === 4) {
-                result += 'mesece';
-            } else {
-                result += 'mesecev';
-            }
-            return result;
-        case 'yy':
-            if (number === 1) {
-                result += 'leto';
-            } else if (number === 2) {
-                result += 'leti';
-            } else if (number === 3 || number === 4) {
-                result += 'leta';
-            } else {
-                result += 'let';
-            }
-            return result;
-        }
-    }
-
-    return moment.lang('sl', {
-        months : "januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),
-        monthsShort : "jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),
-        weekdays : "nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),
-        weekdaysShort : "ned._pon._tor._sre._čet._pet._sob.".split("_"),
-        weekdaysMin : "ne_po_to_sr_če_pe_so".split("_"),
-        longDateFormat : {
-            LT : "H:mm",
-            L : "DD. MM. YYYY",
-            LL : "D. MMMM YYYY",
-            LLL : "D. MMMM YYYY LT",
-            LLLL : "dddd, D. MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay  : '[danes ob] LT',
-            nextDay  : '[jutri ob] LT',
-
-            nextWeek : function () {
-                switch (this.day()) {
-                case 0:
-                    return '[v] [nedeljo] [ob] LT';
-                case 3:
-                    return '[v] [sredo] [ob] LT';
-                case 6:
-                    return '[v] [soboto] [ob] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[v] dddd [ob] LT';
-                }
-            },
-            lastDay  : '[včeraj ob] LT',
-            lastWeek : function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                case 6:
-                    return '[prejšnja] dddd [ob] LT';
-                case 1:
-                case 2:
-                case 4:
-                case 5:
-                    return '[prejšnji] dddd [ob] LT';
-                }
-            },
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "čez %s",
-            past   : "%s nazaj",
-            s      : "nekaj sekund",
-            m      : translate,
-            mm     : translate,
-            h      : translate,
-            hh     : translate,
-            d      : "en dan",
-            dd     : translate,
-            M      : "en mesec",
-            MM     : translate,
-            y      : "eno leto",
-            yy     : translate
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/sq.js b/resources/moment/lang/sq.js
deleted file mode 100644 (file)
index a5e44b5..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// moment.js language configuration
-// language : Albanian (sq)
-// author : Flakërim Ismani : https://github.com/flakerimi
-// author: Menelion Elensúle: https://github.com/Oire (tests)
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('sq', {
-        months : "Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"),
-        monthsShort : "Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"),
-        weekdays : "E Diel_E Hënë_E Marte_E Mërkure_E Enjte_E Premte_E Shtunë".split("_"),
-        weekdaysShort : "Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"),
-        weekdaysMin : "D_H_Ma_Më_E_P_Sh".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[Sot në] LT',
-            nextDay : '[Neser në] LT',
-            nextWeek : 'dddd [në] LT',
-            lastDay : '[Dje në] LT',
-            lastWeek : 'dddd [e kaluar në] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "në %s",
-            past : "%s me parë",
-            s : "disa sekonda",
-            m : "një minut",
-            mm : "%d minuta",
-            h : "një orë",
-            hh : "%d orë",
-            d : "një ditë",
-            dd : "%d ditë",
-            M : "një muaj",
-            MM : "%d muaj",
-            y : "një vit",
-            yy : "%d vite"
-        },
-        ordinal : '%d.',
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/sv.js b/resources/moment/lang/sv.js
deleted file mode 100644 (file)
index 0de8c40..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// moment.js language configuration
-// language : swedish (sv)
-// author : Jens Alm : https://github.com/ulmus
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('sv', {
-        months : "januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),
-        monthsShort : "jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),
-        weekdays : "söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),
-        weekdaysShort : "sön_mån_tis_ons_tor_fre_lör".split("_"),
-        weekdaysMin : "sö_må_ti_on_to_fr_lö".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "YYYY-MM-DD",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: '[Idag] LT',
-            nextDay: '[Imorgon] LT',
-            lastDay: '[Igår] LT',
-            nextWeek: 'dddd LT',
-            lastWeek: '[Förra] dddd[en] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "om %s",
-            past : "för %s sedan",
-            s : "några sekunder",
-            m : "en minut",
-            mm : "%d minuter",
-            h : "en timme",
-            hh : "%d timmar",
-            d : "en dag",
-            dd : "%d dagar",
-            M : "en månad",
-            MM : "%d månader",
-            y : "ett år",
-            yy : "%d år"
-        },
-        ordinal : function (number) {
-            var b = number % 10,
-                output = (~~ (number % 100 / 10) === 1) ? 'e' :
-                (b === 1) ? 'a' :
-                (b === 2) ? 'a' :
-                (b === 3) ? 'e' : 'e';
-            return number + output;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/ta.js b/resources/moment/lang/ta.js
deleted file mode 100644 (file)
index cc742c9..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-// moment.js language configuration
-// language : tamil (ta)
-// author : Arjunkumar Krishnamoorthy : https://github.com/tk120404
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    /*var symbolMap = {
-            '1': '௧',
-            '2': '௨',
-            '3': '௩',
-            '4': '௪',
-            '5': '௫',
-            '6': '௬',
-            '7': '௭',
-            '8': '௮',
-            '9': '௯',
-            '0': '௦'
-        },
-        numberMap = {
-            '௧': '1',
-            '௨': '2',
-            '௩': '3',
-            '௪': '4',
-            '௫': '5',
-            '௬': '6',
-            '௭': '7',
-            '௮': '8',
-            '௯': '9',
-            '௦': '0'
-        }; */
-
-    return moment.lang('ta', {
-        months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split("_"),
-        monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split("_"),
-        weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split("_"),
-        weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split("_"),
-        weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY, LT",
-            LLLL : "dddd, D MMMM YYYY, LT"
-        },
-        calendar : {
-            sameDay : '[இன்று] LT',
-            nextDay : '[நாளை] LT',
-            nextWeek : 'dddd, LT',
-            lastDay : '[நேற்று] LT',
-            lastWeek : '[கடந்த வாரம்] dddd, LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s இல்",
-            past : "%s முன்",
-            s : "ஒரு சில விநாடிகள்",
-            m : "ஒரு நிமிடம்",
-            mm : "%d நிமிடங்கள்",
-            h : "ஒரு மணி நேரம்",
-            hh : "%d மணி நேரம்",
-            d : "ஒரு நாள்",
-            dd : "%d நாட்கள்",
-            M : "ஒரு மாதம்",
-            MM : "%d மாதங்கள்",
-            y : "ஒரு வருடம்",
-            yy : "%d ஆண்டுகள்"
-        },
-/*        preparse: function (string) {
-            return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) {
-                return numberMap[match];
-            });
-        },
-        postformat: function (string) {
-            return string.replace(/\d/g, function (match) {
-                return symbolMap[match];
-            });
-        },*/
-        ordinal : function (number) {
-            return number + 'வது';
-        },
-
-
-// refer http://ta.wikipedia.org/s/1er1      
-
-        meridiem : function (hour, minute, isLower) {
-            if (hour >= 6 && hour <= 10) {
-                return " காலை";
-            } else   if (hour >= 10 && hour <= 14) {
-                return " நண்பகல்";
-            } else    if (hour >= 14 && hour <= 18) {
-                return " எற்பாடு";
-            } else   if (hour >= 18 && hour <= 20) {
-                return " மாலை";
-            } else  if (hour >= 20 && hour <= 24) {
-                return " இரவு";
-            } else  if (hour >= 0 && hour <= 6) {
-                return " வைகறை";
-            }
-        },
-        week : {
-            dow : 0, // Sunday is the first day of the week.
-            doy : 6  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/th.js b/resources/moment/lang/th.js
deleted file mode 100644 (file)
index 70336c8..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// moment.js language configuration
-// language : thai (th)
-// author : Kridsada Thanabulpong : https://github.com/sirn
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('th', {
-        months : "มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),
-        monthsShort : "มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา".split("_"),
-        weekdays : "อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),
-        weekdaysShort : "อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"), // yes, three characters difference
-        weekdaysMin : "อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),
-        longDateFormat : {
-            LT : "H นาฬิกา m นาที",
-            L : "YYYY/MM/DD",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY เวลา LT",
-            LLLL : "วันddddที่ D MMMM YYYY เวลา LT"
-        },
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 12) {
-                return "ก่อนเที่ยง";
-            } else {
-                return "หลังเที่ยง";
-            }
-        },
-        calendar : {
-            sameDay : '[วันนี้ เวลา] LT',
-            nextDay : '[พรุ่งนี้ เวลา] LT',
-            nextWeek : 'dddd[หน้า เวลา] LT',
-            lastDay : '[เมื่อวานนี้ เวลา] LT',
-            lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "อีก %s",
-            past : "%sที่แล้ว",
-            s : "ไม่กี่วินาที",
-            m : "1 นาที",
-            mm : "%d นาที",
-            h : "1 ชั่วโมง",
-            hh : "%d ชั่วโมง",
-            d : "1 วัน",
-            dd : "%d วัน",
-            M : "1 เดือน",
-            MM : "%d เดือน",
-            y : "1 ปี",
-            yy : "%d ปี"
-        }
-    });
-}));
diff --git a/resources/moment/lang/tl-ph.js b/resources/moment/lang/tl-ph.js
deleted file mode 100644 (file)
index 8044483..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// moment.js language configuration
-// language : Tagalog/Filipino (tl-ph)
-// author : Dan Hagman
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('tl-ph', {
-        months : "Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),
-        monthsShort : "Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),
-        weekdays : "Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),
-        weekdaysShort : "Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),
-        weekdaysMin : "Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "MM/D/YYYY",
-            LL : "MMMM D, YYYY",
-            LLL : "MMMM D, YYYY LT",
-            LLLL : "dddd, MMMM DD, YYYY LT"
-        },
-        calendar : {
-            sameDay: "[Ngayon sa] LT",
-            nextDay: '[Bukas sa] LT',
-            nextWeek: 'dddd [sa] LT',
-            lastDay: '[Kahapon sa] LT',
-            lastWeek: 'dddd [huling linggo] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "sa loob ng %s",
-            past : "%s ang nakalipas",
-            s : "ilang segundo",
-            m : "isang minuto",
-            mm : "%d minuto",
-            h : "isang oras",
-            hh : "%d oras",
-            d : "isang araw",
-            dd : "%d araw",
-            M : "isang buwan",
-            MM : "%d buwan",
-            y : "isang taon",
-            yy : "%d taon"
-        },
-        ordinal : function (number) {
-            return number;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/tr.js b/resources/moment/lang/tr.js
deleted file mode 100644 (file)
index e90f250..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-// moment.js language configuration
-// language : turkish (tr)
-// authors : Erhan Gundogan : https://github.com/erhangundogan,
-//           Burak Yiğit Kaya: https://github.com/BYK
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-
-    var suffixes = {
-        1: "'inci",
-        5: "'inci",
-        8: "'inci",
-        70: "'inci",
-        80: "'inci",
-
-        2: "'nci",
-        7: "'nci",
-        20: "'nci",
-        50: "'nci",
-
-        3: "'üncü",
-        4: "'üncü",
-        100: "'üncü",
-
-        6: "'ncı",
-
-        9: "'uncu",
-        10: "'uncu",
-        30: "'uncu",
-
-        60: "'ıncı",
-        90: "'ıncı"
-    };
-
-    return moment.lang('tr', {
-        months : "Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),
-        monthsShort : "Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),
-        weekdays : "Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),
-        weekdaysShort : "Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),
-        weekdaysMin : "Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd, D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay : '[bugün saat] LT',
-            nextDay : '[yarın saat] LT',
-            nextWeek : '[haftaya] dddd [saat] LT',
-            lastDay : '[dün] LT',
-            lastWeek : '[geçen hafta] dddd [saat] LT',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "%s sonra",
-            past : "%s önce",
-            s : "birkaç saniye",
-            m : "bir dakika",
-            mm : "%d dakika",
-            h : "bir saat",
-            hh : "%d saat",
-            d : "bir gün",
-            dd : "%d gün",
-            M : "bir ay",
-            MM : "%d ay",
-            y : "bir yıl",
-            yy : "%d yıl"
-        },
-        ordinal : function (number) {
-            if (number === 0) {  // special case for zero
-                return number + "'ıncı";
-            }
-            var a = number % 10,
-                b = number % 100 - a,
-                c = number >= 100 ? 100 : null;
-
-            return number + (suffixes[a] || suffixes[b] || suffixes[c]);
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/tzm-la.js b/resources/moment/lang/tzm-la.js
deleted file mode 100644 (file)
index be1d878..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// moment.js language configuration
-// language : Morocco Central Atlas Tamaziɣt in Latin (tzm-la)
-// author : Abdel Said : https://github.com/abdelsaid
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('tzm-la', {
-        months : "innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),
-        monthsShort : "innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),
-        weekdays : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),
-        weekdaysShort : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),
-        weekdaysMin : "asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[asdkh g] LT",
-            nextDay: '[aska g] LT',
-            nextWeek: 'dddd [g] LT',
-            lastDay: '[assant g] LT',
-            lastWeek: 'dddd [g] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "dadkh s yan %s",
-            past : "yan %s",
-            s : "imik",
-            m : "minuḍ",
-            mm : "%d minuḍ",
-            h : "saɛa",
-            hh : "%d tassaɛin",
-            d : "ass",
-            dd : "%d ossan",
-            M : "ayowr",
-            MM : "%d iyyirn",
-            y : "asgas",
-            yy : "%d isgasn"
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/tzm.js b/resources/moment/lang/tzm.js
deleted file mode 100644 (file)
index c7c76bd..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// moment.js language configuration
-// language : Morocco Central Atlas Tamaziɣt (tzm)
-// author : Abdel Said : https://github.com/abdelsaid
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('tzm', {
-        months : "ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),
-        monthsShort : "ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),
-        weekdays : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),
-        weekdaysShort : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),
-        weekdaysMin : "ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "dddd D MMMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[ⴰⵙⴷⵅ ⴴ] LT",
-            nextDay: '[ⴰⵙⴽⴰ ⴴ] LT',
-            nextWeek: 'dddd [ⴴ] LT',
-            lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT',
-            lastWeek: 'dddd [ⴴ] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s",
-            past : "ⵢⴰⵏ %s",
-            s : "ⵉⵎⵉⴽ",
-            m : "ⵎⵉⵏⵓⴺ",
-            mm : "%d ⵎⵉⵏⵓⴺ",
-            h : "ⵙⴰⵄⴰ",
-            hh : "%d ⵜⴰⵙⵙⴰⵄⵉⵏ",
-            d : "ⴰⵙⵙ",
-            dd : "%d oⵙⵙⴰⵏ",
-            M : "ⴰⵢoⵓⵔ",
-            MM : "%d ⵉⵢⵢⵉⵔⵏ",
-            y : "ⴰⵙⴳⴰⵙ",
-            yy : "%d ⵉⵙⴳⴰⵙⵏ"
-        },
-        week : {
-            dow : 6, // Saturday is the first day of the week.
-            doy : 12  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/uk.js b/resources/moment/lang/uk.js
deleted file mode 100644 (file)
index 47056cb..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-// moment.js language configuration
-// language : ukrainian (uk)
-// author : zemlanin : https://github.com/zemlanin
-// Author : Menelion Elensúle : https://github.com/Oire
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    function plural(word, num) {
-        var forms = word.split('_');
-        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
-    }
-
-    function relativeTimeWithPlural(number, withoutSuffix, key) {
-        var format = {
-            'mm': 'хвилина_хвилини_хвилин',
-            'hh': 'година_години_годин',
-            'dd': 'день_дні_днів',
-            'MM': 'місяць_місяці_місяців',
-            'yy': 'рік_роки_років'
-        };
-        if (key === 'm') {
-            return withoutSuffix ? 'хвилина' : 'хвилину';
-        }
-        else if (key === 'h') {
-            return withoutSuffix ? 'година' : 'годину';
-        }
-        else {
-            return number + ' ' + plural(format[key], +number);
-        }
-    }
-
-    function monthsCaseReplace(m, format) {
-        var months = {
-            'nominative': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_'),
-            'accusative': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_')
-        },
-
-        nounCase = (/D[oD]? *MMMM?/).test(format) ?
-            'accusative' :
-            'nominative';
-
-        return months[nounCase][m.month()];
-    }
-
-    function weekdaysCaseReplace(m, format) {
-        var weekdays = {
-            'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'),
-            'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'),
-            'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_')
-        },
-
-        nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ?
-            'accusative' :
-            ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ?
-                'genitive' :
-                'nominative');
-
-        return weekdays[nounCase][m.day()];
-    }
-
-    function processHoursFunction(str) {
-        return function () {
-            return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT';
-        };
-    }
-
-    return moment.lang('uk', {
-        months : monthsCaseReplace,
-        monthsShort : "січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),
-        weekdays : weekdaysCaseReplace,
-        weekdaysShort : "нд_пн_вт_ср_чт_пт_сб".split("_"),
-        weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD.MM.YYYY",
-            LL : "D MMMM YYYY р.",
-            LLL : "D MMMM YYYY р., LT",
-            LLLL : "dddd, D MMMM YYYY р., LT"
-        },
-        calendar : {
-            sameDay: processHoursFunction('[Сьогодні '),
-            nextDay: processHoursFunction('[Завтра '),
-            lastDay: processHoursFunction('[Вчора '),
-            nextWeek: processHoursFunction('[У] dddd ['),
-            lastWeek: function () {
-                switch (this.day()) {
-                case 0:
-                case 3:
-                case 5:
-                case 6:
-                    return processHoursFunction('[Минулої] dddd [').call(this);
-                case 1:
-                case 2:
-                case 4:
-                    return processHoursFunction('[Минулого] dddd [').call(this);
-                }
-            },
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "за %s",
-            past : "%s тому",
-            s : "декілька секунд",
-            m : relativeTimeWithPlural,
-            mm : relativeTimeWithPlural,
-            h : "годину",
-            hh : relativeTimeWithPlural,
-            d : "день",
-            dd : relativeTimeWithPlural,
-            M : "місяць",
-            MM : relativeTimeWithPlural,
-            y : "рік",
-            yy : relativeTimeWithPlural
-        },
-
-        // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
-
-        meridiem : function (hour, minute, isLower) {
-            if (hour < 4) {
-                return "ночі";
-            } else if (hour < 12) {
-                return "ранку";
-            } else if (hour < 17) {
-                return "дня";
-            } else {
-                return "вечора";
-            }
-        },
-
-        ordinal: function (number, period) {
-            switch (period) {
-            case 'M':
-            case 'd':
-            case 'DDD':
-            case 'w':
-            case 'W':
-                return number + '-й';
-            case 'D':
-                return number + '-го';
-            default:
-                return number;
-            }
-        },
-
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 1st is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/uz.js b/resources/moment/lang/uz.js
deleted file mode 100644 (file)
index a5b06fa..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// moment.js language configuration
-// language : uzbek
-// author : Sardor Muminov : https://github.com/muminoff
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('uz', {
-        months : "январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),
-        monthsShort : "янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"),
-        weekdays : "Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба".split("_"),
-        weekdaysShort : "Якш_Душ_Сеш_Чор_Пай_Жум_Шан".split("_"),
-        weekdaysMin : "Як_Ду_Се_Чо_Па_Жу_Ша".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM YYYY",
-            LLL : "D MMMM YYYY LT",
-            LLLL : "D MMMM YYYY, dddd LT"
-        },
-        calendar : {
-            sameDay : '[Бугун соат] LT [да]',
-            nextDay : '[Эртага] LT [да]',
-            nextWeek : 'dddd [куни соат] LT [да]',
-            lastDay : '[Кеча соат] LT [да]',
-            lastWeek : '[Утган] dddd [куни соат] LT [да]',
-            sameElse : 'L'
-        },
-        relativeTime : {
-            future : "Якин %s ичида",
-            past : "Бир неча %s олдин",
-            s : "фурсат",
-            m : "бир дакика",
-            mm : "%d дакика",
-            h : "бир соат",
-            hh : "%d соат",
-            d : "бир кун",
-            dd : "%d кун",
-            M : "бир ой",
-            MM : "%d ой",
-            y : "бир йил",
-            yy : "%d йил"
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 7  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/vn.js b/resources/moment/lang/vn.js
deleted file mode 100644 (file)
index f28e7c3..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-// moment.js language configuration
-// language : vietnamese (vn)
-// author : Bang Nguyen : https://github.com/bangnk
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('vn', {
-        months : "tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),
-        monthsShort : "Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12".split("_"),
-        weekdays : "chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy".split("_"),
-        weekdaysShort : "CN_T2_T3_T4_T5_T6_T7".split("_"),
-        weekdaysMin : "CN_T2_T3_T4_T5_T6_T7".split("_"),
-        longDateFormat : {
-            LT : "HH:mm",
-            L : "DD/MM/YYYY",
-            LL : "D MMMM [năm] YYYY",
-            LLL : "D MMMM [năm] YYYY LT",
-            LLLL : "dddd, D MMMM [năm] YYYY LT",
-            l : "DD/M/YYYY",
-            ll : "D MMM YYYY",
-            lll : "D MMM YYYY LT",
-            llll : "ddd, D MMM YYYY LT"
-        },
-        calendar : {
-            sameDay: "[Hôm nay lúc] LT",
-            nextDay: '[Ngày mai lúc] LT',
-            nextWeek: 'dddd [tuần tới lúc] LT',
-            lastDay: '[Hôm qua lúc] LT',
-            lastWeek: 'dddd [tuần rồi lúc] LT',
-            sameElse: 'L'
-        },
-        relativeTime : {
-            future : "%s tới",
-            past : "%s trước",
-            s : "vài giây",
-            m : "một phút",
-            mm : "%d phút",
-            h : "một giờ",
-            hh : "%d giờ",
-            d : "một ngày",
-            dd : "%d ngày",
-            M : "một tháng",
-            MM : "%d tháng",
-            y : "một năm",
-            yy : "%d năm"
-        },
-        ordinal : function (number) {
-            return number;
-        },
-        week : {
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/zh-cn.js b/resources/moment/lang/zh-cn.js
deleted file mode 100644 (file)
index 50a3ed9..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// moment.js language configuration
-// language : chinese
-// author : suupic : https://github.com/suupic
-// author : Zeno Zeng : https://github.com/zenozeng
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('zh-cn', {
-        months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
-        monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
-        weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),
-        weekdaysShort : "周日_周一_周二_周三_周四_周五_周六".split("_"),
-        weekdaysMin : "日_一_二_三_四_五_六".split("_"),
-        longDateFormat : {
-            LT : "Ah点mm",
-            L : "YYYY-MM-DD",
-            LL : "YYYY年MMMD日",
-            LLL : "YYYY年MMMD日LT",
-            LLLL : "YYYY年MMMD日ddddLT",
-            l : "YYYY-MM-DD",
-            ll : "YYYY年MMMD日",
-            lll : "YYYY年MMMD日LT",
-            llll : "YYYY年MMMD日ddddLT"
-        },
-        meridiem : function (hour, minute, isLower) {
-            var hm = hour * 100 + minute;
-            if (hm < 600) {
-                return "凌晨";
-            } else if (hm < 900) {
-                return "早上";
-            } else if (hm < 1130) {
-                return "上午";
-            } else if (hm < 1230) {
-                return "中午";
-            } else if (hm < 1800) {
-                return "下午";
-            } else {
-                return "晚上";
-            }
-        },
-        calendar : {
-            sameDay : function () {
-                return this.minutes() === 0 ? "[今天]Ah[点整]" : "[今天]LT";
-            },
-            nextDay : function () {
-                return this.minutes() === 0 ? "[明天]Ah[点整]" : "[明天]LT";
-            },
-            lastDay : function () {
-                return this.minutes() === 0 ? "[昨天]Ah[点整]" : "[昨天]LT";
-            },
-            nextWeek : function () {
-                var startOfWeek, prefix;
-                startOfWeek = moment().startOf('week');
-                prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]';
-                return this.minutes() === 0 ? prefix + "dddAh点整" : prefix + "dddAh点mm";
-            },
-            lastWeek : function () {
-                var startOfWeek, prefix;
-                startOfWeek = moment().startOf('week');
-                prefix = this.unix() < startOfWeek.unix()  ? '[上]' : '[本]';
-                return this.minutes() === 0 ? prefix + "dddAh点整" : prefix + "dddAh点mm";
-            },
-            sameElse : 'LL'
-        },
-        ordinal : function (number, period) {
-            switch (period) {
-            case "d":
-            case "D":
-            case "DDD":
-                return number + "日";
-            case "M":
-                return number + "月";
-            case "w":
-            case "W":
-                return number + "周";
-            default:
-                return number;
-            }
-        },
-        relativeTime : {
-            future : "%s内",
-            past : "%s前",
-            s : "几秒",
-            m : "1分钟",
-            mm : "%d分钟",
-            h : "1小时",
-            hh : "%d小时",
-            d : "1天",
-            dd : "%d天",
-            M : "1个月",
-            MM : "%d个月",
-            y : "1年",
-            yy : "%d年"
-        },
-        week : {
-            // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
-            dow : 1, // Monday is the first day of the week.
-            doy : 4  // The week that contains Jan 4th is the first week of the year.
-        }
-    });
-}));
diff --git a/resources/moment/lang/zh-tw.js b/resources/moment/lang/zh-tw.js
deleted file mode 100644 (file)
index bbb0737..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-// moment.js language configuration
-// language : traditional chinese (zh-tw)
-// author : Ben : https://github.com/ben-lin
-
-(function (factory) {
-    if (typeof define === 'function' && define.amd) {
-        define(['moment'], factory); // AMD
-    } else if (typeof exports === 'object') {
-        module.exports = factory(require('../moment')); // Node
-    } else {
-        factory(window.moment); // Browser global
-    }
-}(function (moment) {
-    return moment.lang('zh-tw', {
-        months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
-        monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
-        weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),
-        weekdaysShort : "週日_週一_週二_週三_週四_週五_週六".split("_"),
-        weekdaysMin : "日_一_二_三_四_五_六".split("_"),
-        longDateFormat : {
-            LT : "Ah點mm",
-            L : "YYYY年MMMD日",
-            LL : "YYYY年MMMD日",
-            LLL : "YYYY年MMMD日LT",
-            LLLL : "YYYY年MMMD日ddddLT",
-            l : "YYYY年MMMD日",
-            ll : "YYYY年MMMD日",
-            lll : "YYYY年MMMD日LT",
-            llll : "YYYY年MMMD日ddddLT"
-        },
-        meridiem : function (hour, minute, isLower) {
-            var hm = hour * 100 + minute;
-            if (hm < 900) {
-                return "早上";
-            } else if (hm < 1130) {
-                return "上午";
-            } else if (hm < 1230) {
-                return "中午";
-            } else if (hm < 1800) {
-                return "下午";
-            } else {
-                return "晚上";
-            }
-        },
-        calendar : {
-            sameDay : '[今天]LT',
-            nextDay : '[明天]LT',
-            nextWeek : '[下]ddddLT',
-            lastDay : '[昨天]LT',
-            lastWeek : '[上]ddddLT',
-            sameElse : 'L'
-        },
-        ordinal : function (number, period) {
-            switch (period) {
-            case "d" :
-            case "D" :
-            case "DDD" :
-                return number + "日";
-            case "M" :
-                return number + "月";
-            case "w" :
-            case "W" :
-                return number + "週";
-            default :
-                return number;
-            }
-        },
-        relativeTime : {
-            future : "%s內",
-            past : "%s前",
-            s : "幾秒",
-            m : "一分鐘",
-            mm : "%d分鐘",
-            h : "一小時",
-            hh : "%d小時",
-            d : "一天",
-            dd : "%d天",
-            M : "一個月",
-            MM : "%d個月",
-            y : "一年",
-            yy : "%d年"
-        }
-    });
-}));
diff --git a/resources/moment/moment.js b/resources/moment/moment.js
deleted file mode 100644 (file)
index b79da7f..0000000
+++ /dev/null
@@ -1,2400 +0,0 @@
-//! moment.js
-//! version : 2.5.1
-//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
-//! license : MIT
-//! momentjs.com
-
-(function (undefined) {
-
-    /************************************
-        Constants
-    ************************************/
-
-    var moment,
-        VERSION = "2.5.1",
-        global = this,
-        round = Math.round,
-        i,
-
-        YEAR = 0,
-        MONTH = 1,
-        DATE = 2,
-        HOUR = 3,
-        MINUTE = 4,
-        SECOND = 5,
-        MILLISECOND = 6,
-
-        // internal storage for language config files
-        languages = {},
-
-        // moment internal properties
-        momentProperties = {
-            _isAMomentObject: null,
-            _i : null,
-            _f : null,
-            _l : null,
-            _strict : null,
-            _isUTC : null,
-            _offset : null,  // optional. Combine with _isUTC
-            _pf : null,
-            _lang : null  // optional
-        },
-
-        // check for nodeJS
-        hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'),
-
-        // ASP.NET json date format regex
-        aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
-        aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
-
-        // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
-        // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
-        isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
-
-        // format tokens
-        formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
-        localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
-
-        // parsing token regexes
-        parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
-        parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
-        parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
-        parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
-        parseTokenDigits = /\d+/, // nonzero number of digits
-        parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
-        parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
-        parseTokenT = /T/i, // T (ISO separator)
-        parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
-
-        //strict parsing regexes
-        parseTokenOneDigit = /\d/, // 0 - 9
-        parseTokenTwoDigits = /\d\d/, // 00 - 99
-        parseTokenThreeDigits = /\d{3}/, // 000 - 999
-        parseTokenFourDigits = /\d{4}/, // 0000 - 9999
-        parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999
-        parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf
-
-        // iso 8601 regex
-        // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
-        isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
-
-        isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
-
-        isoDates = [
-            ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/],
-            ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/],
-            ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/],
-            ['GGGG-[W]WW', /\d{4}-W\d{2}/],
-            ['YYYY-DDD', /\d{4}-\d{3}/]
-        ],
-
-        // iso time formats and regexes
-        isoTimes = [
-            ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
-            ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
-            ['HH:mm', /(T| )\d\d:\d\d/],
-            ['HH', /(T| )\d\d/]
-        ],
-
-        // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
-        parseTimezoneChunker = /([\+\-]|\d\d)/gi,
-
-        // getter and setter names
-        proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
-        unitMillisecondFactors = {
-            'Milliseconds' : 1,
-            'Seconds' : 1e3,
-            'Minutes' : 6e4,
-            'Hours' : 36e5,
-            'Days' : 864e5,
-            'Months' : 2592e6,
-            'Years' : 31536e6
-        },
-
-        unitAliases = {
-            ms : 'millisecond',
-            s : 'second',
-            m : 'minute',
-            h : 'hour',
-            d : 'day',
-            D : 'date',
-            w : 'week',
-            W : 'isoWeek',
-            M : 'month',
-            y : 'year',
-            DDD : 'dayOfYear',
-            e : 'weekday',
-            E : 'isoWeekday',
-            gg: 'weekYear',
-            GG: 'isoWeekYear'
-        },
-
-        camelFunctions = {
-            dayofyear : 'dayOfYear',
-            isoweekday : 'isoWeekday',
-            isoweek : 'isoWeek',
-            weekyear : 'weekYear',
-            isoweekyear : 'isoWeekYear'
-        },
-
-        // format function strings
-        formatFunctions = {},
-
-        // tokens to ordinalize and pad
-        ordinalizeTokens = 'DDD w W M D d'.split(' '),
-        paddedTokens = 'M D H h m s w W'.split(' '),
-
-        formatTokenFunctions = {
-            M    : function () {
-                return this.month() + 1;
-            },
-            MMM  : function (format) {
-                return this.lang().monthsShort(this, format);
-            },
-            MMMM : function (format) {
-                return this.lang().months(this, format);
-            },
-            D    : function () {
-                return this.date();
-            },
-            DDD  : function () {
-                return this.dayOfYear();
-            },
-            d    : function () {
-                return this.day();
-            },
-            dd   : function (format) {
-                return this.lang().weekdaysMin(this, format);
-            },
-            ddd  : function (format) {
-                return this.lang().weekdaysShort(this, format);
-            },
-            dddd : function (format) {
-                return this.lang().weekdays(this, format);
-            },
-            w    : function () {
-                return this.week();
-            },
-            W    : function () {
-                return this.isoWeek();
-            },
-            YY   : function () {
-                return leftZeroFill(this.year() % 100, 2);
-            },
-            YYYY : function () {
-                return leftZeroFill(this.year(), 4);
-            },
-            YYYYY : function () {
-                return leftZeroFill(this.year(), 5);
-            },
-            YYYYYY : function () {
-                var y = this.year(), sign = y >= 0 ? '+' : '-';
-                return sign + leftZeroFill(Math.abs(y), 6);
-            },
-            gg   : function () {
-                return leftZeroFill(this.weekYear() % 100, 2);
-            },
-            gggg : function () {
-                return leftZeroFill(this.weekYear(), 4);
-            },
-            ggggg : function () {
-                return leftZeroFill(this.weekYear(), 5);
-            },
-            GG   : function () {
-                return leftZeroFill(this.isoWeekYear() % 100, 2);
-            },
-            GGGG : function () {
-                return leftZeroFill(this.isoWeekYear(), 4);
-            },
-            GGGGG : function () {
-                return leftZeroFill(this.isoWeekYear(), 5);
-            },
-            e : function () {
-                return this.weekday();
-            },
-            E : function () {
-                return this.isoWeekday();
-            },
-            a    : function () {
-                return this.lang().meridiem(this.hours(), this.minutes(), true);
-            },
-            A    : function () {
-                return this.lang().meridiem(this.hours(), this.minutes(), false);
-            },
-            H    : function () {
-                return this.hours();
-            },
-            h    : function () {
-                return this.hours() % 12 || 12;
-            },
-            m    : function () {
-                return this.minutes();
-            },
-            s    : function () {
-                return this.seconds();
-            },
-            S    : function () {
-                return toInt(this.milliseconds() / 100);
-            },
-            SS   : function () {
-                return leftZeroFill(toInt(this.milliseconds() / 10), 2);
-            },
-            SSS  : function () {
-                return leftZeroFill(this.milliseconds(), 3);
-            },
-            SSSS : function () {
-                return leftZeroFill(this.milliseconds(), 3);
-            },
-            Z    : function () {
-                var a = -this.zone(),
-                    b = "+";
-                if (a < 0) {
-                    a = -a;
-                    b = "-";
-                }
-                return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
-            },
-            ZZ   : function () {
-                var a = -this.zone(),
-                    b = "+";
-                if (a < 0) {
-                    a = -a;
-                    b = "-";
-                }
-                return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
-            },
-            z : function () {
-                return this.zoneAbbr();
-            },
-            zz : function () {
-                return this.zoneName();
-            },
-            X    : function () {
-                return this.unix();
-            },
-            Q : function () {
-                return this.quarter();
-            }
-        },
-
-        lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
-
-    function defaultParsingFlags() {
-        // We need to deep clone this object, and es5 standard is not very
-        // helpful.
-        return {
-            empty : false,
-            unusedTokens : [],
-            unusedInput : [],
-            overflow : -2,
-            charsLeftOver : 0,
-            nullInput : false,
-            invalidMonth : null,
-            invalidFormat : false,
-            userInvalidated : false,
-            iso: false
-        };
-    }
-
-    function padToken(func, count) {
-        return function (a) {
-            return leftZeroFill(func.call(this, a), count);
-        };
-    }
-    function ordinalizeToken(func, period) {
-        return function (a) {
-            return this.lang().ordinal(func.call(this, a), period);
-        };
-    }
-
-    while (ordinalizeTokens.length) {
-        i = ordinalizeTokens.pop();
-        formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
-    }
-    while (paddedTokens.length) {
-        i = paddedTokens.pop();
-        formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
-    }
-    formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
-
-
-    /************************************
-        Constructors
-    ************************************/
-
-    function Language() {
-
-    }
-
-    // Moment prototype object
-    function Moment(config) {
-        checkOverflow(config);
-        extend(this, config);
-    }
-
-    // Duration Constructor
-    function Duration(duration) {
-        var normalizedInput = normalizeObjectUnits(duration),
-            years = normalizedInput.year || 0,
-            months = normalizedInput.month || 0,
-            weeks = normalizedInput.week || 0,
-            days = normalizedInput.day || 0,
-            hours = normalizedInput.hour || 0,
-            minutes = normalizedInput.minute || 0,
-            seconds = normalizedInput.second || 0,
-            milliseconds = normalizedInput.millisecond || 0;
-
-        // representation for dateAddRemove
-        this._milliseconds = +milliseconds +
-            seconds * 1e3 + // 1000
-            minutes * 6e4 + // 1000 * 60
-            hours * 36e5; // 1000 * 60 * 60
-        // Because of dateAddRemove treats 24 hours as different from a
-        // day when working around DST, we need to store them separately
-        this._days = +days +
-            weeks * 7;
-        // It is impossible translate months into days without knowing
-        // which months you are are talking about, so we have to store
-        // it separately.
-        this._months = +months +
-            years * 12;
-
-        this._data = {};
-
-        this._bubble();
-    }
-
-    /************************************
-        Helpers
-    ************************************/
-
-
-    function extend(a, b) {
-        for (var i in b) {
-            if (b.hasOwnProperty(i)) {
-                a[i] = b[i];
-            }
-        }
-
-        if (b.hasOwnProperty("toString")) {
-            a.toString = b.toString;
-        }
-
-        if (b.hasOwnProperty("valueOf")) {
-            a.valueOf = b.valueOf;
-        }
-
-        return a;
-    }
-
-    function cloneMoment(m) {
-        var result = {}, i;
-        for (i in m) {
-            if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) {
-                result[i] = m[i];
-            }
-        }
-
-        return result;
-    }
-
-    function absRound(number) {
-        if (number < 0) {
-            return Math.ceil(number);
-        } else {
-            return Math.floor(number);
-        }
-    }
-
-    // left zero fill a number
-    // see http://jsperf.com/left-zero-filling for performance comparison
-    function leftZeroFill(number, targetLength, forceSign) {
-        var output = '' + Math.abs(number),
-            sign = number >= 0;
-
-        while (output.length < targetLength) {
-            output = '0' + output;
-        }
-        return (sign ? (forceSign ? '+' : '') : '-') + output;
-    }
-
-    // helper function for _.addTime and _.subtractTime
-    function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
-        var milliseconds = duration._milliseconds,
-            days = duration._days,
-            months = duration._months,
-            minutes,
-            hours;
-
-        if (milliseconds) {
-            mom._d.setTime(+mom._d + milliseconds * isAdding);
-        }
-        // store the minutes and hours so we can restore them
-        if (days || months) {
-            minutes = mom.minute();
-            hours = mom.hour();
-        }
-        if (days) {
-            mom.date(mom.date() + days * isAdding);
-        }
-        if (months) {
-            mom.month(mom.month() + months * isAdding);
-        }
-        if (milliseconds && !ignoreUpdateOffset) {
-            moment.updateOffset(mom);
-        }
-        // restore the minutes and hours after possibly changing dst
-        if (days || months) {
-            mom.minute(minutes);
-            mom.hour(hours);
-        }
-    }
-
-    // check if is an array
-    function isArray(input) {
-        return Object.prototype.toString.call(input) === '[object Array]';
-    }
-
-    function isDate(input) {
-        return  Object.prototype.toString.call(input) === '[object Date]' ||
-                input instanceof Date;
-    }
-
-    // compare two arrays, return the number of differences
-    function compareArrays(array1, array2, dontConvert) {
-        var len = Math.min(array1.length, array2.length),
-            lengthDiff = Math.abs(array1.length - array2.length),
-            diffs = 0,
-            i;
-        for (i = 0; i < len; i++) {
-            if ((dontConvert && array1[i] !== array2[i]) ||
-                (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
-                diffs++;
-            }
-        }
-        return diffs + lengthDiff;
-    }
-
-    function normalizeUnits(units) {
-        if (units) {
-            var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
-            units = unitAliases[units] || camelFunctions[lowered] || lowered;
-        }
-        return units;
-    }
-
-    function normalizeObjectUnits(inputObject) {
-        var normalizedInput = {},
-            normalizedProp,
-            prop;
-
-        for (prop in inputObject) {
-            if (inputObject.hasOwnProperty(prop)) {
-                normalizedProp = normalizeUnits(prop);
-                if (normalizedProp) {
-                    normalizedInput[normalizedProp] = inputObject[prop];
-                }
-            }
-        }
-
-        return normalizedInput;
-    }
-
-    function makeList(field) {
-        var count, setter;
-
-        if (field.indexOf('week') === 0) {
-            count = 7;
-            setter = 'day';
-        }
-        else if (field.indexOf('month') === 0) {
-            count = 12;
-            setter = 'month';
-        }
-        else {
-            return;
-        }
-
-        moment[field] = function (format, index) {
-            var i, getter,
-                method = moment.fn._lang[field],
-                results = [];
-
-            if (typeof format === 'number') {
-                index = format;
-                format = undefined;
-            }
-
-            getter = function (i) {
-                var m = moment().utc().set(setter, i);
-                return method.call(moment.fn._lang, m, format || '');
-            };
-
-            if (index != null) {
-                return getter(index);
-            }
-            else {
-                for (i = 0; i < count; i++) {
-                    results.push(getter(i));
-                }
-                return results;
-            }
-        };
-    }
-
-    function toInt(argumentForCoercion) {
-        var coercedNumber = +argumentForCoercion,
-            value = 0;
-
-        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
-            if (coercedNumber >= 0) {
-                value = Math.floor(coercedNumber);
-            } else {
-                value = Math.ceil(coercedNumber);
-            }
-        }
-
-        return value;
-    }
-
-    function daysInMonth(year, month) {
-        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
-    }
-
-    function daysInYear(year) {
-        return isLeapYear(year) ? 366 : 365;
-    }
-
-    function isLeapYear(year) {
-        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
-    }
-
-    function checkOverflow(m) {
-        var overflow;
-        if (m._a && m._pf.overflow === -2) {
-            overflow =
-                m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
-                m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
-                m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
-                m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
-                m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
-                m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
-                -1;
-
-            if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
-                overflow = DATE;
-            }
-
-            m._pf.overflow = overflow;
-        }
-    }
-
-    function isValid(m) {
-        if (m._isValid == null) {
-            m._isValid = !isNaN(m._d.getTime()) &&
-                m._pf.overflow < 0 &&
-                !m._pf.empty &&
-                !m._pf.invalidMonth &&
-                !m._pf.nullInput &&
-                !m._pf.invalidFormat &&
-                !m._pf.userInvalidated;
-
-            if (m._strict) {
-                m._isValid = m._isValid &&
-                    m._pf.charsLeftOver === 0 &&
-                    m._pf.unusedTokens.length === 0;
-            }
-        }
-        return m._isValid;
-    }
-
-    function normalizeLanguage(key) {
-        return key ? key.toLowerCase().replace('_', '-') : key;
-    }
-
-    // Return a moment from input, that is local/utc/zone equivalent to model.
-    function makeAs(input, model) {
-        return model._isUTC ? moment(input).zone(model._offset || 0) :
-            moment(input).local();
-    }
-
-    /************************************
-        Languages
-    ************************************/
-
-
-    extend(Language.prototype, {
-
-        set : function (config) {
-            var prop, i;
-            for (i in config) {
-                prop = config[i];
-                if (typeof prop === 'function') {
-                    this[i] = prop;
-                } else {
-                    this['_' + i] = prop;
-                }
-            }
-        },
-
-        _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
-        months : function (m) {
-            return this._months[m.month()];
-        },
-
-        _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
-        monthsShort : function (m) {
-            return this._monthsShort[m.month()];
-        },
-
-        monthsParse : function (monthName) {
-            var i, mom, regex;
-
-            if (!this._monthsParse) {
-                this._monthsParse = [];
-            }
-
-            for (i = 0; i < 12; i++) {
-                // make the regex if we don't have it already
-                if (!this._monthsParse[i]) {
-                    mom = moment.utc([2000, i]);
-                    regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
-                    this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
-                }
-                // test the regex
-                if (this._monthsParse[i].test(monthName)) {
-                    return i;
-                }
-            }
-        },
-
-        _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
-        weekdays : function (m) {
-            return this._weekdays[m.day()];
-        },
-
-        _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
-        weekdaysShort : function (m) {
-            return this._weekdaysShort[m.day()];
-        },
-
-        _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
-        weekdaysMin : function (m) {
-            return this._weekdaysMin[m.day()];
-        },
-
-        weekdaysParse : function (weekdayName) {
-            var i, mom, regex;
-
-            if (!this._weekdaysParse) {
-                this._weekdaysParse = [];
-            }
-
-            for (i = 0; i < 7; i++) {
-                // make the regex if we don't have it already
-                if (!this._weekdaysParse[i]) {
-                    mom = moment([2000, 1]).day(i);
-                    regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
-                    this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
-                }
-                // test the regex
-                if (this._weekdaysParse[i].test(weekdayName)) {
-                    return i;
-                }
-            }
-        },
-
-        _longDateFormat : {
-            LT : "h:mm A",
-            L : "MM/DD/YYYY",
-            LL : "MMMM D YYYY",
-            LLL : "MMMM D YYYY LT",
-            LLLL : "dddd, MMMM D YYYY LT"
-        },
-        longDateFormat : function (key) {
-            var output = this._longDateFormat[key];
-            if (!output && this._longDateFormat[key.toUpperCase()]) {
-                output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
-                    return val.slice(1);
-                });
-                this._longDateFormat[key] = output;
-            }
-            return output;
-        },
-
-        isPM : function (input) {
-            // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
-            // Using charAt should be more compatible.
-            return ((input + '').toLowerCase().charAt(0) === 'p');
-        },
-
-        _meridiemParse : /[ap]\.?m?\.?/i,
-        meridiem : function (hours, minutes, isLower) {
-            if (hours > 11) {
-                return isLower ? 'pm' : 'PM';
-            } else {
-                return isLower ? 'am' : 'AM';
-            }
-        },
-
-        _calendar : {
-            sameDay : '[Today at] LT',
-            nextDay : '[Tomorrow at] LT',
-            nextWeek : 'dddd [at] LT',
-            lastDay : '[Yesterday at] LT',
-            lastWeek : '[Last] dddd [at] LT',
-            sameElse : 'L'
-        },
-        calendar : function (key, mom) {
-            var output = this._calendar[key];
-            return typeof output === 'function' ? output.apply(mom) : output;
-        },
-
-        _relativeTime : {
-            future : "in %s",
-            past : "%s ago",
-            s : "a few seconds",
-            m : "a minute",
-            mm : "%d minutes",
-            h : "an hour",
-            hh : "%d hours",
-            d : "a day",
-            dd : "%d days",
-            M : "a month",
-            MM : "%d months",
-            y : "a year",
-            yy : "%d years"
-        },
-        relativeTime : function (number, withoutSuffix, string, isFuture) {
-            var output = this._relativeTime[string];
-            return (typeof output === 'function') ?
-                output(number, withoutSuffix, string, isFuture) :
-                output.replace(/%d/i, number);
-        },
-        pastFuture : function (diff, output) {
-            var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
-            return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
-        },
-
-        ordinal : function (number) {
-            return this._ordinal.replace("%d", number);
-        },
-        _ordinal : "%d",
-
-        preparse : function (string) {
-            return string;
-        },
-
-        postformat : function (string) {
-            return string;
-        },
-
-        week : function (mom) {
-            return weekOfYear(mom, this._week.dow, this._week.doy).week;
-        },
-
-        _week : {
-            dow : 0, // Sunday is the first day of the week.
-            doy : 6  // The week that contains Jan 1st is the first week of the year.
-        },
-
-        _invalidDate: 'Invalid date',
-        invalidDate: function () {
-            return this._invalidDate;
-        }
-    });
-
-    // Loads a language definition into the `languages` cache.  The function
-    // takes a key and optionally values.  If not in the browser and no values
-    // are provided, it will load the language file module.  As a convenience,
-    // this function also returns the language values.
-    function loadLang(key, values) {
-        values.abbr = key;
-        if (!languages[key]) {
-            languages[key] = new Language();
-        }
-        languages[key].set(values);
-        return languages[key];
-    }
-
-    // Remove a language from the `languages` cache. Mostly useful in tests.
-    function unloadLang(key) {
-        delete languages[key];
-    }
-
-    // Determines which language definition to use and returns it.
-    //
-    // With no parameters, it will return the global language.  If you
-    // pass in a language key, such as 'en', it will return the
-    // definition for 'en', so long as 'en' has already been loaded using
-    // moment.lang.
-    function getLangDefinition(key) {
-        var i = 0, j, lang, next, split,
-            get = function (k) {
-                if (!languages[k] && hasModule) {
-                    try {
-                        require('./lang/' + k);
-                    } catch (e) { }
-                }
-                return languages[k];
-            };
-
-        if (!key) {
-            return moment.fn._lang;
-        }
-
-        if (!isArray(key)) {
-            //short-circuit everything else
-            lang = get(key);
-            if (lang) {
-                return lang;
-            }
-            key = [key];
-        }
-
-        //pick the language from the array
-        //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
-        //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
-        while (i < key.length) {
-            split = normalizeLanguage(key[i]).split('-');
-            j = split.length;
-            next = normalizeLanguage(key[i + 1]);
-            next = next ? next.split('-') : null;
-            while (j > 0) {
-                lang = get(split.slice(0, j).join('-'));
-                if (lang) {
-                    return lang;
-                }
-                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
-                    //the next array item is better than a shallower substring of this one
-                    break;
-                }
-                j--;
-            }
-            i++;
-        }
-        return moment.fn._lang;
-    }
-
-    /************************************
-        Formatting
-    ************************************/
-
-
-    function removeFormattingTokens(input) {
-        if (input.match(/\[[\s\S]/)) {
-            return input.replace(/^\[|\]$/g, "");
-        }
-        return input.replace(/\\/g, "");
-    }
-
-    function makeFormatFunction(format) {
-        var array = format.match(formattingTokens), i, length;
-
-        for (i = 0, length = array.length; i < length; i++) {
-            if (formatTokenFunctions[array[i]]) {
-                array[i] = formatTokenFunctions[array[i]];
-            } else {
-                array[i] = removeFormattingTokens(array[i]);
-            }
-        }
-
-        return function (mom) {
-            var output = "";
-            for (i = 0; i < length; i++) {
-                output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
-            }
-            return output;
-        };
-    }
-
-    // format date using native date object
-    function formatMoment(m, format) {
-
-        if (!m.isValid()) {
-            return m.lang().invalidDate();
-        }
-
-        format = expandFormat(format, m.lang());
-
-        if (!formatFunctions[format]) {
-            formatFunctions[format] = makeFormatFunction(format);
-        }
-
-        return formatFunctions[format](m);
-    }
-
-    function expandFormat(format, lang) {
-        var i = 5;
-
-        function replaceLongDateFormatTokens(input) {
-            return lang.longDateFormat(input) || input;
-        }
-
-        localFormattingTokens.lastIndex = 0;
-        while (i >= 0 && localFormattingTokens.test(format)) {
-            format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
-            localFormattingTokens.lastIndex = 0;
-            i -= 1;
-        }
-
-        return format;
-    }
-
-
-    /************************************
-        Parsing
-    ************************************/
-
-
-    // get the regex to find the next token
-    function getParseRegexForToken(token, config) {
-        var a, strict = config._strict;
-        switch (token) {
-        case 'DDDD':
-            return parseTokenThreeDigits;
-        case 'YYYY':
-        case 'GGGG':
-        case 'gggg':
-            return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
-        case 'Y':
-        case 'G':
-        case 'g':
-            return parseTokenSignedNumber;
-        case 'YYYYYY':
-        case 'YYYYY':
-        case 'GGGGG':
-        case 'ggggg':
-            return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
-        case 'S':
-            if (strict) { return parseTokenOneDigit; }
-            /* falls through */
-        case 'SS':
-            if (strict) { return parseTokenTwoDigits; }
-            /* falls through */
-        case 'SSS':
-            if (strict) { return parseTokenThreeDigits; }
-            /* falls through */
-        case 'DDD':
-            return parseTokenOneToThreeDigits;
-        case 'MMM':
-        case 'MMMM':
-        case 'dd':
-        case 'ddd':
-        case 'dddd':
-            return parseTokenWord;
-        case 'a':
-        case 'A':
-            return getLangDefinition(config._l)._meridiemParse;
-        case 'X':
-            return parseTokenTimestampMs;
-        case 'Z':
-        case 'ZZ':
-            return parseTokenTimezone;
-        case 'T':
-            return parseTokenT;
-        case 'SSSS':
-            return parseTokenDigits;
-        case 'MM':
-        case 'DD':
-        case 'YY':
-        case 'GG':
-        case 'gg':
-        case 'HH':
-        case 'hh':
-        case 'mm':
-        case 'ss':
-        case 'ww':
-        case 'WW':
-            return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
-        case 'M':
-        case 'D':
-        case 'd':
-        case 'H':
-        case 'h':
-        case 'm':
-        case 's':
-        case 'w':
-        case 'W':
-        case 'e':
-        case 'E':
-            return parseTokenOneOrTwoDigits;
-        default :
-            a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
-            return a;
-        }
-    }
-
-    function timezoneMinutesFromString(string) {
-        string = string || "";
-        var possibleTzMatches = (string.match(parseTokenTimezone) || []),
-            tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
-            parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
-            minutes = +(parts[1] * 60) + toInt(parts[2]);
-
-        return parts[0] === '+' ? -minutes : minutes;
-    }
-
-    // function to convert string input to date
-    function addTimeToArrayFromToken(token, input, config) {
-        var a, datePartArray = config._a;
-
-        switch (token) {
-        // MONTH
-        case 'M' : // fall through to MM
-        case 'MM' :
-            if (input != null) {
-                datePartArray[MONTH] = toInt(input) - 1;
-            }
-            break;
-        case 'MMM' : // fall through to MMMM
-        case 'MMMM' :
-            a = getLangDefinition(config._l).monthsParse(input);
-            // if we didn't find a month name, mark the date as invalid.
-            if (a != null) {
-                datePartArray[MONTH] = a;
-            } else {
-                config._pf.invalidMonth = input;
-            }
-            break;
-        // DAY OF MONTH
-        case 'D' : // fall through to DD
-        case 'DD' :
-            if (input != null) {
-                datePartArray[DATE] = toInt(input);
-            }
-            break;
-        // DAY OF YEAR
-        case 'DDD' : // fall through to DDDD
-        case 'DDDD' :
-            if (input != null) {
-                config._dayOfYear = toInt(input);
-            }
-
-            break;
-        // YEAR
-        case 'YY' :
-            datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
-            break;
-        case 'YYYY' :
-        case 'YYYYY' :
-        case 'YYYYYY' :
-            datePartArray[YEAR] = toInt(input);
-            break;
-        // AM / PM
-        case 'a' : // fall through to A
-        case 'A' :
-            config._isPm = getLangDefinition(config._l).isPM(input);
-            break;
-        // 24 HOUR
-        case 'H' : // fall through to hh
-        case 'HH' : // fall through to hh
-        case 'h' : // fall through to hh
-        case 'hh' :
-            datePartArray[HOUR] = toInt(input);
-            break;
-        // MINUTE
-        case 'm' : // fall through to mm
-        case 'mm' :
-            datePartArray[MINUTE] = toInt(input);
-            break;
-        // SECOND
-        case 's' : // fall through to ss
-        case 'ss' :
-            datePartArray[SECOND] = toInt(input);
-            break;
-        // MILLISECOND
-        case 'S' :
-        case 'SS' :
-        case 'SSS' :
-        case 'SSSS' :
-            datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
-            break;
-        // UNIX TIMESTAMP WITH MS
-        case 'X':
-            config._d = new Date(parseFloat(input) * 1000);
-            break;
-        // TIMEZONE
-        case 'Z' : // fall through to ZZ
-        case 'ZZ' :
-            config._useUTC = true;
-            config._tzm = timezoneMinutesFromString(input);
-            break;
-        case 'w':
-        case 'ww':
-        case 'W':
-        case 'WW':
-        case 'd':
-        case 'dd':
-        case 'ddd':
-        case 'dddd':
-        case 'e':
-        case 'E':
-            token = token.substr(0, 1);
-            /* falls through */
-        case 'gg':
-        case 'gggg':
-        case 'GG':
-        case 'GGGG':
-        case 'GGGGG':
-            token = token.substr(0, 2);
-            if (input) {
-                config._w = config._w || {};
-                config._w[token] = input;
-            }
-            break;
-        }
-    }
-
-    // convert an array to a date.
-    // the array should mirror the parameters below
-    // note: all values past the year are optional and will default to the lowest possible value.
-    // [year, month, day , hour, minute, second, millisecond]
-    function dateFromConfig(config) {
-        var i, date, input = [], currentDate,
-            yearToUse, fixYear, w, temp, lang, weekday, week;
-
-        if (config._d) {
-            return;
-        }
-
-        currentDate = currentDateArray(config);
-
-        //compute day of the year from weeks and weekdays
-        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
-            fixYear = function (val) {
-                var int_val = parseInt(val, 10);
-                return val ?
-                  (val.length < 3 ? (int_val > 68 ? 1900 + int_val : 2000 + int_val) : int_val) :
-                  (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]);
-            };
-
-            w = config._w;
-            if (w.GG != null || w.W != null || w.E != null) {
-                temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1);
-            }
-            else {
-                lang = getLangDefinition(config._l);
-                weekday = w.d != null ?  parseWeekday(w.d, lang) :
-                  (w.e != null ?  parseInt(w.e, 10) + lang._week.dow : 0);
-
-                week = parseInt(w.w, 10) || 1;
-
-                //if we're parsing 'd', then the low day numbers may be next week
-                if (w.d != null && weekday < lang._week.dow) {
-                    week++;
-                }
-
-                temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow);
-            }
-
-            config._a[YEAR] = temp.year;
-            config._dayOfYear = temp.dayOfYear;
-        }
-
-        //if the day of the year is set, figure out what it is
-        if (config._dayOfYear) {
-            yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
-
-            if (config._dayOfYear > daysInYear(yearToUse)) {
-                config._pf._overflowDayOfYear = true;
-            }
-
-            date = makeUTCDate(yearToUse, 0, config._dayOfYear);
-            config._a[MONTH] = date.getUTCMonth();
-            config._a[DATE] = date.getUTCDate();
-        }
-
-        // Default to current date.
-        // * if no year, month, day of month are given, default to today
-        // * if day of month is given, default month and year
-        // * if month is given, default only year
-        // * if year is given, don't default anything
-        for (i = 0; i < 3 && config._a[i] == null; ++i) {
-            config._a[i] = input[i] = currentDate[i];
-        }
-
-        // Zero out whatever was not defaulted, including time
-        for (; i < 7; i++) {
-            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
-        }
-
-        // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
-        input[HOUR] += toInt((config._tzm || 0) / 60);
-        input[MINUTE] += toInt((config._tzm || 0) % 60);
-
-        config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
-    }
-
-    function dateFromObject(config) {
-        var normalizedInput;
-
-        if (config._d) {
-            return;
-        }
-
-        normalizedInput = normalizeObjectUnits(config._i);
-        config._a = [
-            normalizedInput.year,
-            normalizedInput.month,
-            normalizedInput.day,
-            normalizedInput.hour,
-            normalizedInput.minute,
-            normalizedInput.second,
-            normalizedInput.millisecond
-        ];
-
-        dateFromConfig(config);
-    }
-
-    function currentDateArray(config) {
-        var now = new Date();
-        if (config._useUTC) {
-            return [
-                now.getUTCFullYear(),
-                now.getUTCMonth(),
-                now.getUTCDate()
-            ];
-        } else {
-            return [now.getFullYear(), now.getMonth(), now.getDate()];
-        }
-    }
-
-    // date from string and format string
-    function makeDateFromStringAndFormat(config) {
-
-        config._a = [];
-        config._pf.empty = true;
-
-        // This array is used to make a Date, either with `new Date` or `Date.UTC`
-        var lang = getLangDefinition(config._l),
-            string = '' + config._i,
-            i, parsedInput, tokens, token, skipped,
-            stringLength = string.length,
-            totalParsedInputLength = 0;
-
-        tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
-
-        for (i = 0; i < tokens.length; i++) {
-            token = tokens[i];
-            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
-            if (parsedInput) {
-                skipped = string.substr(0, string.indexOf(parsedInput));
-                if (skipped.length > 0) {
-                    config._pf.unusedInput.push(skipped);
-                }
-                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
-                totalParsedInputLength += parsedInput.length;
-            }
-            // don't parse if it's not a known token
-            if (formatTokenFunctions[token]) {
-                if (parsedInput) {
-                    config._pf.empty = false;
-                }
-                else {
-                    config._pf.unusedTokens.push(token);
-                }
-                addTimeToArrayFromToken(token, parsedInput, config);
-            }
-            else if (config._strict && !parsedInput) {
-                config._pf.unusedTokens.push(token);
-            }
-        }
-
-        // add remaining unparsed input length to the string
-        config._pf.charsLeftOver = stringLength - totalParsedInputLength;
-        if (string.length > 0) {
-            config._pf.unusedInput.push(string);
-        }
-
-        // handle am pm
-        if (config._isPm && config._a[HOUR] < 12) {
-            config._a[HOUR] += 12;
-        }
-        // if is 12 am, change hours to 0
-        if (config._isPm === false && config._a[HOUR] === 12) {
-            config._a[HOUR] = 0;
-        }
-
-        dateFromConfig(config);
-        checkOverflow(config);
-    }
-
-    function unescapeFormat(s) {
-        return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
-            return p1 || p2 || p3 || p4;
-        });
-    }
-
-    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
-    function regexpEscape(s) {
-        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
-    }
-
-    // date from string and array of format strings
-    function makeDateFromStringAndArray(config) {
-        var tempConfig,
-            bestMoment,
-
-            scoreToBeat,
-            i,
-            currentScore;
-
-        if (config._f.length === 0) {
-            config._pf.invalidFormat = true;
-            config._d = new Date(NaN);
-            return;
-        }
-
-        for (i = 0; i < config._f.length; i++) {
-            currentScore = 0;
-            tempConfig = extend({}, config);
-            tempConfig._pf = defaultParsingFlags();
-            tempConfig._f = config._f[i];
-            makeDateFromStringAndFormat(tempConfig);
-
-            if (!isValid(tempConfig)) {
-                continue;
-            }
-
-            // if there is any input that was not parsed add a penalty for that format
-            currentScore += tempConfig._pf.charsLeftOver;
-
-            //or tokens
-            currentScore += tempConfig._pf.unusedTokens.length * 10;
-
-            tempConfig._pf.score = currentScore;
-
-            if (scoreToBeat == null || currentScore < scoreToBeat) {
-                scoreToBeat = currentScore;
-                bestMoment = tempConfig;
-            }
-        }
-
-        extend(config, bestMoment || tempConfig);
-    }
-
-    // date from iso format
-    function makeDateFromString(config) {
-        var i, l,
-            string = config._i,
-            match = isoRegex.exec(string);
-
-        if (match) {
-            config._pf.iso = true;
-            for (i = 0, l = isoDates.length; i < l; i++) {
-                if (isoDates[i][1].exec(string)) {
-                    // match[5] should be "T" or undefined
-                    config._f = isoDates[i][0] + (match[6] || " ");
-                    break;
-                }
-            }
-            for (i = 0, l = isoTimes.length; i < l; i++) {
-                if (isoTimes[i][1].exec(string)) {
-                    config._f += isoTimes[i][0];
-                    break;
-                }
-            }
-            if (string.match(parseTokenTimezone)) {
-                config._f += "Z";
-            }
-            makeDateFromStringAndFormat(config);
-        }
-        else {
-            config._d = new Date(string);
-        }
-    }
-
-    function makeDateFromInput(config) {
-        var input = config._i,
-            matched = aspNetJsonRegex.exec(input);
-
-        if (input === undefined) {
-            config._d = new Date();
-        } else if (matched) {
-            config._d = new Date(+matched[1]);
-        } else if (typeof input === 'string') {
-            makeDateFromString(config);
-        } else if (isArray(input)) {
-            config._a = input.slice(0);
-            dateFromConfig(config);
-        } else if (isDate(input)) {
-            config._d = new Date(+input);
-        } else if (typeof(input) === 'object') {
-            dateFromObject(config);
-        } else {
-            config._d = new Date(input);
-        }
-    }
-
-    function makeDate(y, m, d, h, M, s, ms) {
-        //can't just apply() to create a date:
-        //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
-        var date = new Date(y, m, d, h, M, s, ms);
-
-        //the date constructor doesn't accept years < 1970
-        if (y < 1970) {
-            date.setFullYear(y);
-        }
-        return date;
-    }
-
-    function makeUTCDate(y) {
-        var date = new Date(Date.UTC.apply(null, arguments));
-        if (y < 1970) {
-            date.setUTCFullYear(y);
-        }
-        return date;
-    }
-
-    function parseWeekday(input, language) {
-        if (typeof input === 'string') {
-            if (!isNaN(input)) {
-                input = parseInt(input, 10);
-            }
-            else {
-                input = language.weekdaysParse(input);
-                if (typeof input !== 'number') {
-                    return null;
-                }
-            }
-        }
-        return input;
-    }
-
-    /************************************
-        Relative Time
-    ************************************/
-
-
-    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
-    function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
-        return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
-    }
-
-    function relativeTime(milliseconds, withoutSuffix, lang) {
-        var seconds = round(Math.abs(milliseconds) / 1000),
-            minutes = round(seconds / 60),
-            hours = round(minutes / 60),
-            days = round(hours / 24),
-            years = round(days / 365),
-            args = seconds < 45 && ['s', seconds] ||
-                minutes === 1 && ['m'] ||
-                minutes < 45 && ['mm', minutes] ||
-                hours === 1 && ['h'] ||
-                hours < 22 && ['hh', hours] ||
-                days === 1 && ['d'] ||
-                days <= 25 && ['dd', days] ||
-                days <= 45 && ['M'] ||
-                days < 345 && ['MM', round(days / 30)] ||
-                years === 1 && ['y'] || ['yy', years];
-        args[2] = withoutSuffix;
-        args[3] = milliseconds > 0;
-        args[4] = lang;
-        return substituteTimeAgo.apply({}, args);
-    }
-
-
-    /************************************
-        Week of Year
-    ************************************/
-
-
-    // firstDayOfWeek       0 = sun, 6 = sat
-    //                      the day of the week that starts the week
-    //                      (usually sunday or monday)
-    // firstDayOfWeekOfYear 0 = sun, 6 = sat
-    //                      the first week is the week that contains the first
-    //                      of this day of the week
-    //                      (eg. ISO weeks use thursday (4))
-    function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
-        var end = firstDayOfWeekOfYear - firstDayOfWeek,
-            daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
-            adjustedMoment;
-
-
-        if (daysToDayOfWeek > end) {
-            daysToDayOfWeek -= 7;
-        }
-
-        if (daysToDayOfWeek < end - 7) {
-            daysToDayOfWeek += 7;
-        }
-
-        adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
-        return {
-            week: Math.ceil(adjustedMoment.dayOfYear() / 7),
-            year: adjustedMoment.year()
-        };
-    }
-
-    //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
-    function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
-        var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
-
-        weekday = weekday != null ? weekday : firstDayOfWeek;
-        daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
-        dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
-
-        return {
-            year: dayOfYear > 0 ? year : year - 1,
-            dayOfYear: dayOfYear > 0 ?  dayOfYear : daysInYear(year - 1) + dayOfYear
-        };
-    }
-
-    /************************************
-        Top Level Functions
-    ************************************/
-
-    function makeMoment(config) {
-        var input = config._i,
-            format = config._f;
-
-        if (input === null) {
-            return moment.invalid({nullInput: true});
-        }
-
-        if (typeof input === 'string') {
-            config._i = input = getLangDefinition().preparse(input);
-        }
-
-        if (moment.isMoment(input)) {
-            config = cloneMoment(input);
-
-            config._d = new Date(+input._d);
-        } else if (format) {
-            if (isArray(format)) {
-                makeDateFromStringAndArray(config);
-            } else {
-                makeDateFromStringAndFormat(config);
-            }
-        } else {
-            makeDateFromInput(config);
-        }
-
-        return new Moment(config);
-    }
-
-    moment = function (input, format, lang, strict) {
-        var c;
-
-        if (typeof(lang) === "boolean") {
-            strict = lang;
-            lang = undefined;
-        }
-        // object construction must be done this way.
-        // https://github.com/moment/moment/issues/1423
-        c = {};
-        c._isAMomentObject = true;
-        c._i = input;
-        c._f = format;
-        c._l = lang;
-        c._strict = strict;
-        c._isUTC = false;
-        c._pf = defaultParsingFlags();
-
-        return makeMoment(c);
-    };
-
-    // creating with utc
-    moment.utc = function (input, format, lang, strict) {
-        var c;
-
-        if (typeof(lang) === "boolean") {
-            strict = lang;
-            lang = undefined;
-        }
-        // object construction must be done this way.
-        // https://github.com/moment/moment/issues/1423
-        c = {};
-        c._isAMomentObject = true;
-        c._useUTC = true;
-        c._isUTC = true;
-        c._l = lang;
-        c._i = input;
-        c._f = format;
-        c._strict = strict;
-        c._pf = defaultParsingFlags();
-
-        return makeMoment(c).utc();
-    };
-
-    // creating with unix timestamp (in seconds)
-    moment.unix = function (input) {
-        return moment(input * 1000);
-    };
-
-    // duration
-    moment.duration = function (input, key) {
-        var duration = input,
-            // matching against regexp is expensive, do it on demand
-            match = null,
-            sign,
-            ret,
-            parseIso;
-
-        if (moment.isDuration(input)) {
-            duration = {
-                ms: input._milliseconds,
-                d: input._days,
-                M: input._months
-            };
-        } else if (typeof input === 'number') {
-            duration = {};
-            if (key) {
-                duration[key] = input;
-            } else {
-                duration.milliseconds = input;
-            }
-        } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
-            sign = (match[1] === "-") ? -1 : 1;
-            duration = {
-                y: 0,
-                d: toInt(match[DATE]) * sign,
-                h: toInt(match[HOUR]) * sign,
-                m: toInt(match[MINUTE]) * sign,
-                s: toInt(match[SECOND]) * sign,
-                ms: toInt(match[MILLISECOND]) * sign
-            };
-        } else if (!!(match = isoDurationRegex.exec(input))) {
-            sign = (match[1] === "-") ? -1 : 1;
-            parseIso = function (inp) {
-                // We'd normally use ~~inp for this, but unfortunately it also
-                // converts floats to ints.
-                // inp may be undefined, so careful calling replace on it.
-                var res = inp && parseFloat(inp.replace(',', '.'));
-                // apply sign while we're at it
-                return (isNaN(res) ? 0 : res) * sign;
-            };
-            duration = {
-                y: parseIso(match[2]),
-                M: parseIso(match[3]),
-                d: parseIso(match[4]),
-                h: parseIso(match[5]),
-                m: parseIso(match[6]),
-                s: parseIso(match[7]),
-                w: parseIso(match[8])
-            };
-        }
-
-        ret = new Duration(duration);
-
-        if (moment.isDuration(input) && input.hasOwnProperty('_lang')) {
-            ret._lang = input._lang;
-        }
-
-        return ret;
-    };
-
-    // version number
-    moment.version = VERSION;
-
-    // default format
-    moment.defaultFormat = isoFormat;
-
-    // This function will be called whenever a moment is mutated.
-    // It is intended to keep the offset in sync with the timezone.
-    moment.updateOffset = function () {};
-
-    // This function will load languages and then set the global language.  If
-    // no arguments are passed in, it will simply return the current global
-    // language key.
-    moment.lang = function (key, values) {
-        var r;
-        if (!key) {
-            return moment.fn._lang._abbr;
-        }
-        if (values) {
-            loadLang(normalizeLanguage(key), values);
-        } else if (values === null) {
-            unloadLang(key);
-            key = 'en';
-        } else if (!languages[key]) {
-            getLangDefinition(key);
-        }
-        r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
-        return r._abbr;
-    };
-
-    // returns language data
-    moment.langData = function (key) {
-        if (key && key._lang && key._lang._abbr) {
-            key = key._lang._abbr;
-        }
-        return getLangDefinition(key);
-    };
-
-    // compare moment object
-    moment.isMoment = function (obj) {
-        return obj instanceof Moment ||
-            (obj != null &&  obj.hasOwnProperty('_isAMomentObject'));
-    };
-
-    // for typechecking Duration objects
-    moment.isDuration = function (obj) {
-        return obj instanceof Duration;
-    };
-
-    for (i = lists.length - 1; i >= 0; --i) {
-        makeList(lists[i]);
-    }
-
-    moment.normalizeUnits = function (units) {
-        return normalizeUnits(units);
-    };
-
-    moment.invalid = function (flags) {
-        var m = moment.utc(NaN);
-        if (flags != null) {
-            extend(m._pf, flags);
-        }
-        else {
-            m._pf.userInvalidated = true;
-        }
-
-        return m;
-    };
-
-    moment.parseZone = function (input) {
-        return moment(input).parseZone();
-    };
-
-    /************************************
-        Moment Prototype
-    ************************************/
-
-
-    extend(moment.fn = Moment.prototype, {
-
-        clone : function () {
-            return moment(this);
-        },
-
-        valueOf : function () {
-            return +this._d + ((this._offset || 0) * 60000);
-        },
-
-        unix : function () {
-            return Math.floor(+this / 1000);
-        },
-
-        toString : function () {
-            return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
-        },
-
-        toDate : function () {
-            return this._offset ? new Date(+this) : this._d;
-        },
-
-        toISOString : function () {
-            var m = moment(this).utc();
-            if (0 < m.year() && m.year() <= 9999) {
-                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
-            } else {
-                return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
-            }
-        },
-
-        toArray : function () {
-            var m = this;
-            return [
-                m.year(),
-                m.month(),
-                m.date(),
-                m.hours(),
-                m.minutes(),
-                m.seconds(),
-                m.milliseconds()
-            ];
-        },
-
-        isValid : function () {
-            return isValid(this);
-        },
-
-        isDSTShifted : function () {
-
-            if (this._a) {
-                return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
-            }
-
-            return false;
-        },
-
-        parsingFlags : function () {
-            return extend({}, this._pf);
-        },
-
-        invalidAt: function () {
-            return this._pf.overflow;
-        },
-
-        utc : function () {
-            return this.zone(0);
-        },
-
-        local : function () {
-            this.zone(0);
-            this._isUTC = false;
-            return this;
-        },
-
-        format : function (inputString) {
-            var output = formatMoment(this, inputString || moment.defaultFormat);
-            return this.lang().postformat(output);
-        },
-
-        add : function (input, val) {
-            var dur;
-            // switch args to support add('s', 1) and add(1, 's')
-            if (typeof input === 'string') {
-                dur = moment.duration(+val, input);
-            } else {
-                dur = moment.duration(input, val);
-            }
-            addOrSubtractDurationFromMoment(this, dur, 1);
-            return this;
-        },
-
-        subtract : function (input, val) {
-            var dur;
-            // switch args to support subtract('s', 1) and subtract(1, 's')
-            if (typeof input === 'string') {
-                dur = moment.duration(+val, input);
-            } else {
-                dur = moment.duration(input, val);
-            }
-            addOrSubtractDurationFromMoment(this, dur, -1);
-            return this;
-        },
-
-        diff : function (input, units, asFloat) {
-            var that = makeAs(input, this),
-                zoneDiff = (this.zone() - that.zone()) * 6e4,
-                diff, output;
-
-            units = normalizeUnits(units);
-
-            if (units === 'year' || units === 'month') {
-                // average number of days in the months in the given dates
-                diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
-                // difference in months
-                output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
-                // adjust by taking difference in days, average number of days
-                // and dst in the given months.
-                output += ((this - moment(this).startOf('month')) -
-                        (that - moment(that).startOf('month'))) / diff;
-                // same as above but with zones, to negate all dst
-                output -= ((this.zone() - moment(this).startOf('month').zone()) -
-                        (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff;
-                if (units === 'year') {
-                    output = output / 12;
-                }
-            } else {
-                diff = (this - that);
-                output = units === 'second' ? diff / 1e3 : // 1000
-                    units === 'minute' ? diff / 6e4 : // 1000 * 60
-                    units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
-                    units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
-                    units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
-                    diff;
-            }
-            return asFloat ? output : absRound(output);
-        },
-
-        from : function (time, withoutSuffix) {
-            return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
-        },
-
-        fromNow : function (withoutSuffix) {
-            return this.from(moment(), withoutSuffix);
-        },
-
-        calendar : function () {
-            // We want to compare the start of today, vs this.
-            // Getting start-of-today depends on whether we're zone'd or not.
-            var sod = makeAs(moment(), this).startOf('day'),
-                diff = this.diff(sod, 'days', true),
-                format = diff < -6 ? 'sameElse' :
-                    diff < -1 ? 'lastWeek' :
-                    diff < 0 ? 'lastDay' :
-                    diff < 1 ? 'sameDay' :
-                    diff < 2 ? 'nextDay' :
-                    diff < 7 ? 'nextWeek' : 'sameElse';
-            return this.format(this.lang().calendar(format, this));
-        },
-
-        isLeapYear : function () {
-            return isLeapYear(this.year());
-        },
-
-        isDST : function () {
-            return (this.zone() < this.clone().month(0).zone() ||
-                this.zone() < this.clone().month(5).zone());
-        },
-
-        day : function (input) {
-            var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
-            if (input != null) {
-                input = parseWeekday(input, this.lang());
-                return this.add({ d : input - day });
-            } else {
-                return day;
-            }
-        },
-
-        month : function (input) {
-            var utc = this._isUTC ? 'UTC' : '',
-                dayOfMonth;
-
-            if (input != null) {
-                if (typeof input === 'string') {
-                    input = this.lang().monthsParse(input);
-                    if (typeof input !== 'number') {
-                        return this;
-                    }
-                }
-
-                dayOfMonth = this.date();
-                this.date(1);
-                this._d['set' + utc + 'Month'](input);
-                this.date(Math.min(dayOfMonth, this.daysInMonth()));
-
-                moment.updateOffset(this);
-                return this;
-            } else {
-                return this._d['get' + utc + 'Month']();
-            }
-        },
-
-        startOf: function (units) {
-            units = normalizeUnits(units);
-            // the following switch intentionally omits break keywords
-            // to utilize falling through the cases.
-            switch (units) {
-            case 'year':
-                this.month(0);
-                /* falls through */
-            case 'month':
-                this.date(1);
-                /* falls through */
-            case 'week':
-            case 'isoWeek':
-            case 'day':
-                this.hours(0);
-                /* falls through */
-            case 'hour':
-                this.minutes(0);
-                /* falls through */
-            case 'minute':
-                this.seconds(0);
-                /* falls through */
-            case 'second':
-                this.milliseconds(0);
-                /* falls through */
-            }
-
-            // weeks are a special case
-            if (units === 'week') {
-                this.weekday(0);
-            } else if (units === 'isoWeek') {
-                this.isoWeekday(1);
-            }
-
-            return this;
-        },
-
-        endOf: function (units) {
-            units = normalizeUnits(units);
-            return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
-        },
-
-        isAfter: function (input, units) {
-            units = typeof units !== 'undefined' ? units : 'millisecond';
-            return +this.clone().startOf(units) > +moment(input).startOf(units);
-        },
-
-        isBefore: function (input, units) {
-            units = typeof units !== 'undefined' ? units : 'millisecond';
-            return +this.clone().startOf(units) < +moment(input).startOf(units);
-        },
-
-        isSame: function (input, units) {
-            units = units || 'ms';
-            return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
-        },
-
-        min: function (other) {
-            other = moment.apply(null, arguments);
-            return other < this ? this : other;
-        },
-
-        max: function (other) {
-            other = moment.apply(null, arguments);
-            return other > this ? this : other;
-        },
-
-        zone : function (input) {
-            var offset = this._offset || 0;
-            if (input != null) {
-                if (typeof input === "string") {
-                    input = timezoneMinutesFromString(input);
-                }
-                if (Math.abs(input) < 16) {
-                    input = input * 60;
-                }
-                this._offset = input;
-                this._isUTC = true;
-                if (offset !== input) {
-                    addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
-                }
-            } else {
-                return this._isUTC ? offset : this._d.getTimezoneOffset();
-            }
-            return this;
-        },
-
-        zoneAbbr : function () {
-            return this._isUTC ? "UTC" : "";
-        },
-
-        zoneName : function () {
-            return this._isUTC ? "Coordinated Universal Time" : "";
-        },
-
-        parseZone : function () {
-            if (this._tzm) {
-                this.zone(this._tzm);
-            } else if (typeof this._i === 'string') {
-                this.zone(this._i);
-            }
-            return this;
-        },
-
-        hasAlignedHourOffset : function (input) {
-            if (!input) {
-                input = 0;
-            }
-            else {
-                input = moment(input).zone();
-            }
-
-            return (this.zone() - input) % 60 === 0;
-        },
-
-        daysInMonth : function () {
-            return daysInMonth(this.year(), this.month());
-        },
-
-        dayOfYear : function (input) {
-            var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
-            return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
-        },
-
-        quarter : function () {
-            return Math.ceil((this.month() + 1.0) / 3.0);
-        },
-
-        weekYear : function (input) {
-            var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year;
-            return input == null ? year : this.add("y", (input - year));
-        },
-
-        isoWeekYear : function (input) {
-            var year = weekOfYear(this, 1, 4).year;
-            return input == null ? year : this.add("y", (input - year));
-        },
-
-        week : function (input) {
-            var week = this.lang().week(this);
-            return input == null ? week : this.add("d", (input - week) * 7);
-        },
-
-        isoWeek : function (input) {
-            var week = weekOfYear(this, 1, 4).week;
-            return input == null ? week : this.add("d", (input - week) * 7);
-        },
-
-        weekday : function (input) {
-            var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
-            return input == null ? weekday : this.add("d", input - weekday);
-        },
-
-        isoWeekday : function (input) {
-            // behaves the same as moment#day except
-            // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
-            // as a setter, sunday should belong to the previous week.
-            return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
-        },
-
-        get : function (units) {
-            units = normalizeUnits(units);
-            return this[units]();
-        },
-
-        set : function (units, value) {
-            units = normalizeUnits(units);
-            if (typeof this[units] === 'function') {
-                this[units](value);
-            }
-            return this;
-        },
-
-        // If passed a language key, it will set the language for this
-        // instance.  Otherwise, it will return the language configuration
-        // variables for this instance.
-        lang : function (key) {
-            if (key === undefined) {
-                return this._lang;
-            } else {
-                this._lang = getLangDefinition(key);
-                return this;
-            }
-        }
-    });
-
-    // helper for adding shortcuts
-    function makeGetterAndSetter(name, key) {
-        moment.fn[name] = moment.fn[name + 's'] = function (input) {
-            var utc = this._isUTC ? 'UTC' : '';
-            if (input != null) {
-                this._d['set' + utc + key](input);
-                moment.updateOffset(this);
-                return this;
-            } else {
-                return this._d['get' + utc + key]();
-            }
-        };
-    }
-
-    // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
-    for (i = 0; i < proxyGettersAndSetters.length; i ++) {
-        makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
-    }
-
-    // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
-    makeGetterAndSetter('year', 'FullYear');
-
-    // add plural methods
-    moment.fn.days = moment.fn.day;
-    moment.fn.months = moment.fn.month;
-    moment.fn.weeks = moment.fn.week;
-    moment.fn.isoWeeks = moment.fn.isoWeek;
-
-    // add aliased format methods
-    moment.fn.toJSON = moment.fn.toISOString;
-
-    /************************************
-        Duration Prototype
-    ************************************/
-
-
-    extend(moment.duration.fn = Duration.prototype, {
-
-        _bubble : function () {
-            var milliseconds = this._milliseconds,
-                days = this._days,
-                months = this._months,
-                data = this._data,
-                seconds, minutes, hours, years;
-
-            // The following code bubbles up values, see the tests for
-            // examples of what that means.
-            data.milliseconds = milliseconds % 1000;
-
-            seconds = absRound(milliseconds / 1000);
-            data.seconds = seconds % 60;
-
-            minutes = absRound(seconds / 60);
-            data.minutes = minutes % 60;
-
-            hours = absRound(minutes / 60);
-            data.hours = hours % 24;
-
-            days += absRound(hours / 24);
-            data.days = days % 30;
-
-            months += absRound(days / 30);
-            data.months = months % 12;
-
-            years = absRound(months / 12);
-            data.years = years;
-        },
-
-        weeks : function () {
-            return absRound(this.days() / 7);
-        },
-
-        valueOf : function () {
-            return this._milliseconds +
-              this._days * 864e5 +
-              (this._months % 12) * 2592e6 +
-              toInt(this._months / 12) * 31536e6;
-        },
-
-        humanize : function (withSuffix) {
-            var difference = +this,
-                output = relativeTime(difference, !withSuffix, this.lang());
-
-            if (withSuffix) {
-                output = this.lang().pastFuture(difference, output);
-            }
-
-            return this.lang().postformat(output);
-        },
-
-        add : function (input, val) {
-            // supports only 2.0-style add(1, 's') or add(moment)
-            var dur = moment.duration(input, val);
-
-            this._milliseconds += dur._milliseconds;
-            this._days += dur._days;
-            this._months += dur._months;
-
-            this._bubble();
-
-            return this;
-        },
-
-        subtract : function (input, val) {
-            var dur = moment.duration(input, val);
-
-            this._milliseconds -= dur._milliseconds;
-            this._days -= dur._days;
-            this._months -= dur._months;
-
-            this._bubble();
-
-            return this;
-        },
-
-        get : function (units) {
-            units = normalizeUnits(units);
-            return this[units.toLowerCase() + 's']();
-        },
-
-        as : function (units) {
-            units = normalizeUnits(units);
-            return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
-        },
-
-        lang : moment.fn.lang,
-
-        toIsoString : function () {
-            // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
-            var years = Math.abs(this.years()),
-                months = Math.abs(this.months()),
-                days = Math.abs(this.days()),
-                hours = Math.abs(this.hours()),
-                minutes = Math.abs(this.minutes()),
-                seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
-
-            if (!this.asSeconds()) {
-                // this is the same as C#'s (Noda) and python (isodate)...
-                // but not other JS (goog.date)
-                return 'P0D';
-            }
-
-            return (this.asSeconds() < 0 ? '-' : '') +
-                'P' +
-                (years ? years + 'Y' : '') +
-                (months ? months + 'M' : '') +
-                (days ? days + 'D' : '') +
-                ((hours || minutes || seconds) ? 'T' : '') +
-                (hours ? hours + 'H' : '') +
-                (minutes ? minutes + 'M' : '') +
-                (seconds ? seconds + 'S' : '');
-        }
-    });
-
-    function makeDurationGetter(name) {
-        moment.duration.fn[name] = function () {
-            return this._data[name];
-        };
-    }
-
-    function makeDurationAsGetter(name, factor) {
-        moment.duration.fn['as' + name] = function () {
-            return +this / factor;
-        };
-    }
-
-    for (i in unitMillisecondFactors) {
-        if (unitMillisecondFactors.hasOwnProperty(i)) {
-            makeDurationAsGetter(i, unitMillisecondFactors[i]);
-            makeDurationGetter(i.toLowerCase());
-        }
-    }
-
-    makeDurationAsGetter('Weeks', 6048e5);
-    moment.duration.fn.asMonths = function () {
-        return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
-    };
-
-
-    /************************************
-        Default Lang
-    ************************************/
-
-
-    // Set default language, other languages will inherit from English.
-    moment.lang('en', {
-        ordinal : function (number) {
-            var b = number % 10,
-                output = (toInt(number % 100 / 10) === 1) ? 'th' :
-                (b === 1) ? 'st' :
-                (b === 2) ? 'nd' :
-                (b === 3) ? 'rd' : 'th';
-            return number + output;
-        }
-    });
-
-    /* EMBED_LANGUAGES */
-
-    /************************************
-        Exposing Moment
-    ************************************/
-
-    function makeGlobal(deprecate) {
-        var warned = false, local_moment = moment;
-        /*global ender:false */
-        if (typeof ender !== 'undefined') {
-            return;
-        }
-        // here, `this` means `window` in the browser, or `global` on the server
-        // add `moment` as a global object via a string identifier,
-        // for Closure Compiler "advanced" mode
-        if (deprecate) {
-            global.moment = function () {
-                if (!warned && console && console.warn) {
-                    warned = true;
-                    console.warn(
-                            "Accessing Moment through the global scope is " +
-                            "deprecated, and will be removed in an upcoming " +
-                            "release.");
-                }
-                return local_moment.apply(null, arguments);
-            };
-            extend(global.moment, local_moment);
-        } else {
-            global['moment'] = moment;
-        }
-    }
-
-    // CommonJS module is defined
-    if (hasModule) {
-        module.exports = moment;
-        makeGlobal(true);
-    } else if (typeof define === "function" && define.amd) {
-        define("moment", function (require, exports, module) {
-            if (module.config && module.config() && module.config().noGlobal !== true) {
-                // If user provided noGlobal, he is aware of global
-                makeGlobal(module.config().noGlobal === undefined);
-            }
-
-            return moment;
-        });
-    } else {
-        makeGlobal();
-    }
-}).call(this);
diff --git a/resources/oojs-ui/i18n/ace.json b/resources/oojs-ui/i18n/ace.json
deleted file mode 100644 (file)
index 554ae57..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Si Gam Acèh"
-        ]
-    },
-    "ooui-dialog-action-close": "Tôp",
-    "ooui-outline-control-move-down": "Pinah item u yup",
-    "ooui-outline-control-move-up": "Pinah item u ateuëh",
-    "ooui-toolbar-more": "Lom"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/af.json b/resources/oojs-ui/i18n/af.json
deleted file mode 100644 (file)
index a622f89..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Naudefj"
-        ]
-    },
-    "ooui-dialog-action-close": "Sluit",
-    "ooui-outline-control-move-down": "Skuif item af",
-    "ooui-outline-control-move-up": "Skuif item op"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/am.json b/resources/oojs-ui/i18n/am.json
deleted file mode 100644 (file)
index 61e4ff6..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Elfalem"
-        ]
-    },
-    "ooui-dialog-action-close": "ለመዝጋት"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ar.json b/resources/oojs-ui/i18n/ar.json
deleted file mode 100644 (file)
index 65e1364..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ciphers",
-            "Claw eg",
-            "Elfalem",
-            "Jdforrester",
-            "Mido",
-            "OsamaK",
-            "زكريا",
-            "مشعل الحربي"
-        ]
-    },
-    "ooui-dialog-action-close": "أغلق",
-    "ooui-outline-control-move-down": "انقل العنصر للأسفل",
-    "ooui-outline-control-move-up": "انقل العنصر للأعلى",
-    "ooui-toolbar-more": "مزيد"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/arc.json b/resources/oojs-ui/i18n/arc.json
deleted file mode 100644 (file)
index 0f9e75d..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Basharh"
-        ]
-    },
-    "ooui-dialog-action-close": "ܣܟܘܪ"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ast.json b/resources/oojs-ui/i18n/ast.json
deleted file mode 100644 (file)
index fe6ea0a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Basharh",
-            "Bishnu Saikia",
-            "Xuacu"
-        ]
-    },
-    "ooui-dialog-action-close": "Zarrar",
-    "ooui-outline-control-move-down": "Mover abaxo l'elementu",
-    "ooui-outline-control-move-up": "Mover arriba l'elementu",
-    "ooui-outline-control-remove": "Desaniciar elementu",
-    "ooui-toolbar-more": "Más"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/az.json b/resources/oojs-ui/i18n/az.json
deleted file mode 100644 (file)
index 257680b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cekli829",
-            "Interfase",
-            "Jduranboger"
-        ]
-    },
-    "ooui-dialog-action-close": "Bağla",
-    "ooui-outline-control-move-down": "Bəndi aşağı apar",
-    "ooui-outline-control-move-up": "Bəndi yuxarı apar",
-    "ooui-outline-control-remove": "Bəndi sil",
-    "ooui-toolbar-more": "Daha artıq"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ba.json b/resources/oojs-ui/i18n/ba.json
deleted file mode 100644 (file)
index 4af0114..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "AiseluRB",
-            "Amire80",
-            "Assele",
-            "Haqmar",
-            "Sagan",
-            "Рустам Нурыев"
-        ]
-    },
-    "ooui-dialog-action-close": "Ябырға",
-    "ooui-outline-control-move-down": "Аҫҡа күсерергә",
-    "ooui-outline-control-move-up": "Өҫкә күсерергә"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/bcl.json b/resources/oojs-ui/i18n/bcl.json
deleted file mode 100644 (file)
index aff451e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Geopoet",
-            "Sky Harbor"
-        ]
-    },
-    "ooui-dialog-action-close": "Seraduhon",
-    "ooui-outline-control-move-down": "Balyuhon an aytem paibaba",
-    "ooui-outline-control-move-up": "Balyuhon an aytem paitaas",
-    "ooui-toolbar-more": "Kadugangan"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/be-tarask.json b/resources/oojs-ui/i18n/be-tarask.json
deleted file mode 100644 (file)
index 5922f61..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "EugeneZelenko",
-            "Wizardist",
-            "Чаховіч Уладзіслаў",
-            "Zedlik"
-        ]
-    },
-    "ooui-dialog-action-close": "Закрыць",
-    "ooui-outline-control-move-down": "Перасунуць ніжэй",
-    "ooui-outline-control-move-up": "Перасунуць вышэй",
-    "ooui-toolbar-more": "Болей"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/be.json b/resources/oojs-ui/i18n/be.json
deleted file mode 100644 (file)
index 3058ab8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Чаховіч Уладзіслаў"
-        ]
-    },
-    "ooui-dialog-action-close": "Закрыць"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/bg.json b/resources/oojs-ui/i18n/bg.json
deleted file mode 100644 (file)
index 6006244..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "DCLXVI",
-            "Hristofor.mirchev",
-            "පසිඳු කාවින්ද",
-            "Mitzev"
-        ]
-    },
-    "ooui-dialog-action-close": "Затваряне",
-    "ooui-outline-control-remove": "Премахване на обекта",
-    "ooui-toolbar-more": "Още"
-}
diff --git a/resources/oojs-ui/i18n/bn.json b/resources/oojs-ui/i18n/bn.json
deleted file mode 100644 (file)
index c321ab1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Aftab1995",
-            "Bellayet",
-            "Jayantanth",
-            "Nasir8891",
-            "Runab",
-            "Sayak Sarkar"
-        ]
-    },
-    "ooui-dialog-action-close": "বন্ধ",
-    "ooui-outline-control-move-down": "আইটেম নিচে স্থানান্তর",
-    "ooui-outline-control-move-up": "আইটেম উপরে স্থানান্তর",
-    "ooui-toolbar-more": "আরও"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/br.json b/resources/oojs-ui/i18n/br.json
deleted file mode 100644 (file)
index 38eb9e8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Fohanno",
-            "Fulup",
-            "Y-M D"
-        ]
-    },
-    "ooui-dialog-action-close": "Serriñ",
-    "ooui-outline-control-move-down": "Lakaat an elfenn da ziskenn",
-    "ooui-outline-control-move-up": "Lakaat an elfenn da bignat"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/bs.json b/resources/oojs-ui/i18n/bs.json
deleted file mode 100644 (file)
index 95ba48d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "DzWiki"
-        ]
-    },
-    "ooui-dialog-action-close": "Zatvori",
-    "ooui-outline-control-move-down": "Premjesti stavku dole",
-    "ooui-outline-control-move-up": "Premjesti stavku gore",
-    "ooui-outline-control-remove": "Ukloni stavku",
-    "ooui-toolbar-more": "Više"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ca.json b/resources/oojs-ui/i18n/ca.json
deleted file mode 100644 (file)
index 61bb1f6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Alvaro Vidal-Abarca",
-            "Amire80",
-            "Arnaugir",
-            "Pginer",
-            "QuimGil",
-            "SMP",
-            "Vriullop"
-        ]
-    },
-    "ooui-dialog-action-close": "Tanca",
-    "ooui-outline-control-move-down": "Baixa element",
-    "ooui-outline-control-move-up": "Puja element",
-    "ooui-toolbar-more": "Més"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ce.json b/resources/oojs-ui/i18n/ce.json
deleted file mode 100644 (file)
index ff14ff3..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Amire80",
-            "Умар"
-        ]
-    },
-    "ooui-dialog-action-close": "ДӀачӀагӀа",
-    "ooui-outline-control-move-down": "Лаха яккха элемент",
-    "ooui-outline-control-move-up": "Лаккха яккха элемент",
-    "ooui-outline-control-remove": "ДӀадаха меттиг",
-    "ooui-toolbar-more": "Кхин тӀе"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ckb.json b/resources/oojs-ui/i18n/ckb.json
deleted file mode 100644 (file)
index 839f4a8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Calak",
-            "Muhammed taha"
-        ]
-    },
-    "ooui-dialog-action-close": "دایخە"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/co.json b/resources/oojs-ui/i18n/co.json
deleted file mode 100644 (file)
index e5edb21..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Paulu"
-        ]
-    },
-    "ooui-dialog-action-close": "Chjude",
-    "ooui-outline-control-move-down": "Fà falà l'ogettu",
-    "ooui-outline-control-move-up": "Fà cullà l'ogettu"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/cs.json b/resources/oojs-ui/i18n/cs.json
deleted file mode 100644 (file)
index 670073f..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Chmee2",
-            "Jkjk",
-            "Juandev",
-            "Koo6",
-            "Littledogboy",
-            "Michaelbrabec",
-            "Mormegil",
-            "Polda18",
-            "Tchoř",
-            "ශ්වෙත"
-        ]
-    },
-    "ooui-dialog-action-close": "Zavřít",
-    "ooui-outline-control-move-down": "Přesunout položku dolů",
-    "ooui-outline-control-move-up": "Přesunout položku nahoru",
-    "ooui-outline-control-remove": "Odstranit položku",
-    "ooui-toolbar-more": "Další"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/cu.json b/resources/oojs-ui/i18n/cu.json
deleted file mode 100644 (file)
index 55594c1..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "ОйЛ"
-        ]
-    },
-    "ooui-dialog-action-close": "ꙁакрꙑи",
-    "ooui-toolbar-more": "вѧщє"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/cy.json b/resources/oojs-ui/i18n/cy.json
deleted file mode 100644 (file)
index d37912d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Lloffiwr",
-            "Robin Owain",
-            "ОйЛ"
-        ]
-    },
-    "ooui-dialog-action-close": "Caeer",
-    "ooui-outline-control-move-down": "Symud yr eitem lawr",
-    "ooui-outline-control-move-up": "Symud yr eitem lan",
-    "ooui-toolbar-more": "Rhagor"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/da.json b/resources/oojs-ui/i18n/da.json
deleted file mode 100644 (file)
index bf47bcb..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cgtdk",
-            "Christian List",
-            "EileenSanda",
-            "Laketown",
-            "Palnatoke",
-            "Simeondahl",
-            "Tehnix"
-        ]
-    },
-    "ooui-dialog-action-close": "Luk",
-    "ooui-outline-control-move-down": "Flyt ned",
-    "ooui-outline-control-move-up": "Flyt op",
-    "ooui-toolbar-more": "Mere"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/de.json b/resources/oojs-ui/i18n/de.json
deleted file mode 100644 (file)
index bed2b2c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "APPER",
-            "G.Hagedorn",
-            "Inkowik",
-            "Jcornelius",
-            "Jdforrester",
-            "Kghbln",
-            "Metalhead64",
-            "Murma174",
-            "Se4598",
-            "Tomabrafix"
-        ]
-    },
-    "ooui-dialog-action-close": "Schließen",
-    "ooui-outline-control-move-down": "Element nach unten verschieben",
-    "ooui-outline-control-move-up": "Element nach oben verschieben",
-    "ooui-outline-control-remove": "Element entfernen",
-    "ooui-toolbar-more": "Mehr"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/diq.json b/resources/oojs-ui/i18n/diq.json
deleted file mode 100644 (file)
index bb0ac35..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Erdemaslancan",
-            "Gorizon",
-            "Kghbln",
-            "Marmase",
-            "Mirzali",
-            "Se4598"
-        ]
-    },
-    "ooui-dialog-action-close": "Racnê",
-    "ooui-outline-control-move-down": "Bendi bere cêr",
-    "ooui-outline-control-move-up": "Bendi bere cor",
-    "ooui-toolbar-more": "Zewbi"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/dsb.json b/resources/oojs-ui/i18n/dsb.json
deleted file mode 100644 (file)
index ef60093..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Michawiki"
-        ]
-    },
-    "ooui-dialog-action-close": "Zacyniś",
-    "ooui-outline-control-move-down": "Element dołoj pśesunuś",
-    "ooui-outline-control-move-up": "Element górjej pśesunuś",
-    "ooui-outline-control-remove": "Zapisk wótpóraś",
-    "ooui-toolbar-more": "Wěcej"
-}
diff --git a/resources/oojs-ui/i18n/el.json b/resources/oojs-ui/i18n/el.json
deleted file mode 100644 (file)
index d1ef8b2..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Astralnet",
-            "Dipa1965",
-            "Evropi",
-            "FocalPoint",
-            "Geraki",
-            "Glavkos",
-            "Nikosguard",
-            "Tifa93"
-        ]
-    },
-    "ooui-dialog-action-close": "Κλείσιμο",
-    "ooui-outline-control-move-down": "Μετακίνηση στοιχείου προς τα κάτω",
-    "ooui-outline-control-move-up": "Μετακίνηση στοιχείου προς τα επάνω",
-    "ooui-outline-control-remove": "Αφαίρεση στοιχείου",
-    "ooui-toolbar-more": "Περισσότερα"
-}
diff --git a/resources/oojs-ui/i18n/eml.json b/resources/oojs-ui/i18n/eml.json
deleted file mode 100644 (file)
index 5dd09f5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Gloria sah",
-            "Lévi"
-        ]
-    },
-    "ooui-dialog-action-close": "Sèra",
-    "ooui-outline-control-move-down": "Spôsta in bâs",
-    "ooui-outline-control-move-up": "Spôsta in êlt",
-    "ooui-toolbar-more": "Êter"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/en.json b/resources/oojs-ui/i18n/en.json
deleted file mode 100644 (file)
index 5ff9915..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Trevor Parscal",
-            "Ed Sanders",
-            "James D. Forrester",
-            "Raimond Spekking",
-            "Erik Moeller",
-            "Moriel Schottlender",
-            "Yuki Shira",
-            "Siebrand Mazeland",
-            "Rob Moen",
-            "Timo Tijhof",
-            "Roan Kattouw",
-            "Christian Williams",
-            "Amir E. Aharoni"
-        ]
-    },
-    "ooui-dialog-action-close": "Close",
-    "ooui-outline-control-move-down": "Move item down",
-    "ooui-outline-control-move-up": "Move item up",
-    "ooui-outline-control-remove": "Remove item",
-    "ooui-toolbar-more": "More"
-}
diff --git a/resources/oojs-ui/i18n/eo.json b/resources/oojs-ui/i18n/eo.json
deleted file mode 100644 (file)
index 51f3261..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Happy5214",
-            "KuboF",
-            "Shirayuki",
-            "Yekrats"
-        ]
-    },
-    "ooui-dialog-action-close": "Fermi",
-    "ooui-outline-control-move-down": "Movi eron suben",
-    "ooui-outline-control-move-up": "Movi eron supren",
-    "ooui-toolbar-more": "Pli"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/es.json b/resources/oojs-ui/i18n/es.json
deleted file mode 100644 (file)
index a3be749..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Armando-Martin",
-            "Aruizdr",
-            "Benfutbol10",
-            "DJ Nietzsche",
-            "Erdemaslancan",
-            "Fitoschido",
-            "Imre",
-            "Invadinado",
-            "Jdforrester",
-            "Jduranboger",
-            "PoLuX124",
-            "Ralgis",
-            "Thehelpfulone"
-        ]
-    },
-    "ooui-dialog-action-close": "Cerrar",
-    "ooui-outline-control-move-down": "Mover abajo",
-    "ooui-outline-control-move-up": "Mover arriba",
-    "ooui-outline-control-remove": "Eliminar elemento",
-    "ooui-toolbar-more": "Más"
-}
diff --git a/resources/oojs-ui/i18n/et.json b/resources/oojs-ui/i18n/et.json
deleted file mode 100644 (file)
index f0ddc39..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Avjoska",
-            "Pikne"
-        ]
-    },
-    "ooui-dialog-action-close": "Sule",
-    "ooui-outline-control-move-down": "Liiguta üksust allapoole",
-    "ooui-outline-control-move-up": "Liiguta üksust ülespoole",
-    "ooui-outline-control-remove": "Eemalda üksus",
-    "ooui-toolbar-more": "Veel"
-}
diff --git a/resources/oojs-ui/i18n/eu.json b/resources/oojs-ui/i18n/eu.json
deleted file mode 100644 (file)
index 5d3f08b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "An13sa",
-            "Unai Fdz. de Betoño",
-            "Xabier Armendaritz"
-        ]
-    },
-    "ooui-dialog-action-close": "Itxi",
-    "ooui-outline-control-move-down": "Mugitu itema beherantz",
-    "ooui-outline-control-move-up": "Mugitu itema gorantz",
-    "ooui-toolbar-more": "Gehiago"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/fa.json b/resources/oojs-ui/i18n/fa.json
deleted file mode 100644 (file)
index 3f1ad0c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Dalba",
-            "Ebraminio",
-            "Jdforrester",
-            "Ladsgroup",
-            "Mjbmr",
-            "Nojan Madinehi",
-            "Reza1615",
-            "Taha",
-            "درفش کاویانی",
-            "Armin1392"
-        ]
-    },
-    "ooui-dialog-action-close": "بستن",
-    "ooui-outline-control-move-down": "انتقال مورد به پایین",
-    "ooui-outline-control-move-up": "انتقال مورد به بالا",
-    "ooui-outline-control-remove": "حذف مورد",
-    "ooui-toolbar-more": "بیشتر"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/fi.json b/resources/oojs-ui/i18n/fi.json
deleted file mode 100644 (file)
index ce2f6d0..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Beluga",
-            "Crt",
-            "Harriv",
-            "Linnea",
-            "Nedergard",
-            "Nike",
-            "Olli",
-            "Pxos",
-            "Samoasambia",
-            "Silvonen",
-            "Skalman",
-            "Stryn",
-            "VezonThunder"
-        ]
-    },
-    "ooui-dialog-action-close": "Sulje",
-    "ooui-outline-control-move-down": "Siirrä kohdetta alaspäin",
-    "ooui-outline-control-move-up": "Siirrä kohdetta ylöspäin",
-    "ooui-outline-control-remove": "Poista kohde",
-    "ooui-toolbar-more": "Lisää"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/fo.json b/resources/oojs-ui/i18n/fo.json
deleted file mode 100644 (file)
index 00a48ff..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "EileenSanda"
-        ]
-    },
-    "ooui-dialog-action-close": "Lat aftur",
-    "ooui-outline-control-move-down": "Flyt lutin niður",
-    "ooui-outline-control-move-up": "Flyt lutin upp",
-    "ooui-toolbar-more": "Meira"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/fr.json b/resources/oojs-ui/i18n/fr.json
deleted file mode 100644 (file)
index 7674d2f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Automatik",
-            "Benoit Rochon",
-            "Boniface",
-            "Brunoperel",
-            "Crochet.david",
-            "DavidL",
-            "Dereckson",
-            "Gomoko",
-            "Guillom",
-            "Hello71",
-            "Jean-Frédéric",
-            "Linedwell",
-            "Ltrlg",
-            "Metroitendo",
-            "NemesisIII",
-            "Nicolas NALLET",
-            "Npettiaux",
-            "Rastus Vernon",
-            "Seb35",
-            "Sherbrooke",
-            "Tpt",
-            "Trizek",
-            "Urhixidur",
-            "Verdy p",
-            "Wyz"
-        ]
-    },
-    "ooui-dialog-action-close": "Fermer",
-    "ooui-outline-control-move-down": "Faire descendre l’élément",
-    "ooui-outline-control-move-up": "Faire monter l’élément",
-    "ooui-outline-control-remove": "Supprimer l’élément",
-    "ooui-toolbar-more": "Plus"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/frr.json b/resources/oojs-ui/i18n/frr.json
deleted file mode 100644 (file)
index adf8ce8..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "ChrisPtDe",
-            "Murma174"
-        ]
-    },
-    "ooui-dialog-action-close": "Slütj",
-    "ooui-outline-control-move-down": "Element efter onern sküüw",
-    "ooui-outline-control-move-up": "Element efter boowen sküüw",
-    "ooui-outline-control-remove": "Element wechnem",
-    "ooui-toolbar-more": "Muar"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/fur.json b/resources/oojs-ui/i18n/fur.json
deleted file mode 100644 (file)
index 18ea383..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Klenje",
-            "Tocaibon"
-        ]
-    },
-    "ooui-dialog-action-close": "Siere",
-    "ooui-outline-control-move-down": "sposte sot",
-    "ooui-outline-control-move-up": "sposte in su",
-    "ooui-toolbar-more": "Altri"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/gl.json b/resources/oojs-ui/i18n/gl.json
deleted file mode 100644 (file)
index a029456..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Alison",
-            "Kscanne",
-            "Toliño"
-        ]
-    },
-    "ooui-dialog-action-close": "Pechar",
-    "ooui-outline-control-move-down": "Mover o elemento abaixo",
-    "ooui-outline-control-move-up": "Mover o elemento arriba",
-    "ooui-outline-control-remove": "Eliminar o elemento",
-    "ooui-toolbar-more": "Máis"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/gu.json b/resources/oojs-ui/i18n/gu.json
deleted file mode 100644 (file)
index ccabf8d..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ashok modhvadia",
-            "KartikMistry",
-            "The Discoverer"
-        ]
-    },
-    "ooui-dialog-action-close": "બંધ કરો",
-    "ooui-outline-control-move-down": "વસ્તુ નીચે ખસેડો",
-    "ooui-outline-control-move-up": "વસ્તુ ઉપર ખસેડો",
-    "ooui-outline-control-remove": "વસ્તુ હટાવો",
-    "ooui-toolbar-more": "વધુ"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/he.json b/resources/oojs-ui/i18n/he.json
deleted file mode 100644 (file)
index 404dc82..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Amire80",
-            "ExampleTomer",
-            "Guycn2",
-            "Matanya",
-            "Mooeypoo",
-            "Orsa",
-            "Shimmin Beg",
-            "אור שפירא",
-            "חיים",
-            "ערן",
-            "פוילישער",
-            "קיפודנחש"
-        ]
-    },
-    "ooui-dialog-action-close": "סגירה",
-    "ooui-outline-control-move-down": "להזיז את הפריט מטה",
-    "ooui-outline-control-move-up": "להזיז את הפריט מעלה",
-    "ooui-outline-control-remove": "הסרת פריט",
-    "ooui-toolbar-more": "עוד"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/hi.json b/resources/oojs-ui/i18n/hi.json
deleted file mode 100644 (file)
index ae895d1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ansumang",
-            "Devayon",
-            "Rajesh",
-            "Siddhartha Ghai",
-            "Goelujjwal"
-        ]
-    },
-    "ooui-dialog-action-close": "बंद करें",
-    "ooui-outline-control-move-down": "प्रविष्टि नीचे ले जाएँ",
-    "ooui-outline-control-move-up": "प्रविष्टि ऊपर ले जाएँ",
-    "ooui-outline-control-remove": "आइटम हटाएँ",
-    "ooui-toolbar-more": "अधिक"
-}
diff --git a/resources/oojs-ui/i18n/hr.json b/resources/oojs-ui/i18n/hr.json
deleted file mode 100644 (file)
index 1c3f925..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "MaGa",
-            "Roberta F.",
-            "SpeedyGonsales"
-        ]
-    },
-    "ooui-dialog-action-close": "zatvori",
-    "ooui-outline-control-move-down": "Premjesti stavku dolje",
-    "ooui-outline-control-move-up": "Premjesti stavku gore",
-    "ooui-toolbar-more": "Više mogućnosti"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/hsb.json b/resources/oojs-ui/i18n/hsb.json
deleted file mode 100644 (file)
index f674cd2..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "J budissin",
-            "Michawiki"
-        ]
-    },
-    "ooui-dialog-action-close": "Začinić",
-    "ooui-outline-control-move-down": "Zapisk dele přesunyć",
-    "ooui-outline-control-move-up": "Zapisk horje přesunyć",
-    "ooui-outline-control-remove": "Zapisk wotstronić",
-    "ooui-toolbar-more": "Wjace"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/hu.json b/resources/oojs-ui/i18n/hu.json
deleted file mode 100644 (file)
index b2cf2c0..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Dj",
-            "Einstein2",
-            "Misibacsi",
-            "ViDam",
-            "Tacsipacsi"
-        ]
-    },
-    "ooui-dialog-action-close": "Bezár",
-    "ooui-outline-control-move-down": "Elem mozgatása lefelé",
-    "ooui-outline-control-move-up": "Elem mozgatása felfelé",
-    "ooui-outline-control-remove": "Elem eltávolítása",
-    "ooui-toolbar-more": "Tovább..."
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/hy.json b/resources/oojs-ui/i18n/hy.json
deleted file mode 100644 (file)
index 4cb8821..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Vacio",
-            "Xelgen"
-        ]
-    },
-    "ooui-dialog-action-close": "Փակել",
-    "ooui-outline-control-move-down": "Իջեցնել կետը",
-    "ooui-outline-control-move-up": "Բարձրացնել կետը",
-    "ooui-outline-control-remove": "Հեռացնել տարրը",
-    "ooui-toolbar-more": "Ավելին"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ia.json b/resources/oojs-ui/i18n/ia.json
deleted file mode 100644 (file)
index e335553..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "McDutchie"
-        ]
-    },
-    "ooui-dialog-action-close": "Clauder"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/id.json b/resources/oojs-ui/i18n/id.json
deleted file mode 100644 (file)
index 6d3ba4d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Farras",
-            "Ilham151096",
-            "Iwan Novirion",
-            "Iyan",
-            "Kenrick95",
-            "McDutchie",
-            "Rv77ax",
-            "William Surya Permana"
-        ]
-    },
-    "ooui-dialog-action-close": "Tutup",
-    "ooui-outline-control-move-down": "Pindahkan butir ke bawah",
-    "ooui-outline-control-move-up": "Pindahkan butir ke atas",
-    "ooui-toolbar-more": "Lainnya"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ie.json b/resources/oojs-ui/i18n/ie.json
deleted file mode 100644 (file)
index 84d002d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Makuba"
-        ]
-    },
-    "ooui-dialog-action-close": "Terminar",
-    "ooui-outline-control-move-down": "Mover element a infra",
-    "ooui-outline-control-move-up": "Mover element a supra",
-    "ooui-toolbar-more": "Plu"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ilo.json b/resources/oojs-ui/i18n/ilo.json
deleted file mode 100644 (file)
index 838face..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Lam-ang"
-        ]
-    },
-    "ooui-dialog-action-close": "Irekep",
-    "ooui-outline-control-move-down": "Ipababa ti banag",
-    "ooui-outline-control-move-up": "Ipangato ti banag",
-    "ooui-outline-control-remove": "Ikkaten ti banag",
-    "ooui-toolbar-more": "Adu pay"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/is.json b/resources/oojs-ui/i18n/is.json
deleted file mode 100644 (file)
index fbdb5d1..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Maxí",
-            "Snævar"
-        ]
-    },
-    "ooui-dialog-action-close": "Loka",
-    "ooui-outline-control-move-down": "Færa atriði niður",
-    "ooui-outline-control-move-up": "Færa atriði upp",
-    "ooui-toolbar-more": "Fleira"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/it.json b/resources/oojs-ui/i18n/it.json
deleted file mode 100644 (file)
index 747ec79..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Beta16",
-            "Darth Kule",
-            "Doc.mari",
-            "Eleonora negri",
-            "Elitre",
-            "F. Cosoleto",
-            "FRacco",
-            "Gianfranco",
-            "Minerva Titani",
-            "Raoli",
-            "Una giornata uggiosa '94"
-        ]
-    },
-    "ooui-dialog-action-close": "Chiudi",
-    "ooui-outline-control-move-down": "Sposta in basso",
-    "ooui-outline-control-move-up": "Sposta in alto",
-    "ooui-outline-control-remove": "Rimuovi elemento",
-    "ooui-toolbar-more": "Altro"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ja.json b/resources/oojs-ui/i18n/ja.json
deleted file mode 100644 (file)
index c7c0851..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Fryed-peach",
-            "Miya",
-            "Penn Station",
-            "Shirayuki"
-        ]
-    },
-    "ooui-dialog-action-close": "閉じる",
-    "ooui-outline-control-move-down": "項目を下に移動させる",
-    "ooui-outline-control-move-up": "項目を上に移動させる",
-    "ooui-outline-control-remove": "項目を除去",
-    "ooui-toolbar-more": "その他"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/jv.json b/resources/oojs-ui/i18n/jv.json
deleted file mode 100644 (file)
index a362079..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Gleki",
-            "NoiX180",
-            "Pras"
-        ]
-    },
-    "ooui-dialog-action-close": "Tutup",
-    "ooui-outline-control-move-down": "Pindhahaken butir mangandhap"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ka.json b/resources/oojs-ui/i18n/ka.json
deleted file mode 100644 (file)
index c9d2774..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "BRUTE",
-            "David1010",
-            "Gleki",
-            "ITshnik",
-            "MIKHEIL",
-            "NoiX180",
-            "Pras",
-            "Tokoko"
-        ]
-    },
-    "ooui-dialog-action-close": "დახურვა",
-    "ooui-outline-control-move-down": "ელემენტის ქვემოთ გადატანა",
-    "ooui-outline-control-move-up": "ელემენტის ზემოთ გადატანა",
-    "ooui-toolbar-more": "მეტი"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/kk-cyrl.json b/resources/oojs-ui/i18n/kk-cyrl.json
deleted file mode 100644 (file)
index 7213dad..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Arystanbek"
-        ]
-    },
-    "ooui-dialog-action-close": "Жабу",
-    "ooui-outline-control-move-down": "Элементті төмен жылжыту",
-    "ooui-outline-control-move-up": "Элементті жоғары жылжыту",
-    "ooui-outline-control-remove": "Элементті алып тастау",
-    "ooui-toolbar-more": "толығырақ"
-}
diff --git a/resources/oojs-ui/i18n/km.json b/resources/oojs-ui/i18n/km.json
deleted file mode 100644 (file)
index 2013ee3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Sovichet"
-        ]
-    },
-    "ooui-dialog-action-close": "បិទ",
-    "ooui-outline-control-move-down": "រុញ​ទៅ​ក្រោម",
-    "ooui-outline-control-move-up": "រុញ​ទៅ​លើ",
-    "ooui-toolbar-more": "បន្ថែម"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/kn.json b/resources/oojs-ui/i18n/kn.json
deleted file mode 100644 (file)
index 4932f6d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Vikassy"
-        ]
-    },
-    "ooui-dialog-action-close": "ಮುಚ್ಚಿ",
-    "ooui-outline-control-remove": "ವಸ್ತು ತೆಗೆ",
-    "ooui-toolbar-more": "ಹೆಚ್ಚು"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ko.json b/resources/oojs-ui/i18n/ko.json
deleted file mode 100644 (file)
index 25749ce..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Freebiekr",
-            "Hym411",
-            "Kwj2772",
-            "LFM",
-            "아라"
-        ]
-    },
-    "ooui-dialog-action-close": "닫기",
-    "ooui-outline-control-move-down": "항목을 아래로 옮기기",
-    "ooui-outline-control-move-up": "항목을 위로 옮기기",
-    "ooui-outline-control-remove": "항목 지우기",
-    "ooui-toolbar-more": "더 보기"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/krc.json b/resources/oojs-ui/i18n/krc.json
deleted file mode 100644 (file)
index f629139..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Iltever"
-        ]
-    },
-    "ooui-dialog-action-close": "Джаб",
-    "ooui-outline-control-move-down": "Элементни тюбюне кёчюр",
-    "ooui-outline-control-move-up": "Элементни башына кёчюр"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/kw.json b/resources/oojs-ui/i18n/kw.json
deleted file mode 100644 (file)
index 95a9b91..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "George Animal",
-            "Nrowe",
-            "Purodha"
-        ]
-    },
-    "ooui-dialog-action-close": "Degea"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ky.json b/resources/oojs-ui/i18n/ky.json
deleted file mode 100644 (file)
index 2d62bda..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Chorobek",
-            "George Animal",
-            "Nrowe",
-            "Tynchtyk Chorotegin",
-            "Викиней"
-        ]
-    },
-    "ooui-dialog-action-close": "Жабуу"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/lb.json b/resources/oojs-ui/i18n/lb.json
deleted file mode 100644 (file)
index 6359026..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Autokrator",
-            "Chorobek",
-            "Robby",
-            "Soued031",
-            "Tynchtyk Chorotegin",
-            "UV",
-            "Викиней"
-        ]
-    },
-    "ooui-dialog-action-close": "Zoumaachen",
-    "ooui-outline-control-move-down": "Element erof réckelen",
-    "ooui-outline-control-move-up": "Element erop réckelen",
-    "ooui-outline-control-remove": "Element ewechhuelen",
-    "ooui-toolbar-more": "Méi"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/lmo.json b/resources/oojs-ui/i18n/lmo.json
deleted file mode 100644 (file)
index e506b7a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ninonino"
-        ]
-    },
-    "ooui-dialog-action-close": "Sèra",
-    "ooui-outline-control-move-down": "Spòsta 'n zó",
-    "ooui-outline-control-move-up": "Spòsta 'n sö",
-    "ooui-toolbar-more": "Amò"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/lt.json b/resources/oojs-ui/i18n/lt.json
deleted file mode 100644 (file)
index db679bc..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Audriusa",
-            "Eitvys200",
-            "Mantak111"
-        ]
-    },
-    "ooui-dialog-action-close": "Uždaryti",
-    "ooui-outline-control-remove": "Šalinti elementus"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/lv.json b/resources/oojs-ui/i18n/lv.json
deleted file mode 100644 (file)
index c633339..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Admresdeserv.",
-            "Audriusa",
-            "Eitvys200",
-            "Papuass",
-            "PeterisP"
-        ]
-    },
-    "ooui-dialog-action-close": "Aizvērt",
-    "ooui-outline-control-move-down": "Pārvietot vienumu uz leju",
-    "ooui-outline-control-move-up": "Pārvietot vienumu uz augšu",
-    "ooui-toolbar-more": "Vairāk"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/mg.json b/resources/oojs-ui/i18n/mg.json
deleted file mode 100644 (file)
index dcb5fd5..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Jagwar"
-        ]
-    },
-    "ooui-dialog-action-close": "Hidiana"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/min.json b/resources/oojs-ui/i18n/min.json
deleted file mode 100644 (file)
index 55174c0..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Iwan Novirion",
-            "Jagwar"
-        ]
-    },
-    "ooui-dialog-action-close": "Tutuik"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/mk.json b/resources/oojs-ui/i18n/mk.json
deleted file mode 100644 (file)
index 22fd037..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Bjankuloski06",
-            "Brest",
-            "Iwan Novirion"
-        ]
-    },
-    "ooui-dialog-action-close": "Затвори",
-    "ooui-outline-control-move-down": "Помести надолу",
-    "ooui-outline-control-move-up": "Помести нагоре",
-    "ooui-outline-control-remove": "Отстрани ставка",
-    "ooui-toolbar-more": "Повеќе"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ml.json b/resources/oojs-ui/i18n/ml.json
deleted file mode 100644 (file)
index 355e337..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Kavya Manohar",
-            "Praveenp",
-            "Santhosh.thottingal",
-            "Vssun"
-        ]
-    },
-    "ooui-dialog-action-close": "അടയ്ക്കുക",
-    "ooui-outline-control-move-down": "ഇനം താഴേയ്ക്ക് മാറ്റുക",
-    "ooui-outline-control-move-up": "ഇനം മുകളിലേയ്ക്ക് മാറ്റുക",
-    "ooui-toolbar-more": "കൂടുതൽ"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/mr.json b/resources/oojs-ui/i18n/mr.json
deleted file mode 100644 (file)
index d4db84f..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Kaajawa",
-            "Mahitgar",
-            "Praju23",
-            "V.narsikar",
-            "Ydyashad",
-            "संतोष दहिवळ"
-        ]
-    },
-    "ooui-dialog-action-close": "बंद करा",
-    "ooui-outline-control-move-down": "घटक (आयटम) खाली सरकवा",
-    "ooui-outline-control-move-up": "घटक (आयटम) वर सरकवा",
-    "ooui-toolbar-more": "अधिक"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ms.json b/resources/oojs-ui/i18n/ms.json
deleted file mode 100644 (file)
index 4f78aaa..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Anakmalaysia",
-            "Aurora"
-        ]
-    },
-    "ooui-dialog-action-close": "Tutup",
-    "ooui-outline-control-move-down": "Alihkan perkara ke bawah",
-    "ooui-outline-control-move-up": "Alihkan perkara ke atas",
-    "ooui-outline-control-remove": "Buang perkara",
-    "ooui-toolbar-more": "Selebihnya"
-}
diff --git a/resources/oojs-ui/i18n/nap.json b/resources/oojs-ui/i18n/nap.json
deleted file mode 100644 (file)
index 6b0b3ec..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Chelin",
-            "Chrisportelli",
-            "PiRSquared17"
-        ]
-    },
-    "ooui-dialog-action-close": "Chiure",
-    "ooui-toolbar-more": "Atro"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/nb.json b/resources/oojs-ui/i18n/nb.json
deleted file mode 100644 (file)
index 7cdecaa..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Danmichaelo",
-            "Event",
-            "Jeblad",
-            "Laaknor",
-            "Njardarlogar"
-        ]
-    },
-    "ooui-dialog-action-close": "Lukk",
-    "ooui-outline-control-move-down": "Flytt ned",
-    "ooui-outline-control-move-up": "Flytt opp",
-    "ooui-toolbar-more": "Mer"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/nds-nl.json b/resources/oojs-ui/i18n/nds-nl.json
deleted file mode 100644 (file)
index 81f8a43..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Servien"
-        ]
-    },
-    "ooui-dialog-action-close": "Sluten",
-    "ooui-outline-control-move-down": "Onderwarp ummeneer zetten",
-    "ooui-outline-control-move-up": "Onderwarp umhoge zetten"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/nds.json b/resources/oojs-ui/i18n/nds.json
deleted file mode 100644 (file)
index d0806d0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Zylbath"
-        ]
-    },
-    "ooui-dialog-action-close": "Dichtmaken",
-    "ooui-outline-control-move-down": "Element na ünnen schuven",
-    "ooui-outline-control-move-up": "Element na baven schuven",
-    "ooui-toolbar-more": "Mehr"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ne.json b/resources/oojs-ui/i18n/ne.json
deleted file mode 100644 (file)
index ae948c6..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "RajeshPandey",
-            "सरोज कुमार ढकाल"
-        ]
-    }
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/nl.json b/resources/oojs-ui/i18n/nl.json
deleted file mode 100644 (file)
index 549fad2..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Bluyten",
-            "Breghtje",
-            "Catrope",
-            "Flightmare",
-            "Hansmuller",
-            "Jdforrester",
-            "Keegan",
-            "Konovalov",
-            "RajeshPandey",
-            "Romaine",
-            "SPQRobin",
-            "Saruman",
-            "Siebrand",
-            "Southparkfan",
-            "सरोज कुमार ढकाल",
-            "Sjoerddebruin"
-        ]
-    },
-    "ooui-dialog-action-close": "Sluiten",
-    "ooui-outline-control-move-down": "Item omlaag verplaatsen",
-    "ooui-outline-control-move-up": "Item omhoog verplaatsen",
-    "ooui-outline-control-remove": "Item verwijderen",
-    "ooui-toolbar-more": "Meer"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/nn.json b/resources/oojs-ui/i18n/nn.json
deleted file mode 100644 (file)
index dd86f5e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Jeblad",
-            "Njardarlogar"
-        ]
-    },
-    "ooui-dialog-action-close": "Lat att",
-    "ooui-outline-control-move-down": "Flytt element ned",
-    "ooui-outline-control-move-up": "Flytt element opp",
-    "ooui-toolbar-more": "Fleire"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/om.json b/resources/oojs-ui/i18n/om.json
deleted file mode 100644 (file)
index cd22c40..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cedric31",
-            "Tumsaa"
-        ]
-    },
-    "ooui-dialog-action-close": "Cufi",
-    "ooui-outline-control-move-down": "Gad buusi",
-    "ooui-outline-control-move-up": "Ol baasi",
-    "ooui-outline-control-remove": "Balleessi",
-    "ooui-toolbar-more": "Dabalata"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/or.json b/resources/oojs-ui/i18n/or.json
deleted file mode 100644 (file)
index 35721a1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Odisha1",
-            "Psubhashish",
-            "ଶିତିକଣ୍ଠ ଦାଶ"
-        ]
-    },
-    "ooui-dialog-action-close": "ବନ୍ଦ କରିବେ"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/pa.json b/resources/oojs-ui/i18n/pa.json
deleted file mode 100644 (file)
index 6c76d7f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Amikeco",
-            "Babanwalia",
-            "Bouron",
-            "Nasir8891"
-        ]
-    },
-    "ooui-dialog-action-close": "বন্ধ"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/pfl.json b/resources/oojs-ui/i18n/pfl.json
deleted file mode 100644 (file)
index 40cc15d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Manuae"
-        ]
-    },
-    "ooui-dialog-action-close": "Schließe",
-    "ooui-outline-control-move-down": "Bweeschs nunna",
-    "ooui-outline-control-move-up": "Bweeschs nuff",
-    "ooui-outline-control-remove": "Leschs",
-    "ooui-toolbar-more": "Mea"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/pl.json b/resources/oojs-ui/i18n/pl.json
deleted file mode 100644 (file)
index 2cb7330..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Babanwalia",
-            "Chrumps",
-            "Matma Rex",
-            "Mikołka",
-            "Nasir8891",
-            "Odie2",
-            "Rzuwig",
-            "Tar Lócesilion",
-            "Ty221",
-            "WTM",
-            "Woytecr",
-            "Wpedzich",
-            "Jacenty359"
-        ]
-    },
-    "ooui-dialog-action-close": "Zamknij",
-    "ooui-outline-control-move-down": "Przenieś niżej",
-    "ooui-outline-control-move-up": "Przenieś wyżej",
-    "ooui-outline-control-remove": "Usuń element",
-    "ooui-toolbar-more": "Więcej"
-}
diff --git a/resources/oojs-ui/i18n/pms.json b/resources/oojs-ui/i18n/pms.json
deleted file mode 100644 (file)
index bb8f113..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Borichèt",
-            "Dragonòt",
-            "පසිඳු කාවින්ද"
-        ]
-    },
-    "ooui-dialog-action-close": "Saré",
-    "ooui-outline-control-move-down": "Fé calé giù l'element",
-    "ooui-outline-control-move-up": "Fé monté l'element",
-    "ooui-toolbar-more": "Ëd pi"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ps.json b/resources/oojs-ui/i18n/ps.json
deleted file mode 100644 (file)
index 4f21707..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ahmed-Najib-Biabani-Ibrahimkhel"
-        ]
-    },
-    "ooui-dialog-action-close": "تړل",
-    "ooui-outline-control-move-down": "توکی ښکته راوړل",
-    "ooui-outline-control-move-up": "توکی پورته راوړل",
-    "ooui-toolbar-more": "نور"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/pt-br.json b/resources/oojs-ui/i18n/pt-br.json
deleted file mode 100644 (file)
index f758660..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cainamarques",
-            "Dianakc",
-            "Fúlvio",
-            "Helder.wiki",
-            "HenriqueCrang",
-            "Jaideraf",
-            "Luckas",
-            "OTAVIO1981",
-            555
-        ]
-    },
-    "ooui-dialog-action-close": "Fechar",
-    "ooui-outline-control-move-down": "Mover item para baixo",
-    "ooui-outline-control-move-up": "Mover item para cima",
-    "ooui-toolbar-more": "Mais"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/pt.json b/resources/oojs-ui/i18n/pt.json
deleted file mode 100644 (file)
index 53b5280..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cainamarques",
-            "Fúlvio",
-            "GoEThe",
-            "Hamilton Abreu",
-            "Helder.wiki",
-            "Jaideraf",
-            "Jdforrester",
-            "Luckas",
-            "Vitorvicentevalente",
-            "SandroHc"
-        ]
-    },
-    "ooui-dialog-action-close": "Fechar",
-    "ooui-outline-control-move-down": "Mover item para baixo",
-    "ooui-outline-control-move-up": "Mover item para cima",
-    "ooui-outline-control-remove": "Remover elemento",
-    "ooui-toolbar-more": "Mais"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/qqq.json b/resources/oojs-ui/i18n/qqq.json
deleted file mode 100644 (file)
index 75bbec4..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Amire80",
-            "Beta16",
-            "Erik Moeller",
-            "Jdforrester",
-            "Lloffiwr",
-            "Mooeypoo",
-            "Mormegil",
-            "Nike",
-            "PoLuX124",
-            "Purodha",
-            "Raymond",
-            "Sagan",
-            "Sayak Sarkar",
-            "Shirayuki",
-            "Siebrand",
-            "Trevor Parscal"
-        ]
-    },
-    "ooui-dialog-action-close": "Label text for button to exit from dialog.\n\n{{Identical|Close}}",
-    "ooui-outline-control-move-down": "Tool tip for a button that moves items in a list down one place",
-    "ooui-outline-control-move-up": "Tool tip for a button that moves items in a list up one place",
-    "ooui-outline-control-remove": "Tool tip for a button that removes items from a list.\n{{Identical|Remove item}}",
-    "ooui-toolbar-more": "Label for the toolbar group that contains a list of all other available tools.\n{{Identical|More}}"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/qu.json b/resources/oojs-ui/i18n/qu.json
deleted file mode 100644 (file)
index 4442528..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "AlimanRuna",
-            "Jduranboger"
-        ]
-    },
-    "ooui-dialog-action-close": "Wichq'ay",
-    "ooui-outline-control-move-down": "Qallawata uraykuchiy",
-    "ooui-outline-control-move-up": "Qallawata huqariy",
-    "ooui-outline-control-remove": "P'anqa sutikunata qichuy",
-    "ooui-toolbar-more": "Aswan"
-}
diff --git a/resources/oojs-ui/i18n/ro.json b/resources/oojs-ui/i18n/ro.json
deleted file mode 100644 (file)
index 4892975..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "AlimanRuna",
-            "Firilacroco",
-            "Minisarm",
-            "Stelistcristi"
-        ]
-    },
-    "ooui-dialog-action-close": "Închide",
-    "ooui-outline-control-move-down": "Mută elementul mai jos",
-    "ooui-outline-control-move-up": "Mută elementul mai sus",
-    "ooui-outline-control-remove": "Elimină elementul",
-    "ooui-toolbar-more": "Mai mult"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/roa-tara.json b/resources/oojs-ui/i18n/roa-tara.json
deleted file mode 100644 (file)
index c7699d6..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Joetaras"
-        ]
-    },
-    "ooui-dialog-action-close": "Achiude",
-    "ooui-outline-control-move-down": "Spuèste 'a vôsce sotte",
-    "ooui-outline-control-move-up": "Spuèste 'a vôsce sus",
-    "ooui-toolbar-more": "De cchiù"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ru.json b/resources/oojs-ui/i18n/ru.json
deleted file mode 100644 (file)
index f6e76a6..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Amire80",
-            "DR",
-            "Eugrus",
-            "Iluvatar",
-            "KPu3uC B Poccuu",
-            "Kalan",
-            "MaxBioHazard",
-            "NBS",
-            "Niklem",
-            "Okras",
-            "Ole Yves",
-            "Putnik",
-            "Sunpriat",
-            "Yury Katkov",
-            "Умар"
-        ]
-    },
-    "ooui-dialog-action-close": "Закрыть",
-    "ooui-outline-control-move-down": "Переместить элемент вниз",
-    "ooui-outline-control-move-up": "Переместить элемент вверх",
-    "ooui-outline-control-remove": "Удалить пункт",
-    "ooui-toolbar-more": "Ещё"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sah.json b/resources/oojs-ui/i18n/sah.json
deleted file mode 100644 (file)
index 9b3fcc8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Gazeb",
-            "HalanTul"
-        ]
-    },
-    "ooui-dialog-action-close": "Сап"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/scn.json b/resources/oojs-ui/i18n/scn.json
deleted file mode 100644 (file)
index a699911..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Gazeb",
-            "Gmelfi",
-            "HalanTul"
-        ]
-    },
-    "ooui-dialog-action-close": "Chiùi",
-    "ooui-outline-control-move-down": "Sposta di sutta",
-    "ooui-outline-control-move-up": "Sposta di supra",
-    "ooui-toolbar-more": "Àutri cosi"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sco.json b/resources/oojs-ui/i18n/sco.json
deleted file mode 100644 (file)
index f8dc77c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "John Reid"
-        ]
-    },
-    "ooui-dialog-action-close": "Claise",
-    "ooui-outline-control-move-down": "Muiv eetem doon",
-    "ooui-outline-control-move-up": "Muiv eetem up",
-    "ooui-outline-control-remove": "Remuiv eitem",
-    "ooui-toolbar-more": "Mair"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sh.json b/resources/oojs-ui/i18n/sh.json
deleted file mode 100644 (file)
index 5e29980..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "OC Ripper"
-        ]
-    },
-    "ooui-dialog-action-close": "Zatvori",
-    "ooui-outline-control-move-down": "Pomakni stavku dolje",
-    "ooui-outline-control-move-up": "Pomakni stavku gore"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/si.json b/resources/oojs-ui/i18n/si.json
deleted file mode 100644 (file)
index cf7a9fd..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Singhalawap",
-            "පසිඳු කාවින්ද",
-            "ශ්වෙත"
-        ]
-    },
-    "ooui-dialog-action-close": "නිමවන්න",
-    "ooui-outline-control-move-down": "අයිතමය පහලටදමන්න",
-    "ooui-outline-control-move-up": "අයිතමය ඉහලටදමන්න"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sk.json b/resources/oojs-ui/i18n/sk.json
deleted file mode 100644 (file)
index 60b6f43..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Mimarik",
-            "Teslaton"
-        ]
-    },
-    "ooui-dialog-action-close": "Zatvoriť",
-    "ooui-outline-control-move-down": "Posunúť položku nadol",
-    "ooui-outline-control-move-up": "Posunúť položku nahor",
-    "ooui-toolbar-more": "Viac"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sl.json b/resources/oojs-ui/i18n/sl.json
deleted file mode 100644 (file)
index b14d47b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Dbc334",
-            "Eleassar",
-            "Pinky sl",
-            "Yerpo"
-        ]
-    },
-    "ooui-dialog-action-close": "Zapri",
-    "ooui-outline-control-move-down": "Prestavi predmet nižje",
-    "ooui-outline-control-move-up": "Prestavi predmet višje",
-    "ooui-outline-control-remove": "Odstrani vnos",
-    "ooui-toolbar-more": "Več"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sq.json b/resources/oojs-ui/i18n/sq.json
deleted file mode 100644 (file)
index 24a5af2..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Euriditi",
-            "Kushtrim",
-            "Elioqoshi"
-        ]
-    },
-    "ooui-dialog-action-close": "Mbylle",
-    "ooui-outline-control-move-down": "Zhvendose artikullin më poshtë",
-    "ooui-outline-control-move-up": "Zhvendose artikullin më lart",
-    "ooui-outline-control-remove": "Hiq artikullin",
-    "ooui-toolbar-more": "Më tepër..."
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sr-ec.json b/resources/oojs-ui/i18n/sr-ec.json
deleted file mode 100644 (file)
index 7eaaacd..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Milicevic01",
-            "Nikola Smolenski",
-            "Милан Јелисавчић"
-        ]
-    },
-    "ooui-dialog-action-close": "Затвори",
-    "ooui-outline-control-move-down": "Премести ставку на доле",
-    "ooui-outline-control-move-up": "Премести ставку на горе",
-    "ooui-outline-control-remove": "Уклони ставку",
-    "ooui-toolbar-more": "Више"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sv.json b/resources/oojs-ui/i18n/sv.json
deleted file mode 100644 (file)
index f7d6f04..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ainali",
-            "Haxpett",
-            "Jopparn",
-            "Knuckles",
-            "Magol",
-            "Milicevic01",
-            "Per",
-            "Sendelbach",
-            "Skalman",
-            "WikiPhoenix",
-            "Lokal Profil"
-        ]
-    },
-    "ooui-dialog-action-close": "Stäng",
-    "ooui-outline-control-move-down": "Flytta ned objekt",
-    "ooui-outline-control-move-up": "Flytta upp objekt",
-    "ooui-outline-control-remove": "Ta bort objekt",
-    "ooui-toolbar-more": "Mer"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sw.json b/resources/oojs-ui/i18n/sw.json
deleted file mode 100644 (file)
index 1c61b06..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Lloffiwr",
-            "Muddyb Blast Producer"
-        ]
-    },
-    "ooui-dialog-action-close": "Funga",
-    "ooui-outline-control-move-down": "Sogeza kipengee chini",
-    "ooui-outline-control-move-up": "Sogeza kipengee juu",
-    "ooui-toolbar-more": "Zaidi"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ta.json b/resources/oojs-ui/i18n/ta.json
deleted file mode 100644 (file)
index a9795fd..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Jayarathina",
-            "Sank",
-            "Shanmugamp7",
-            "மதனாஹரன்"
-        ]
-    },
-    "ooui-dialog-action-close": "மூடுக"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/te.json b/resources/oojs-ui/i18n/te.json
deleted file mode 100644 (file)
index a1f1285..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Arjunaraoc",
-            "Jayarathina",
-            "Sank",
-            "Shanmugamp7",
-            "Veeven",
-            "Visdaviva",
-            "மதனாஹரன்"
-        ]
-    },
-    "ooui-dialog-action-close": "మూయి"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/th.json b/resources/oojs-ui/i18n/th.json
deleted file mode 100644 (file)
index b7ee05a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Supasate",
-            "Taweetham"
-        ]
-    },
-    "ooui-dialog-action-close": "ปิด",
-    "ooui-outline-control-move-down": "เลื่อนรายการลง",
-    "ooui-outline-control-move-up": "ย้ายรายการขึ้น"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/tl.json b/resources/oojs-ui/i18n/tl.json
deleted file mode 100644 (file)
index a073882..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "AnakngAraw",
-            "Sky Harbor"
-        ]
-    },
-    "ooui-dialog-action-close": "Isara",
-    "ooui-outline-control-move-down": "Ilipat ang aytem pababa",
-    "ooui-outline-control-move-up": "Ilipat ang aytem pataas",
-    "ooui-toolbar-more": "Marami pa"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/tr.json b/resources/oojs-ui/i18n/tr.json
deleted file mode 100644 (file)
index 94d34a2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Emperyan",
-            "Incelemeelemani",
-            "LuCKY",
-            "Maidis",
-            "Rapsar",
-            "Talha Samil Cakir",
-            "TurkishStyles"
-        ]
-    },
-    "ooui-dialog-action-close": "Kapat",
-    "ooui-outline-control-move-down": "Ögeyi aşağı taşı",
-    "ooui-outline-control-move-up": "Ögeyi yukarı taşı",
-    "ooui-toolbar-more": "Daha fazla"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/tt-cyrl.json b/resources/oojs-ui/i18n/tt-cyrl.json
deleted file mode 100644 (file)
index 1c0bd90..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ajdar"
-        ]
-    },
-    "ooui-dialog-action-close": "Ябу",
-    "ooui-outline-control-move-down": "Элементны аска күчерү",
-    "ooui-outline-control-move-up": "Элементны өскә күчерү"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ug-arab.json b/resources/oojs-ui/i18n/ug-arab.json
deleted file mode 100644 (file)
index efba086..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Sahran",
-            "Tel'et",
-            "Tifinaghes"
-        ]
-    }
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/uk.json b/resources/oojs-ui/i18n/uk.json
deleted file mode 100644 (file)
index 42487c9..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "AS",
-            "Aced",
-            "Ahonc",
-            "Andriykopanytsia",
-            "Base",
-            "Perohanych",
-            "RLuts",
-            "Sahran",
-            "Sergento",
-            "Steve.rusyn",
-            "SteveR",
-            "Tel'et",
-            "Tifinaghes",
-            "Ата"
-        ]
-    },
-    "ooui-dialog-action-close": "Закрити",
-    "ooui-outline-control-move-down": "Перемістити елемент униз",
-    "ooui-outline-control-move-up": "Перемістити елемент вгору",
-    "ooui-outline-control-remove": "Видалити елемент",
-    "ooui-toolbar-more": "Більше"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/uz.json b/resources/oojs-ui/i18n/uz.json
deleted file mode 100644 (file)
index 473fc75..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "CoderSI",
-            "Noor2020",
-            "Sociologist",
-            "පසිඳු කාවින්ද"
-        ]
-    },
-    "ooui-dialog-action-close": "Yopish",
-    "ooui-outline-control-move-down": "Elementni pastga koʻchirish",
-    "ooui-outline-control-move-up": "Elementni yuqoriga koʻchirish",
-    "ooui-toolbar-more": "Yana"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/vec.json b/resources/oojs-ui/i18n/vec.json
deleted file mode 100644 (file)
index 01833f7..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Candalua",
-            "GatoSelvadego"
-        ]
-    },
-    "ooui-dialog-action-close": "Sara",
-    "ooui-outline-control-move-down": "Sposta in baso",
-    "ooui-outline-control-move-up": "Sposta in sima",
-    "ooui-toolbar-more": "Altro"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/vi.json b/resources/oojs-ui/i18n/vi.json
deleted file mode 100644 (file)
index 342ad6f..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cheers!",
-            "Jdforrester",
-            "Minh Nguyen"
-        ]
-    },
-    "ooui-dialog-action-close": "Đóng",
-    "ooui-outline-control-move-down": "Chuyển mục xuống",
-    "ooui-outline-control-move-up": "Chuyển mục lên",
-    "ooui-outline-control-remove": "Xóa khoản",
-    "ooui-toolbar-more": "Thêm"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/vo.json b/resources/oojs-ui/i18n/vo.json
deleted file mode 100644 (file)
index 2ed7e2f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Malafaya"
-        ]
-    },
-    "ooui-dialog-action-close": "Färmükön",
-    "ooui-toolbar-more": "Pluikos"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/wuu.json b/resources/oojs-ui/i18n/wuu.json
deleted file mode 100644 (file)
index 72aa48b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Malafaya",
-            "十弌"
-        ]
-    },
-    "ooui-toolbar-more": "還多"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/yi.json b/resources/oojs-ui/i18n/yi.json
deleted file mode 100644 (file)
index ab5c510..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Malafaya",
-            "פוילישער",
-            "十弌"
-        ]
-    },
-    "ooui-dialog-action-close": "שליסן",
-    "ooui-outline-control-move-down": "רוקן עלעמענט אראפ",
-    "ooui-outline-control-move-up": "רוקן עלעמענט ארויף",
-    "ooui-toolbar-more": "נאך"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/yo.json b/resources/oojs-ui/i18n/yo.json
deleted file mode 100644 (file)
index f71d3dd..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Demmy"
-        ]
-    },
-    "ooui-dialog-action-close": "Ìpadé",
-    "ooui-outline-control-move-down": "Sún onítòún sí sàlẹ̀",
-    "ooui-outline-control-move-up": "Sún onítòún s'ókè",
-    "ooui-toolbar-more": "Míràn"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/zh-hans.json b/resources/oojs-ui/i18n/zh-hans.json
deleted file mode 100644 (file)
index e8041ca..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Anakmalaysia",
-            "Bencmq",
-            "Demmy",
-            "Hydra",
-            "Hzy980512",
-            "Liangent",
-            "Liuxinyu970226",
-            "Qiyue2001",
-            "Shirayuki",
-            "Shizhao",
-            "TianyinLee",
-            "Xiaomingyan",
-            "Yfdyh000",
-            "Zhangjintao",
-            "乌拉跨氪"
-        ]
-    },
-    "ooui-dialog-action-close": "关闭",
-    "ooui-outline-control-move-down": "下移项",
-    "ooui-outline-control-move-up": "上移项",
-    "ooui-outline-control-remove": "移除项",
-    "ooui-toolbar-more": "更多"
-}
diff --git a/resources/oojs-ui/i18n/zh-hant.json b/resources/oojs-ui/i18n/zh-hant.json
deleted file mode 100644 (file)
index 6e7b12e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Anakmalaysia",
-            "Ch.Andrew",
-            "Hydra",
-            "Justincheng12345",
-            "Liflon",
-            "Liuxinyu970226",
-            "Qiyue2001",
-            "Radish10cm",
-            "Shirayuki",
-            "Simon Shek",
-            "Spring Roll Conan",
-            "Waihorace"
-        ]
-    },
-    "ooui-dialog-action-close": "關閉",
-    "ooui-outline-control-move-down": "向下移項",
-    "ooui-outline-control-move-up": "向上移項",
-    "ooui-outline-control-remove": "移除項",
-    "ooui-toolbar-more": "更多"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/zh-hk.json b/resources/oojs-ui/i18n/zh-hk.json
deleted file mode 100644 (file)
index 60e8fbd..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "@metadata": [],
-    "ooui-dialog-action-close": "關閉"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/zh-tw.json b/resources/oojs-ui/i18n/zh-tw.json
deleted file mode 100644 (file)
index f7987e5..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-    "@metadata": [],
-    "ooui-dialog-action-close": "關閉",
-    "ooui-outline-control-move-down": "向下移",
-    "ooui-outline-control-move-up": "向上移",
-    "ooui-toolbar-more": "更多"
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/images/fade-down.png b/resources/oojs-ui/images/fade-down.png
deleted file mode 100644 (file)
index 50c7931..0000000
Binary files a/resources/oojs-ui/images/fade-down.png and /dev/null differ
diff --git a/resources/oojs-ui/images/fade-up.png b/resources/oojs-ui/images/fade-up.png
deleted file mode 100644 (file)
index 7a0cb87..0000000
Binary files a/resources/oojs-ui/images/fade-up.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/accept.png b/resources/oojs-ui/images/icons/accept.png
deleted file mode 100644 (file)
index 1075110..0000000
Binary files a/resources/oojs-ui/images/icons/accept.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/accept.svg b/resources/oojs-ui/images/icons/accept.svg
deleted file mode 100644 (file)
index df78186..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="apply" style="opacity:0.75;">
-       <polygon id="check" style="fill-rule:evenodd;clip-rule:evenodd;" points="19.062,5.139 17.418,4 8.867,16.357 5.413,12.903 4,14.316 9.021,19.338"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/add-item.png b/resources/oojs-ui/images/icons/add-item.png
deleted file mode 100644 (file)
index 5cf353f..0000000
Binary files a/resources/oojs-ui/images/icons/add-item.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/add-item.svg b/resources/oojs-ui/images/icons/add-item.svg
deleted file mode 100644 (file)
index 2620e76..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="apply" style="opacity:0.75;">
-       <path d="M13,8 L11,8 L11,11 L8,11 L8,13 L11,13 L11,16 L13,16 L13,13 L16,13 L16,11 L13,11 z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/advanced.png b/resources/oojs-ui/images/icons/advanced.png
deleted file mode 100644 (file)
index 7f5ada5..0000000
Binary files a/resources/oojs-ui/images/icons/advanced.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/advanced.svg b/resources/oojs-ui/images/icons/advanced.svg
deleted file mode 100644 (file)
index 3e87cab..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="settings" style="opacity:0.75;">
-       <path id="gear" style="fill-rule:evenodd;clip-rule:evenodd;" d="M20.869,13.476C20.948,12.994,21,12.504,21,12
-               s-0.052-0.994-0.131-1.476l-2.463-0.259c-0.149-0.556-0.367-1.082-0.648-1.57l1.558-1.924c-0.576-0.806-1.281-1.511-2.087-2.087
-               l-1.924,1.558c-0.488-0.281-1.015-0.499-1.57-0.648l-0.259-2.463C12.994,3.052,12.504,3,12,3s-0.994,0.052-1.476,0.131
-               l-0.259,2.463C9.71,5.743,9.184,5.961,8.695,6.242L6.771,4.685C5.966,5.261,5.261,5.966,4.685,6.771l1.558,1.924
-               c-0.281,0.488-0.499,1.015-0.648,1.57l-2.463,0.259C3.052,11.006,3,11.496,3,12s0.052,0.994,0.131,1.476l2.463,0.259
-               c0.149,0.556,0.367,1.082,0.648,1.57l-1.558,1.924c0.576,0.806,1.281,1.511,2.087,2.087l1.924-1.558
-               c0.488,0.281,1.015,0.499,1.57,0.648l0.259,2.463C11.006,20.948,11.496,21,12,21s0.994-0.052,1.476-0.131l0.259-2.463
-               c0.556-0.149,1.082-0.367,1.57-0.648l1.924,1.558c0.806-0.576,1.511-1.281,2.087-2.087l-1.558-1.924
-               c0.281-0.488,0.499-1.015,0.648-1.57L20.869,13.476z M12,15.998c-2.209,0-3.998-1.789-3.998-3.998S9.791,8.002,12,8.002
-               S15.998,9.791,15.998,12S14.209,15.998,12,15.998z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/alert.png b/resources/oojs-ui/images/icons/alert.png
deleted file mode 100644 (file)
index 992ea2a..0000000
Binary files a/resources/oojs-ui/images/icons/alert.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/alert.svg b/resources/oojs-ui/images/icons/alert.svg
deleted file mode 100644 (file)
index 886a7c0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="alert" style="opacity:0.75;">
-       <rect id="point" x="11" y="16" style="fill-rule:evenodd;clip-rule:evenodd;" width="2" height="2"/>
-       <polygon id="stroke" style="fill-rule:evenodd;clip-rule:evenodd;" points="13.516,10 10.516,10 11,15 13,15"/>
-       <path id="triangle" d="M12.017,5.974L19.536,19H4.496L12.017,5.974 M12.017,3.5c-0.544,0-1.088,0.357-1.5,1.071L2.532,18.402 C1.707,19.831,2.382,21,4.032,21H20c1.65,0,2.325-1.169,1.5-2.599L13.517,4.572C13.104,3.857,12.561,3.5,12.017,3.5L12.017,3.5z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/arched-arrow-ltr.png b/resources/oojs-ui/images/icons/arched-arrow-ltr.png
deleted file mode 100644 (file)
index 5db1c4d..0000000
Binary files a/resources/oojs-ui/images/icons/arched-arrow-ltr.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/arched-arrow-ltr.svg b/resources/oojs-ui/images/icons/arched-arrow-ltr.svg
deleted file mode 100644 (file)
index 5b343a5..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="arched-arrow-ltr" style="opacity:0.75;">
-       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M19.925,14.937l-2.391-6.901l-1.48,2.329 c-0.964-0.845-2.699-1.85-5.513-1.823c-4.887,0.046-6.524,4.244-6.524,4.244s2.753-2.639,6.925-1.949 c1.729,0.286,3.007,1.206,3.675,1.791l-1.474,2.319L19.925,14.937z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/arched-arrow-rtl.png b/resources/oojs-ui/images/icons/arched-arrow-rtl.png
deleted file mode 100644 (file)
index 7931971..0000000
Binary files a/resources/oojs-ui/images/icons/arched-arrow-rtl.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/arched-arrow-rtl.svg b/resources/oojs-ui/images/icons/arched-arrow-rtl.svg
deleted file mode 100644 (file)
index bb5f10e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="arched-arrow-rtl" style="opacity:0.75;">
-       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M13.401,8.542c-2.814-0.027-4.549,0.978-5.513,1.823 l-1.48-2.329l-2.391,6.901l6.782,0.009l-1.474-2.319c0.668-0.584,1.945-1.504,3.675-1.791c4.172-0.69,6.925,1.949,6.925,1.949 S18.288,8.588,13.401,8.542z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/check.png b/resources/oojs-ui/images/icons/check.png
deleted file mode 100644 (file)
index 82c3cb4..0000000
Binary files a/resources/oojs-ui/images/icons/check.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/check.svg b/resources/oojs-ui/images/icons/check.svg
deleted file mode 100644 (file)
index e67cd6c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
-  <g id="check">
-    <path d="M7.105,13.473 L8.527,12.05 L10.428,13.952 L15.238,7 L16.895,8.148 L10.635,17 z" fill="#000000"/>
-  </g>
-  <defs/>
-</svg>
diff --git a/resources/oojs-ui/images/icons/clear.png b/resources/oojs-ui/images/icons/clear.png
deleted file mode 100644 (file)
index 697dd62..0000000
Binary files a/resources/oojs-ui/images/icons/clear.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/clear.svg b/resources/oojs-ui/images/icons/clear.svg
deleted file mode 100644 (file)
index d83eb02..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="clear" style="opacity:0.75;">
-       <path id="circle_with_strike" style="fill-rule:evenodd;clip-rule:evenodd;" d="M11.999,5.022c-3.853,0-6.977,3.124-6.977,6.978 c0,3.853,3.124,6.978,6.977,6.978c3.854,0,6.979-3.125,6.979-6.978C18.978,8.146,15.853,5.022,11.999,5.022z M6.886,12 c0-1.092,0.572-3.25,0.93-2.929l7.113,7.113c0.488,0.525-1.837,0.931-2.93,0.931C9.174,17.114,6.886,14.824,6.886,12z M16.184,14.929L9.07,7.816c-0.445-0.483,1.837-0.931,2.929-0.931c2.827,0,5.115,2.289,5.115,5.114 C17.114,13.092,16.75,15.542,16.184,14.929z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/close.png b/resources/oojs-ui/images/icons/close.png
deleted file mode 100644 (file)
index f7eed9f..0000000
Binary files a/resources/oojs-ui/images/icons/close.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/close.svg b/resources/oojs-ui/images/icons/close.svg
deleted file mode 100644 (file)
index a0118c2..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="close" style="opacity:0.75;">
-       <polygon id="x" style="fill-rule:evenodd;clip-rule:evenodd;" points="18.717,6.697 17.303,5.283 12,10.586 6.697,5.283 5.283,6.697 10.586,12 5.283,17.303 6.697,18.717 12,13.414 17.303,18.717 18.717,17.303 13.414,12            "/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/code.png b/resources/oojs-ui/images/icons/code.png
deleted file mode 100644 (file)
index a5ebdbf..0000000
Binary files a/resources/oojs-ui/images/icons/code.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/code.svg b/resources/oojs-ui/images/icons/code.svg
deleted file mode 100644 (file)
index 6f1ed53..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-        width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
-<g id="code" opacity="0.75">
-       <path id="left-bracket" d="M4,12v-1h1c1,0,1,0,1-1V7.614C6,7.1,6.024,6.718,6.073,6.472C6.127,6.22,6.212,6.009,6.33,5.839
-               C6.534,5.56,6.803,5.364,7.138,5.255C7.473,5.14,8.01,5,8.973,5H10v1H9.248c-0.457,0-0.77,0.191-0.936,0.408
-               C8.145,6.623,8,6.853,8,7.476v1.857c0,0.729-0.041,1.18-0.244,1.493c-0.2,0.307-0.562,0.529-1.09,0.667
-               c0.535,0.155,0.9,0.385,1.096,0.688C7.961,12.484,8,12.938,8,13.665v1.862c0,0.619,0.145,0.848,0.312,1.062
-               c0.166,0.22,0.479,0.407,0.936,0.407L10,17l0,0v1H8.973c-0.963,0-1.5-0.133-1.835-0.248c-0.335-0.109-0.604-0.307-0.808-0.591
-               c-0.118-0.165-0.203-0.374-0.257-0.625C6.024,16.283,6,15.9,6,15.387V13c0-1,0-1-1-1H4z"/>
-       <use transform="matrix(-1,0,0,1,24,0)" id="right-bracket" x="0" y="0" width="24" height="24" xlink:href="#left-bracket" />
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/collapse.png b/resources/oojs-ui/images/icons/collapse.png
deleted file mode 100644 (file)
index 38b796f..0000000
Binary files a/resources/oojs-ui/images/icons/collapse.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/collapse.svg b/resources/oojs-ui/images/icons/collapse.svg
deleted file mode 100644 (file)
index a89cebf..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="collapse" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="6.697,15.714 12,10.412 17.303,15.714 18.717,14.3 12,7.583 5.283,14.3"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/comment.png b/resources/oojs-ui/images/icons/comment.png
deleted file mode 100644 (file)
index 9546455..0000000
Binary files a/resources/oojs-ui/images/icons/comment.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/comment.svg b/resources/oojs-ui/images/icons/comment.svg
deleted file mode 100644 (file)
index e052935..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="comment" style="opacity:0.75;">
-       <path id="speech_bubble" style="fill-rule:evenodd;clip-rule:evenodd;" d="M15,6H9C7.343,6,6,7.344,6,9v4c0,1.656,1.343,3,3,3v3 l3-3h3c1.657,0,3-1.344,3-3V9C18,7.344,16.657,6,15,6z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/expand.png b/resources/oojs-ui/images/icons/expand.png
deleted file mode 100644 (file)
index e90aca1..0000000
Binary files a/resources/oojs-ui/images/icons/expand.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/expand.svg b/resources/oojs-ui/images/icons/expand.svg
deleted file mode 100644 (file)
index b542f5f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="expand" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="17.303,8.283 12,13.586 6.697,8.283 5.283,9.697 12,16.414 18.717,9.697"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/help.png b/resources/oojs-ui/images/icons/help.png
deleted file mode 100644 (file)
index dca745b..0000000
Binary files a/resources/oojs-ui/images/icons/help.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/help.svg b/resources/oojs-ui/images/icons/help.svg
deleted file mode 100644 (file)
index c68bdda..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="help" style="opacity:0.75;">
-       <path id="circle" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12.001,2.085c-5.478,0-9.916,4.438-9.916,9.916 c0,5.476,4.438,9.914,9.916,9.914c5.476,0,9.914-4.438,9.914-9.914C21.915,6.523,17.477,2.085,12.001,2.085z M12.002,20.085 c-4.465,0-8.084-3.619-8.084-8.083c0-4.465,3.619-8.084,8.084-8.084c4.464,0,8.083,3.619,8.083,8.084 C20.085,16.466,16.466,20.085,12.002,20.085z"/>
-       <g id="question_mark">
-               <path id="top" style="fill-rule:evenodd;clip-rule:evenodd;" d="M11.766,6.688c-2.5,0-3.219,2.188-3.219,2.188l1.411,0.854 c0,0,0.298-0.791,0.901-1.229c0.516-0.375,1.625-0.625,2.219,0.125c0.701,0.885-0.17,1.587-1.078,2.719 C11.047,12.531,11,15,11,15h1.969c0,0,0.135-2.318,1.041-3.381c0.603-0.707,1.443-1.338,1.443-2.494S14.266,6.688,11.766,6.688z"/>
-               <rect id="bottom" x="11" y="16" style="fill-rule:evenodd;clip-rule:evenodd;" width="2" height="2"/>
-       </g>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/history.png b/resources/oojs-ui/images/icons/history.png
deleted file mode 100644 (file)
index c049931..0000000
Binary files a/resources/oojs-ui/images/icons/history.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/history.svg b/resources/oojs-ui/images/icons/history.svg
deleted file mode 100644 (file)
index 40c0ae3..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="history" style="opacity:0.75;">
-       <path id="clock_hands" style="fill-rule:evenodd;clip-rule:evenodd;" d="M17.26,15.076c0,0-2.385-1.935-4.005-3.062 c0.72-2.397,1.702-6.559,1.702-6.559s-4.35,5.363-4.877,6.699c-0.463,1.168,1.459,2.209,2.346,1.678 C14.326,14.383,17.26,15.076,17.26,15.076z"/>
-       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12.086,2.085c-5.478,0-9.916,4.438-9.916,9.916 c0,1.783,0.476,3.454,1.301,4.898l-2.223,2.04h5.688v-5.219l-2.066,1.896c-0.55-1.088-0.866-2.312-0.866-3.615 c0-4.465,3.619-8.084,8.084-8.084c4.464,0,8.083,3.619,8.083,8.084c0,4.464-3.619,8.083-8.083,8.083 c-1.145,0-2.228-0.247-3.213-0.678l-0.833,1.634c1.235,0.557,2.602,0.874,4.045,0.874c5.476,0,9.914-4.438,9.914-9.914 C22,6.523,17.562,2.085,12.086,2.085z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/link.png b/resources/oojs-ui/images/icons/link.png
deleted file mode 100644 (file)
index 7dfa268..0000000
Binary files a/resources/oojs-ui/images/icons/link.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/link.svg b/resources/oojs-ui/images/icons/link.svg
deleted file mode 100644 (file)
index dadf69c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="link" style="opacity:0.75;">
-       <path id="right" d="M19.188,12.001c0,1.1-0.891,2.015-1.988,2.015l-4.195-0.015C13.543,15.089,13.968,16,15.002,16h3
-               C19.658,16,21,13.657,21,12s-1.342-4-2.998-4h-3c-1.034,0-1.459,0.911-1.998,1.999l4.195-0.015
-               C18.297,9.984,19.188,10.901,19.188,12.001z"/>
-       <path id="center" d="M8,12c0,0.535,0.42,1,0.938,1h6.109c0.518,0,0.938-0.465,0.938-1c0-0.534-0.42-1-0.938-1H8.938
-               C8.42,11,8,11.466,8,12z"/>
-       <path id="left" d="M4.816,11.999c0-1.1,0.891-2.015,1.988-2.015L11,9.999C10.461,8.911,10.036,8,9.002,8h-3
-               c-1.656,0-2.998,2.343-2.998,4s1.342,4,2.998,4h3c1.034,0,1.459-0.911,1.998-1.999l-4.195,0.015
-               C5.707,14.016,4.816,13.099,4.816,11.999z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/menu.png b/resources/oojs-ui/images/icons/menu.png
deleted file mode 100644 (file)
index b5ac60f..0000000
Binary files a/resources/oojs-ui/images/icons/menu.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/menu.svg b/resources/oojs-ui/images/icons/menu.svg
deleted file mode 100644 (file)
index 657fab2..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="menu" style="opacity:0.75;">
-       <path id="lines" d="M6,15h12c0.553,0,1,0.447,1,1v1c0,0.553-0.447,1-1,1H6c-0.553,0-1-0.447-1-1v-1C5,15.447,5.447,15,6,15z M5,11v1
-               c0,0.553,0.447,1,1,1h12c0.553,0,1-0.447,1-1v-1c0-0.553-0.447-1-1-1H6C5.447,10,5,10.447,5,11z M5,6v1c0,0.553,0.447,1,1,1h12
-               c0.553,0,1-0.447,1-1V6c0-0.553-0.447-1-1-1H6C5.447,5,5,5.447,5,6z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/move-ltr.png b/resources/oojs-ui/images/icons/move-ltr.png
deleted file mode 100644 (file)
index ded5f05..0000000
Binary files a/resources/oojs-ui/images/icons/move-ltr.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/move-ltr.svg b/resources/oojs-ui/images/icons/move-ltr.svg
deleted file mode 100644 (file)
index a378a5d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="move-ltr" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="8.935,7.181 14.237,12.483 8.935,17.786
-               10.349,19.2 17.065,12.483 10.349,5.767"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/move-rtl.png b/resources/oojs-ui/images/icons/move-rtl.png
deleted file mode 100644 (file)
index fc6e62d..0000000
Binary files a/resources/oojs-ui/images/icons/move-rtl.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/move-rtl.svg b/resources/oojs-ui/images/icons/move-rtl.svg
deleted file mode 100644 (file)
index c0b334b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="move-rtl" style="opacity:0.75;">
-       <polygon id="arrow_9_" style="fill-rule:evenodd;clip-rule:evenodd;" points="15.065,17.786 9.763,12.483 15.065,7.181
-               13.651,5.767 6.935,12.483 13.651,19.2"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/picture.png b/resources/oojs-ui/images/icons/picture.png
deleted file mode 100644 (file)
index faf8af9..0000000
Binary files a/resources/oojs-ui/images/icons/picture.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/picture.svg b/resources/oojs-ui/images/icons/picture.svg
deleted file mode 100644 (file)
index 078ce10..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="picture" style="opacity:0.75;">
-       <path id="frame" style="fill-rule:evenodd;clip-rule:evenodd;" d="M18,4H6C4,3.993,3,4.993,3,6.993L3.014,16C3,18,4,18.988,6,19h12
-               c2-0.012,2.994-1,3-3.006V6.993C20.994,4.993,20,3.993,18,4z M19,17H5V6h14V17z"/>
-       <polygon id="mountains" style="fill-rule:evenodd;clip-rule:evenodd;" points="6,13.5 9.5,10 11.828,12.312 10.516,13.406
-               11.391,14.438 15.5,11 18,13 18,16 6,16"/>
-       <polygon id="sky" style="fill-rule:evenodd;clip-rule:evenodd;" points="6,12 9.516,7.844 12.562,11.016 15.5,9 18,11 18,7 6,7"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/remove-item.png b/resources/oojs-ui/images/icons/remove-item.png
deleted file mode 100644 (file)
index 2f11db3..0000000
Binary files a/resources/oojs-ui/images/icons/remove-item.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/remove-item.svg b/resources/oojs-ui/images/icons/remove-item.svg
deleted file mode 100644 (file)
index b95e7d3..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
-  <g id="remove-item">
-    <path d="M8,11 L16,11 L16,13 L8,13 z" fill="#000000"/>
-  </g>
-  <defs/>
-</svg>
diff --git a/resources/oojs-ui/images/icons/remove.png b/resources/oojs-ui/images/icons/remove.png
deleted file mode 100644 (file)
index d7e116c..0000000
Binary files a/resources/oojs-ui/images/icons/remove.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/remove.svg b/resources/oojs-ui/images/icons/remove.svg
deleted file mode 100644 (file)
index 17c8d39..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="remove" style="opacity:0.75;">
-       <path id="trash_can" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12,10h-1v6h1V10z M10,10H9v6h1V10z M14,10h-1v6h1V10z
-                M14,6V5H9v1H6v3h1v7.966l1,1.031v-0.074V18h6.984L15,17.982v0.015l1-1.031V9h1V6H14z M15,17H8V9h7V17z M16,8H7V7h9V8z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/search.png b/resources/oojs-ui/images/icons/search.png
deleted file mode 100644 (file)
index df29792..0000000
Binary files a/resources/oojs-ui/images/icons/search.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/search.svg b/resources/oojs-ui/images/icons/search.svg
deleted file mode 100644 (file)
index 37feda4..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="search" style="opacity:0.75;">
-       <path id="magnifying_glass" d="M16.021,15.96l-2.374-2.375c-0.048-0.047-0.105-0.079-0.169-0.099c0.403-0.566,0.643-1.26,0.643-2.009
-               C14.12,9.557,12.563,8,10.644,8c-1.921,0-3.478,1.557-3.478,3.478c0,1.92,1.557,3.477,3.478,3.477c0.749,0,1.442-0.239,2.01-0.643
-               c0.019,0.063,0.051,0.121,0.098,0.169l2.375,2.374c0.19,0.189,0.543,0.143,0.79-0.104S16.21,16.15,16.021,15.96z M10.644,13.69
-               c-1.221,0-2.213-0.991-2.213-2.213c0-1.221,0.992-2.213,2.213-2.213c1.222,0,2.213,0.992,2.213,2.213
-               C12.856,12.699,11.865,13.69,10.644,13.69z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/settings.png b/resources/oojs-ui/images/icons/settings.png
deleted file mode 100644 (file)
index b1b35e9..0000000
Binary files a/resources/oojs-ui/images/icons/settings.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/settings.svg b/resources/oojs-ui/images/icons/settings.svg
deleted file mode 100644 (file)
index 1464a79..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
-  <g id="settings" opacity="0.75">
-    <path d="M3,4 L6,4 L6,6 L3,6 z" fill="#000000"/>
-    <path d="M12,4 L21,4 L21,6 L12,6 z" fill="#000000"/>
-    <path d="M8,3 L10,3 C10.552,3 11,3.448 11,4 L11,6 C11,6.552 10.552,7 10,7 L8,7 C7.448,7 7,6.552 7,6 L7,4 C7,3.448 7.448,3 8,3 z" fill="#000000"/>
-    <path d="M3,11 L12,11 L12,13 L3,13 z" fill="#000000"/>
-    <path d="M18,11 L21,11 L21,13 L18,13 z" fill="#000000"/>
-    <path d="M14,10 L16,10 C16.552,10 17,10.448 17,11 L17,13 C17,13.552 16.552,14 16,14 L14,14 C13.448,14 13,13.552 13,13 L13,11 C13,10.448 13.448,10 14,10 z" fill="#000000"/>
-    <path d="M3,18 L9,18 L9,20 L3,20 z" fill="#000000"/>
-    <path d="M15,18 L21,18 L21,20 L15,20 z" fill="#000000"/>
-    <path d="M11,17 L13,17 C13.552,17 14,17.448 14,18 L14,20 C14,20.552 13.552,21 13,21 L11,21 C10.448,21 10,20.552 10,20 L10,18 C10,17.448 10.448,17 11,17 z" fill="#000000"/>
-  </g>
-  <defs/>
-</svg>
diff --git a/resources/oojs-ui/images/icons/tag.png b/resources/oojs-ui/images/icons/tag.png
deleted file mode 100644 (file)
index 722f4d7..0000000
Binary files a/resources/oojs-ui/images/icons/tag.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/tag.svg b/resources/oojs-ui/images/icons/tag.svg
deleted file mode 100644 (file)
index d21e5e3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="tag" style="opacity:0.75;">
-       <path d="M18.748,11.717c0.389,0.389,0.389,1.025,0,1.414l-4.949,4.95c-0.389,0.389-1.025,0.389-1.414,0l-6.01-6.01
-               c-0.389-0.389-0.707-1.157-0.707-1.707L5.667,6c0-0.55,0.45-1,1-1h4.364c0.55,0,1.318,0.318,1.707,0.707L18.748,11.717z
-                M8.104,7.456C7.525,8.032,7.526,8.97,8.103,9.549c0.578,0.577,1.516,0.577,2.095,0.001c0.576-0.578,0.576-1.517,0-2.095
-               C9.617,6.879,8.68,6.878,8.104,7.456z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/icons/window.png b/resources/oojs-ui/images/icons/window.png
deleted file mode 100644 (file)
index 3d48a3c..0000000
Binary files a/resources/oojs-ui/images/icons/window.png and /dev/null differ
diff --git a/resources/oojs-ui/images/icons/window.svg b/resources/oojs-ui/images/icons/window.svg
deleted file mode 100644 (file)
index 621cf2c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="window" style="opacity:0.75;">
-       <rect id="title" x="7" y="10" width="10" height="1"/>
-       <path id="window" d="M16,19H8c-2.206,0-4-1.794-4-4V9c0-2.206,1.794-4,4-4h8c2.206,0,4,1.794,4,4v6C20,17.206,18.206,19,16,19z
-                M8,7C6.897,7,6,7.897,6,9v6c0,1.103,0.897,2,2,2h8c1.103,0,2-0.897,2-2V9c0-1.103-0.897-2-2-2H8z"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/indicators/down.png b/resources/oojs-ui/images/indicators/down.png
deleted file mode 100644 (file)
index 47ff54c..0000000
Binary files a/resources/oojs-ui/images/indicators/down.png and /dev/null differ
diff --git a/resources/oojs-ui/images/indicators/down.svg b/resources/oojs-ui/images/indicators/down.svg
deleted file mode 100644 (file)
index c871f60..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
-        height="12px" viewBox="0 0 12 12" style="enable-background:new 0 0 12 12;" xml:space="preserve">
-<g id="down" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="2.023,3 5.512,8.953 9,3"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/indicators/required.png b/resources/oojs-ui/images/indicators/required.png
deleted file mode 100644 (file)
index aeb35a3..0000000
Binary files a/resources/oojs-ui/images/indicators/required.png and /dev/null differ
diff --git a/resources/oojs-ui/images/indicators/required.svg b/resources/oojs-ui/images/indicators/required.svg
deleted file mode 100644 (file)
index 7c60ec0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12" height="12" viewBox="0, 0, 12, 12">
-  <g id="required" opacity="0.75">
-    <path d="M7,0 L7,4.268 L10.696,2.134 L11.696,3.866 L8,6 L11.696,8.134 L10.696,9.866 L7,7.732 L7,12 L5,12 L5,7.732 L1.304,9.866 L0.304,8.134 L4,6 L0.304,3.866 L1.304,2.134 L5,4.268 L5,0 z" fill="#000000"/>
-  </g>
-  <defs/>
-</svg>
diff --git a/resources/oojs-ui/images/indicators/up.png b/resources/oojs-ui/images/indicators/up.png
deleted file mode 100644 (file)
index b827f6d..0000000
Binary files a/resources/oojs-ui/images/indicators/up.png and /dev/null differ
diff --git a/resources/oojs-ui/images/indicators/up.svg b/resources/oojs-ui/images/indicators/up.svg
deleted file mode 100644 (file)
index a5d7f38..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
-        height="12px" viewBox="0 0 12 12" style="enable-background:new 0 0 12 12;" xml:space="preserve">
-<g id="up" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="5.512,2.006 2,8 9.024,8                "/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/tail.svg b/resources/oojs-ui/images/tail.svg
deleted file mode 100644 (file)
index 4df8bb2..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-        width="15px" height="8px" viewBox="0 0 15 8" style="enable-background:new 0 0 15 8;" xml:space="preserve">
-<g id="tail">
-       <polygon id="outline" style="fill-rule:evenodd;clip-rule:evenodd;fill:#808080;" points="7.609,2.499 2.096,8 13.125,8"/>
-       <polygon id="fill" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;" points="7.609,3 2.598,8 12.622,8"/>
-</g>
-</svg>
diff --git a/resources/oojs-ui/images/textures/pending.gif b/resources/oojs-ui/images/textures/pending.gif
deleted file mode 100644 (file)
index 1194eed..0000000
Binary files a/resources/oojs-ui/images/textures/pending.gif and /dev/null differ
diff --git a/resources/oojs-ui/images/textures/transparency.png b/resources/oojs-ui/images/textures/transparency.png
deleted file mode 100644 (file)
index b8e36d3..0000000
Binary files a/resources/oojs-ui/images/textures/transparency.png and /dev/null differ
diff --git a/resources/oojs-ui/images/toolbar-shadow.png b/resources/oojs-ui/images/toolbar-shadow.png
deleted file mode 100644 (file)
index 97e8d13..0000000
Binary files a/resources/oojs-ui/images/toolbar-shadow.png and /dev/null differ
diff --git a/resources/oojs-ui/oojs-ui-agora.css b/resources/oojs-ui/oojs-ui-agora.css
deleted file mode 100644 (file)
index 8aedde5..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-.oo-ui-window-head {
-  height: 3.35em;
-  border-bottom: 1px solid #dddddd;
-}
-
-.oo-ui-window-body {
-  padding: 2em 3.35em;
-}
-
-.oo-ui-window-icon {
-  width: 3.35em;
-  height: 3.35em;
-  background-size: 2em auto;
-  border-left: 1px solid #dddddd;
-}
-
-.oo-ui-window-title {
-  line-height: 3.35em;
-}
-
-.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
-.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  width: 3.35em;
-  height: 3.35em;
-  background-size: 2em auto;
-}
-
-.oo-ui-optionWidget {
-  padding: 0.8em 1em 0.8em 3.35em;
-  font-weight: bold;
-  border-bottom: 1px solid #dddddd;
-}
-
-.oo-ui-optionWidget.oo-ui-indicatedElement .oo-ui-labeledElement-label {
-  padding-right: 1.5em;
-}
-
-.oo-ui-optionWidget-level-0 {
-  padding-left: 3.5em;
-}
-
-.oo-ui-optionWidget-level-0 .oo-ui-iconedElement-icon {
-  left: 1em;
-}
-
-.oo-ui-optionWidget-level-1 {
-  padding-left: 5em;
-}
-
-.oo-ui-optionWidget-level-1 .oo-ui-iconedElement-icon {
-  left: 2.5em;
-}
-
-.oo-ui-optionWidget-level-2 {
-  padding-left: 6.5em;
-}
-
-.oo-ui-optionWidget-level-2 .oo-ui-iconedElement-icon {
-  left: 4em;
-}
-
-.oo-ui-buttonOptionWidget {
-  padding: 0;
-}
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
-  color: #ffffff;
-  background: #347bff;
-}
-
-.oo-ui-menuSectionItemWidget {
-  font-weight: normal;
-  color: #777777;
-  border: none;
-}
-
-.oo-ui-textInputWidget input,
-.oo-ui-textInputWidget textarea {
-  padding: .8em 1em;
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/oojs-ui-apex.css b/resources/oojs-ui/oojs-ui-apex.css
deleted file mode 100644 (file)
index aa5d78f..0000000
+++ /dev/null
@@ -1,777 +0,0 @@
-.oo-ui-dialog {
-  background-color: #fff;
-  background-color: rgba(255, 255, 255, 0.5);
-  opacity: 0;
-  -webkit-transition: all 250ms ease-in-out;
-     -moz-transition: all 250ms ease-in-out;
-      -ms-transition: all 250ms ease-in-out;
-       -o-transition: all 250ms ease-in-out;
-          transition: all 250ms ease-in-out;
-}
-
-.oo-ui-dialog .oo-ui-window-frame {
-  background-color: #fff;
-  border: solid 1px #ccc;
-  border-radius: 0.5em;
-  -webkit-transform: scale(0.5);
-     -moz-transform: scale(0.5);
-      -ms-transform: scale(0.5);
-       -o-transform: scale(0.5);
-          transform: scale(0.5);
-  box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
-  -webkit-transition: all 250ms ease-in-out;
-     -moz-transition: all 250ms ease-in-out;
-      -ms-transition: all 250ms ease-in-out;
-       -o-transition: all 250ms ease-in-out;
-          transition: all 250ms ease-in-out;
-}
-
-.oo-ui-dialog-open {
-  opacity: 1;
-}
-
-.oo-ui-dialog-open .oo-ui-window-frame {
-  -webkit-transform: scale(1);
-     -moz-transform: scale(1);
-      -ms-transform: scale(1);
-       -o-transform: scale(1);
-          transform: scale(1);
-}
-
-.oo-ui-dialog-content .oo-ui-window-body {
-  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
-}
-
-.oo-ui-frame-content {
-  font-family: sans-serif;
-  font-size: 0.8em;
-}
-
-.oo-ui-toolbar-bar {
-  background: #f8fbfd;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #f1f7fb));
-  background-image: -webkit-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
-  background-image: -moz-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
-  background-image: -ms-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
-  background-image: -o-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
-  background-image: linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
-  border-bottom: solid 1px #ccc;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#f1f7fb');
-}
-
-.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
-  background: none;
-  border: none;
-}
-
-.oo-ui-toolbar-shadow {
-  bottom: -9px;
-  height: 9px;
-  background-image: /* @embed */ url(images/toolbar-shadow.png);
-  opacity: 0.125;
-  -webkit-transition: opacity 500ms ease-in-out;
-     -moz-transition: opacity 500ms ease-in-out;
-      -ms-transition: opacity 500ms ease-in-out;
-       -o-transition: opacity 500ms ease-in-out;
-          transition: opacity 500ms ease-in-out;
-}
-
-.oo-ui-toolGroup {
-  border: solid 1px transparent;
-  border-radius: 0.25em;
-  -webkit-transition: border-color 300ms ease-in-out;
-     -moz-transition: border-color 300ms ease-in-out;
-      -ms-transition: border-color 300ms ease-in-out;
-       -o-transition: border-color 300ms ease-in-out;
-          transition: border-color 300ms ease-in-out;
-}
-
-.oo-ui-toolGroup.oo-ui-widget-enabled:hover {
-  border-color: rgba(0, 0, 0, 0.1);
-}
-
-.oo-ui-toolGroup.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-tool-title {
-  color: #000;
-}
-
-.oo-ui-window-body {
-  padding: 0 0.75em;
-}
-
-.oo-ui-window-icon {
-  width: 2em;
-  height: 2em;
-  margin-right: 0.5em;
-  line-height: 2em;
-}
-
-.oo-ui-window-title {
-  line-height: 2em;
-  color: #333;
-}
-
-.oo-ui-window-overlay {
-  font-family: sans-serif;
-  font-size: 1em;
-  line-height: 1.5em;
-}
-
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button {
-  color: #333;
-}
-
-.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
-.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  width: 1.9em;
-  height: 1.9em;
-  opacity: 0.8;
-}
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  /* Don't animate opacities for now, causes wiggling in Chrome (bug 63020) */
-
-  /*.oo-ui-transition(opacity 200ms);*/
-
-}
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-iconedElement-icon,
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-iconedElement-icon {
-  opacity: 1;
-}
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-labeledElement-label,
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-labeledElement-label {
-  color: #000;
-}
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-  color: #333;
-}
-
-.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  opacity: 0.2;
-}
-
-.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-  color: #ccc;
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
-  background: #eeeeee;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #dddddd));
-  background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  border: 1px #c9c9c9 solid;
-  border-radius: 0.3em;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
-  -webkit-transition: border-color 100ms ease-in-out;
-     -moz-transition: border-color 100ms ease-in-out;
-      -ms-transition: border-color 100ms ease-in-out;
-       -o-transition: border-color 100ms ease-in-out;
-          transition: border-color 100ms ease-in-out;
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:focus {
-  border-color: #aaa;
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
-  color: black;
-  background: #eeeeee;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #dddddd), color-stop(100%, #ffffff));
-  background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  border-color: #c9c9c9;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
-  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button {
-  background: #cde7f4;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #eaf4fa), color-stop(100%, #b0d9ee));
-  background-image: -webkit-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-  background-image: -moz-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-  background-image: -ms-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-  background-image: -o-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-  background-image: linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-  border: solid 1px #a6cee1;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#eaf4fa', endColorstr='#b0d9ee');
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:focus {
-  border-color: #9dc2d4;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
-  background: #cde7f4;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #b0d9ee), color-stop(100%, #eaf4fa));
-  background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  border: solid 1px #a6cee1;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button {
-  background: #daf0be;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f0fbe1), color-stop(100%, #c3e59a));
-  background-image: -webkit-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-  background-image: -moz-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-  background-image: -ms-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-  background-image: -o-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-  background-image: linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-  border: solid 1px #b8d892;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f0fbe1', endColorstr='#c3e59a');
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:focus {
-  border-color: #adcb89;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
-  background: #daf0be;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #c3e59a), color-stop(100%, #f0fbe1));
-  background-image: -webkit-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-  background-image: -moz-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-  background-image: -ms-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-  background-image: -o-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-  background-image: linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-  border: solid 1px #b8d892;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#c3e59a', endColorstr='#f0fbe1');
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-destructive .oo-ui-buttonedElement-button {
-  color: #d45353;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
-  color: #333;
-  background: #eee;
-  border-color: #ccc;
-  opacity: 0.5;
-  box-shadow: none;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active:hover,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed:hover,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:focus,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active:focus,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed:focus {
-  border-color: #ccc;
-  box-shadow: none;
-}
-
-.oo-ui-bookletLayout > .oo-ui-gridLayout > .oo-ui-panelLayout {
-  -webkit-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
-     -moz-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
-      -ms-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
-       -o-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
-          transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
-}
-
-.oo-ui-bookletLayout-outlinePanel {
-  border-right: solid 1px #ddd;
-}
-
-.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
-  box-shadow: 0 0 0.25em rgba(0, 0, 0, 0.25);
-}
-
-.oo-ui-fieldsetLayout {
-  border: none;
-}
-
-.oo-ui-fieldsetLayout > legend.oo-ui-labeledElement-label {
-  font-size: 1.5em;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool {
-  margin: -1px 0 -1px -1px;
-  border: solid 1px transparent;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool:first-child {
-  border-bottom-left-radius: 0.25em;
-  border-top-left-radius: 0.25em;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool:last-child {
-  margin-right: -1px;
-  border-top-right-radius: 0.25em;
-  border-bottom-right-radius: 0.25em;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  opacity: 0.8;
-}
-
-.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled:hover {
-  border-color: rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-active.oo-ui-widget-enabled {
-  background: #f8fbfd;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
-  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  border-color: rgba(0, 0, 0, 0.2);
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
-  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
-}
-
-.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
-  border-left-color: rgba(0, 0, 0, 0.1);
-}
-
-.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  opacity: 0.2;
-}
-
-.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  opacity: 0.8;
-}
-
-.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  opacity: 1;
-}
-
-.oo-ui-barToolGroup.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  opacity: 0.2;
-}
-
-.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
-  border-color: rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-listToolGroup .oo-ui-tool {
-  margin: -1px 0;
-  border: solid 1px transparent;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled {
-  background: #f8fbfd;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
-  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  border-color: rgba(0, 0, 0, 0.1);
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
-  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
-}
-
-.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
-  border-top-color: rgba(0, 0, 0, 0.1);
-}
-
-.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled:hover {
-  border-color: rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
-  border-color: rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  opacity: 0.8;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  opacity: 1;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
-  color: #ccc;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  opacity: 0.2;
-}
-
-.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-indicatedElement-indicator,
-.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-iconedElement-icon {
-  opacity: 0.2;
-}
-
-.oo-ui-menuToolGroup {
-  border-color: rgba(0, 0, 0, 0.1);
-}
-
-.oo-ui-menuToolGroup.oo-ui-widget-enabled:hover {
-  border-color: rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-menuToolGroup.oo-ui-popupToolGroup-active {
-  border-color: rgba(0, 0, 0, 0.25);
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
-  background-color: #e1f3ff;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
-  color: #ccc;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  opacity: 0.2;
-}
-
-.oo-ui-menuToolGroup.oo-ui-widget-disabled {
-  color: #ccc;
-  text-shadow: 0 1px 1px #fff;
-  background-color: #f3f3f3;
-  border-color: #ddd;
-}
-
-.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-indicatedElement-indicator,
-.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-iconedElement-icon {
-  opacity: 0.2;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator,
-.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
-  opacity: 0.8;
-}
-
-.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
-  background-color: white;
-  border: solid 1px #ccc;
-  box-shadow: 0 0.25em 1em rgba(0, 0, 0, 0.25);
-}
-
-.oo-ui-popupToolGroup-active.oo-ui-widget-enabled {
-  background: #f8fbfd;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
-  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
-  border-bottom-right-radius: 0;
-  border-bottom-left-radius: 0;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
-  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
-}
-
-.oo-ui-optionWidget {
-  padding: 0.5em 2em 0.5em 3em;
-}
-
-.oo-ui-optionWidget-highlighted {
-  background-color: #e1f3ff;
-}
-
-.oo-ui-optionWidget-selected {
-  background-color: #a7dcff;
-}
-
-.oo-ui-optionWidget.oo-ui-widget-disabled {
-  color: #ccc;
-}
-
-.oo-ui-menuWidget {
-  margin-top: -1px;
-  background: #fff;
-  border: solid 1px #ccc;
-  border-radius: 0 0 0.25em 0.25em;
-  box-shadow: 0 0.15em 1em 0 rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-popupWidget-popup {
-  background-color: #fff;
-  border: solid 1px #ccc;
-  border-radius: 0.25em;
-  box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-popupWidget-tailed .oo-ui-popupWidget-tail {
-  width: 15px;
-  height: 8px;
-  margin-left: -7px;
-  background-image: /* @embed */ url(images/tail.svg);
-}
-
-.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
-  -webkit-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
-     -moz-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
-      -ms-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
-       -o-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
-          transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
-}
-
-.oo-ui-popupWidget-body {
-  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
-}
-
-.oo-ui-buttonGroupWidget {
-  display: inline-block;
-  white-space: nowrap;
-}
-
-.oo-ui-buttonOptionWidget {
-  padding: 0;
-}
-
-.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected,
-.oo-ui-buttonOptionWidget.oo-ui-optionWidget-highlighted {
-  background-color: transparent;
-}
-
-.oo-ui-buttonSelectWidget {
-  border-radius: 0.3em;
-}
-
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
-  margin-left: -1px;
-  border-radius: 0;
-}
-
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonedElement-button {
-  margin-left: 0;
-  border-bottom-left-radius: 0.3em;
-  border-top-left-radius: 0.3em;
-}
-
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonedElement-button {
-  border-top-right-radius: 0.3em;
-  border-bottom-right-radius: 0.3em;
-}
-
-.oo-ui-inlineMenuWidget-handle {
-  border: solid 1px rgba(0, 0, 0, 0.1);
-  border-radius: 0.25em;
-}
-
-.oo-ui-inlineMenuWidget-handle:hover {
-  border-color: rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator,
-.oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
-  opacity: 0.8;
-}
-
-.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
-  color: #ccc;
-  text-shadow: 0 1px 1px #fff;
-  background-color: #f3f3f3;
-  border-color: #ddd;
-}
-
-.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-indicatedElement-indicator {
-  opacity: 0.2;
-}
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted {
-  background-color: #e1f3ff;
-}
-
-.oo-ui-menuSectionItemWidget {
-  padding: 0.33em 0.75em;
-  color: #888;
-}
-
-.oo-ui-outlineControlsWidget {
-  background-color: #fff;
-}
-
-.oo-ui-outlineControlsWidget > .oo-ui-iconedElement-icon {
-  opacity: 0.2;
-}
-
-.oo-ui-outlineItemWidget {
-  font-size: 1.1em;
-}
-
-.oo-ui-outlineItemWidget.oo-ui-indicatedElement .oo-ui-labeledElement-label {
-  padding-right: 1.5em;
-}
-
-.oo-ui-outlineItemWidget-level-0 {
-  padding-left: 3.5em;
-}
-
-.oo-ui-outlineItemWidget-level-0 .oo-ui-iconedElement-icon {
-  left: 1em;
-}
-
-.oo-ui-outlineItemWidget-level-1 {
-  padding-left: 5em;
-}
-
-.oo-ui-outlineItemWidget-level-1 .oo-ui-iconedElement-icon {
-  left: 2.5em;
-}
-
-.oo-ui-outlineItemWidget-level-2 {
-  padding-left: 6.5em;
-}
-
-.oo-ui-outlineItemWidget-level-2 .oo-ui-iconedElement-icon {
-  left: 4em;
-}
-
-.oo-ui-outlineItemWidget.oo-ui-optionWidget-selected {
-  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
-  background-color: #a7dcff;
-}
-
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-important {
-  font-weight: bold;
-}
-
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-placeholder {
-  font-style: italic;
-}
-
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-iconedElement-icon,
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-indicatedElement-indicator {
-  opacity: 0.5;
-}
-
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-labeledElement-label {
-  color: #777;
-}
-
-.oo-ui-searchWidget-query {
-  box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-textInputWidget {
-  width: 20em;
-}
-
-.oo-ui-textInputWidget input,
-.oo-ui-textInputWidget textarea {
-  padding: 0.5em;
-  font-family: sans-serif;
-  font-size: 1em;
-  background-color: #fff;
-  border: solid 1px #ccc;
-  border-radius: 0.25em;
-  box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
-  -webkit-transition: border-color 200ms, box-shadow 200ms;
-     -moz-transition: border-color 200ms, box-shadow 200ms;
-      -ms-transition: border-color 200ms, box-shadow 200ms;
-       -o-transition: border-color 200ms, box-shadow 200ms;
-          transition: border-color 200ms, box-shadow 200ms;
-}
-
-.oo-ui-textInputWidget-decorated input,
-.oo-ui-textInputWidget-decorated textarea {
-  padding-left: 2em;
-}
-
-.oo-ui-textInputWidget-icon {
-  width: 2em;
-}
-
-.oo-ui-textInputWidget.oo-ui-widget-enabled input:focus,
-.oo-ui-textInputWidget.oo-ui-widget-enabled textarea:focus {
-  border-color: #a7dcff;
-  outline: none;
-  box-shadow: 0 0 0.3em #a7dcff, 0 0 0 white;
-}
-
-.oo-ui-textInputWidget input[readonly],
-.oo-ui-textInputWidget textarea[readonly] {
-  color: #777;
-  text-shadow: 0 1px 1px #fff;
-}
-
-.oo-ui-textInputWidget-pending input,
-.oo-ui-textInputWidget-pending textarea {
-  background-color: transparent;
-}
-
-.oo-ui-textInputWidget.oo-ui-widget-disabled input,
-.oo-ui-textInputWidget.oo-ui-widget-disabled input:focus,
-.oo-ui-textInputWidget.oo-ui-widget-disabled textarea,
-.oo-ui-textInputWidget.oo-ui-widget-disabled textarea:focus {
-  color: #ccc;
-  text-shadow: 0 1px 1px #fff;
-  background-color: #f3f3f3;
-  border-color: #ddd;
-}
-
-.oo-ui-toggleSwitchWidget {
-  background: #eeeeee;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #dddddd), color-stop(100%, #ffffff));
-  background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
-  border: solid 1px #ccc;
-  border-radius: 1em;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
-  box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
-}
-
-.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
-  opacity: 0.5;
-}
-
-.oo-ui-toggleSwitchWidget-grip {
-  background: #eeeeee;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #dddddd));
-  background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
-  border: 1px #c9c9c9 solid;
-  border-radius: 1em;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
-  box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
-}
-
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover,
-.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover .oo-ui-toggleSwitchWidget-grip {
-  border-color: #aaa;
-}
-
-.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
-  background: #cde7f4;
-  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #b0d9ee), color-stop(100%, #eaf4fa));
-  background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-  border-radius: 1em;
-  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
-  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
-}
-
-.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-glow {
-  opacity: 1;
-}
-
-.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
-  display: block;
-  opacity: 0;
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/oojs-ui.js b/resources/oojs-ui/oojs-ui.js
deleted file mode 100644 (file)
index 9a1e324..0000000
+++ /dev/null
@@ -1,8105 +0,0 @@
-/*!
- * OOjs UI v0.1.0-pre (8986c46d35)
- * https://www.mediawiki.org/wiki/OOjs_UI
- *
- * Copyright 2011–2014 OOjs Team and other contributors.
- * Released under the MIT license
- * http://oojs.mit-license.org
- *
- * Date: Tue Apr 01 2014 19:33:39 GMT-0700 (PDT)
- */
-( function ( OO ) {
-
-'use strict';
-/**
- * Namespace for all classes, static methods and static properties.
- *
- * @class
- * @singleton
- */
-OO.ui = {};
-
-OO.ui.bind = $.proxy;
-
-/**
- * @property {Object}
- */
-OO.ui.Keys = {
-       'UNDEFINED': 0,
-       'BACKSPACE': 8,
-       'DELETE': 46,
-       'LEFT': 37,
-       'RIGHT': 39,
-       'UP': 38,
-       'DOWN': 40,
-       'ENTER': 13,
-       'END': 35,
-       'HOME': 36,
-       'TAB': 9,
-       'PAGEUP': 33,
-       'PAGEDOWN': 34,
-       'ESCAPE': 27,
-       'SHIFT': 16,
-       'SPACE': 32
-};
-
-/**
- * Get the user's language and any fallback languages.
- *
- * These language codes are used to localize user interface elements in the user's language.
- *
- * In environments that provide a localization system, this function should be overridden to
- * return the user's language(s). The default implementation returns English (en) only.
- *
- * @return {string[]} Language codes, in descending order of priority
- */
-OO.ui.getUserLanguages = function () {
-       return [ 'en' ];
-};
-
-/**
- * Get a value in an object keyed by language code.
- *
- * @param {Object.<string,Mixed>} obj Object keyed by language code
- * @param {string|null} [lang] Language code, if omitted or null defaults to any user language
- * @param {string} [fallback] Fallback code, used if no matching language can be found
- * @return {Mixed} Local value
- */
-OO.ui.getLocalValue = function ( obj, lang, fallback ) {
-       var i, len, langs;
-
-       // Requested language
-       if ( obj[lang] ) {
-               return obj[lang];
-       }
-       // Known user language
-       langs = OO.ui.getUserLanguages();
-       for ( i = 0, len = langs.length; i < len; i++ ) {
-               lang = langs[i];
-               if ( obj[lang] ) {
-                       return obj[lang];
-               }
-       }
-       // Fallback language
-       if ( obj[fallback] ) {
-               return obj[fallback];
-       }
-       // First existing language
-       for ( lang in obj ) {
-               return obj[lang];
-       }
-
-       return undefined;
-};
-
-( function () {
-
-/**
- * Message store for the default implementation of OO.ui.msg
- *
- * Environments that provide a localization system should not use this, but should override
- * OO.ui.msg altogether.
- *
- * @private
- */
-var messages = {
-       // Label text for button to exit from dialog
-       'ooui-dialog-action-close': 'Close',
-       // Tool tip for a button that moves items in a list down one place
-       'ooui-outline-control-move-down': 'Move item down',
-       // Tool tip for a button that moves items in a list up one place
-       'ooui-outline-control-move-up': 'Move item up',
-       // Tool tip for a button that removes items from a list
-       'ooui-outline-control-remove': 'Remove item',
-       // Label for the toolbar group that contains a list of all other available tools
-       'ooui-toolbar-more': 'More'
-};
-
-/**
- * Get a localized message.
- *
- * In environments that provide a localization system, this function should be overridden to
- * return the message translated in the user's language. The default implementation always returns
- * English messages.
- *
- * After the message key, message parameters may optionally be passed. In the default implementation,
- * any occurrences of $1 are replaced with the first parameter, $2 with the second parameter, etc.
- * Alternative implementations of OO.ui.msg may use any substitution system they like, as long as
- * they support unnamed, ordered message parameters.
- *
- * @abstract
- * @param {string} key Message key
- * @param {Mixed...} [params] Message parameters
- * @return {string} Translated message with parameters substituted
- */
-OO.ui.msg = function ( key ) {
-       var message = messages[key], params = Array.prototype.slice.call( arguments, 1 );
-       if ( typeof message === 'string' ) {
-               // Perform $1 substitution
-               message = message.replace( /\$(\d+)/g, function ( unused, n ) {
-                       var i = parseInt( n, 10 );
-                       return params[i - 1] !== undefined ? params[i - 1] : '$' + n;
-               } );
-       } else {
-               // Return placeholder if message not found
-               message = '[' + key + ']';
-       }
-       return message;
-};
-
-/** */
-OO.ui.deferMsg = function ( key ) {
-       return function () {
-               return OO.ui.msg( key );
-       };
-};
-
-/** */
-OO.ui.resolveMsg = function ( msg ) {
-       if ( $.isFunction( msg ) ) {
-               return msg();
-       }
-       return msg;
-};
-
-} )();
-/**
- * DOM element abstraction.
- *
- * @abstract
- * @class
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {Function} [$] jQuery for the frame the widget is in
- * @cfg {string[]} [classes] CSS class names
- * @cfg {jQuery} [$content] Content elements to append
- */
-OO.ui.Element = function OoUiElement( config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Properties
-       this.$ = config.$ || OO.ui.Element.getJQuery( document );
-       this.$element = this.$( this.$.context.createElement( this.getTagName() ) );
-       this.elementGroup = null;
-
-       // Initialization
-       if ( $.isArray( config.classes ) ) {
-               this.$element.addClass( config.classes.join( ' ' ) );
-       }
-       if ( config.$content ) {
-               this.$element.append( config.$content );
-       }
-};
-
-/* Static Properties */
-
-OO.ui.Element.static = {};
-
-/**
- * HTML tag name.
- *
- * This may be ignored if getTagName is overridden.
- *
- * @static
- * @property {string}
- * @inheritable
- */
-OO.ui.Element.static.tagName = 'div';
-
-/* Static Methods */
-
-/**
- * Get a jQuery function within a specific document.
- *
- * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} context Context to bind the function to
- * @param {OO.ui.Frame} [frame] Frame of the document context
- * @return {Function} Bound jQuery function
- */
-OO.ui.Element.getJQuery = function ( context, frame ) {
-       function wrapper( selector ) {
-               return $( selector, wrapper.context );
-       }
-
-       wrapper.context = this.getDocument( context );
-
-       if ( frame ) {
-               wrapper.frame = frame;
-       }
-
-       return wrapper;
-};
-
-/**
- * Get the document of an element.
- *
- * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Object to get the document for
- * @return {HTMLDocument|null} Document object
- */
-OO.ui.Element.getDocument = function ( obj ) {
-       // jQuery - selections created "offscreen" won't have a context, so .context isn't reliable
-       return ( obj[0] && obj[0].ownerDocument ) ||
-               // Empty jQuery selections might have a context
-               obj.context ||
-               // HTMLElement
-               obj.ownerDocument ||
-               // Window
-               obj.document ||
-               // HTMLDocument
-               ( obj.nodeType === 9 && obj ) ||
-               null;
-};
-
-/**
- * Get the window of an element or document.
- *
- * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the window for
- * @return {Window} Window object
- */
-OO.ui.Element.getWindow = function ( obj ) {
-       var doc = this.getDocument( obj );
-       return doc.parentWindow || doc.defaultView;
-};
-
-/**
- * Get the direction of an element or document.
- *
- * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the direction for
- * @return {string} Text direction, either `ltr` or `rtl`
- */
-OO.ui.Element.getDir = function ( obj ) {
-       var isDoc, isWin;
-
-       if ( obj instanceof jQuery ) {
-               obj = obj[0];
-       }
-       isDoc = obj.nodeType === 9;
-       isWin = obj.document !== undefined;
-       if ( isDoc || isWin ) {
-               if ( isWin ) {
-                       obj = obj.document;
-               }
-               obj = obj.body;
-       }
-       return $( obj ).css( 'direction' );
-};
-
-/**
- * Get the offset between two frames.
- *
- * TODO: Make this function not use recursion.
- *
- * @static
- * @param {Window} from Window of the child frame
- * @param {Window} [to=window] Window of the parent frame
- * @param {Object} [offset] Offset to start with, used internally
- * @return {Object} Offset object, containing left and top properties
- */
-OO.ui.Element.getFrameOffset = function ( from, to, offset ) {
-       var i, len, frames, frame, rect;
-
-       if ( !to ) {
-               to = window;
-       }
-       if ( !offset ) {
-               offset = { 'top': 0, 'left': 0 };
-       }
-       if ( from.parent === from ) {
-               return offset;
-       }
-
-       // Get iframe element
-       frames = from.parent.document.getElementsByTagName( 'iframe' );
-       for ( i = 0, len = frames.length; i < len; i++ ) {
-               if ( frames[i].contentWindow === from ) {
-                       frame = frames[i];
-                       break;
-               }
-       }
-
-       // Recursively accumulate offset values
-       if ( frame ) {
-               rect = frame.getBoundingClientRect();
-               offset.left += rect.left;
-               offset.top += rect.top;
-               if ( from !== to ) {
-                       this.getFrameOffset( from.parent, offset );
-               }
-       }
-       return offset;
-};
-
-/**
- * Get the offset between two elements.
- *
- * @static
- * @param {jQuery} $from
- * @param {jQuery} $to
- * @return {Object} Translated position coordinates, containing top and left properties
- */
-OO.ui.Element.getRelativePosition = function ( $from, $to ) {
-       var from = $from.offset(),
-               to = $to.offset();
-       return { 'top': Math.round( from.top - to.top ), 'left': Math.round( from.left - to.left ) };
-};
-
-/**
- * Get element border sizes.
- *
- * @static
- * @param {HTMLElement} el Element to measure
- * @return {Object} Dimensions object with `top`, `left`, `bottom` and `right` properties
- */
-OO.ui.Element.getBorders = function ( el ) {
-       var doc = el.ownerDocument,
-               win = doc.parentWindow || doc.defaultView,
-               style = win && win.getComputedStyle ?
-                       win.getComputedStyle( el, null ) :
-                       el.currentStyle,
-               $el = $( el ),
-               top = parseFloat( style ? style.borderTopWidth : $el.css( 'borderTopWidth' ) ) || 0,
-               left = parseFloat( style ? style.borderLeftWidth : $el.css( 'borderLeftWidth' ) ) || 0,
-               bottom = parseFloat( style ? style.borderBottomWidth : $el.css( 'borderBottomWidth' ) ) || 0,
-               right = parseFloat( style ? style.borderRightWidth : $el.css( 'borderRightWidth' ) ) || 0;
-
-       return {
-               'top': Math.round( top ),
-               'left': Math.round( left ),
-               'bottom': Math.round( bottom ),
-               'right': Math.round( right )
-       };
-};
-
-/**
- * Get dimensions of an element or window.
- *
- * @static
- * @param {HTMLElement|Window} el Element to measure
- * @return {Object} Dimensions object with `borders`, `scroll`, `scrollbar` and `rect` properties
- */
-OO.ui.Element.getDimensions = function ( el ) {
-       var $el, $win,
-               doc = el.ownerDocument || el.document,
-               win = doc.parentWindow || doc.defaultView;
-
-       if ( win === el || el === doc.documentElement ) {
-               $win = $( win );
-               return {
-                       'borders': { 'top': 0, 'left': 0, 'bottom': 0, 'right': 0 },
-                       'scroll': {
-                               'top': $win.scrollTop(),
-                               'left': $win.scrollLeft()
-                       },
-                       'scrollbar': { 'right': 0, 'bottom': 0 },
-                       'rect': {
-                               'top': 0,
-                               'left': 0,
-                               'bottom': $win.innerHeight(),
-                               'right': $win.innerWidth()
-                       }
-               };
-       } else {
-               $el = $( el );
-               return {
-                       'borders': this.getBorders( el ),
-                       'scroll': {
-                               'top': $el.scrollTop(),
-                               'left': $el.scrollLeft()
-                       },
-                       'scrollbar': {
-                               'right': $el.innerWidth() - el.clientWidth,
-                               'bottom': $el.innerHeight() - el.clientHeight
-                       },
-                       'rect': el.getBoundingClientRect()
-               };
-       }
-};
-
-/**
- * Get closest scrollable container.
- *
- * Traverses up until either a scrollable element or the root is reached, in which case the window
- * will be returned.
- *
- * @static
- * @param {HTMLElement} el Element to find scrollable container for
- * @param {string} [dimension] Dimension of scrolling to look for; `x`, `y` or omit for either
- * @return {HTMLElement|Window} Closest scrollable container
- */
-OO.ui.Element.getClosestScrollableContainer = function ( el, dimension ) {
-       var i, val,
-               props = [ 'overflow' ],
-               $parent = $( el ).parent();
-
-       if ( dimension === 'x' || dimension === 'y' ) {
-               props.push( 'overflow-' + dimension );
-       }
-
-       while ( $parent.length ) {
-               if ( $parent[0] === el.ownerDocument.body ) {
-                       return $parent[0];
-               }
-               i = props.length;
-               while ( i-- ) {
-                       val = $parent.css( props[i] );
-                       if ( val === 'auto' || val === 'scroll' ) {
-                               return $parent[0];
-                       }
-               }
-               $parent = $parent.parent();
-       }
-       return this.getDocument( el ).body;
-};
-
-/**
- * Scroll element into view.
- *
- * @static
- * @param {HTMLElement} el Element to scroll into view
- * @param {Object} [config={}] Configuration config
- * @param {string} [config.duration] jQuery animation duration value
- * @param {string} [config.direction] Scroll in only one direction, e.g. 'x' or 'y', omit
- *  to scroll in both directions
- * @param {Function} [config.complete] Function to call when scrolling completes
- */
-OO.ui.Element.scrollIntoView = function ( el, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       var anim = {},
-               callback = typeof config.complete === 'function' && config.complete,
-               sc = this.getClosestScrollableContainer( el, config.direction ),
-               $sc = $( sc ),
-               eld = this.getDimensions( el ),
-               scd = this.getDimensions( sc ),
-               rel = {
-                       'top': eld.rect.top - ( scd.rect.top + scd.borders.top ),
-                       'bottom': scd.rect.bottom - scd.borders.bottom - scd.scrollbar.bottom - eld.rect.bottom,
-                       'left': eld.rect.left - ( scd.rect.left + scd.borders.left ),
-                       'right': scd.rect.right - scd.borders.right - scd.scrollbar.right - eld.rect.right
-               };
-
-       if ( !config.direction || config.direction === 'y' ) {
-               if ( rel.top < 0 ) {
-                       anim.scrollTop = scd.scroll.top + rel.top;
-               } else if ( rel.top > 0 && rel.bottom < 0 ) {
-                       anim.scrollTop = scd.scroll.top + Math.min( rel.top, -rel.bottom );
-               }
-       }
-       if ( !config.direction || config.direction === 'x' ) {
-               if ( rel.left < 0 ) {
-                       anim.scrollLeft = scd.scroll.left + rel.left;
-               } else if ( rel.left > 0 && rel.right < 0 ) {
-                       anim.scrollLeft = scd.scroll.left + Math.min( rel.left, -rel.right );
-               }
-       }
-       if ( !$.isEmptyObject( anim ) ) {
-               $sc.stop( true ).animate( anim, config.duration || 'fast' );
-               if ( callback ) {
-                       $sc.queue( function ( next ) {
-                               callback();
-                               next();
-                       } );
-               }
-       } else {
-               if ( callback ) {
-                       callback();
-               }
-       }
-};
-
-/* Methods */
-
-/**
- * Get the HTML tag name.
- *
- * Override this method to base the result on instance information.
- *
- * @return {string} HTML tag name
- */
-OO.ui.Element.prototype.getTagName = function () {
-       return this.constructor.static.tagName;
-};
-
-/**
- * Check if the element is attached to the DOM
- * @return {boolean} The element is attached to the DOM
- */
-OO.ui.Element.prototype.isElementAttached = function () {
-       return $.contains( this.getElementDocument(), this.$element[0] );
-};
-
-/**
- * Get the DOM document.
- *
- * @return {HTMLDocument} Document object
- */
-OO.ui.Element.prototype.getElementDocument = function () {
-       return OO.ui.Element.getDocument( this.$element );
-};
-
-/**
- * Get the DOM window.
- *
- * @return {Window} Window object
- */
-OO.ui.Element.prototype.getElementWindow = function () {
-       return OO.ui.Element.getWindow( this.$element );
-};
-
-/**
- * Get closest scrollable container.
- *
- * @see #static-method-getClosestScrollableContainer
- */
-OO.ui.Element.prototype.getClosestScrollableElementContainer = function () {
-       return OO.ui.Element.getClosestScrollableContainer( this.$element[0] );
-};
-
-/**
- * Get group element is in.
- *
- * @return {OO.ui.GroupElement|null} Group element, null if none
- */
-OO.ui.Element.prototype.getElementGroup = function () {
-       return this.elementGroup;
-};
-
-/**
- * Set group element is in.
- *
- * @param {OO.ui.GroupElement|null} group Group element, null if none
- * @chainable
- */
-OO.ui.Element.prototype.setElementGroup = function ( group ) {
-       this.elementGroup = group;
-       return this;
-};
-
-/**
- * Scroll element into view.
- *
- * @see #static-method-scrollIntoView
- * @param {Object} [config={}]
- */
-OO.ui.Element.prototype.scrollElementIntoView = function ( config ) {
-       return OO.ui.Element.scrollIntoView( this.$element[0], config );
-};
-
-( function () {
-       // Static
-       var specialFocusin;
-
-       function handler( e ) {
-               jQuery.event.simulate( 'focusin', e.target, jQuery.event.fix( e ), /* bubble = */ true );
-       }
-
-       specialFocusin = {
-               setup: function () {
-                       var doc = this.ownerDocument || this,
-                               attaches = $.data( doc, 'ooui-focusin-attaches' );
-                       if ( !attaches ) {
-                               doc.addEventListener( 'focus', handler, true );
-                       }
-                       $.data( doc, 'ooui-focusin-attaches', ( attaches || 0 ) + 1 );
-               },
-               teardown: function () {
-                       var doc = this.ownerDocument || this,
-                               attaches = $.data( doc, 'ooui-focusin-attaches' ) - 1;
-                       if ( !attaches ) {
-                               doc.removeEventListener( 'focus', handler, true );
-                               $.removeData( doc, 'ooui-focusin-attaches' );
-                       } else {
-                               $.data( doc, 'ooui-focusin-attaches', attaches );
-                       }
-               }
-       };
-
-       /**
-        * Bind a handler for an event on the DOM element.
-        *
-        * Uses jQuery internally for everything except for events which are
-        * known to have issues in the browser or in jQuery. This method
-        * should become obsolete eventually.
-        *
-        * @param {string} event
-        * @param {Function} callback
-        */
-       OO.ui.Element.prototype.onDOMEvent = function ( event, callback ) {
-               var orig;
-
-               if ( event === 'focusin' ) {
-                       // jQuery 1.8.3 has a bug with handling focusin events inside iframes.
-                       // Firefox doesn't support focusin at all, so we listen for 'focus' on the
-                       // document, and simulate a 'focusin' event on the target element and make
-                       // it bubble from there.
-                       //
-                       // - http://jsfiddle.net/sw3hr/
-                       // - http://bugs.jquery.com/ticket/14180
-                       // - https://github.com/jquery/jquery/commit/1cecf64e5aa4153
-
-                       // Replace jQuery's override with our own
-                       orig = $.event.special.focusin;
-                       $.event.special.focusin = specialFocusin;
-
-                       this.$element.on( event, callback );
-
-                       // Restore
-                       $.event.special.focusin = orig;
-
-               } else {
-                       this.$element.on( event, callback );
-               }
-       };
-
-       /**
-        * @param {string} event
-        * @param {Function} callback
-        */
-       OO.ui.Element.prototype.offDOMEvent = function ( event, callback ) {
-               var orig;
-               if ( event === 'focusin' ) {
-                       orig = $.event.special.focusin;
-                       $.event.special.focusin = specialFocusin;
-                       this.$element.off( event, callback );
-                       $.event.special.focusin = orig;
-               } else {
-                       this.$element.off( event, callback );
-               }
-       };
-}() );
-/**
- * Embedded iframe with the same styles as its parent.
- *
- * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.Frame = function OoUiFrame( config ) {
-       // Parent constructor
-       OO.ui.Frame.super.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-
-       // Properties
-       this.loading = false;
-       this.loaded = false;
-       this.config = config;
-
-       // Initialize
-       this.$element
-               .addClass( 'oo-ui-frame' )
-               .attr( { 'frameborder': 0, 'scrolling': 'no' } );
-
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Frame, OO.ui.Element );
-
-OO.mixinClass( OO.ui.Frame, OO.EventEmitter );
-
-/* Static Properties */
-
-/**
- * @static
- * @inheritdoc
- */
-OO.ui.Frame.static.tagName = 'iframe';
-
-/* Events */
-
-/**
- * @event load
- */
-
-/* Static Methods */
-
-/**
- * Transplant the CSS styles from as parent document to a frame's document.
- *
- * This loops over the style sheets in the parent document, and copies their nodes to the
- * frame's document. It then polls the document to see when all styles have loaded, and once they
- * have, invokes the callback.
- *
- * If the styles still haven't loaded after a long time (5 seconds by default), we give up waiting
- * and invoke the callback anyway. This protects against cases like a display: none; iframe in
- * Firefox, where the styles won't load until the iframe becomes visible.
- *
- * For details of how we arrived at the strategy used in this function, see #load.
- *
- * @static
- * @inheritable
- * @param {HTMLDocument} parentDoc Document to transplant styles from
- * @param {HTMLDocument} frameDoc Document to transplant styles to
- * @param {Function} [callback] Callback to execute once styles have loaded
- * @param {number} [timeout=5000] How long to wait before giving up (in ms). If 0, never give up.
- */
-OO.ui.Frame.static.transplantStyles = function ( parentDoc, frameDoc, callback, timeout ) {
-       var i, numSheets, styleNode, newNode, timeoutID, pollNodeId, $pendingPollNodes,
-               $pollNodes = $( [] ),
-               // Fake font-family value
-               fontFamily = 'oo-ui-frame-transplantStyles-loaded';
-
-       for ( i = 0, numSheets = parentDoc.styleSheets.length; i < numSheets; i++ ) {
-               styleNode = parentDoc.styleSheets[i].ownerNode;
-               if ( callback && styleNode.nodeName.toLowerCase() === 'link' ) {
-                       // External stylesheet
-                       // Create a node with a unique ID that we're going to monitor to see when the CSS
-                       // has loaded
-                       pollNodeId = 'oo-ui-frame-transplantStyles-loaded-' + i;
-                       $pollNodes = $pollNodes.add( $( '<div>', frameDoc )
-                               .attr( 'id', pollNodeId )
-                               .appendTo( frameDoc.body )
-                       );
-
-                       // Add <style>@import url(...); #pollNodeId { font-family: ... }</style>
-                       // The font-family rule will only take effect once the @import finishes
-                       newNode = frameDoc.createElement( 'style' );
-                       newNode.textContent = '@import url(' + styleNode.href + ');\n' +
-                               '#' + pollNodeId + ' { font-family: ' + fontFamily + '; }';
-               } else {
-                       // Not an external stylesheet, or no polling required; just copy the node over
-                       newNode = frameDoc.importNode( styleNode, true );
-               }
-               frameDoc.head.appendChild( newNode );
-       }
-
-       if ( callback ) {
-               // Poll every 100ms until all external stylesheets have loaded
-               $pendingPollNodes = $pollNodes;
-               timeoutID = setTimeout( function pollExternalStylesheets() {
-                       while (
-                               $pendingPollNodes.length > 0 &&
-                               $pendingPollNodes.eq( 0 ).css( 'font-family' ) === fontFamily
-                       ) {
-                               $pendingPollNodes = $pendingPollNodes.slice( 1 );
-                       }
-
-                       if ( $pendingPollNodes.length === 0 ) {
-                               // We're done!
-                               if ( timeoutID !== null ) {
-                                       timeoutID = null;
-                                       $pollNodes.remove();
-                                       callback();
-                               }
-                       } else {
-                               timeoutID = setTimeout( pollExternalStylesheets, 100 );
-                       }
-               }, 100 );
-               // ...but give up after a while
-               if ( timeout !== 0 ) {
-                       setTimeout( function () {
-                               if ( timeoutID ) {
-                                       clearTimeout( timeoutID );
-                                       timeoutID = null;
-                                       $pollNodes.remove();
-                                       callback();
-                               }
-                       }, timeout || 5000 );
-               }
-       }
-};
-
-/* Methods */
-
-/**
- * Load the frame contents.
- *
- * Once the iframe's stylesheets are loaded, the `initialize` event will be emitted.
- *
- * Sounds simple right? Read on...
- *
- * When you create a dynamic iframe using open/write/close, the window.load event for the
- * iframe is triggered when you call close, and there's no further load event to indicate that
- * everything is actually loaded.
- *
- * In Chrome, stylesheets don't show up in document.styleSheets until they have loaded, so we could
- * just poll that array and wait for it to have the right length. However, in Firefox, stylesheets
- * are added to document.styleSheets immediately, and the only way you can determine whether they've
- * loaded is to attempt to access .cssRules and wait for that to stop throwing an exception. But
- * cross-domain stylesheets never allow .cssRules to be accessed even after they have loaded.
- *
- * The workaround is to change all `<link href="...">` tags to `<style>@import url(...)</style>` tags.
- * Because `@import` is blocking, Chrome won't add the stylesheet to document.styleSheets until
- * the `@import` has finished, and Firefox won't allow .cssRules to be accessed until the `@import`
- * has finished. And because the contents of the `<style>` tag are from the same origin, accessing
- * .cssRules is allowed.
- *
- * However, now that we control the styles we're injecting, we might as well do away with
- * browser-specific polling hacks like document.styleSheets and .cssRules, and instead inject
- * `<style>@import url(...); #foo { font-family: someValue; }</style>`, then create `<div id="foo">`
- * and wait for its font-family to change to someValue. Because `@import` is blocking, the font-family
- * rule is not applied until after the `@import` finishes.
- *
- * All this stylesheet injection and polling magic is in #transplantStyles.
- *
- * @private
- * @fires load
- */
-OO.ui.Frame.prototype.load = function () {
-       var win = this.$element.prop( 'contentWindow' ),
-               doc = win.document,
-               frame = this;
-
-       this.loading = true;
-
-       // Figure out directionality:
-       this.dir = this.$element.closest( '[dir]' ).prop( 'dir' ) || 'ltr';
-
-       // Initialize contents
-       doc.open();
-       doc.write(
-               '<!doctype html>' +
-               '<html>' +
-                       '<body class="oo-ui-frame-body oo-ui-' + this.dir + '" style="direction:' + this.dir + ';" dir="' + this.dir + '">' +
-                               '<div class="oo-ui-frame-content"></div>' +
-                       '</body>' +
-               '</html>'
-       );
-       doc.close();
-
-       // Properties
-       this.$ = OO.ui.Element.getJQuery( doc, this );
-       this.$content = this.$( '.oo-ui-frame-content' );
-       this.$document = this.$( doc );
-
-       this.constructor.static.transplantStyles(
-               this.getElementDocument(),
-               this.$document[0],
-               function () {
-                       frame.loading = false;
-                       frame.loaded = true;
-                       frame.emit( 'load' );
-               }
-       );
-};
-
-/**
- * Run a callback as soon as the frame has been loaded.
- *
- *
- * This will start loading if it hasn't already, and runs
- * immediately if the frame is already loaded.
- *
- * Don't call this until the element is attached.
- *
- * @param {Function} callback
- */
-OO.ui.Frame.prototype.run = function ( callback ) {
-       if ( this.loaded ) {
-               callback();
-       } else {
-               if ( !this.loading ) {
-                       this.load();
-               }
-               this.once( 'load', callback );
-       }
-};
-
-/**
- * Sets the size of the frame.
- *
- * @param {number} width Frame width in pixels
- * @param {number} height Frame height in pixels
- * @chainable
- */
-OO.ui.Frame.prototype.setSize = function ( width, height ) {
-       this.$element.css( { 'width': width, 'height': height } );
-       return this;
-};
-/**
- * Container for elements in a child frame.
- *
- * There are two ways to specify a title: set the static `title` property or provide a `title`
- * property in the configuration options. The latter will override the former.
- *
- * @abstract
- * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string|Function} [title] Title string or function that returns a string
- * @cfg {string} [icon] Symbolic name of icon
- * @fires initialize
- */
-OO.ui.Window = function OoUiWindow( config ) {
-       // Parent constructor
-       OO.ui.Window.super.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-
-       // Properties
-       this.visible = false;
-       this.opening = false;
-       this.closing = false;
-       this.title = OO.ui.resolveMsg( config.title || this.constructor.static.title );
-       this.icon = config.icon || this.constructor.static.icon;
-       this.frame = new OO.ui.Frame( { '$': this.$ } );
-       this.$frame = this.$( '<div>' );
-       this.$ = function () {
-               throw new Error( 'this.$() cannot be used until the frame has been initialized.' );
-       };
-
-       // Initialization
-       this.$element
-               .addClass( 'oo-ui-window' )
-               // Hide the window using visibility: hidden; while the iframe is still loading
-               // Can't use display: none; because that prevents the iframe from loading in Firefox
-               .css( 'visibility', 'hidden' )
-               .append( this.$frame );
-       this.$frame
-               .addClass( 'oo-ui-window-frame' )
-               .append( this.frame.$element );
-
-       // Events
-       this.frame.connect( this, { 'load': 'initialize' } );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Window, OO.ui.Element );
-
-OO.mixinClass( OO.ui.Window, OO.EventEmitter );
-
-/* Events */
-
-/**
- * Initialize contents.
- *
- * Fired asynchronously after construction when iframe is ready.
- *
- * @event initialize
- */
-
-/**
- * Open window.
- *
- * Fired after window has been opened.
- *
- * @event open
- * @param {Object} data Window opening data
- */
-
-/**
- * Close window.
- *
- * Fired after window has been closed.
- *
- * @event close
- * @param {Object} data Window closing data
- */
-
-/* Static Properties */
-
-/**
- * Symbolic name of icon.
- *
- * @static
- * @inheritable
- * @property {string}
- */
-OO.ui.Window.static.icon = 'window';
-
-/**
- * Window title.
- *
- * Subclasses must implement this property before instantiating the window.
- * Alternatively, override #getTitle with an alternative implementation.
- *
- * @static
- * @abstract
- * @inheritable
- * @property {string|Function} Title string or function that returns a string
- */
-OO.ui.Window.static.title = null;
-
-/* Methods */
-
-/**
- * Check if window is visible.
- *
- * @return {boolean} Window is visible
- */
-OO.ui.Window.prototype.isVisible = function () {
-       return this.visible;
-};
-
-/**
- * Check if window is opening.
- *
- * @return {boolean} Window is opening
- */
-OO.ui.Window.prototype.isOpening = function () {
-       return this.opening;
-};
-
-/**
- * Check if window is closing.
- *
- * @return {boolean} Window is closing
- */
-OO.ui.Window.prototype.isClosing = function () {
-       return this.closing;
-};
-
-/**
- * Get the window frame.
- *
- * @return {OO.ui.Frame} Frame of window
- */
-OO.ui.Window.prototype.getFrame = function () {
-       return this.frame;
-};
-
-/**
- * Get the title of the window.
- *
- * @return {string} Title text
- */
-OO.ui.Window.prototype.getTitle = function () {
-       return this.title;
-};
-
-/**
- * Get the window icon.
- *
- * @return {string} Symbolic name of icon
- */
-OO.ui.Window.prototype.getIcon = function () {
-       return this.icon;
-};
-
-/**
- * Set the size of window frame.
- *
- * @param {number} [width=auto] Custom width
- * @param {number} [height=auto] Custom height
- * @chainable
- */
-OO.ui.Window.prototype.setSize = function ( width, height ) {
-       if ( !this.frame.$content ) {
-               return;
-       }
-
-       this.frame.$element.css( {
-               'width': width === undefined ? 'auto' : width,
-               'height': height === undefined ? 'auto' : height
-       } );
-
-       return this;
-};
-
-/**
- * Set the title of the window.
- *
- * @param {string|Function} title Title text or a function that returns text
- * @chainable
- */
-OO.ui.Window.prototype.setTitle = function ( title ) {
-       this.title = OO.ui.resolveMsg( title );
-       if ( this.$title ) {
-               this.$title.text( title );
-       }
-       return this;
-};
-
-/**
- * Set the icon of the window.
- *
- * @param {string} icon Symbolic name of icon
- * @chainable
- */
-OO.ui.Window.prototype.setIcon = function ( icon ) {
-       if ( this.$icon ) {
-               this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
-       }
-       this.icon = icon;
-       if ( this.$icon ) {
-               this.$icon.addClass( 'oo-ui-icon-' + this.icon );
-       }
-
-       return this;
-};
-
-/**
- * Set the position of window to fit with contents.
- *
- * @param {string} left Left offset
- * @param {string} top Top offset
- * @chainable
- */
-OO.ui.Window.prototype.setPosition = function ( left, top ) {
-       this.$element.css( { 'left': left, 'top': top } );
-       return this;
-};
-
-/**
- * Set the height of window to fit with contents.
- *
- * @param {number} [min=0] Min height
- * @param {number} [max] Max height (defaults to content's outer height)
- * @chainable
- */
-OO.ui.Window.prototype.fitHeightToContents = function ( min, max ) {
-       var height = this.frame.$content.outerHeight();
-
-       this.frame.$element.css(
-               'height', Math.max( min || 0, max === undefined ? height : Math.min( max, height ) )
-       );
-
-       return this;
-};
-
-/**
- * Set the width of window to fit with contents.
- *
- * @param {number} [min=0] Min height
- * @param {number} [max] Max height (defaults to content's outer width)
- * @chainable
- */
-OO.ui.Window.prototype.fitWidthToContents = function ( min, max ) {
-       var width = this.frame.$content.outerWidth();
-
-       this.frame.$element.css(
-               'width', Math.max( min || 0, max === undefined ? width : Math.min( max, width ) )
-       );
-
-       return this;
-};
-
-/**
- * Initialize window contents.
- *
- * The first time the window is opened, #initialize is called when it's safe to begin populating
- * its contents. See #setup for a way to make changes each time the window opens.
- *
- * Once this method is called, this.$$ can be used to create elements within the frame.
- *
- * @fires initialize
- * @chainable
- */
-OO.ui.Window.prototype.initialize = function () {
-       // Properties
-       this.$ = this.frame.$;
-       this.$title = this.$( '<div class="oo-ui-window-title"></div>' )
-               .text( this.title );
-       this.$icon = this.$( '<div class="oo-ui-window-icon"></div>' )
-               .addClass( 'oo-ui-icon-' + this.icon );
-       this.$head = this.$( '<div class="oo-ui-window-head"></div>' );
-       this.$body = this.$( '<div class="oo-ui-window-body"></div>' );
-       this.$foot = this.$( '<div class="oo-ui-window-foot"></div>' );
-       this.$overlay = this.$( '<div class="oo-ui-window-overlay"></div>' );
-
-       // Initialization
-       this.frame.$content.append(
-               this.$head.append( this.$icon, this.$title ),
-               this.$body,
-               this.$foot,
-               this.$overlay
-       );
-
-       // Undo the visibility: hidden; hack from the constructor and apply display: none;
-       // We can do this safely now that the iframe has initialized
-       this.$element.hide().css( 'visibility', '' );
-
-       this.emit( 'initialize' );
-
-       return this;
-};
-
-/**
- * Setup window for use.
- *
- * Each time the window is opened, once it's ready to be interacted with, this will set it up for
- * use in a particular context, based on the `data` argument.
- *
- * When you override this method, you must call the parent method at the very beginning.
- *
- * @abstract
- * @param {Object} [data] Window opening data
- */
-OO.ui.Window.prototype.setup = function () {
-       // Override to do something
-};
-
-/**
- * Tear down window after use.
- *
- * Each time the window is closed, and it's done being interacted with, this will tear it down and
- * do something with the user's interactions within the window, based on the `data` argument.
- *
- * When you override this method, you must call the parent method at the very end.
- *
- * @abstract
- * @param {Object} [data] Window closing data
- */
-OO.ui.Window.prototype.teardown = function () {
-       // Override to do something
-};
-
-/**
- * Open window.
- *
- * Do not override this method. See #setup for a way to make changes each time the window opens.
- *
- * @param {Object} [data] Window opening data
- * @fires open
- * @chainable
- */
-OO.ui.Window.prototype.open = function ( data ) {
-       if ( !this.opening && !this.closing && !this.visible ) {
-               this.opening = true;
-               this.frame.run( OO.ui.bind( function () {
-                       this.$element.show();
-                       this.visible = true;
-                       this.frame.$element.focus();
-                       this.emit( 'opening', data );
-                       this.setup( data );
-                       this.emit( 'open', data );
-                       this.opening = false;
-               }, this ) );
-       }
-
-       return this;
-};
-
-/**
- * Close window.
- *
- * See #teardown for a way to do something each time the window closes.
- *
- * @param {Object} [data] Window closing data
- * @fires close
- * @chainable
- */
-OO.ui.Window.prototype.close = function ( data ) {
-       if ( !this.opening && !this.closing && this.visible ) {
-               this.frame.$content.find( ':focus' ).blur();
-               this.closing = true;
-               this.$element.hide();
-               this.visible = false;
-               this.emit( 'closing', data );
-               this.teardown( data );
-               this.emit( 'close', data );
-               this.closing = false;
-       }
-
-       return this;
-};
-/**
- * Set of mutually exclusive windows.
- *
- * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
- *
- * @constructor
- * @param {OO.Factory} factory Window factory
- * @param {Object} [config] Configuration options
- */
-OO.ui.WindowSet = function OoUiWindowSet( factory, config ) {
-       // Parent constructor
-       OO.ui.WindowSet.super.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-
-       // Properties
-       this.factory = factory;
-
-       /**
-        * List of all windows associated with this window set.
-        *
-        * @property {OO.ui.Window[]}
-        */
-       this.windowList = [];
-
-       /**
-        * Mapping of OO.ui.Window objects created by name from the #factory.
-        *
-        * @property {Object}
-        */
-       this.windows = {};
-       this.currentWindow = null;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-windowSet' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.WindowSet, OO.ui.Element );
-
-OO.mixinClass( OO.ui.WindowSet, OO.EventEmitter );
-
-/* Events */
-
-/**
- * @event opening
- * @param {OO.ui.Window} win Window that's being opened
- * @param {Object} config Window opening information
- */
-
-/**
- * @event open
- * @param {OO.ui.Window} win Window that's been opened
- * @param {Object} config Window opening information
- */
-
-/**
- * @event closing
- * @param {OO.ui.Window} win Window that's being closed
- * @param {Object} config Window closing information
- */
-
-/**
- * @event close
- * @param {OO.ui.Window} win Window that's been closed
- * @param {Object} config Window closing information
- */
-
-/* Methods */
-
-/**
- * Handle a window that's being opened.
- *
- * @param {OO.ui.Window} win Window that's being opened
- * @param {Object} [config] Window opening information
- * @fires opening
- */
-OO.ui.WindowSet.prototype.onWindowOpening = function ( win, config ) {
-       if ( this.currentWindow && this.currentWindow !== win ) {
-               this.currentWindow.close();
-       }
-       this.currentWindow = win;
-       this.emit( 'opening', win, config );
-};
-
-/**
- * Handle a window that's been opened.
- *
- * @param {OO.ui.Window} win Window that's been opened
- * @param {Object} [config] Window opening information
- * @fires open
- */
-OO.ui.WindowSet.prototype.onWindowOpen = function ( win, config ) {
-       this.emit( 'open', win, config );
-};
-
-/**
- * Handle a window that's being closed.
- *
- * @param {OO.ui.Window} win Window that's being closed
- * @param {Object} [config] Window closing information
- * @fires closing
- */
-OO.ui.WindowSet.prototype.onWindowClosing = function ( win, config ) {
-       this.currentWindow = null;
-       this.emit( 'closing', win, config );
-};
-
-/**
- * Handle a window that's been closed.
- *
- * @param {OO.ui.Window} win Window that's been closed
- * @param {Object} [config] Window closing information
- * @fires close
- */
-OO.ui.WindowSet.prototype.onWindowClose = function ( win, config ) {
-       this.emit( 'close', win, config );
-};
-
-/**
- * Get the current window.
- *
- * @return {OO.ui.Window} Current window
- */
-OO.ui.WindowSet.prototype.getCurrentWindow = function () {
-       return this.currentWindow;
-};
-
-/**
- * Return a given window.
- *
- * @param {string} name Symbolic name of window
- * @return {OO.ui.Window} Window with specified name
- */
-OO.ui.WindowSet.prototype.getWindow = function ( name ) {
-       var win;
-
-       if ( !this.factory.lookup( name ) ) {
-               throw new Error( 'Unknown window: ' + name );
-       }
-       if ( !( name in this.windows ) ) {
-               win = this.windows[name] = this.createWindow( name );
-               this.addWindow( win );
-       }
-       return this.windows[name];
-};
-
-/**
- * Create a window for use in this window set.
- *
- * @param {string} name Symbolic name of window
- * @return {OO.ui.Window} Window with specified name
- */
-OO.ui.WindowSet.prototype.createWindow = function ( name ) {
-       return this.factory.create( name, { '$': this.$ } );
-};
-
-/**
- * Add a given window to this window set.
- *
- * Connects event handlers and attaches it to the DOM. Calling
- * OO.ui.Window#open will not work until the window is added to the set.
- *
- * @param {OO.ui.Window} win
- */
-OO.ui.WindowSet.prototype.addWindow = function ( win ) {
-       if ( this.windowList.indexOf( win ) !== -1 ) {
-               // Already set up
-               return;
-       }
-       this.windowList.push( win );
-
-       win.connect( this, {
-               'opening': [ 'onWindowOpening', win ],
-               'open': [ 'onWindowOpen', win ],
-               'closing': [ 'onWindowClosing', win ],
-               'close': [ 'onWindowClose', win ]
-       } );
-       this.$element.append( win.$element );
-};
-/**
- * @abstract
- * @class
- * @extends OO.ui.Window
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [footless] Hide foot
- * @cfg {string} [size='large'] Symbolic name of dialog size, `small`, `medium` or `large`
- */
-OO.ui.Dialog = function OoUiDialog( config ) {
-       // Configuration initialization
-       config = $.extend( { 'size': 'large' }, config );
-
-       // Parent constructor
-       OO.ui.Dialog.super.call( this, config );
-
-       // Properties
-       this.visible = false;
-       this.footless = !!config.footless;
-       this.size = null;
-       this.onWindowMouseWheelHandler = OO.ui.bind( this.onWindowMouseWheel, this );
-       this.onDocumentKeyDownHandler = OO.ui.bind( this.onDocumentKeyDown, this );
-
-       // Events
-       this.$element.on( 'mousedown', false );
-       this.connect( this, { 'opening': 'onOpening' } );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-dialog' );
-       this.setSize( config.size );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Dialog, OO.ui.Window );
-
-/* Static Properties */
-
-/**
- * Symbolic name of dialog.
- *
- * @abstract
- * @static
- * @property {string}
- * @inheritable
- */
-OO.ui.Dialog.static.name = '';
-
-/**
- * Map of symbolic size names and CSS classes.
- *
- * @static
- * @property {Object}
- * @inheritable
- */
-OO.ui.Dialog.static.sizeCssClasses = {
-       'small': 'oo-ui-dialog-small',
-       'medium': 'oo-ui-dialog-medium',
-       'large': 'oo-ui-dialog-large'
-};
-
-/* Methods */
-
-/**
- * Handle close button click events.
- */
-OO.ui.Dialog.prototype.onCloseButtonClick = function () {
-       this.close( { 'action': 'cancel' } );
-};
-
-/**
- * Handle window mouse wheel events.
- *
- * @param {jQuery.Event} e Mouse wheel event
- */
-OO.ui.Dialog.prototype.onWindowMouseWheel = function () {
-       return false;
-};
-
-/**
- * Handle document key down events.
- *
- * @param {jQuery.Event} e Key down event
- */
-OO.ui.Dialog.prototype.onDocumentKeyDown = function ( e ) {
-       switch ( e.which ) {
-               case OO.ui.Keys.PAGEUP:
-               case OO.ui.Keys.PAGEDOWN:
-               case OO.ui.Keys.END:
-               case OO.ui.Keys.HOME:
-               case OO.ui.Keys.LEFT:
-               case OO.ui.Keys.UP:
-               case OO.ui.Keys.RIGHT:
-               case OO.ui.Keys.DOWN:
-                       // Prevent any key events that might cause scrolling
-                       return false;
-       }
-};
-
-/**
- * Handle frame document key down events.
- *
- * @param {jQuery.Event} e Key down event
- */
-OO.ui.Dialog.prototype.onFrameDocumentKeyDown = function ( e ) {
-       if ( e.which === OO.ui.Keys.ESCAPE ) {
-               this.close( { 'action': 'cancel' } );
-               return false;
-       }
-};
-
-/** */
-OO.ui.Dialog.prototype.onOpening = function () {
-       this.$element.addClass( 'oo-ui-dialog-open' );
-};
-
-/**
- * Set dialog size.
- *
- * @param {string} [size='large'] Symbolic name of dialog size, `small`, `medium` or `large`
- */
-OO.ui.Dialog.prototype.setSize = function ( size ) {
-       var name, state, cssClass,
-               sizeCssClasses = OO.ui.Dialog.static.sizeCssClasses;
-
-       if ( !sizeCssClasses[size] ) {
-               size = 'large';
-       }
-       this.size = size;
-       for ( name in sizeCssClasses ) {
-               state = name === size;
-               cssClass = sizeCssClasses[name];
-               this.$element.toggleClass( cssClass, state );
-               if ( this.frame.$content ) {
-                       this.frame.$content.toggleClass( cssClass, state );
-               }
-       }
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.Dialog.prototype.initialize = function () {
-       // Parent method
-       OO.ui.Window.prototype.initialize.call( this );
-
-       // Properties
-       this.closeButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'close',
-               'title': OO.ui.msg( 'ooui-dialog-action-close' )
-       } );
-
-       // Events
-       this.closeButton.connect( this, { 'click': 'onCloseButtonClick' } );
-       this.frame.$document.on( 'keydown', OO.ui.bind( this.onFrameDocumentKeyDown, this ) );
-
-       // Initialization
-       this.frame.$content.addClass( 'oo-ui-dialog-content' );
-       if ( this.footless ) {
-               this.frame.$content.addClass( 'oo-ui-dialog-content-footless' );
-       }
-       this.closeButton.$element.addClass( 'oo-ui-window-closeButton' );
-       this.$head.append( this.closeButton.$element );
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.Dialog.prototype.setup = function ( data ) {
-       // Parent method
-       OO.ui.Window.prototype.setup.call( this, data );
-
-       // Prevent scrolling in top-level window
-       this.$( window ).on( 'mousewheel', this.onWindowMouseWheelHandler );
-       this.$( document ).on( 'keydown', this.onDocumentKeyDownHandler );
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.Dialog.prototype.teardown = function ( data ) {
-       // Parent method
-       OO.ui.Window.prototype.teardown.call( this, data );
-
-       // Allow scrolling in top-level window
-       this.$( window ).off( 'mousewheel', this.onWindowMouseWheelHandler );
-       this.$( document ).off( 'keydown', this.onDocumentKeyDownHandler );
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.Dialog.prototype.close = function ( data ) {
-       var dialog = this;
-       if ( !dialog.opening && !dialog.closing && dialog.visible ) {
-               // Trigger transition
-               dialog.$element.removeClass( 'oo-ui-dialog-open' );
-               // Allow transition to complete before actually closing
-               setTimeout( function () {
-                       // Parent method
-                       OO.ui.Window.prototype.close.call( dialog, data );
-               }, 250 );
-       }
-};
-/**
- * Container for elements.
- *
- * @abstract
- * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.Layout = function OoUiLayout( config ) {
-       // Initialize config
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Layout.super.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-layout' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Layout, OO.ui.Element );
-
-OO.mixinClass( OO.ui.Layout, OO.EventEmitter );
-/**
- * User interface control.
- *
- * @abstract
- * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [disabled=false] Disable
- */
-OO.ui.Widget = function OoUiWidget( config ) {
-       // Initialize config
-       config = $.extend( { 'disabled': false }, config );
-
-       // Parent constructor
-       OO.ui.Widget.super.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-
-       // Properties
-       this.disabled = null;
-       this.wasDisabled = null;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-widget' );
-       this.setDisabled( !!config.disabled );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Widget, OO.ui.Element );
-
-OO.mixinClass( OO.ui.Widget, OO.EventEmitter );
-
-/* Events */
-
-/**
- * @event disable
- * @param {boolean} disabled Widget is disabled
- */
-
-/* Methods */
-
-/**
- * Check if the widget is disabled.
- *
- * @param {boolean} Button is disabled
- */
-OO.ui.Widget.prototype.isDisabled = function () {
-       return this.disabled;
-};
-
-/**
- * Update the disabled state, in case of changes in parent widget.
- *
- * @chainable
- */
-OO.ui.Widget.prototype.updateDisabled = function () {
-       this.setDisabled( this.disabled );
-       return this;
-};
-
-/**
- * Set the disabled state of the widget.
- *
- * This should probably change the widgets' appearance and prevent it from being used.
- *
- * @param {boolean} disabled Disable widget
- * @chainable
- */
-OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
-       var isDisabled;
-
-       this.disabled = !!disabled;
-       isDisabled = this.isDisabled();
-       if ( isDisabled !== this.wasDisabled ) {
-               this.$element.toggleClass( 'oo-ui-widget-disabled', isDisabled );
-               this.$element.toggleClass( 'oo-ui-widget-enabled', !isDisabled );
-               this.emit( 'disable', isDisabled );
-       }
-       this.wasDisabled = isDisabled;
-       return this;
-};
-/**
- * Element with a button.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $button Button node, assigned to #$button
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [frameless] Render button without a frame
- * @cfg {number} [tabIndex=0] Button's tab index, use -1 to prevent tab focusing
- */
-OO.ui.ButtonedElement = function OoUiButtonedElement( $button, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Properties
-       this.$button = $button;
-       this.tabIndex = null;
-       this.active = false;
-       this.onMouseUpHandler = OO.ui.bind( this.onMouseUp, this );
-
-       // Events
-       this.$button.on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-buttonedElement' );
-       this.$button
-               .addClass( 'oo-ui-buttonedElement-button' )
-               .attr( 'role', 'button' )
-               .prop( 'tabIndex', config.tabIndex || 0 );
-       if ( config.frameless ) {
-               this.$element.addClass( 'oo-ui-buttonedElement-frameless' );
-       } else {
-               this.$element.addClass( 'oo-ui-buttonedElement-framed' );
-       }
-};
-
-/* Methods */
-
-/**
- * Handles mouse down events.
- *
- * @method
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.ButtonedElement.prototype.onMouseDown = function () {
-       this.tabIndex = this.$button.attr( 'tabIndex' );
-       // Remove the tab-index while the button is down to prevent the button from stealing focus
-       this.$button
-               .removeAttr( 'tabIndex' )
-               .addClass( 'oo-ui-buttonedElement-pressed' );
-       this.getElementDocument().addEventListener( 'mouseup', this.onMouseUpHandler, true );
-};
-
-/**
- * Handles mouse up events.
- *
- * @method
- * @param {jQuery.Event} e Mouse up event
- */
-OO.ui.ButtonedElement.prototype.onMouseUp = function () {
-       // Restore the tab-index after the button is up to restore the button's accesssibility
-       this.$button
-               .attr( 'tabIndex', this.tabIndex )
-               .removeClass( 'oo-ui-buttonedElement-pressed' );
-       this.getElementDocument().removeEventListener( 'mouseup', this.onMouseUpHandler, true );
-};
-
-/**
- * Set active state.
- *
- * @method
- * @param {boolean} [value] Make button active
- * @chainable
- */
-OO.ui.ButtonedElement.prototype.setActive = function ( value ) {
-       this.$button.toggleClass( 'oo-ui-buttonedElement-active', !!value );
-       return this;
-};
-/**
- * Element that can be automatically clipped to visible boundaies.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $clippable Nodes to clip, assigned to #$clippable
- * @param {Object} [config] Configuration options
- */
-OO.ui.ClippableElement = function OoUiClippableElement( $clippable, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Properties
-       this.$clippable = $clippable;
-       this.clipping = false;
-       this.clipped = false;
-       this.$clippableContainer = null;
-       this.$clippableScroller = null;
-       this.$clippableWindow = null;
-       this.idealWidth = null;
-       this.idealHeight = null;
-       this.onClippableContainerScrollHandler = OO.ui.bind( this.clip, this );
-       this.onClippableWindowResizeHandler = OO.ui.bind( this.clip, this );
-
-       // Initialization
-       this.$clippable.addClass( 'oo-ui-clippableElement-clippable' );
-};
-
-/* Methods */
-
-/**
- * Set clipping.
- *
- * @method
- * @param {boolean} value Enable clipping
- * @chainable
- */
-OO.ui.ClippableElement.prototype.setClipping = function ( value ) {
-       value = !!value;
-
-       if ( this.clipping !== value ) {
-               this.clipping = value;
-               if ( this.clipping ) {
-                       this.$clippableContainer = this.$( this.getClosestScrollableElementContainer() );
-                       // If the clippable container is the body, we have to listen to scroll events and check
-                       // jQuery.scrollTop on the window because of browser inconsistencies
-                       this.$clippableScroller = this.$clippableContainer.is( 'body' ) ?
-                               this.$( OO.ui.Element.getWindow( this.$clippableContainer ) ) :
-                               this.$clippableContainer;
-                       this.$clippableScroller.on( 'scroll', this.onClippableContainerScrollHandler );
-                       this.$clippableWindow = this.$( this.getElementWindow() )
-                               .on( 'resize', this.onClippableWindowResizeHandler );
-                       // Initial clip after visible
-                       setTimeout( OO.ui.bind( this.clip, this ) );
-               } else {
-                       this.$clippableContainer = null;
-                       this.$clippableScroller.off( 'scroll', this.onClippableContainerScrollHandler );
-                       this.$clippableScroller = null;
-                       this.$clippableWindow.off( 'resize', this.onClippableWindowResizeHandler );
-                       this.$clippableWindow = null;
-               }
-       }
-
-       return this;
-};
-
-/**
- * Check if the element will be clipped to fit the visible area of the nearest scrollable container.
- *
- * @method
- * @return {boolean} Element will be clipped to the visible area
- */
-OO.ui.ClippableElement.prototype.isClipping = function () {
-       return this.clipping;
-};
-
-/**
- * Check if the bottom or right of the element is being clipped by the nearest scrollable container.
- *
- * @method
- * @return {boolean} Part of the element is being clipped
- */
-OO.ui.ClippableElement.prototype.isClipped = function () {
-       return this.clipped;
-};
-
-/**
- * Set the ideal size.
- *
- * @method
- * @param {number|string} [width] Width as a number of pixels or CSS string with unit suffix
- * @param {number|string} [height] Height as a number of pixels or CSS string with unit suffix
- */
-OO.ui.ClippableElement.prototype.setIdealSize = function ( width, height ) {
-       this.idealWidth = width;
-       this.idealHeight = height;
-};
-
-/**
- * Clip element to visible boundaries and allow scrolling when needed.
- *
- * Element will be clipped the bottom or right of the element is within 10px of the edge of, or
- * overlapped by, the visible area of the nearest scrollable container.
- *
- * @method
- * @chainable
- */
-OO.ui.ClippableElement.prototype.clip = function () {
-       if ( !this.clipping ) {
-               // this.$clippableContainer and this.$clippableWindow are null, so the below will fail
-               return this;
-       }
-
-       var buffer = 10,
-               cOffset = this.$clippable.offset(),
-               ccOffset = this.$clippableContainer.offset() || { 'top': 0, 'left': 0 },
-               ccHeight = this.$clippableContainer.innerHeight() - buffer,
-               ccWidth = this.$clippableContainer.innerWidth() - buffer,
-               scrollTop = this.$clippableScroller.scrollTop(),
-               scrollLeft = this.$clippableScroller.scrollLeft(),
-               desiredWidth = ( ccOffset.left + scrollLeft + ccWidth ) - cOffset.left,
-               desiredHeight = ( ccOffset.top + scrollTop + ccHeight ) - cOffset.top,
-               naturalWidth = this.$clippable.prop( 'scrollWidth' ),
-               naturalHeight = this.$clippable.prop( 'scrollHeight' ),
-               clipWidth = desiredWidth < naturalWidth,
-               clipHeight = desiredHeight < naturalHeight;
-
-       if ( clipWidth ) {
-               this.$clippable.css( { 'overflow-x': 'auto', 'width': desiredWidth } );
-       } else {
-               this.$clippable.css( { 'overflow-x': '', 'width': this.idealWidth || '' } );
-       }
-       if ( clipHeight ) {
-               this.$clippable.css( { 'overflow-y': 'auto', 'height': desiredHeight } );
-       } else {
-               this.$clippable.css( { 'overflow-y': '', 'height': this.idealHeight || '' } );
-       }
-
-       this.clipped = clipWidth || clipHeight;
-
-       return this;
-};
-/**
- * Element with named flags, used for styling, that can be added, removed and listed and checked.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string[]} [flags=[]] Styling flags, e.g. 'primary', 'destructive' or 'constructive'
- */
-OO.ui.FlaggableElement = function OoUiFlaggableElement( config ) {
-       // Config initialization
-       config = config || {};
-
-       // Properties
-       this.flags = {};
-
-       // Initialization
-       this.setFlags( config.flags );
-};
-
-/* Methods */
-
-/**
- * Check if a flag is set.
- *
- * @method
- * @param {string} flag Flag name to check
- * @returns {boolean} Has flag
- */
-OO.ui.FlaggableElement.prototype.hasFlag = function ( flag ) {
-       return flag in this.flags;
-};
-
-/**
- * Get the names of all flags.
- *
- * @method
- * @returns {string[]} flags Flag names
- */
-OO.ui.FlaggableElement.prototype.getFlags = function () {
-       return Object.keys( this.flags );
-};
-
-/**
- * Add one or more flags.
- *
- * @method
- * @param {string[]|Object.<string, boolean>} flags List of flags to add, or list of set/remove
- *  values, keyed by flag name
- * @chainable
- */
-OO.ui.FlaggableElement.prototype.setFlags = function ( flags ) {
-       var i, len, flag,
-               classPrefix = 'oo-ui-flaggableElement-';
-
-       if ( $.isArray( flags ) ) {
-               for ( i = 0, len = flags.length; i < len; i++ ) {
-                       flag = flags[i];
-                       // Set
-                       this.flags[flag] = true;
-                       this.$element.addClass( classPrefix + flag );
-               }
-       } else if ( OO.isPlainObject( flags ) ) {
-               for ( flag in flags ) {
-                       if ( flags[flag] ) {
-                               // Set
-                               this.flags[flag] = true;
-                               this.$element.addClass( classPrefix + flag );
-                       } else {
-                               // Remove
-                               delete this.flags[flag];
-                               this.$element.removeClass( classPrefix + flag );
-                       }
-               }
-       }
-       return this;
-};
-/**
- * Element containing a sequence of child elements.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $group Container node, assigned to #$group
- * @param {Object} [config] Configuration options
- * @cfg {Object.<string,string>} [aggregations] Events to aggregate, keyed by item event name
- */
-OO.ui.GroupElement = function OoUiGroupElement( $group, config ) {
-       // Configuration
-       config = config || {};
-
-       // Properties
-       this.$group = $group;
-       this.items = [];
-       this.$items = this.$( [] );
-       this.aggregate = !$.isEmptyObject( config.aggregations );
-       this.aggregations = config.aggregations || {};
-};
-
-/* Methods */
-
-/**
- * Get items.
- *
- * @method
- * @returns {OO.ui.Element[]} Items
- */
-OO.ui.GroupElement.prototype.getItems = function () {
-       return this.items.slice( 0 );
-};
-
-/**
- * Add items.
- *
- * @method
- * @param {OO.ui.Element[]} items Item
- * @param {number} [index] Index to insert items at
- * @chainable
- */
-OO.ui.GroupElement.prototype.addItems = function ( items, index ) {
-       var i, len, item, event, events, currentIndex,
-               $items = this.$( [] );
-
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-
-               // Check if item exists then remove it first, effectively "moving" it
-               currentIndex = $.inArray( item, this.items );
-               if ( currentIndex >= 0 ) {
-                       this.removeItems( [ item ] );
-                       // Adjust index to compensate for removal
-                       if ( currentIndex < index ) {
-                               index--;
-                       }
-               }
-               // Add the item
-               if ( this.aggregate ) {
-                       events = {};
-                       for ( event in this.aggregations ) {
-                               events[event] = [ 'emit', this.aggregations[event], item ];
-                       }
-                       item.connect( this, events );
-               }
-               item.setElementGroup( this );
-               $items = $items.add( item.$element );
-       }
-
-       if ( index === undefined || index < 0 || index >= this.items.length ) {
-               this.$group.append( $items );
-               this.items.push.apply( this.items, items );
-       } else if ( index === 0 ) {
-               this.$group.prepend( $items );
-               this.items.unshift.apply( this.items, items );
-       } else {
-               this.$items.eq( index ).before( $items );
-               this.items.splice.apply( this.items, [ index, 0 ].concat( items ) );
-       }
-
-       this.$items = this.$items.add( $items );
-
-       return this;
-};
-
-/**
- * Remove items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @param {OO.ui.Element[]} items Items to remove
- * @chainable
- */
-OO.ui.GroupElement.prototype.removeItems = function ( items ) {
-       var i, len, item, index;
-
-       // Remove specific items
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-               index = $.inArray( item, this.items );
-               if ( index !== -1 ) {
-                       if ( this.aggregate ) {
-                               item.disconnect( this );
-                       }
-                       item.setElementGroup( null );
-                       this.items.splice( index, 1 );
-                       item.$element.detach();
-                       this.$items = this.$items.not( item.$element );
-               }
-       }
-
-       return this;
-};
-
-/**
- * Clear all items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @chainable
- */
-OO.ui.GroupElement.prototype.clearItems = function () {
-       var i, len, item;
-
-       // Remove all items
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               item = this.items[i];
-               if ( this.aggregate ) {
-                       item.disconnect( this );
-               }
-               item.setElementGroup( null );
-       }
-       this.items = [];
-       this.$items.detach();
-       this.$items = this.$( [] );
-};
-/**
- * Element containing an icon.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $icon Icon node, assigned to #$icon
- * @param {Object} [config] Configuration options
- * @cfg {Object|string} [icon=''] Symbolic icon name, or map of icon names keyed by language ID;
- *  use the 'default' key to specify the icon to be used when there is no icon in the user's
- *  language
- */
-OO.ui.IconedElement = function OoUiIconedElement( $icon, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.$icon = $icon;
-       this.icon = null;
-
-       // Initialization
-       this.$icon.addClass( 'oo-ui-iconedElement-icon' );
-       this.setIcon( config.icon || this.constructor.static.icon );
-};
-
-/* Static Properties */
-
-OO.ui.IconedElement.static = {};
-
-/**
- * Icon.
- *
- * Value should be the unique portion of an icon CSS class name, such as 'up' for 'oo-ui-icon-up'.
- *
- * For i18n purposes, this property can be an object containing a `default` icon name property and
- * additional icon names keyed by language code.
- *
- * Example of i18n icon definition:
- *     { 'default': 'bold-a', 'en': 'bold-b', 'de': 'bold-f' }
- *
- * @static
- * @inheritable
- * @property {Object|string} Symbolic icon name, or map of icon names keyed by language ID;
- *  use the 'default' key to specify the icon to be used when there is no icon in the user's
- *  language
- */
-OO.ui.IconedElement.static.icon = null;
-
-/* Methods */
-
-/**
- * Set icon.
- *
- * @method
- * @param {Object|string} icon Symbolic icon name, or map of icon names keyed by language ID;
- *  use the 'default' key to specify the icon to be used when there is no icon in the user's
- *  language
- * @chainable
- */
-OO.ui.IconedElement.prototype.setIcon = function ( icon ) {
-       icon = OO.isPlainObject( icon ) ? OO.ui.getLocalValue( icon, null, 'default' ) : icon;
-
-       if ( this.icon ) {
-               this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
-       }
-       if ( typeof icon === 'string' ) {
-               icon = icon.trim();
-               if ( icon.length ) {
-                       this.$icon.addClass( 'oo-ui-icon-' + icon );
-                       this.icon = icon;
-               }
-       }
-       this.$element.toggleClass( 'oo-ui-iconedElement', !!this.icon );
-
-       return this;
-};
-
-/**
- * Get icon.
- *
- * @method
- * @returns {string} Icon
- */
-OO.ui.IconedElement.prototype.getIcon = function () {
-       return this.icon;
-};
-/**
- * Element containing an indicator.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $indicator Indicator node, assigned to #$indicator
- * @param {Object} [config] Configuration options
- * @cfg {string} [indicator] Symbolic indicator name
- * @cfg {string} [indicatorTitle] Indicator title text or a function that return text
- */
-OO.ui.IndicatedElement = function OoUiIndicatedElement( $indicator, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.$indicator = $indicator;
-       this.indicator = null;
-       this.indicatorLabel = null;
-
-       // Initialization
-       this.$indicator.addClass( 'oo-ui-indicatedElement-indicator' );
-       this.setIndicator( config.indicator || this.constructor.static.indicator );
-       this.setIndicatorTitle( config.indicatorTitle  || this.constructor.static.indicatorTitle );
-};
-
-/* Static Properties */
-
-OO.ui.IndicatedElement.static = {};
-
-/**
- * indicator.
- *
- * @static
- * @inheritable
- * @property {string|null} Symbolic indicator name or null for no indicator
- */
-OO.ui.IndicatedElement.static.indicator = null;
-
-/**
- * Indicator title.
- *
- * @static
- * @inheritable
- * @property {string|Function|null} Indicator title text, a function that return text or null for no
- *  indicator title
- */
-OO.ui.IndicatedElement.static.indicatorTitle = null;
-
-/* Methods */
-
-/**
- * Set indicator.
- *
- * @method
- * @param {string|null} indicator Symbolic name of indicator to use or null for no indicator
- * @chainable
- */
-OO.ui.IndicatedElement.prototype.setIndicator = function ( indicator ) {
-       if ( this.indicator ) {
-               this.$indicator.removeClass( 'oo-ui-indicator-' + this.indicator );
-               this.indicator = null;
-       }
-       if ( typeof indicator === 'string' ) {
-               indicator = indicator.trim();
-               if ( indicator.length ) {
-                       this.$indicator.addClass( 'oo-ui-indicator-' + indicator );
-                       this.indicator = indicator;
-               }
-       }
-       this.$element.toggleClass( 'oo-ui-indicatedElement', !!this.indicator );
-
-       return this;
-};
-
-/**
- * Set indicator label.
- *
- * @method
- * @param {string|Function|null} indicator Indicator title text, a function that return text or null
- *  for no indicator title
- * @chainable
- */
-OO.ui.IndicatedElement.prototype.setIndicatorTitle = function ( indicatorTitle ) {
-       this.indicatorTitle = indicatorTitle = OO.ui.resolveMsg( indicatorTitle );
-
-       if ( typeof indicatorTitle === 'string' && indicatorTitle.length ) {
-               this.$indicator.attr( 'title', indicatorTitle );
-       } else {
-               this.$indicator.removeAttr( 'title' );
-       }
-
-       return this;
-};
-
-/**
- * Get indicator.
- *
- * @method
- * @returns {string} title Symbolic name of indicator
- */
-OO.ui.IndicatedElement.prototype.getIndicator = function () {
-       return this.indicator;
-};
-
-/**
- * Get indicator title.
- *
- * @method
- * @returns {string} Indicator title text
- */
-OO.ui.IndicatedElement.prototype.getIndicatorTitle = function () {
-       return this.indicatorTitle;
-};
-/**
- * Element containing a label.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $label Label node, assigned to #$label
- * @param {Object} [config] Configuration options
- * @cfg {jQuery|string|Function} [label] Label nodes, text or a function that returns nodes or text
- * @cfg {boolean} [autoFitLabel=true] Whether to fit the label or not.
- */
-OO.ui.LabeledElement = function OoUiLabeledElement( $label, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.$label = $label;
-       this.label = null;
-
-       // Initialization
-       this.$label.addClass( 'oo-ui-labeledElement-label' );
-       this.setLabel( config.label || this.constructor.static.label );
-       this.autoFitLabel = config.autoFitLabel === undefined || !!config.autoFitLabel;
-};
-
-/* Static Properties */
-
-OO.ui.LabeledElement.static = {};
-
-/**
- * Label.
- *
- * @static
- * @inheritable
- * @property {string|Function|null} Label text; a function that returns a nodes or text; or null for
- *  no label
- */
-OO.ui.LabeledElement.static.label = null;
-
-/* Methods */
-
-/**
- * Set the label.
- *
- * An empty string will result in the label being hidden. A string containing only whitespace will
- * be converted to a single &nbsp;
- *
- * @method
- * @param {jQuery|string|Function|null} label Label nodes; text; a function that retuns nodes or
- *  text; or null for no label
- * @chainable
- */
-OO.ui.LabeledElement.prototype.setLabel = function ( label ) {
-       var empty = false;
-
-       this.label = label = OO.ui.resolveMsg( label ) || null;
-       if ( typeof label === 'string' && label.length ) {
-               if ( label.match( /^\s*$/ ) ) {
-                       // Convert whitespace only string to a single non-breaking space
-                       this.$label.html( '&nbsp;' );
-               } else {
-                       this.$label.text( label );
-               }
-       } else if ( label instanceof jQuery ) {
-               this.$label.empty().append( label );
-       } else {
-               this.$label.empty();
-               empty = true;
-       }
-       this.$element.toggleClass( 'oo-ui-labeledElement', !empty );
-       this.$label.css( 'display', empty ? 'none' : '' );
-
-       return this;
-};
-
-/**
- * Get the label.
- *
- * @method
- * @returns {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
- *  text; or null for no label
- */
-OO.ui.LabeledElement.prototype.getLabel = function () {
-       return this.label;
-};
-
-/**
- * Fit the label.
- *
- * @method
- * @chainable
- */
-OO.ui.LabeledElement.prototype.fitLabel = function () {
-       if ( this.$label.autoEllipsis && this.autoFitLabel ) {
-               this.$label.autoEllipsis( { 'hasSpan': false, 'tooltip': true } );
-       }
-       return this;
-};
-/**
- * Popuppable element.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {number} [popupWidth=320] Width of popup
- * @cfg {number} [popupHeight] Height of popup
- * @cfg {Object} [popup] Configuration to pass to popup
- */
-OO.ui.PopuppableElement = function OoUiPopuppableElement( config ) {
-       // Configuration initialization
-       config = $.extend( { 'popupWidth': 320 }, config );
-
-       // Properties
-       this.popup = new OO.ui.PopupWidget( $.extend(
-               { 'align': 'center', 'autoClose': true },
-               config.popup,
-               { '$': this.$, '$autoCloseIgnore': this.$element }
-       ) );
-       this.popupWidth = config.popupWidth;
-       this.popupHeight = config.popupHeight;
-};
-
-/* Methods */
-
-/**
- * Get popup.
- *
- * @method
- * @returns {OO.ui.PopupWidget} Popup widget
- */
-OO.ui.PopuppableElement.prototype.getPopup = function () {
-       return this.popup;
-};
-
-/**
- * Show popup.
- *
- * @method
- */
-OO.ui.PopuppableElement.prototype.showPopup = function () {
-       this.popup.show().display( this.popupWidth, this.popupHeight );
-};
-
-/**
- * Hide popup.
- *
- * @method
- */
-OO.ui.PopuppableElement.prototype.hidePopup = function () {
-       this.popup.hide();
-};
-/**
- * Element with a title.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $label Titled node, assigned to #$titled
- * @param {Object} [config] Configuration options
- * @cfg {string|Function} [title] Title text or a function that returns text
- */
-OO.ui.TitledElement = function OoUiTitledElement( $titled, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.$titled = $titled;
-       this.title = null;
-
-       // Initialization
-       this.setTitle( config.title || this.constructor.static.title );
-};
-
-/* Static Properties */
-
-OO.ui.TitledElement.static = {};
-
-/**
- * Title.
- *
- * @static
- * @inheritable
- * @property {string|Function} Title text or a function that returns text
- */
-OO.ui.TitledElement.static.title = null;
-
-/* Methods */
-
-/**
- * Set title.
- *
- * @method
- * @param {string|Function|null} title Title text, a function that returns text or null for no title
- * @chainable
- */
-OO.ui.TitledElement.prototype.setTitle = function ( title ) {
-       this.title = title = OO.ui.resolveMsg( title ) || null;
-
-       if ( typeof title === 'string' && title.length ) {
-               this.$titled.attr( 'title', title );
-       } else {
-               this.$titled.removeAttr( 'title' );
-       }
-
-       return this;
-};
-
-/**
- * Get title.
- *
- * @method
- * @returns {string} Title string
- */
-OO.ui.TitledElement.prototype.getTitle = function () {
-       return this.title;
-};
-/**
- * Generic toolbar tool.
- *
- * @abstract
- * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.IconedElement
- *
- * @constructor
- * @param {OO.ui.ToolGroup} toolGroup
- * @param {Object} [config] Configuration options
- * @cfg {string|Function} [title] Title text or a function that returns text
- */
-OO.ui.Tool = function OoUiTool( toolGroup, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Tool.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-
-       // Properties
-       this.toolGroup = toolGroup;
-       this.toolbar = this.toolGroup.getToolbar();
-       this.active = false;
-       this.$title = this.$( '<span>' );
-       this.$link = this.$( '<a>' );
-       this.title = null;
-
-       // Events
-       this.toolbar.connect( this, { 'updateState': 'onUpdateState' } );
-
-       // Initialization
-       this.$title.addClass( 'oo-ui-tool-title' );
-       this.$link
-               .addClass( 'oo-ui-tool-link' )
-               .append( this.$icon, this.$title );
-       this.$element
-               .data( 'oo-ui-tool', this )
-               .addClass(
-                       'oo-ui-tool ' + 'oo-ui-tool-name-' +
-                       this.constructor.static.name.replace( /^([^\/]+)\/([^\/]+).*$/, '$1-$2' )
-               )
-               .append( this.$link );
-       this.setTitle( config.title || this.constructor.static.title );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Tool, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.Tool, OO.ui.IconedElement );
-
-/* Events */
-
-/**
- * @event select
- */
-
-/* Static Properties */
-
-/**
- * @static
- * @inheritdoc
- */
-OO.ui.Tool.static.tagName = 'span';
-
-/**
- * Symbolic name of tool.
- *
- * @abstract
- * @static
- * @property {string}
- * @inheritable
- */
-OO.ui.Tool.static.name = '';
-
-/**
- * Tool group.
- *
- * @abstract
- * @static
- * @property {string}
- * @inheritable
- */
-OO.ui.Tool.static.group = '';
-
-/**
- * Tool title.
- *
- * Title is used as a tooltip when the tool is part of a bar tool group, or a label when the tool
- * is part of a list or menu tool group. If a trigger is associated with an action by the same name
- * as the tool, a description of its keyboard shortcut for the appropriate platform will be
- * appended to the title if the tool is part of a bar tool group.
- *
- * @abstract
- * @static
- * @property {string|Function} Title text or a function that returns text
- * @inheritable
- */
-OO.ui.Tool.static.title = '';
-
-/**
- * Tool can be automatically added to catch-all groups.
- *
- * @static
- * @property {boolean}
- * @inheritable
- */
-OO.ui.Tool.static.autoAddToCatchall = true;
-
-/**
- * Tool can be automatically added to named groups.
- *
- * @static
- * @property {boolean}
- * @inheritable
- */
-OO.ui.Tool.static.autoAddToGroup = true;
-
-/**
- * Check if this tool is compatible with given data.
- *
- * @static
- * @method
- * @inheritable
- * @param {Mixed} data Data to check
- * @return {boolean} Tool can be used with data
- */
-OO.ui.Tool.static.isCompatibleWith = function () {
-       return false;
-};
-
-/* Methods */
-
-/**
- * Handle the toolbar state being updated.
- *
- * This is an abstract method that must be overridden in a concrete subclass.
- *
- * @abstract
- */
-OO.ui.Tool.prototype.onUpdateState = function () {
-       throw new Error(
-               'OO.ui.Tool.onUpdateState not implemented in this subclass:' + this.constructor
-       );
-};
-
-/**
- * Handle the tool being selected.
- *
- * This is an abstract method that must be overridden in a concrete subclass.
- *
- * @abstract
- */
-OO.ui.Tool.prototype.onSelect = function () {
-       throw new Error(
-               'OO.ui.Tool.onSelect not implemented in this subclass:' + this.constructor
-       );
-};
-
-/**
- * Check if the button is active.
- *
- * @param {boolean} Button is active
- */
-OO.ui.Tool.prototype.isActive = function () {
-       return this.active;
-};
-
-/**
- * Make the button appear active or inactive.
- *
- * @param {boolean} state Make button appear active
- */
-OO.ui.Tool.prototype.setActive = function ( state ) {
-       this.active = !!state;
-       if ( this.active ) {
-               this.$element.addClass( 'oo-ui-tool-active' );
-       } else {
-               this.$element.removeClass( 'oo-ui-tool-active' );
-       }
-};
-
-/**
- * Get the tool title.
- *
- * @param {string|Function} title Title text or a function that returns text
- * @chainable
- */
-OO.ui.Tool.prototype.setTitle = function ( title ) {
-       this.title = OO.ui.resolveMsg( title );
-       this.updateTitle();
-       return this;
-};
-
-/**
- * Get the tool title.
- *
- * @return {string} Title text
- */
-OO.ui.Tool.prototype.getTitle = function () {
-       return this.title;
-};
-
-/**
- * Get the tool's symbolic name.
- *
- * @return {string} Symbolic name of tool
- */
-OO.ui.Tool.prototype.getName = function () {
-       return this.constructor.static.name;
-};
-
-/**
- * Update the title.
- */
-OO.ui.Tool.prototype.updateTitle = function () {
-       var titleTooltips = this.toolGroup.constructor.static.titleTooltips,
-               accelTooltips = this.toolGroup.constructor.static.accelTooltips,
-               accel = this.toolbar.getToolAccelerator( this.constructor.static.name ),
-               tooltipParts = [];
-
-       this.$title.empty()
-               .text( this.title )
-               .append(
-                       this.$( '<span>' )
-                               .addClass( 'oo-ui-tool-accel' )
-                               .text( accel )
-               );
-
-       if ( titleTooltips && typeof this.title === 'string' && this.title.length ) {
-               tooltipParts.push( this.title );
-       }
-       if ( accelTooltips && typeof accel === 'string' && accel.length ) {
-               tooltipParts.push( accel );
-       }
-       if ( tooltipParts.length ) {
-               this.$link.attr( 'title', tooltipParts.join( ' ' ) );
-       } else {
-               this.$link.removeAttr( 'title' );
-       }
-};
-
-/**
- * Destroy tool.
- */
-OO.ui.Tool.prototype.destroy = function () {
-       this.toolbar.disconnect( this );
-       this.$element.remove();
-};
-/**
- * Collection of tool groups.
- *
- * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
- * @mixins OO.ui.GroupElement
- *
- * @constructor
- * @param {OO.ui.ToolFactory} toolFactory Factory for creating tools
- * @param {OO.ui.ToolGroupFactory} toolGroupFactory Factory for creating tool groups
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [actions] Add an actions section opposite to the tools
- * @cfg {boolean} [shadow] Add a shadow below the toolbar
- */
-OO.ui.Toolbar = function OoUiToolbar( toolFactory, toolGroupFactory, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Toolbar.super.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
-
-       // Properties
-       this.toolFactory = toolFactory;
-       this.toolGroupFactory = toolGroupFactory;
-       this.groups = [];
-       this.tools = {};
-       this.$bar = this.$( '<div>' );
-       this.$actions = this.$( '<div>' );
-       this.initialized = false;
-
-       // Events
-       this.$element
-               .add( this.$bar ).add( this.$group ).add( this.$actions )
-               .on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
-
-       // Initialization
-       this.$group.addClass( 'oo-ui-toolbar-tools' );
-       this.$bar.addClass( 'oo-ui-toolbar-bar' ).append( this.$group );
-       if ( config.actions ) {
-               this.$actions.addClass( 'oo-ui-toolbar-actions' );
-               this.$bar.append( this.$actions );
-       }
-       this.$bar.append( '<div style="clear:both"></div>' );
-       if ( config.shadow ) {
-               this.$bar.append( '<div class="oo-ui-toolbar-shadow"></div>' );
-       }
-       this.$element.addClass( 'oo-ui-toolbar' ).append( this.$bar );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Toolbar, OO.ui.Element );
-
-OO.mixinClass( OO.ui.Toolbar, OO.EventEmitter );
-OO.mixinClass( OO.ui.Toolbar, OO.ui.GroupElement );
-
-/* Methods */
-
-/**
- * Get the tool factory.
- *
- * @return {OO.ui.ToolFactory} Tool factory
- */
-OO.ui.Toolbar.prototype.getToolFactory = function () {
-       return this.toolFactory;
-};
-
-/**
- * Get the tool group factory.
- *
- * @return {OO.Factory} Tool group factory
- */
-OO.ui.Toolbar.prototype.getToolGroupFactory = function () {
-       return this.toolGroupFactory;
-};
-
-/**
- * Handles mouse down events.
- *
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.Toolbar.prototype.onMouseDown = function ( e ) {
-       var $closestWidgetToEvent = this.$( e.target ).closest( '.oo-ui-widget' ),
-               $closestWidgetToToolbar = this.$element.closest( '.oo-ui-widget' );
-       if ( !$closestWidgetToEvent.length || $closestWidgetToEvent[0] === $closestWidgetToToolbar[0] ) {
-               return false;
-       }
-};
-
-/**
- * Sets up handles and preloads required information for the toolbar to work.
- * This must be called immediately after it is attached to a visible document.
- */
-OO.ui.Toolbar.prototype.initialize = function () {
-       this.initialized = true;
-};
-
-/**
- * Setup toolbar.
- *
- * Tools can be specified in the following ways:
- *
- * - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
- * - All tools in a group: `{ 'group': 'group-name' }`
- * - All tools: `'*'` - Using this will make the group a list with a "More" label by default
- *
- * @param {Object.<string,Array>} groups List of tool group configurations
- * @param {Array|string} [groups.include] Tools to include
- * @param {Array|string} [groups.exclude] Tools to exclude
- * @param {Array|string} [groups.promote] Tools to promote to the beginning
- * @param {Array|string} [groups.demote] Tools to demote to the end
- */
-OO.ui.Toolbar.prototype.setup = function ( groups ) {
-       var i, len, type, group,
-               items = [],
-               defaultType = 'bar';
-
-       // Cleanup previous groups
-       this.reset();
-
-       // Build out new groups
-       for ( i = 0, len = groups.length; i < len; i++ ) {
-               group = groups[i];
-               if ( group.include === '*' ) {
-                       // Apply defaults to catch-all groups
-                       if ( group.type === undefined ) {
-                               group.type = 'list';
-                       }
-                       if ( group.label === undefined ) {
-                               group.label = 'ooui-toolbar-more';
-                       }
-               }
-               // Check type has been registered
-               type = this.getToolGroupFactory().lookup( group.type ) ? group.type : defaultType;
-               items.push(
-                       this.getToolGroupFactory().create( type, this, $.extend( { '$': this.$ }, group ) )
-               );
-       }
-       this.addItems( items );
-};
-
-/**
- * Remove all tools and groups from the toolbar.
- */
-OO.ui.Toolbar.prototype.reset = function () {
-       var i, len;
-
-       this.groups = [];
-       this.tools = {};
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               this.items[i].destroy();
-       }
-       this.clearItems();
-};
-
-/**
- * Destroys toolbar, removing event handlers and DOM elements.
- *
- * Call this whenever you are done using a toolbar.
- */
-OO.ui.Toolbar.prototype.destroy = function () {
-       this.reset();
-       this.$element.remove();
-};
-
-/**
- * Check if tool has not been used yet.
- *
- * @param {string} name Symbolic name of tool
- * @return {boolean} Tool is available
- */
-OO.ui.Toolbar.prototype.isToolAvailable = function ( name ) {
-       return !this.tools[name];
-};
-
-/**
- * Prevent tool from being used again.
- *
- * @param {OO.ui.Tool} tool Tool to reserve
- */
-OO.ui.Toolbar.prototype.reserveTool = function ( tool ) {
-       this.tools[tool.getName()] = tool;
-};
-
-/**
- * Allow tool to be used again.
- *
- * @param {OO.ui.Tool} tool Tool to release
- */
-OO.ui.Toolbar.prototype.releaseTool = function ( tool ) {
-       delete this.tools[tool.getName()];
-};
-
-/**
- * Get accelerator label for tool.
- *
- * This is a stub that should be overridden to provide access to accelerator information.
- *
- * @param {string} name Symbolic name of tool
- * @return {string|undefined} Tool accelerator label if available
- */
-OO.ui.Toolbar.prototype.getToolAccelerator = function () {
-       return undefined;
-};
-/**
- * Factory for tools.
- *
- * @class
- * @extends OO.Factory
- * @constructor
- */
-OO.ui.ToolFactory = function OoUiToolFactory() {
-       // Parent constructor
-       OO.ui.ToolFactory.super.call( this );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ToolFactory, OO.Factory );
-
-/* Methods */
-
-/** */
-OO.ui.ToolFactory.prototype.getTools = function ( include, exclude, promote, demote ) {
-       var i, len, included, promoted, demoted,
-               auto = [],
-               used = {};
-
-       // Collect included and not excluded tools
-       included = OO.simpleArrayDifference( this.extract( include ), this.extract( exclude ) );
-
-       // Promotion
-       promoted = this.extract( promote, used );
-       demoted = this.extract( demote, used );
-
-       // Auto
-       for ( i = 0, len = included.length; i < len; i++ ) {
-               if ( !used[included[i]] ) {
-                       auto.push( included[i] );
-               }
-       }
-
-       return promoted.concat( auto ).concat( demoted );
-};
-
-/**
- * Get a flat list of names from a list of names or groups.
- *
- * Tools can be specified in the following ways:
- *
- * - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
- * - All tools in a group: `{ 'group': 'group-name' }`
- * - All tools: `'*'`
- *
- * @private
- * @param {Array|string} collection List of tools
- * @param {Object} [used] Object with names that should be skipped as properties; extracted
- *  names will be added as properties
- * @return {string[]} List of extracted names
- */
-OO.ui.ToolFactory.prototype.extract = function ( collection, used ) {
-       var i, len, item, name, tool,
-               names = [];
-
-       if ( collection === '*' ) {
-               for ( name in this.registry ) {
-                       tool = this.registry[name];
-                       if (
-                               // Only add tools by group name when auto-add is enabled
-                               tool.static.autoAddToCatchall &&
-                               // Exclude already used tools
-                               ( !used || !used[name] )
-                       ) {
-                               names.push( name );
-                               if ( used ) {
-                                       used[name] = true;
-                               }
-                       }
-               }
-       } else if ( $.isArray( collection ) ) {
-               for ( i = 0, len = collection.length; i < len; i++ ) {
-                       item = collection[i];
-                       // Allow plain strings as shorthand for named tools
-                       if ( typeof item === 'string' ) {
-                               item = { 'name': item };
-                       }
-                       if ( OO.isPlainObject( item ) ) {
-                               if ( item.group ) {
-                                       for ( name in this.registry ) {
-                                               tool = this.registry[name];
-                                               if (
-                                                       // Include tools with matching group
-                                                       tool.static.group === item.group &&
-                                                       // Only add tools by group name when auto-add is enabled
-                                                       tool.static.autoAddToGroup &&
-                                                       // Exclude already used tools
-                                                       ( !used || !used[name] )
-                                               ) {
-                                                       names.push( name );
-                                                       if ( used ) {
-                                                               used[name] = true;
-                                                       }
-                                               }
-                                       }
-                               // Include tools with matching name and exclude already used tools
-                               } else if ( item.name && ( !used || !used[item.name] ) ) {
-                                       names.push( item.name );
-                                       if ( used ) {
-                                               used[item.name] = true;
-                                       }
-                               }
-                       }
-               }
-       }
-       return names;
-};
-/**
- * Collection of tools.
- *
- * Tools can be specified in the following ways:
- *
- * - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
- * - All tools in a group: `{ 'group': 'group-name' }`
- * - All tools: `'*'`
- *
- * @abstract
- * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.GroupElement
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- * @cfg {Array|string} [include=[]] List of tools to include
- * @cfg {Array|string} [exclude=[]] List of tools to exclude
- * @cfg {Array|string} [promote=[]] List of tools to promote to the beginning
- * @cfg {Array|string} [demote=[]] List of tools to demote to the end
- */
-OO.ui.ToolGroup = function OoUiToolGroup( toolbar, config ) {
-       // Configuration initialization
-       config = $.extend( true, {
-               'aggregations': { 'disable': 'itemDisable' }
-       }, config );
-
-       // Parent constructor
-       OO.ui.ToolGroup.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
-
-       // Properties
-       this.toolbar = toolbar;
-       this.tools = {};
-       this.pressed = null;
-       this.autoDisabled = false;
-       this.include = config.include || [];
-       this.exclude = config.exclude || [];
-       this.promote = config.promote || [];
-       this.demote = config.demote || [];
-       this.onCapturedMouseUpHandler = OO.ui.bind( this.onCapturedMouseUp, this );
-
-       // Events
-       this.$element.on( {
-               'mousedown': OO.ui.bind( this.onMouseDown, this ),
-               'mouseup': OO.ui.bind( this.onMouseUp, this ),
-               'mouseover': OO.ui.bind( this.onMouseOver, this ),
-               'mouseout': OO.ui.bind( this.onMouseOut, this )
-       } );
-       this.toolbar.getToolFactory().connect( this, { 'register': 'onToolFactoryRegister' } );
-       this.connect( this, { 'itemDisable': 'updateDisabled' } );
-
-       // Initialization
-       this.$group.addClass( 'oo-ui-toolGroup-tools' );
-       this.$element
-               .addClass( 'oo-ui-toolGroup' )
-               .append( this.$group );
-       this.populate();
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ToolGroup, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.ToolGroup, OO.ui.GroupElement );
-
-/* Events */
-
-/**
- * @event update
- */
-
-/* Static Properties */
-
-/**
- * Show labels in tooltips.
- *
- * @static
- * @property {boolean}
- * @inheritable
- */
-OO.ui.ToolGroup.static.titleTooltips = false;
-
-/**
- * Show acceleration labels in tooltips.
- *
- * @static
- * @property {boolean}
- * @inheritable
- */
-OO.ui.ToolGroup.static.accelTooltips = false;
-
-/**
- * Automatically disable the toolgroup when all tools are disabled
- *
- * @static
- * @property {boolean}
- * @inheritable
- */
-OO.ui.ToolGroup.static.autoDisable = true;
-
-/* Methods */
-
-/**
- * @inheritdoc
- */
-OO.ui.ToolGroup.prototype.isDisabled = function () {
-       return this.autoDisabled || OO.ui.ToolGroup.super.prototype.isDisabled.apply( this, arguments );
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.ToolGroup.prototype.updateDisabled = function () {
-       var i, item, allDisabled = true;
-
-       if ( this.constructor.static.autoDisable ) {
-               for ( i = this.items.length - 1; i >= 0; i-- ) {
-                       item = this.items[i];
-                       if ( !item.isDisabled() ) {
-                               allDisabled = false;
-                               break;
-                       }
-               }
-               this.autoDisabled = allDisabled;
-       }
-       OO.ui.ToolGroup.super.prototype.updateDisabled.apply( this, arguments );
-};
-
-/**
- * Handle mouse down events.
- *
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.ToolGroup.prototype.onMouseDown = function ( e ) {
-       if ( !this.disabled && e.which === 1 ) {
-               this.pressed = this.getTargetTool( e );
-               if ( this.pressed ) {
-                       this.pressed.setActive( true );
-                       this.getElementDocument().addEventListener(
-                               'mouseup', this.onCapturedMouseUpHandler, true
-                       );
-                       return false;
-               }
-       }
-};
-
-/**
- * Handle captured mouse up events.
- *
- * @param {Event} e Mouse up event
- */
-OO.ui.ToolGroup.prototype.onCapturedMouseUp = function ( e ) {
-       this.getElementDocument().removeEventListener( 'mouseup', this.onCapturedMouseUpHandler, true );
-       // onMouseUp may be called a second time, depending on where the mouse is when the button is
-       // released, but since `this.pressed` will no longer be true, the second call will be ignored.
-       this.onMouseUp( e );
-};
-
-/**
- * Handle mouse up events.
- *
- * @param {jQuery.Event} e Mouse up event
- */
-OO.ui.ToolGroup.prototype.onMouseUp = function ( e ) {
-       var tool = this.getTargetTool( e );
-
-       if ( !this.disabled && e.which === 1 && this.pressed && this.pressed === tool ) {
-               this.pressed.onSelect();
-       }
-
-       this.pressed = null;
-       return false;
-};
-
-/**
- * Handle mouse over events.
- *
- * @param {jQuery.Event} e Mouse over event
- */
-OO.ui.ToolGroup.prototype.onMouseOver = function ( e ) {
-       var tool = this.getTargetTool( e );
-
-       if ( this.pressed && this.pressed === tool ) {
-               this.pressed.setActive( true );
-       }
-};
-
-/**
- * Handle mouse out events.
- *
- * @param {jQuery.Event} e Mouse out event
- */
-OO.ui.ToolGroup.prototype.onMouseOut = function ( e ) {
-       var tool = this.getTargetTool( e );
-
-       if ( this.pressed && this.pressed === tool ) {
-               this.pressed.setActive( false );
-       }
-};
-
-/**
- * Get the closest tool to a jQuery.Event.
- *
- * Only tool links are considered, which prevents other elements in the tool such as popups from
- * triggering tool group interactions.
- *
- * @private
- * @param {jQuery.Event} e
- * @return {OO.ui.Tool|null} Tool, `null` if none was found
- */
-OO.ui.ToolGroup.prototype.getTargetTool = function ( e ) {
-       var tool,
-               $item = this.$( e.target ).closest( '.oo-ui-tool-link' );
-
-       if ( $item.length ) {
-               tool = $item.parent().data( 'oo-ui-tool' );
-       }
-
-       return tool && !tool.isDisabled() ? tool : null;
-};
-
-/**
- * Handle tool registry register events.
- *
- * If a tool is registered after the group is created, we must repopulate the list to account for:
- *
- * - a tool being added that may be included
- * - a tool already included being overridden
- *
- * @param {string} name Symbolic name of tool
- */
-OO.ui.ToolGroup.prototype.onToolFactoryRegister = function () {
-       this.populate();
-};
-
-/**
- * Get the toolbar this group is in.
- *
- * @return {OO.ui.Toolbar} Toolbar of group
- */
-OO.ui.ToolGroup.prototype.getToolbar = function () {
-       return this.toolbar;
-};
-
-/**
- * Add and remove tools based on configuration.
- */
-OO.ui.ToolGroup.prototype.populate = function () {
-       var i, len, name, tool,
-               toolFactory = this.toolbar.getToolFactory(),
-               names = {},
-               add = [],
-               remove = [],
-               list = this.toolbar.getToolFactory().getTools(
-                       this.include, this.exclude, this.promote, this.demote
-               );
-
-       // Build a list of needed tools
-       for ( i = 0, len = list.length; i < len; i++ ) {
-               name = list[i];
-               if (
-                       // Tool exists
-                       toolFactory.lookup( name ) &&
-                       // Tool is available or is already in this group
-                       ( this.toolbar.isToolAvailable( name ) || this.tools[name] )
-               ) {
-                       tool = this.tools[name];
-                       if ( !tool ) {
-                               // Auto-initialize tools on first use
-                               this.tools[name] = tool = toolFactory.create( name, this );
-                               tool.updateTitle();
-                       }
-                       this.toolbar.reserveTool( tool );
-                       add.push( tool );
-                       names[name] = true;
-               }
-       }
-       // Remove tools that are no longer needed
-       for ( name in this.tools ) {
-               if ( !names[name] ) {
-                       this.tools[name].destroy();
-                       this.toolbar.releaseTool( this.tools[name] );
-                       remove.push( this.tools[name] );
-                       delete this.tools[name];
-               }
-       }
-       if ( remove.length ) {
-               this.removeItems( remove );
-       }
-       // Update emptiness state
-       if ( add.length ) {
-               this.$element.removeClass( 'oo-ui-toolGroup-empty' );
-       } else {
-               this.$element.addClass( 'oo-ui-toolGroup-empty' );
-       }
-       // Re-add tools (moving existing ones to new locations)
-       this.addItems( add );
-       // Disabled state may depend on items
-       this.updateDisabled();
-};
-
-/**
- * Destroy tool group.
- */
-OO.ui.ToolGroup.prototype.destroy = function () {
-       var name;
-
-       this.clearItems();
-       this.toolbar.getToolFactory().disconnect( this );
-       for ( name in this.tools ) {
-               this.toolbar.releaseTool( this.tools[name] );
-               this.tools[name].disconnect( this ).destroy();
-               delete this.tools[name];
-       }
-       this.$element.remove();
-};
-/**
- * Factory for tools.
- *
- * @class
- * @extends OO.Factory
- * @constructor
- */
-OO.ui.ToolGroupFactory = function OoUiToolGroupFactory() {
-       // Parent constructor
-       OO.Factory.call( this );
-
-       var i, l,
-               defaultClasses = this.constructor.static.getDefaultClasses();
-
-       // Register default toolgroups
-       for ( i = 0, l = defaultClasses.length; i < l; i++ ) {
-               this.register( defaultClasses[i] );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ToolGroupFactory, OO.Factory );
-
-/* Static Methods */
-
-/**
- * Get a default set of classes to be registered on construction
- * @return {Function[]} Default classes
- */
-OO.ui.ToolGroupFactory.static.getDefaultClasses = function () {
-       return [
-               OO.ui.BarToolGroup,
-               OO.ui.ListToolGroup,
-               OO.ui.MenuToolGroup
-       ];
-};
-/**
- * Layout made of a fieldset and optional legend.
- *
- * Just add OO.ui.FieldLayout items.
- *
- * @class
- * @extends OO.ui.Layout
- * @mixins OO.ui.LabeledElement
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.GroupElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string} [icon] Symbolic icon name
- * @cfg {OO.ui.FieldLayout[]} [items] Items to add
- */
-OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) {
-       // Config initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.FieldsetLayout.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$( '<div>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<legend>' ), config );
-       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
-
-       // Initialization
-       this.$element
-               .addClass( 'oo-ui-fieldsetLayout' )
-               .append( this.$icon, this.$label, this.$group );
-       if ( $.isArray( config.items ) ) {
-               this.addItems( config.items );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.FieldsetLayout, OO.ui.Layout );
-
-OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.GroupElement );
-
-/* Static Properties */
-
-OO.ui.FieldsetLayout.static.tagName = 'fieldset';
-/**
- * Layout made of a field and optional label.
- *
- * @class
- * @extends OO.ui.Layout
- * @mixins OO.ui.LabeledElement
- *
- * Available label alignment modes include:
- *  - 'left': Label is before the field and aligned away from it, best for when the user will be
- *    scanning for a specific label in a form with many fields
- *  - 'right': Label is before the field and aligned toward it, best for forms the user is very
- *    familiar with and will tab through field checking quickly to verify which field they are in
- *  - 'top': Label is before the field and above it, best for when the use will need to fill out all
- *    fields from top to bottom in a form with few fields
- *  - 'inline': Label is after the field and aligned toward it, best for small boolean fields like
- *    checkboxes or radio buttons
- *
- * @constructor
- * @param {OO.ui.Widget} field Field widget
- * @param {Object} [config] Configuration options
- * @cfg {string} [align='left'] Alignment mode, either 'left', 'right', 'top' or 'inline'
- */
-OO.ui.FieldLayout = function OoUiFieldLayout( field, config ) {
-       // Config initialization
-       config = $.extend( { 'align': 'left' }, config );
-
-       // Parent constructor
-       OO.ui.FieldLayout.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.LabeledElement.call( this, this.$( '<label>' ), config );
-
-       // Properties
-       this.$field = this.$( '<div>' );
-       this.field = field;
-       this.align = null;
-
-       // Events
-       if ( this.field instanceof OO.ui.InputWidget ) {
-               this.$label.on( 'click', OO.ui.bind( this.onLabelClick, this ) );
-       }
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-fieldLayout' );
-       this.$field
-               .addClass( 'oo-ui-fieldLayout-field' )
-               .append( this.field.$element );
-       this.setAlignment( config.align );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.FieldLayout, OO.ui.Layout );
-
-OO.mixinClass( OO.ui.FieldLayout, OO.ui.LabeledElement );
-
-/* Methods */
-
-/**
- * Handles label mouse click events.
- *
- * @method
- * @param {jQuery.Event} e Mouse click event
- */
-OO.ui.FieldLayout.prototype.onLabelClick = function () {
-       this.field.simulateLabelClick();
-       return false;
-};
-
-/**
- * Get the field.
- *
- * @returns {OO.ui.Widget} Field widget
- */
-OO.ui.FieldLayout.prototype.getField = function () {
-       return this.field;
-};
-
-/**
- * Set the field alignment mode.
- *
- * @param {string} value Alignment mode, either 'left', 'right', 'top' or 'inline'
- * @chainable
- */
-OO.ui.FieldLayout.prototype.setAlignment = function ( value ) {
-       if ( value !== this.align ) {
-               // Default to 'left'
-               if ( [ 'left', 'right', 'top', 'inline' ].indexOf( value ) === -1 ) {
-                       value = 'left';
-               }
-               // Reorder elements
-               if ( value === 'inline' ) {
-                       this.$element.append( this.$field, this.$label );
-               } else {
-                       this.$element.append( this.$label, this.$field );
-               }
-               // Set classes
-               if ( this.align ) {
-                       this.$element.removeClass( 'oo-ui-fieldLayout-align-' + this.align );
-               }
-               this.align = value;
-               this.$element.addClass( 'oo-ui-fieldLayout-align-' + this.align );
-       }
-
-       return this;
-};
-/**
- * Layout made of proportionally sized columns and rows.
- *
- * @class
- * @extends OO.ui.Layout
- *
- * @constructor
- * @param {OO.ui.PanelLayout[]} panels Panels in the grid
- * @param {Object} [config] Configuration options
- * @cfg {number[]} [widths] Widths of columns as ratios
- * @cfg {number[]} [heights] Heights of columns as ratios
- */
-OO.ui.GridLayout = function OoUiGridLayout( panels, config ) {
-       var i, len, widths;
-
-       // Config initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.GridLayout.super.call( this, config );
-
-       // Properties
-       this.panels = [];
-       this.widths = [];
-       this.heights = [];
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-gridLayout' );
-       for ( i = 0, len = panels.length; i < len; i++ ) {
-               this.panels.push( panels[i] );
-               this.$element.append( panels[i].$element );
-       }
-       if ( config.widths || config.heights ) {
-               this.layout( config.widths || [1], config.heights || [1] );
-       } else {
-               // Arrange in columns by default
-               widths = [];
-               for ( i = 0, len = this.panels.length; i < len; i++ ) {
-                       widths[i] = 1;
-               }
-               this.layout( widths, [1] );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.GridLayout, OO.ui.Layout );
-
-/* Events */
-
-/**
- * @event layout
- */
-
-/**
- * @event update
- */
-
-/* Static Properties */
-
-OO.ui.GridLayout.static.tagName = 'div';
-
-/* Methods */
-
-/**
- * Set grid dimensions.
- *
- * @method
- * @param {number[]} widths Widths of columns as ratios
- * @param {number[]} heights Heights of rows as ratios
- * @fires layout
- * @throws {Error} If grid is not large enough to fit all panels
- */
-OO.ui.GridLayout.prototype.layout = function ( widths, heights ) {
-       var x, y,
-               xd = 0,
-               yd = 0,
-               cols = widths.length,
-               rows = heights.length;
-
-       // Verify grid is big enough to fit panels
-       if ( cols * rows < this.panels.length ) {
-               throw new Error( 'Grid is not large enough to fit ' + this.panels.length + 'panels' );
-       }
-
-       // Sum up denominators
-       for ( x = 0; x < cols; x++ ) {
-               xd += widths[x];
-       }
-       for ( y = 0; y < rows; y++ ) {
-               yd += heights[y];
-       }
-       // Store factors
-       this.widths = [];
-       this.heights = [];
-       for ( x = 0; x < cols; x++ ) {
-               this.widths[x] = widths[x] / xd;
-       }
-       for ( y = 0; y < rows; y++ ) {
-               this.heights[y] = heights[y] / yd;
-       }
-       // Synchronize view
-       this.update();
-       this.emit( 'layout' );
-};
-
-/**
- * Update panel positions and sizes.
- *
- * @method
- * @fires update
- */
-OO.ui.GridLayout.prototype.update = function () {
-       var x, y, panel,
-               i = 0,
-               left = 0,
-               top = 0,
-               dimensions,
-               width = 0,
-               height = 0,
-               cols = this.widths.length,
-               rows = this.heights.length;
-
-       for ( y = 0; y < rows; y++ ) {
-               for ( x = 0; x < cols; x++ ) {
-                       panel = this.panels[i];
-                       width = this.widths[x];
-                       height = this.heights[y];
-                       dimensions = {
-                               'width': Math.round( width * 100 ) + '%',
-                               'height': Math.round( height * 100 ) + '%',
-                               'top': Math.round( top * 100 ) + '%'
-                       };
-                       // If RTL, reverse:
-                       if ( OO.ui.Element.getDir( this.$.context ) === 'rtl' ) {
-                               dimensions.right = Math.round( left * 100 ) + '%';
-                       } else {
-                               dimensions.left = Math.round( left * 100 ) + '%';
-                       }
-                       panel.$element.css( dimensions );
-                       i++;
-                       left += width;
-               }
-               top += height;
-               left = 0;
-       }
-
-       this.emit( 'update' );
-};
-
-/**
- * Get a panel at a given position.
- *
- * The x and y position is affected by the current grid layout.
- *
- * @method
- * @param {number} x Horizontal position
- * @param {number} y Vertical position
- * @returns {OO.ui.PanelLayout} The panel at the given postion
- */
-OO.ui.GridLayout.prototype.getPanel = function ( x, y ) {
-       return this.panels[( x * this.widths.length ) + y];
-};
-/**
- * Layout containing a series of pages.
- *
- * @class
- * @extends OO.ui.Layout
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [continuous=false] Show all pages, one after another
- * @cfg {boolean} [autoFocus=false] Focus on the first focusable element when changing to a page
- * @cfg {boolean} [outlined=false] Show an outline
- * @cfg {boolean} [editable=false] Show controls for adding, removing and reordering pages
- * @cfg {Object[]} [adders] List of adders for controls, each with name, icon and title properties
- */
-OO.ui.BookletLayout = function OoUiBookletLayout( config ) {
-       // Initialize configuration
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.BookletLayout.super.call( this, config );
-
-       // Properties
-       this.currentPageName = null;
-       this.pages = {};
-       this.ignoreFocus = false;
-       this.stackLayout = new OO.ui.StackLayout( { '$': this.$, 'continuous': !!config.continuous } );
-       this.autoFocus = !!config.autoFocus;
-       this.outlineVisible = false;
-       this.outlined = !!config.outlined;
-       if ( this.outlined ) {
-               this.editable = !!config.editable;
-               this.adders = config.adders || null;
-               this.outlineControlsWidget = null;
-               this.outlineWidget = new OO.ui.OutlineWidget( { '$': this.$ } );
-               this.outlinePanel = new OO.ui.PanelLayout( { '$': this.$, 'scrollable': true } );
-               this.gridLayout = new OO.ui.GridLayout(
-                       [this.outlinePanel, this.stackLayout], { '$': this.$, 'widths': [1, 2] }
-               );
-               this.outlineVisible = true;
-               if ( this.editable ) {
-                       this.outlineControlsWidget = new OO.ui.OutlineControlsWidget(
-                               this.outlineWidget,
-                               { '$': this.$, 'adders': this.adders }
-                       );
-               }
-       }
-
-       // Events
-       this.stackLayout.connect( this, { 'set': 'onStackLayoutSet' } );
-       if ( this.outlined ) {
-               this.outlineWidget.connect( this, { 'select': 'onOutlineWidgetSelect' } );
-       }
-       if ( this.autoFocus ) {
-               // Event 'focus' does not bubble, but 'focusin' does
-               this.stackLayout.onDOMEvent( 'focusin', OO.ui.bind( this.onStackLayoutFocus, this ) );
-       }
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-bookletLayout' );
-       this.stackLayout.$element.addClass( 'oo-ui-bookletLayout-stackLayout' );
-       if ( this.outlined ) {
-               this.outlinePanel.$element
-                       .addClass( 'oo-ui-bookletLayout-outlinePanel' )
-                       .append( this.outlineWidget.$element );
-               if ( this.editable ) {
-                       this.outlinePanel.$element
-                               .addClass( 'oo-ui-bookletLayout-outlinePanel-editable' )
-                               .append( this.outlineControlsWidget.$element );
-               }
-               this.$element.append( this.gridLayout.$element );
-       } else {
-               this.$element.append( this.stackLayout.$element );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.BookletLayout, OO.ui.Layout );
-
-/* Events */
-
-/**
- * @event set
- * @param {OO.ui.PageLayout} page Current page
- */
-
-/**
- * @event add
- * @param {OO.ui.PageLayout[]} page Added pages
- * @param {number} index Index pages were added at
- */
-
-/**
- * @event remove
- * @param {OO.ui.PageLayout[]} pages Removed pages
- */
-
-/* Methods */
-
-/**
- * Handle stack layout focus.
- *
- * @method
- * @param {jQuery.Event} e Focusin event
- */
-OO.ui.BookletLayout.prototype.onStackLayoutFocus = function ( e ) {
-       var name, $target;
-
-       if ( this.ignoreFocus ) {
-               // Avoid recursion from programmatic focus trigger in #onStackLayoutSet
-               return;
-       }
-
-       $target = $( e.target ).closest( '.oo-ui-pageLayout' );
-       for ( name in this.pages ) {
-               if ( this.pages[ name ].$element[0] === $target[0] ) {
-                       this.setPage( name );
-                       break;
-               }
-       }
-};
-
-/**
- * Handle stack layout set events.
- *
- * @method
- * @param {OO.ui.PanelLayout|null} page The page panel that is now the current panel
- */
-OO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) {
-       if ( page ) {
-               this.stackLayout.$element.find( ':focus' ).blur();
-               page.scrollElementIntoView( { 'complete': OO.ui.bind( function () {
-                       this.ignoreFocus = true;
-                       if ( this.autoFocus ) {
-                               page.$element.find( ':input:first' ).focus();
-                       }
-                       this.ignoreFocus = false;
-               }, this ) } );
-       }
-};
-
-/**
- * Handle outline widget select events.
- *
- * @method
- * @param {OO.ui.OptionWidget|null} item Selected item
- */
-OO.ui.BookletLayout.prototype.onOutlineWidgetSelect = function ( item ) {
-       if ( item ) {
-               this.setPage( item.getData() );
-       }
-};
-
-/**
- * Check if booklet has an outline.
- *
- * @method
- * @returns {boolean} Booklet is outlined
- */
-OO.ui.BookletLayout.prototype.isOutlined = function () {
-       return this.outlined;
-};
-
-/**
- * Check if booklet has editing controls.
- *
- * @method
- * @returns {boolean} Booklet is outlined
- */
-OO.ui.BookletLayout.prototype.isEditable = function () {
-       return this.editable;
-};
-
-/**
- * Check if booklet has editing controls.
- *
- * @method
- * @returns {boolean} Booklet is outlined
- */
-OO.ui.BookletLayout.prototype.isOutlineVisible = function () {
-       return this.outlined && this.outlineVisible;
-};
-
-/**
- * Hide or show the outline.
- *
- * @param {boolean} [show] Show outline, omit to invert current state
- * @chainable
- */
-OO.ui.BookletLayout.prototype.toggleOutline = function ( show ) {
-       if ( this.outlined ) {
-               show = show === undefined ? !this.outlineVisible : !!show;
-               this.outlineVisible = show;
-               this.gridLayout.layout( show ? [ 1, 2 ] : [ 0, 1 ], [ 1 ] );
-       }
-
-       return this;
-};
-
-/**
- * Get the outline widget.
- *
- * @method
- * @param {OO.ui.PageLayout} page Page to be selected
- * @returns {OO.ui.PageLayout|null} Closest page to another
- */
-OO.ui.BookletLayout.prototype.getClosestPage = function ( page ) {
-       var next, prev, level,
-               pages = this.stackLayout.getItems(),
-               index = $.inArray( page, pages );
-
-       if ( index !== -1 ) {
-               next = pages[index + 1];
-               prev = pages[index - 1];
-               // Prefer adjacent pages at the same level
-               if ( this.outlined ) {
-                       level = this.outlineWidget.getItemFromData( page.getName() ).getLevel();
-                       if (
-                               prev &&
-                               level === this.outlineWidget.getItemFromData( prev.getName() ).getLevel()
-                       ) {
-                               return prev;
-                       }
-                       if (
-                               next &&
-                               level === this.outlineWidget.getItemFromData( next.getName() ).getLevel()
-                       ) {
-                               return next;
-                       }
-               }
-       }
-       return prev || next || null;
-};
-
-/**
- * Get the outline widget.
- *
- * @method
- * @returns {OO.ui.OutlineWidget|null} Outline widget, or null if boolet has no outline
- */
-OO.ui.BookletLayout.prototype.getOutline = function () {
-       return this.outlineWidget;
-};
-
-/**
- * Get the outline controls widget. If the outline is not editable, null is returned.
- *
- * @method
- * @returns {OO.ui.OutlineControlsWidget|null} The outline controls widget.
- */
-OO.ui.BookletLayout.prototype.getOutlineControls = function () {
-       return this.outlineControlsWidget;
-};
-
-/**
- * Get a page by name.
- *
- * @method
- * @param {string} name Symbolic name of page
- * @returns {OO.ui.PageLayout|undefined} Page, if found
- */
-OO.ui.BookletLayout.prototype.getPage = function ( name ) {
-       return this.pages[name];
-};
-
-/**
- * Get the current page name.
- *
- * @method
- * @returns {string|null} Current page name
- */
-OO.ui.BookletLayout.prototype.getPageName = function () {
-       return this.currentPageName;
-};
-
-/**
- * Add a page to the layout.
- *
- * When pages are added with the same names as existing pages, the existing pages will be
- * automatically removed before the new pages are added.
- *
- * @method
- * @param {OO.ui.PageLayout[]} pages Pages to add
- * @param {number} index Index to insert pages after
- * @fires add
- * @chainable
- */
-OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) {
-       var i, len, name, page, item, currentIndex,
-               stackLayoutPages = this.stackLayout.getItems(),
-               remove = [],
-               items = [];
-
-       // Remove pages with same names
-       for ( i = 0, len = pages.length; i < len; i++ ) {
-               page = pages[i];
-               name = page.getName();
-
-               if ( Object.prototype.hasOwnProperty.call( this.pages, name ) ) {
-                       // Correct the insertion index
-                       currentIndex = $.inArray( this.pages[name], stackLayoutPages );
-                       if ( currentIndex !== -1 && currentIndex + 1 < index ) {
-                               index--;
-                       }
-                       remove.push( this.pages[name] );
-               }
-       }
-       if ( remove.length ) {
-               this.removePages( remove );
-       }
-
-       // Add new pages
-       for ( i = 0, len = pages.length; i < len; i++ ) {
-               page = pages[i];
-               name = page.getName();
-               this.pages[page.getName()] = page;
-               if ( this.outlined ) {
-                       item = new OO.ui.OutlineItemWidget( name, page, { '$': this.$ } );
-                       page.setOutlineItem( item );
-                       items.push( item );
-               }
-       }
-
-       if ( this.outlined && items.length ) {
-               this.outlineWidget.addItems( items, index );
-               this.updateOutlineWidget();
-       }
-       this.stackLayout.addItems( pages, index );
-       this.emit( 'add', pages, index );
-
-       return this;
-};
-
-/**
- * Remove a page from the layout.
- *
- * @method
- * @fires remove
- * @chainable
- */
-OO.ui.BookletLayout.prototype.removePages = function ( pages ) {
-       var i, len, name, page,
-               items = [];
-
-       for ( i = 0, len = pages.length; i < len; i++ ) {
-               page = pages[i];
-               name = page.getName();
-               delete this.pages[name];
-               if ( this.outlined ) {
-                       items.push( this.outlineWidget.getItemFromData( name ) );
-                       page.setOutlineItem( null );
-               }
-       }
-       if ( this.outlined && items.length ) {
-               this.outlineWidget.removeItems( items );
-               this.updateOutlineWidget();
-       }
-       this.stackLayout.removeItems( pages );
-       this.emit( 'remove', pages );
-
-       return this;
-};
-
-/**
- * Clear all pages from the layout.
- *
- * @method
- * @fires remove
- * @chainable
- */
-OO.ui.BookletLayout.prototype.clearPages = function () {
-       var i, len,
-               pages = this.stackLayout.getItems();
-
-       this.pages = {};
-       this.currentPageName = null;
-       if ( this.outlined ) {
-               this.outlineWidget.clearItems();
-               for ( i = 0, len = pages.length; i < len; i++ ) {
-                       pages[i].setOutlineItem( null );
-               }
-       }
-       this.stackLayout.clearItems();
-
-       this.emit( 'remove', pages );
-
-       return this;
-};
-
-/**
- * Set the current page by name.
- *
- * @method
- * @fires set
- * @param {string} name Symbolic name of page
- */
-OO.ui.BookletLayout.prototype.setPage = function ( name ) {
-       var selectedItem,
-               page = this.pages[name];
-
-       if ( name !== this.currentPageName ) {
-               if ( this.outlined ) {
-                       selectedItem = this.outlineWidget.getSelectedItem();
-                       if ( selectedItem && selectedItem.getData() !== name ) {
-                               this.outlineWidget.selectItem( this.outlineWidget.getItemFromData( name ) );
-                       }
-               }
-               if ( page ) {
-                       if ( this.currentPageName && this.pages[this.currentPageName] ) {
-                               this.pages[this.currentPageName].setActive( false );
-                       }
-                       this.currentPageName = name;
-                       this.stackLayout.setItem( page );
-                       page.setActive( true );
-                       this.emit( 'set', page );
-               }
-       }
-};
-
-/**
- * Call this after adding or removing items from the OutlineWidget.
- *
- * @method
- * @chainable
- */
-OO.ui.BookletLayout.prototype.updateOutlineWidget = function () {
-       // Auto-select first item when nothing is selected anymore
-       if ( !this.outlineWidget.getSelectedItem() ) {
-               this.outlineWidget.selectItem( this.outlineWidget.getFirstSelectableItem() );
-       }
-
-       return this;
-};
-/**
- * Layout that expands to cover the entire area of its parent, with optional scrolling and padding.
- *
- * @class
- * @extends OO.ui.Layout
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [scrollable] Allow vertical scrolling
- * @cfg {boolean} [padded] Pad the content from the edges
- */
-OO.ui.PanelLayout = function OoUiPanelLayout( config ) {
-       // Config initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.PanelLayout.super.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-panelLayout' );
-       if ( config.scrollable ) {
-               this.$element.addClass( 'oo-ui-panelLayout-scrollable' );
-       }
-
-       if ( config.padded ) {
-               this.$element.addClass( 'oo-ui-panelLayout-padded' );
-       }
-
-       // Add directionality class:
-       this.$element.addClass( 'oo-ui-' + OO.ui.Element.getDir( this.$.context ) );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PanelLayout, OO.ui.Layout );
-/**
- * Page within an OO.ui.BookletLayout.
- *
- * @class
- * @extends OO.ui.PanelLayout
- *
- * @constructor
- * @param {string} name Unique symbolic name of page
- * @param {Object} [config] Configuration options
- * @param {string} [outlineItem] Outline item widget
- */
-OO.ui.PageLayout = function OoUiPageLayout( name, config ) {
-       // Configuration initialization
-       config = $.extend( { 'scrollable': true }, config );
-
-       // Parent constructor
-       OO.ui.PageLayout.super.call( this, config );
-
-       // Properties
-       this.name = name;
-       this.outlineItem = config.outlineItem || null;
-       this.active = false;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-pageLayout' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PageLayout, OO.ui.PanelLayout );
-
-/* Events */
-
-/**
- * @event active
- * @param {boolean} active Page is active
- */
-
-/* Methods */
-
-/**
- * Get page name.
- *
- * @returns {string} Symbolic name of page
- */
-OO.ui.PageLayout.prototype.getName = function () {
-       return this.name;
-};
-
-/**
- * Check if page is active.
- *
- * @returns {boolean} Page is active
- */
-OO.ui.PageLayout.prototype.isActive = function () {
-       return this.active;
-};
-
-/**
- * Get outline item.
- *
- * @returns {OO.ui.OutlineItemWidget|null} Outline item widget
- */
-OO.ui.PageLayout.prototype.getOutlineItem = function () {
-       return this.outlineItem;
-};
-
-/**
- * Get outline item.
- *
- * @param {OO.ui.OutlineItemWidget|null} outlineItem Outline item widget, null to clear
- * @chainable
- */
-OO.ui.PageLayout.prototype.setOutlineItem = function ( outlineItem ) {
-       this.outlineItem = outlineItem;
-       return this;
-};
-
-/**
- * Set page active state.
- *
- * @param {boolean} Page is active
- * @fires active
- */
-OO.ui.PageLayout.prototype.setActive = function ( active ) {
-       active = !!active;
-
-       if ( active !== this.active ) {
-               this.active = active;
-               this.$element.toggleClass( 'oo-ui-pageLayout-active', active );
-               this.emit( 'active', this.active );
-       }
-};
-/**
- * Layout containing a series of mutually exclusive pages.
- *
- * @class
- * @extends OO.ui.PanelLayout
- * @mixins OO.ui.GroupElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [continuous=false] Show all pages, one after another
- * @cfg {string} [icon=''] Symbolic icon name
- * @cfg {OO.ui.Layout[]} [items] Layouts to add
- */
-OO.ui.StackLayout = function OoUiStackLayout( config ) {
-       // Config initialization
-       config = $.extend( { 'scrollable': true }, config );
-
-       // Parent constructor
-       OO.ui.StackLayout.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$element, config );
-
-       // Properties
-       this.currentItem = null;
-       this.continuous = !!config.continuous;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-stackLayout' );
-       if ( this.continuous ) {
-               this.$element.addClass( 'oo-ui-stackLayout-continuous' );
-       }
-       if ( $.isArray( config.items ) ) {
-               this.addItems( config.items );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.StackLayout, OO.ui.PanelLayout );
-
-OO.mixinClass( OO.ui.StackLayout, OO.ui.GroupElement );
-
-/* Events */
-
-/**
- * @event set
- * @param {OO.ui.PanelLayout|null} [item] Current item
- */
-
-/* Methods */
-
-/**
- * Add items.
- *
- * Adding an existing item (by value) will move it.
- *
- * @method
- * @param {OO.ui.PanelLayout[]} items Items to add
- * @param {number} [index] Index to insert items after
- * @chainable
- */
-OO.ui.StackLayout.prototype.addItems = function ( items, index ) {
-       OO.ui.GroupElement.prototype.addItems.call( this, items, index );
-
-       if ( !this.currentItem && items.length ) {
-               this.setItem( items[0] );
-       }
-
-       return this;
-};
-
-/**
- * Remove items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @param {OO.ui.PanelLayout[]} items Items to remove
- * @chainable
- */
-OO.ui.StackLayout.prototype.removeItems = function ( items ) {
-       OO.ui.GroupElement.prototype.removeItems.call( this, items );
-       if ( $.inArray( this.currentItem, items  ) !== -1 ) {
-               this.currentItem = null;
-               if ( !this.currentItem && this.items.length ) {
-                       this.setItem( this.items[0] );
-               }
-       }
-
-       return this;
-};
-
-/**
- * Clear all items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @chainable
- */
-OO.ui.StackLayout.prototype.clearItems = function () {
-       this.currentItem = null;
-       OO.ui.GroupElement.prototype.clearItems.call( this );
-
-       return this;
-};
-
-/**
- * Show item.
- *
- * Any currently shown item will be hidden.
- *
- * @method
- * @param {OO.ui.PanelLayout} item Item to show
- * @chainable
- */
-OO.ui.StackLayout.prototype.setItem = function ( item ) {
-       if ( item !== this.currentItem ) {
-               if ( !this.continuous ) {
-                       this.$items.css( 'display', '' );
-               }
-               if ( $.inArray( item, this.items ) !== -1 ) {
-                       if ( !this.continuous ) {
-                               item.$element.css( 'display', 'block' );
-                       }
-               } else {
-                       item = null;
-               }
-               this.currentItem = item;
-               this.emit( 'set', item );
-       }
-
-       return this;
-};
-/**
- * Horizontal bar layout of tools as icon buttons.
- *
- * @class
- * @abstract
- * @extends OO.ui.ToolGroup
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- */
-OO.ui.BarToolGroup = function OoUiBarToolGroup( toolbar, config ) {
-       // Parent constructor
-       OO.ui.BarToolGroup.super.call( this, toolbar, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-barToolGroup' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.BarToolGroup, OO.ui.ToolGroup );
-
-/* Static Properties */
-
-OO.ui.BarToolGroup.static.titleTooltips = true;
-
-OO.ui.BarToolGroup.static.accelTooltips = true;
-
-OO.ui.BarToolGroup.static.name = 'bar';
-/**
- * Popup list of tools with an icon and optional label.
- *
- * @class
- * @abstract
- * @extends OO.ui.ToolGroup
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.LabeledElement
- * @mixins OO.ui.TitledElement
- * @mixins OO.ui.ClippableElement
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- */
-OO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.PopupToolGroup.super.call( this, toolbar, config );
-
-       // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
-       OO.ui.TitledElement.call( this, this.$element, config );
-       OO.ui.ClippableElement.call( this, this.$group, config );
-
-       // Properties
-       this.active = false;
-       this.dragging = false;
-       this.onBlurHandler = OO.ui.bind( this.onBlur, this );
-       this.$handle = this.$( '<span>' );
-
-       // Events
-       this.$handle.on( {
-               'mousedown': OO.ui.bind( this.onHandleMouseDown, this ),
-               'mouseup': OO.ui.bind( this.onHandleMouseUp, this )
-       } );
-
-       // Initialization
-       this.$handle
-               .addClass( 'oo-ui-popupToolGroup-handle' )
-               .append( this.$icon, this.$label, this.$indicator );
-       this.$element
-               .addClass( 'oo-ui-popupToolGroup' )
-               .prepend( this.$handle );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PopupToolGroup, OO.ui.ToolGroup );
-
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.TitledElement );
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.ClippableElement );
-
-/* Static Properties */
-
-/* Methods */
-
-/**
- * @inheritdoc
- */
-OO.ui.PopupToolGroup.prototype.setDisabled = function () {
-       // Parent method
-       OO.ui.PopupToolGroup.super.prototype.setDisabled.apply( this, arguments );
-
-       if ( this.isDisabled() && this.isElementAttached() ) {
-               this.setActive( false );
-       }
-};
-
-/**
- * Handle focus being lost.
- *
- * The event is actually generated from a mouseup, so it is not a normal blur event object.
- *
- * @method
- * @param {jQuery.Event} e Mouse up event
- */
-OO.ui.PopupToolGroup.prototype.onBlur = function ( e ) {
-       // Only deactivate when clicking outside the dropdown element
-       if ( this.$( e.target ).closest( '.oo-ui-popupToolGroup' )[0] !== this.$element[0] ) {
-               this.setActive( false );
-       }
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.PopupToolGroup.prototype.onMouseUp = function ( e ) {
-       if ( !this.disabled && e.which === 1 ) {
-               this.setActive( false );
-       }
-       return OO.ui.ToolGroup.prototype.onMouseUp.call( this, e );
-};
-
-/**
- * Handle mouse up events.
- *
- * @method
- * @param {jQuery.Event} e Mouse up event
- */
-OO.ui.PopupToolGroup.prototype.onHandleMouseUp = function () {
-       return false;
-};
-
-/**
- * Handle mouse down events.
- *
- * @method
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.PopupToolGroup.prototype.onHandleMouseDown = function ( e ) {
-       if ( !this.disabled && e.which === 1 ) {
-               this.setActive( !this.active );
-       }
-       return false;
-};
-
-/**
- * Switch into active mode.
- *
- * When active, mouseup events anywhere in the document will trigger deactivation.
- *
- * @method
- */
-OO.ui.PopupToolGroup.prototype.setActive = function ( value ) {
-       value = !!value;
-       if ( this.active !== value ) {
-               this.active = value;
-               if ( value ) {
-                       this.setClipping( true );
-                       this.$element.addClass( 'oo-ui-popupToolGroup-active' );
-                       this.getElementDocument().addEventListener( 'mouseup', this.onBlurHandler, true );
-               } else {
-                       this.setClipping( false );
-                       this.$element.removeClass( 'oo-ui-popupToolGroup-active' );
-                       this.getElementDocument().removeEventListener( 'mouseup', this.onBlurHandler, true );
-               }
-       }
-};
-/**
- * Drop down list layout of tools as labeled icon buttons.
- *
- * @class
- * @abstract
- * @extends OO.ui.PopupToolGroup
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- */
-OO.ui.ListToolGroup = function OoUiListToolGroup( toolbar, config ) {
-       // Parent constructor
-       OO.ui.ListToolGroup.super.call( this, toolbar, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-listToolGroup' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ListToolGroup, OO.ui.PopupToolGroup );
-
-/* Static Properties */
-
-OO.ui.ListToolGroup.static.accelTooltips = true;
-
-OO.ui.ListToolGroup.static.name = 'list';
-/**
- * Drop down menu layout of tools as selectable menu items.
- *
- * @class
- * @abstract
- * @extends OO.ui.PopupToolGroup
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- */
-OO.ui.MenuToolGroup = function OoUiMenuToolGroup( toolbar, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.MenuToolGroup.super.call( this, toolbar, config );
-
-       // Events
-       this.toolbar.connect( this, { 'updateState': 'onUpdateState' } );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-menuToolGroup' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.MenuToolGroup, OO.ui.PopupToolGroup );
-
-/* Static Properties */
-
-OO.ui.MenuToolGroup.static.accelTooltips = true;
-
-OO.ui.MenuToolGroup.static.name = 'menu';
-
-/* Methods */
-
-/**
- * Handle the toolbar state being updated.
- *
- * When the state changes, the title of each active item in the menu will be joined together and
- * used as a label for the group. The label will be empty if none of the items are active.
- *
- * @method
- */
-OO.ui.MenuToolGroup.prototype.onUpdateState = function () {
-       var name,
-               labelTexts = [];
-
-       for ( name in this.tools ) {
-               if ( this.tools[name].isActive() ) {
-                       labelTexts.push( this.tools[name].getTitle() );
-               }
-       }
-
-       this.setLabel( labelTexts.join( ', ' ) || ' ' );
-};
-/**
- * UserInterface popup tool.
- *
- * @abstract
- * @class
- * @extends OO.ui.Tool
- * @mixins OO.ui.PopuppableElement
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- */
-OO.ui.PopupTool = function OoUiPopupTool( toolbar, config ) {
-       // Parent constructor
-       OO.ui.PopupTool.super.call( this, toolbar, config );
-
-       // Mixin constructors
-       OO.ui.PopuppableElement.call( this, config );
-
-       // Initialization
-       this.$element
-               .addClass( 'oo-ui-popupTool' )
-               .append( this.popup.$element );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PopupTool, OO.ui.Tool );
-
-OO.mixinClass( OO.ui.PopupTool, OO.ui.PopuppableElement );
-
-/* Methods */
-
-/**
- * Handle the tool being selected.
- *
- * @inheritdoc
- */
-OO.ui.PopupTool.prototype.onSelect = function () {
-       if ( !this.disabled ) {
-               if ( this.popup.isVisible() ) {
-                       this.hidePopup();
-               } else {
-                       this.showPopup();
-               }
-       }
-       this.setActive( false );
-       return false;
-};
-
-/**
- * Handle the toolbar state being updated.
- *
- * @inheritdoc
- */
-OO.ui.PopupTool.prototype.onUpdateState = function () {
-       this.setActive( false );
-};
-/**
- * Group widget.
- *
- * Mixin for OO.ui.Widget subclasses.
- *
- * Use together with OO.ui.ItemWidget to make disabled state inheritable.
- *
- * @class
- * @abstract
- * @extends OO.ui.GroupElement
- *
- * @constructor
- * @param {jQuery} $group Container node, assigned to #$group
- * @param {Object} [config] Configuration options
- */
-OO.ui.GroupWidget = function OoUiGroupWidget( $element, config ) {
-       // Parent constructor
-       OO.ui.GroupWidget.super.call( this, $element, config );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.GroupWidget, OO.ui.GroupElement );
-
-/* Methods */
-
-/**
- * Set the disabled state of the widget.
- *
- * This will also update the disabled state of child widgets.
- *
- * @method
- * @param {boolean} disabled Disable widget
- * @chainable
- */
-OO.ui.GroupWidget.prototype.setDisabled = function ( disabled ) {
-       var i, len;
-
-       // Parent method
-       // Note this is calling OO.ui.Widget; we're assuming the class this is mixed into
-       // is a subclass of OO.ui.Widget.
-       OO.ui.Widget.prototype.setDisabled.call( this, disabled );
-
-       // During construction, #setDisabled is called before the OO.ui.GroupElement constructor
-       if ( this.items ) {
-               for ( i = 0, len = this.items.length; i < len; i++ ) {
-                       this.items[i].updateDisabled();
-               }
-       }
-
-       return this;
-};
-/**
- * Item widget.
- *
- * Use together with OO.ui.GroupWidget to make disabled state inheritable.
- *
- * @class
- * @abstract
- *
- * @constructor
- */
-OO.ui.ItemWidget = function OoUiItemWidget() {
-       //
-};
-
-/* Methods */
-
-/**
- * Check if widget is disabled.
- *
- * Checks parent if present, making disabled state inheritable.
- *
- * @returns {boolean} Widget is disabled
- */
-OO.ui.ItemWidget.prototype.isDisabled = function () {
-       return this.disabled ||
-               ( this.elementGroup instanceof OO.ui.Widget && this.elementGroup.isDisabled() );
-};
-
-/**
- * Set group element is in.
- *
- * @param {OO.ui.GroupElement|null} group Group element, null if none
- * @chainable
- */
-OO.ui.ItemWidget.prototype.setElementGroup = function ( group ) {
-       // Parent method
-       OO.ui.Element.prototype.setElementGroup.call( this, group );
-
-       // Initialize item disabled states
-       this.updateDisabled();
-
-       return this;
-};
-/**
- * Creates an OO.ui.IconWidget object.
- *
- * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.TitledElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.IconWidget = function OoUiIconWidget( config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.IconWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$element, config );
-       OO.ui.TitledElement.call( this, this.$element, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-iconWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.IconWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.IconWidget, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.IconWidget, OO.ui.TitledElement );
-
-/* Static Properties */
-
-OO.ui.IconWidget.static.tagName = 'span';
-/**
- * Creates an OO.ui.IndicatorWidget object.
- *
- * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.TitledElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.IndicatorWidget = function OoUiIndicatorWidget( config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.IndicatorWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.IndicatedElement.call( this, this.$element, config );
-       OO.ui.TitledElement.call( this, this.$element, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-indicatorWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.IndicatorWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.TitledElement );
-
-/* Static Properties */
-
-OO.ui.IndicatorWidget.static.tagName = 'span';
-/**
- * Container for multiple related buttons.
- *
- * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.GroupElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {OO.ui.ButtonWidget} [items] Buttons to add
- */
-OO.ui.ButtonGroupWidget = function OoUiButtonGroupWidget( config ) {
-       // Parent constructor
-       OO.ui.ButtonGroupWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$element, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-buttonGroupWidget' );
-       if ( $.isArray( config.items ) ) {
-               this.addItems( config.items );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ButtonGroupWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.ButtonGroupWidget, OO.ui.GroupElement );
-/**
- * Creates an OO.ui.ButtonWidget object.
- *
- * @class
- * @abstract
- * @extends OO.ui.Widget
- * @mixins OO.ui.ButtonedElement
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.LabeledElement
- * @mixins OO.ui.TitledElement
- * @mixins OO.ui.FlaggableElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string} [title=''] Title text
- * @cfg {string} [href] Hyperlink to visit when clicked
- * @cfg {string} [target] Target to open hyperlink in
- */
-OO.ui.ButtonWidget = function OoUiButtonWidget( config ) {
-       // Configuration initialization
-       config = $.extend( { 'target': '_blank' }, config );
-
-       // Parent constructor
-       OO.ui.ButtonWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.ButtonedElement.call( this, this.$( '<a>' ), config );
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
-       OO.ui.TitledElement.call( this, this.$button, config );
-       OO.ui.FlaggableElement.call( this, config );
-
-       // Properties
-       this.isHyperlink = typeof config.href === 'string';
-
-       // Events
-       this.$button.on( {
-               'click': OO.ui.bind( this.onClick, this ),
-               'keypress': OO.ui.bind( this.onKeyPress, this )
-       } );
-
-       // Initialization
-       this.$button
-               .append( this.$icon, this.$label, this.$indicator )
-               .attr( { 'href': config.href, 'target': config.target } );
-       this.$element
-               .addClass( 'oo-ui-buttonWidget' )
-               .append( this.$button );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ButtonWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.ButtonedElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.TitledElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.FlaggableElement );
-
-/* Events */
-
-/**
- * @event click
- */
-
-/* Methods */
-
-/**
- * Handles mouse click events.
- *
- * @method
- * @param {jQuery.Event} e Mouse click event
- * @fires click
- */
-OO.ui.ButtonWidget.prototype.onClick = function () {
-       if ( !this.disabled ) {
-               this.emit( 'click' );
-               if ( this.isHyperlink ) {
-                       return true;
-               }
-       }
-       return false;
-};
-
-/**
- * Handles keypress events.
- *
- * @method
- * @param {jQuery.Event} e Keypress event
- * @fires click
- */
-OO.ui.ButtonWidget.prototype.onKeyPress = function ( e ) {
-       if ( !this.disabled && e.which === OO.ui.Keys.SPACE ) {
-               if ( this.isHyperlink ) {
-                       this.onClick();
-                       return true;
-               }
-       }
-       return false;
-};
-/**
- * Creates an OO.ui.InputWidget object.
- *
- * @class
- * @abstract
- * @extends OO.ui.Widget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string} [name=''] HTML input name
- * @cfg {string} [value=''] Input value
- * @cfg {boolean} [readOnly=false] Prevent changes
- * @cfg {Function} [inputFilter] Filter function to apply to the input. Takes a string argument and returns a string.
- */
-OO.ui.InputWidget = function OoUiInputWidget( config ) {
-       // Config intialization
-       config = $.extend( { 'readOnly': false }, config );
-
-       // Parent constructor
-       OO.ui.InputWidget.super.call( this, config );
-
-       // Properties
-       this.$input = this.getInputElement( config );
-       this.value = '';
-       this.readOnly = false;
-       this.inputFilter = config.inputFilter;
-
-       // Events
-       this.$input.on( 'keydown mouseup cut paste change input select', OO.ui.bind( this.onEdit, this ) );
-
-       // Initialization
-       this.$input
-               .attr( 'name', config.name )
-               .prop( 'disabled', this.disabled );
-       this.setReadOnly( config.readOnly );
-       this.$element.addClass( 'oo-ui-inputWidget' ).append( this.$input );
-       this.setValue( config.value );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.InputWidget, OO.ui.Widget );
-
-/* Events */
-
-/**
- * @event change
- * @param value
- */
-
-/* Methods */
-
-/**
- * Get input element.
- *
- * @method
- * @param {Object} [config] Configuration options
- * @returns {jQuery} Input element
- */
-OO.ui.InputWidget.prototype.getInputElement = function () {
-       return this.$( '<input>' );
-};
-
-/**
- * Handle potentially value-changing events.
- *
- * @method
- * @param {jQuery.Event} e Key down, mouse up, cut, paste, change, input, or select event
- */
-OO.ui.InputWidget.prototype.onEdit = function () {
-       if ( !this.disabled ) {
-               // Allow the stack to clear so the value will be updated
-               setTimeout( OO.ui.bind( function () {
-                       this.setValue( this.$input.val() );
-               }, this ) );
-       }
-};
-
-/**
- * Get the value of the input.
- *
- * @method
- * @returns {string} Input value
- */
-OO.ui.InputWidget.prototype.getValue = function () {
-       return this.value;
-};
-
-/**
- * Sets the direction of the current input, either RTL or LTR
- *
- * @method
- * @param {boolean} isRTL
- */
-OO.ui.InputWidget.prototype.setRTL = function ( isRTL ) {
-       if ( isRTL ) {
-               this.$input.removeClass( 'oo-ui-ltr' );
-               this.$input.addClass( 'oo-ui-rtl' );
-       } else {
-               this.$input.removeClass( 'oo-ui-rtl' );
-               this.$input.addClass( 'oo-ui-ltr' );
-       }
-};
-
-/**
- * Set the value of the input.
- *
- * @method
- * @param {string} value New value
- * @fires change
- * @chainable
- */
-OO.ui.InputWidget.prototype.setValue = function ( value ) {
-       value = this.sanitizeValue( value );
-       if ( this.value !== value ) {
-               this.value = value;
-               this.emit( 'change', this.value );
-       }
-       // Update the DOM if it has changed. Note that with sanitizeValue, it
-       // is possible for the DOM value to change without this.value changing.
-       if ( this.$input.val() !== this.value ) {
-               this.$input.val( this.value );
-       }
-       return this;
-};
-
-/**
- * Sanitize incoming value.
- *
- * Ensures value is a string, and converts undefined and null to empty strings.
- *
- * @method
- * @param {string} value Original value
- * @returns {string} Sanitized value
- */
-OO.ui.InputWidget.prototype.sanitizeValue = function ( value ) {
-       if ( value === undefined || value === null ) {
-               return '';
-       } else if ( this.inputFilter ) {
-               return this.inputFilter( String( value ) );
-       } else {
-               return String( value );
-       }
-};
-
-/**
- * Simulate the behavior of clicking on a label bound to this input.
- *
- * @method
- */
-OO.ui.InputWidget.prototype.simulateLabelClick = function () {
-       if ( !this.isDisabled() ) {
-               if ( this.$input.is( ':checkbox,:radio' ) ) {
-                       this.$input.click();
-               } else if ( this.$input.is( ':input' ) ) {
-                       this.$input.focus();
-               }
-       }
-};
-
-/**
- * Check if the widget is read-only.
- *
- * @method
- * @param {boolean} Input is read-only
- */
-OO.ui.InputWidget.prototype.isReadOnly = function () {
-       return this.readOnly;
-};
-
-/**
- * Set the read-only state of the widget.
- *
- * This should probably change the widgets's appearance and prevent it from being used.
- *
- * @method
- * @param {boolean} state Make input read-only
- * @chainable
- */
-OO.ui.InputWidget.prototype.setReadOnly = function ( state ) {
-       this.readOnly = !!state;
-       this.$input.prop( 'readonly', this.readOnly );
-       return this;
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.InputWidget.prototype.setDisabled = function ( state ) {
-       OO.ui.Widget.prototype.setDisabled.call( this, state );
-       if ( this.$input ) {
-               this.$input.prop( 'disabled', this.disabled );
-       }
-       return this;
-};
-/**
- * Creates an OO.ui.CheckboxInputWidget object.
- *
- * @class
- * @extends OO.ui.InputWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.CheckboxInputWidget = function OoUiCheckboxInputWidget( config ) {
-       // Parent constructor
-       OO.ui.CheckboxInputWidget.super.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-checkboxInputWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.CheckboxInputWidget, OO.ui.InputWidget );
-
-/* Events */
-
-/* Methods */
-
-/**
- * Get input element.
- *
- * @returns {jQuery} Input element
- */
-OO.ui.CheckboxInputWidget.prototype.getInputElement = function () {
-       return this.$( '<input type="checkbox" />' );
-};
-
-/**
- * Get checked state of the checkbox
- *
- * @returns {boolean} If the checkbox is checked
- */
-OO.ui.CheckboxInputWidget.prototype.getValue = function () {
-       return this.value;
-};
-
-/**
- * Set value
- */
-OO.ui.CheckboxInputWidget.prototype.setValue = function ( value ) {
-       value = !!value;
-       if ( this.value !== value ) {
-               this.value = value;
-               this.$input.prop( 'checked', this.value );
-               this.emit( 'change', this.value );
-       }
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.CheckboxInputWidget.prototype.onEdit = function () {
-       if ( !this.disabled ) {
-               // Allow the stack to clear so the value will be updated
-               setTimeout( OO.ui.bind( function () {
-                       this.setValue( this.$input.prop( 'checked' ) );
-               }, this ) );
-       }
-};
-/**
- * Creates an OO.ui.LabelWidget object.
- *
- * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.LabeledElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.LabelWidget = function OoUiLabelWidget( config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.LabelWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.LabeledElement.call( this, this.$element, config );
-
-       // Properties
-       this.input = config.input;
-
-       // Events
-       if ( this.input instanceof OO.ui.InputWidget ) {
-               this.$element.on( 'click', OO.ui.bind( this.onClick, this ) );
-       }
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-labelWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.LabelWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.LabelWidget, OO.ui.LabeledElement );
-
-/* Static Properties */
-
-OO.ui.LabelWidget.static.tagName = 'label';
-
-/* Methods */
-
-/**
- * Handles label mouse click events.
- *
- * @method
- * @param {jQuery.Event} e Mouse click event
- */
-OO.ui.LabelWidget.prototype.onClick = function () {
-       this.input.simulateLabelClick();
-       return false;
-};
-/**
- * Lookup input widget.
- *
- * Mixin that adds a menu showing suggested values to a text input. Subclasses must handle `select`
- * events on #lookupMenu to make use of selections.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {OO.ui.TextInputWidget} input Input widget
- * @param {Object} [config] Configuration options
- * @cfg {jQuery} [$overlay=this.$( 'body' )] Overlay layer
- */
-OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.lookupInput = input;
-       this.$overlay = config.$overlay || this.$( 'body,.oo-ui-window-overlay' ).last();
-       this.lookupMenu = new OO.ui.TextInputMenuWidget( this, {
-               '$': OO.ui.Element.getJQuery( this.$overlay ),
-               'input': this.lookupInput,
-               '$container': config.$container
-       } );
-       this.lookupCache = {};
-       this.lookupQuery = null;
-       this.lookupRequest = null;
-       this.populating = false;
-
-       // Events
-       this.$overlay.append( this.lookupMenu.$element );
-
-       this.lookupInput.$input.on( {
-               'focus': OO.ui.bind( this.onLookupInputFocus, this ),
-               'blur': OO.ui.bind( this.onLookupInputBlur, this ),
-               'mousedown': OO.ui.bind( this.onLookupInputMouseDown, this )
-       } );
-       this.lookupInput.connect( this, { 'change': 'onLookupInputChange' } );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-lookupWidget' );
-       this.lookupMenu.$element.addClass( 'oo-ui-lookupWidget-menu' );
-};
-
-/* Methods */
-
-/**
- * Handle input focus event.
- *
- * @method
- * @param {jQuery.Event} e Input focus event
- */
-OO.ui.LookupInputWidget.prototype.onLookupInputFocus = function () {
-       this.openLookupMenu();
-};
-
-/**
- * Handle input blur event.
- *
- * @method
- * @param {jQuery.Event} e Input blur event
- */
-OO.ui.LookupInputWidget.prototype.onLookupInputBlur = function () {
-       this.lookupMenu.hide();
-};
-
-/**
- * Handle input mouse down event.
- *
- * @method
- * @param {jQuery.Event} e Input mouse down event
- */
-OO.ui.LookupInputWidget.prototype.onLookupInputMouseDown = function () {
-       this.openLookupMenu();
-};
-
-/**
- * Handle input change event.
- *
- * @method
- * @param {string} value New input value
- */
-OO.ui.LookupInputWidget.prototype.onLookupInputChange = function () {
-       this.openLookupMenu();
-};
-
-/**
- * Open the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.LookupInputWidget.prototype.openLookupMenu = function () {
-       var value = this.lookupInput.getValue();
-
-       if ( this.lookupMenu.$input.is( ':focus' ) && $.trim( value ) !== '' ) {
-               this.populateLookupMenu();
-               if ( !this.lookupMenu.isVisible() ) {
-                       this.lookupMenu.show();
-               }
-       } else {
-               this.lookupMenu.clearItems();
-               this.lookupMenu.hide();
-       }
-
-       return this;
-};
-
-/**
- * Populate lookup menu with current information.
- *
- * @method
- * @chainable
- */
-OO.ui.LookupInputWidget.prototype.populateLookupMenu = function () {
-       if ( !this.populating ) {
-               this.populating = true;
-               this.getLookupMenuItems()
-                       .done( OO.ui.bind( function ( items ) {
-                               this.lookupMenu.clearItems();
-                               if ( items.length ) {
-                                       this.lookupMenu.show();
-                                       this.lookupMenu.addItems( items );
-                                       this.initializeLookupMenuSelection();
-                                       this.openLookupMenu();
-                               } else {
-                                       this.lookupMenu.hide();
-                               }
-                               this.populating = false;
-                       }, this ) )
-                       .fail( OO.ui.bind( function () {
-                               this.lookupMenu.clearItems();
-                               this.populating = false;
-                       }, this ) );
-       }
-
-       return this;
-};
-
-/**
- * Set selection in the lookup menu with current information.
- *
- * @method
- * @chainable
- */
-OO.ui.LookupInputWidget.prototype.initializeLookupMenuSelection = function () {
-       if ( !this.lookupMenu.getSelectedItem() ) {
-               this.lookupMenu.intializeSelection( this.lookupMenu.getFirstSelectableItem() );
-       }
-       this.lookupMenu.highlightItem( this.lookupMenu.getSelectedItem() );
-};
-
-/**
- * Get lookup menu items for the current query.
- *
- * @method
- * @returns {jQuery.Promise} Promise object which will be passed menu items as the first argument
- * of the done event
- */
-OO.ui.LookupInputWidget.prototype.getLookupMenuItems = function () {
-       var value = this.lookupInput.getValue(),
-               deferred = $.Deferred();
-
-       if ( value && value !== this.lookupQuery ) {
-               // Abort current request if query has changed
-               if ( this.lookupRequest ) {
-                       this.lookupRequest.abort();
-                       this.lookupQuery = null;
-                       this.lookupRequest = null;
-               }
-               if ( value in this.lookupCache ) {
-                       deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) );
-               } else {
-                       this.lookupQuery = value;
-                       this.lookupRequest = this.getLookupRequest()
-                               .always( OO.ui.bind( function () {
-                                       this.lookupQuery = null;
-                                       this.lookupRequest = null;
-                               }, this ) )
-                               .done( OO.ui.bind( function ( data ) {
-                                       this.lookupCache[value] = this.getLookupCacheItemFromData( data );
-                                       deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) );
-                               }, this ) )
-                               .fail( function () {
-                                       deferred.reject();
-                               } );
-                       this.pushPending();
-                       this.lookupRequest.always( OO.ui.bind( function () {
-                               this.popPending();
-                       }, this ) );
-               }
-       }
-       return deferred.promise();
-};
-
-/**
- * Get a new request object of the current lookup query value.
- *
- * @method
- * @abstract
- * @returns {jqXHR} jQuery AJAX object, or promise object with an .abort() method
- */
-OO.ui.LookupInputWidget.prototype.getLookupRequest = function () {
-       // Stub, implemented in subclass
-       return null;
-};
-
-/**
- * Handle successful lookup request.
- *
- * Overriding methods should call #populateLookupMenu when results are available and cache results
- * for future lookups in #lookupCache as an array of #OO.ui.MenuItemWidget objects.
- *
- * @method
- * @abstract
- * @param {Mixed} data Response from server
- */
-OO.ui.LookupInputWidget.prototype.onLookupRequestDone = function () {
-       // Stub, implemented in subclass
-};
-
-/**
- * Get a list of menu item widgets from the data stored by the lookup request's done handler.
- *
- * @method
- * @abstract
- * @param {Mixed} data Cached result data, usually an array
- * @returns {OO.ui.MenuItemWidget[]} Menu items
- */
-OO.ui.LookupInputWidget.prototype.getLookupMenuItemsFromData = function () {
-       // Stub, implemented in subclass
-       return [];
-};
-/**
- * Creates an OO.ui.OptionWidget object.
- *
- * @class
- * @abstract
- * @extends OO.ui.Widget
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.LabeledElement
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.FlaggableElement
- *
- * @constructor
- * @param {Mixed} data Option data
- * @param {Object} [config] Configuration options
- * @cfg {string} [rel] Value for `rel` attribute in DOM, allowing per-option styling
- */
-OO.ui.OptionWidget = function OoUiOptionWidget( data, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.OptionWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.ItemWidget.call( this );
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
-       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.FlaggableElement.call( this, config );
-
-       // Properties
-       this.data = data;
-       this.selected = false;
-       this.highlighted = false;
-
-       // Initialization
-       this.$element
-               .data( 'oo-ui-optionWidget', this )
-               .attr( 'rel', config.rel )
-               .addClass( 'oo-ui-optionWidget' )
-               .append( this.$label );
-       this.$element
-               .prepend( this.$icon )
-               .append( this.$indicator );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.OptionWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.ItemWidget );
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.FlaggableElement );
-
-/* Static Properties */
-
-OO.ui.OptionWidget.static.tagName = 'li';
-
-OO.ui.OptionWidget.static.selectable = true;
-
-OO.ui.OptionWidget.static.highlightable = true;
-
-OO.ui.OptionWidget.static.scrollIntoViewOnSelect = false;
-
-/* Methods */
-
-/**
- * Check if option can be selected.
- *
- * @method
- * @returns {boolean} Item is selectable
- */
-OO.ui.OptionWidget.prototype.isSelectable = function () {
-       return this.constructor.static.selectable && !this.disabled;
-};
-
-/**
- * Check if option can be highlighted.
- *
- * @method
- * @returns {boolean} Item is highlightable
- */
-OO.ui.OptionWidget.prototype.isHighlightable = function () {
-       return this.constructor.static.highlightable && !this.disabled;
-};
-
-/**
- * Check if option is selected.
- *
- * @method
- * @returns {boolean} Item is selected
- */
-OO.ui.OptionWidget.prototype.isSelected = function () {
-       return this.selected;
-};
-
-/**
- * Check if option is highlighted.
- *
- * @method
- * @returns {boolean} Item is highlighted
- */
-OO.ui.OptionWidget.prototype.isHighlighted = function () {
-       return this.highlighted;
-};
-
-/**
- * Set selected state.
- *
- * @method
- * @param {boolean} [state=false] Select option
- * @chainable
- */
-OO.ui.OptionWidget.prototype.setSelected = function ( state ) {
-       if ( !this.disabled && this.constructor.static.selectable ) {
-               this.selected = !!state;
-               if ( this.selected ) {
-                       this.$element.addClass( 'oo-ui-optionWidget-selected' );
-                       if ( this.constructor.static.scrollIntoViewOnSelect ) {
-                               this.scrollElementIntoView();
-                       }
-               } else {
-                       this.$element.removeClass( 'oo-ui-optionWidget-selected' );
-               }
-       }
-       return this;
-};
-
-/**
- * Set highlighted state.
- *
- * @method
- * @param {boolean} [state=false] Highlight option
- * @chainable
- */
-OO.ui.OptionWidget.prototype.setHighlighted = function ( state ) {
-       if ( !this.disabled && this.constructor.static.highlightable ) {
-               this.highlighted = !!state;
-               if ( this.highlighted ) {
-                       this.$element.addClass( 'oo-ui-optionWidget-highlighted' );
-               } else {
-                       this.$element.removeClass( 'oo-ui-optionWidget-highlighted' );
-               }
-       }
-       return this;
-};
-
-/**
- * Make the option's highlight flash.
- *
- * @method
- * @param {Function} [done] Callback to execute when flash effect is complete.
- */
-OO.ui.OptionWidget.prototype.flash = function ( done ) {
-       var $this = this.$element;
-
-       if ( !this.disabled && this.constructor.static.highlightable ) {
-               $this.removeClass( 'oo-ui-optionWidget-highlighted' );
-               setTimeout( OO.ui.bind( function () {
-                       $this.addClass( 'oo-ui-optionWidget-highlighted' );
-                       if ( done ) {
-                               setTimeout( done, 100 );
-                       }
-               }, this ), 100 );
-       }
-};
-
-/**
- * Get option data.
- *
- * @method
- * @returns {Mixed} Option data
- */
-OO.ui.OptionWidget.prototype.getData = function () {
-       return this.data;
-};
-/**
- * Create an OO.ui.SelectWidget object.
- *
- * @class
- * @abstract
- * @extends OO.ui.Widget
- * @mixins OO.ui.GroupElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {OO.ui.OptionWidget[]} [items] Options to add
- */
-OO.ui.SelectWidget = function OoUiSelectWidget( config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.SelectWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.GroupWidget.call( this, this.$element, config );
-
-       // Properties
-       this.pressed = false;
-       this.selecting = null;
-       this.hashes = {};
-
-       // Events
-       this.$element.on( {
-               'mousedown': OO.ui.bind( this.onMouseDown, this ),
-               'mouseup': OO.ui.bind( this.onMouseUp, this ),
-               'mousemove': OO.ui.bind( this.onMouseMove, this ),
-               'mouseover': OO.ui.bind( this.onMouseOver, this ),
-               'mouseleave': OO.ui.bind( this.onMouseLeave, this )
-       } );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-selectWidget' );
-       if ( $.isArray( config.items ) ) {
-               this.addItems( config.items );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.SelectWidget, OO.ui.Widget );
-
-// Need to mixin base class as well
-OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupElement );
-
-OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupWidget );
-
-/* Events */
-
-/**
- * @event highlight
- * @param {OO.ui.OptionWidget|null} item Highlighted item
- */
-
-/**
- * @event select
- * @param {OO.ui.OptionWidget|null} item Selected item
- */
-
-/**
- * @event add
- * @param {OO.ui.OptionWidget[]} items Added items
- * @param {number} index Index items were added at
- */
-
-/**
- * @event remove
- * @param {OO.ui.OptionWidget[]} items Removed items
- */
-
-/* Static Properties */
-
-OO.ui.SelectWidget.static.tagName = 'ul';
-
-/* Methods */
-
-/**
- * Handle mouse down events.
- *
- * @method
- * @private
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.SelectWidget.prototype.onMouseDown = function ( e ) {
-       var item;
-
-       if ( !this.disabled && e.which === 1 ) {
-               this.pressed = true;
-               item = this.getTargetItem( e );
-               if ( item && item.isSelectable() ) {
-                       this.intializeSelection( item );
-                       this.selecting = item;
-                       this.$( this.$.context ).one( 'mouseup', OO.ui.bind( this.onMouseUp, this ) );
-               }
-       }
-       return false;
-};
-
-/**
- * Handle mouse up events.
- *
- * @method
- * @private
- * @param {jQuery.Event} e Mouse up event
- */
-OO.ui.SelectWidget.prototype.onMouseUp = function ( e ) {
-       var item;
-       this.pressed = false;
-       if ( !this.selecting ) {
-               item = this.getTargetItem( e );
-               if ( item && item.isSelectable() ) {
-                       this.selecting = item;
-               }
-       }
-       if ( !this.disabled && e.which === 1 && this.selecting ) {
-               this.selectItem( this.selecting );
-               this.selecting = null;
-       }
-       return false;
-};
-
-/**
- * Handle mouse move events.
- *
- * @method
- * @private
- * @param {jQuery.Event} e Mouse move event
- */
-OO.ui.SelectWidget.prototype.onMouseMove = function ( e ) {
-       var item;
-
-       if ( !this.disabled && this.pressed ) {
-               item = this.getTargetItem( e );
-               if ( item && item !== this.selecting && item.isSelectable() ) {
-                       this.intializeSelection( item );
-                       this.selecting = item;
-               }
-       }
-       return false;
-};
-
-/**
- * Handle mouse over events.
- *
- * @method
- * @private
- * @param {jQuery.Event} e Mouse over event
- */
-OO.ui.SelectWidget.prototype.onMouseOver = function ( e ) {
-       var item;
-
-       if ( !this.disabled ) {
-               item = this.getTargetItem( e );
-               if ( item && item.isHighlightable() ) {
-                       this.highlightItem( item );
-               }
-       }
-       return false;
-};
-
-/**
- * Handle mouse leave events.
- *
- * @method
- * @private
- * @param {jQuery.Event} e Mouse over event
- */
-OO.ui.SelectWidget.prototype.onMouseLeave = function () {
-       if ( !this.disabled ) {
-               this.highlightItem();
-       }
-       return false;
-};
-
-/**
- * Get the closest item to a jQuery.Event.
- *
- * @method
- * @private
- * @param {jQuery.Event} e
- * @returns {OO.ui.OptionWidget|null} Outline item widget, `null` if none was found
- */
-OO.ui.SelectWidget.prototype.getTargetItem = function ( e ) {
-       var $item = this.$( e.target ).closest( '.oo-ui-optionWidget' );
-       if ( $item.length ) {
-               return $item.data( 'oo-ui-optionWidget' );
-       }
-       return null;
-};
-
-/**
- * Get selected item.
- *
- * @method
- * @returns {OO.ui.OptionWidget|null} Selected item, `null` if no item is selected
- */
-OO.ui.SelectWidget.prototype.getSelectedItem = function () {
-       var i, len;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               if ( this.items[i].isSelected() ) {
-                       return this.items[i];
-               }
-       }
-       return null;
-};
-
-/**
- * Get highlighted item.
- *
- * @method
- * @returns {OO.ui.OptionWidget|null} Highlighted item, `null` if no item is highlighted
- */
-OO.ui.SelectWidget.prototype.getHighlightedItem = function () {
-       var i, len;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               if ( this.items[i].isHighlighted() ) {
-                       return this.items[i];
-               }
-       }
-       return null;
-};
-
-/**
- * Get an existing item with equivilant data.
- *
- * @method
- * @param {Object} data Item data to search for
- * @returns {OO.ui.OptionWidget|null} Item with equivilent value, `null` if none exists
- */
-OO.ui.SelectWidget.prototype.getItemFromData = function ( data ) {
-       var hash = OO.getHash( data );
-
-       if ( hash in this.hashes ) {
-               return this.hashes[hash];
-       }
-
-       return null;
-};
-
-/**
- * Highlight an item.
- *
- * Highlighting is mutually exclusive.
- *
- * @method
- * @param {OO.ui.OptionWidget} [item] Item to highlight, omit to deselect all
- * @fires highlight
- * @chainable
- */
-OO.ui.SelectWidget.prototype.highlightItem = function ( item ) {
-       var i, len, highlighted,
-               changed = false;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               highlighted = this.items[i] === item;
-               if ( this.items[i].isHighlighted() !== highlighted ) {
-                       this.items[i].setHighlighted( highlighted );
-                       changed = true;
-               }
-       }
-       if ( changed ) {
-               this.emit( 'highlight', item );
-       }
-
-       return this;
-};
-
-/**
- * Select an item.
- *
- * @method
- * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
- * @fires select
- * @chainable
- */
-OO.ui.SelectWidget.prototype.selectItem = function ( item ) {
-       var i, len, selected,
-               changed = false;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               selected = this.items[i] === item;
-               if ( this.items[i].isSelected() !== selected ) {
-                       this.items[i].setSelected( selected );
-                       changed = true;
-               }
-       }
-       if ( changed ) {
-               this.emit( 'select', item );
-       }
-
-       return this;
-};
-
-/**
- * Setup selection and highlighting.
- *
- * This should be used to synchronize the UI with the model without emitting events that would in
- * turn update the model.
- *
- * @param {OO.ui.OptionWidget} [item] Item to select
- * @chainable
- */
-OO.ui.SelectWidget.prototype.intializeSelection = function ( item ) {
-       var i, len, selected;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               selected = this.items[i] === item;
-               this.items[i].setSelected( selected );
-               this.items[i].setHighlighted( selected );
-       }
-
-       return this;
-};
-
-/**
- * Get an item relative to another one.
- *
- * @method
- * @param {OO.ui.OptionWidget} item Item to start at
- * @param {number} direction Direction to move in
- * @returns {OO.ui.OptionWidget|null} Item at position, `null` if there are no items in the menu
- */
-OO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direction ) {
-       var inc = direction > 0 ? 1 : -1,
-               len = this.items.length,
-               index = item instanceof OO.ui.OptionWidget ?
-                       $.inArray( item, this.items ) : ( inc > 0 ? -1 : 0 ),
-               stopAt = Math.max( Math.min( index, len - 1 ), 0 ),
-               i = inc > 0 ?
-                       // Default to 0 instead of -1, if nothing is selected let's start at the beginning
-                       Math.max( index, -1 ) :
-                       // Default to n-1 instead of -1, if nothing is selected let's start at the end
-                       Math.min( index, len );
-
-       while ( true ) {
-               i = ( i + inc + len ) % len;
-               item = this.items[i];
-               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
-                       return item;
-               }
-               // Stop iterating when we've looped all the way around
-               if ( i === stopAt ) {
-                       break;
-               }
-       }
-       return null;
-};
-
-/**
- * Get the next selectable item.
- *
- * @method
- * @returns {OO.ui.OptionWidget|null} Item, `null` if ther aren't any selectable items
- */
-OO.ui.SelectWidget.prototype.getFirstSelectableItem = function () {
-       var i, len, item;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               item = this.items[i];
-               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
-                       return item;
-               }
-       }
-
-       return null;
-};
-
-/**
- * Add items.
- *
- * When items are added with the same values as existing items, the existing items will be
- * automatically removed before the new items are added.
- *
- * @method
- * @param {OO.ui.OptionWidget[]} items Items to add
- * @param {number} [index] Index to insert items after
- * @fires add
- * @chainable
- */
-OO.ui.SelectWidget.prototype.addItems = function ( items, index ) {
-       var i, len, item, hash,
-               remove = [];
-
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-               hash = OO.getHash( item.getData() );
-               if ( hash in this.hashes ) {
-                       // Remove item with same value
-                       remove.push( this.hashes[hash] );
-               }
-               this.hashes[hash] = item;
-       }
-       if ( remove.length ) {
-               this.removeItems( remove );
-       }
-
-       OO.ui.GroupElement.prototype.addItems.call( this, items, index );
-
-       // Always provide an index, even if it was omitted
-       this.emit( 'add', items, index === undefined ? this.items.length - items.length - 1 : index );
-
-       return this;
-};
-
-/**
- * Remove items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @param {OO.ui.OptionWidget[]} items Items to remove
- * @fires remove
- * @chainable
- */
-OO.ui.SelectWidget.prototype.removeItems = function ( items ) {
-       var i, len, item, hash;
-
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-               hash = OO.getHash( item.getData() );
-               if ( hash in this.hashes ) {
-                       // Remove existing item
-                       delete this.hashes[hash];
-               }
-               if ( item.isSelected() ) {
-                       this.selectItem( null );
-               }
-       }
-       OO.ui.GroupElement.prototype.removeItems.call( this, items );
-
-       this.emit( 'remove', items );
-
-       return this;
-};
-
-/**
- * Clear all items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @fires remove
- * @chainable
- */
-OO.ui.SelectWidget.prototype.clearItems = function () {
-       var items = this.items.slice();
-
-       // Clear all items
-       this.hashes = {};
-       OO.ui.GroupElement.prototype.clearItems.call( this );
-       this.selectItem( null );
-
-       this.emit( 'remove', items );
-
-       return this;
-};
-/**
- * Creates an OO.ui.MenuItemWidget object.
- *
- * @class
- * @extends OO.ui.OptionWidget
- *
- * @constructor
- * @param {Mixed} data Item data
- * @param {Object} [config] Configuration options
- */
-OO.ui.MenuItemWidget = function OoUiMenuItemWidget( data, config ) {
-       // Configuration initialization
-       config = $.extend( { 'icon': 'check' }, config );
-
-       // Parent constructor
-       OO.ui.MenuItemWidget.super.call( this, data, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-menuItemWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.MenuItemWidget, OO.ui.OptionWidget );
-/**
- * Create an OO.ui.MenuWidget object.
- *
- * @class
- * @extends OO.ui.SelectWidget
- * @mixins OO.ui.ClippableElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {OO.ui.InputWidget} [input] Input to bind keyboard handlers to
- */
-OO.ui.MenuWidget = function OoUiMenuWidget( config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.MenuWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.ClippableElement.call( this, this.$group, config );
-
-       // Properties
-       this.newItems = null;
-       this.$input = config.input ? config.input.$input : null;
-       this.$previousFocus = null;
-       this.isolated = !config.input;
-       this.visible = false;
-       this.onKeyDownHandler = OO.ui.bind( this.onKeyDown, this );
-
-       // Initialization
-       this.$element.hide().addClass( 'oo-ui-menuWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.MenuWidget, OO.ui.SelectWidget );
-
-OO.mixinClass( OO.ui.MenuWidget, OO.ui.ClippableElement );
-
-/* Methods */
-
-/**
- * Handles key down events.
- *
- * @method
- * @param {jQuery.Event} e Key down event
- */
-OO.ui.MenuWidget.prototype.onKeyDown = function ( e ) {
-       var nextItem,
-               handled = false,
-               highlightItem = this.getHighlightedItem();
-
-       if ( !this.disabled && this.visible ) {
-               if ( !highlightItem ) {
-                       highlightItem = this.getSelectedItem();
-               }
-               switch ( e.keyCode ) {
-                       case OO.ui.Keys.ENTER:
-                               this.selectItem( highlightItem );
-                               handled = true;
-                               break;
-                       case OO.ui.Keys.UP:
-                               nextItem = this.getRelativeSelectableItem( highlightItem, -1 );
-                               handled = true;
-                               break;
-                       case OO.ui.Keys.DOWN:
-                               nextItem = this.getRelativeSelectableItem( highlightItem, 1 );
-                               handled = true;
-                               break;
-                       case OO.ui.Keys.ESCAPE:
-                               if ( highlightItem ) {
-                                       highlightItem.setHighlighted( false );
-                               }
-                               this.hide();
-                               handled = true;
-                               break;
-               }
-
-               if ( nextItem ) {
-                       this.highlightItem( nextItem );
-                       nextItem.scrollElementIntoView();
-               }
-
-               if ( handled ) {
-                       e.preventDefault();
-                       e.stopPropagation();
-                       return false;
-               }
-       }
-};
-
-/**
- * Check if the menu is visible.
- *
- * @method
- * @returns {boolean} Menu is visible
- */
-OO.ui.MenuWidget.prototype.isVisible = function () {
-       return this.visible;
-};
-
-/**
- * Bind key down listener
- *
- * @method
- */
-OO.ui.MenuWidget.prototype.bindKeyDownListener = function () {
-       if ( this.$input ) {
-               this.$input.on( 'keydown', this.onKeyDownHandler );
-       } else {
-               // Capture menu navigation keys
-               this.getElementWindow().addEventListener( 'keydown', this.onKeyDownHandler, true );
-       }
-};
-
-/**
- * Unbind key down listener
- *
- * @method
- */
-OO.ui.MenuWidget.prototype.unbindKeyDownListener = function () {
-       if ( this.$input ) {
-               this.$input.off( 'keydown' );
-       } else {
-               this.getElementWindow().removeEventListener( 'keydown', this.onKeyDownHandler, true );
-       }
-};
-
-/**
- * Select an item.
- *
- * The menu will stay open if an item is silently selected.
- *
- * @method
- * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
- * @chainable
- */
-OO.ui.MenuWidget.prototype.selectItem = function ( item ) {
-       // Parent method
-       OO.ui.SelectWidget.prototype.selectItem.call( this, item );
-
-       if ( !this.disabled ) {
-               if ( item ) {
-                       this.disabled = true;
-                       item.flash( OO.ui.bind( function () {
-                               this.hide();
-                               this.disabled = false;
-                       }, this ) );
-               } else {
-                       this.hide();
-               }
-       }
-
-       return this;
-};
-
-/**
- * Add items.
- *
- * Adding an existing item (by value) will move it.
- *
- * @method
- * @param {OO.ui.MenuItemWidget[]} items Items to add
- * @param {number} [index] Index to insert items after
- * @chainable
- */
-OO.ui.MenuWidget.prototype.addItems = function ( items, index ) {
-       var i, len, item;
-
-       // Parent method
-       OO.ui.SelectWidget.prototype.addItems.call( this, items, index );
-
-       // Auto-initialize
-       if ( !this.newItems ) {
-               this.newItems = [];
-       }
-
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-               if ( this.visible ) {
-                       // Defer fitting label until
-                       item.fitLabel();
-               } else {
-                       this.newItems.push( item );
-               }
-       }
-
-       return this;
-};
-
-/**
- * Show the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.MenuWidget.prototype.show = function () {
-       var i, len;
-
-       if ( this.items.length ) {
-               this.$element.show();
-               this.visible = true;
-               this.bindKeyDownListener();
-
-               // Change focus to enable keyboard navigation
-               if ( this.isolated && this.$input && !this.$input.is( ':focus' ) ) {
-                       this.$previousFocus = this.$( ':focus' );
-                       this.$input.focus();
-               }
-               if ( this.newItems && this.newItems.length ) {
-                       for ( i = 0, len = this.newItems.length; i < len; i++ ) {
-                               this.newItems[i].fitLabel();
-                       }
-                       this.newItems = null;
-               }
-
-               this.setClipping( true );
-       }
-
-       return this;
-};
-
-/**
- * Hide the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.MenuWidget.prototype.hide = function () {
-       this.$element.hide();
-       this.visible = false;
-       this.unbindKeyDownListener();
-
-       if ( this.isolated && this.$previousFocus ) {
-               this.$previousFocus.focus();
-               this.$previousFocus = null;
-       }
-
-       this.setClipping( false );
-
-       return this;
-};
-/**
- * Inline menu of options.
- *
- * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.LabeledElement
- * @mixins OO.ui.TitledElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {Object} [menu] Configuration options to pass to menu widget
- */
-OO.ui.InlineMenuWidget = function OoUiInlineMenuWidget( config ) {
-       // Configuration initialization
-       config = $.extend( { 'indicator': 'down' }, config );
-
-       // Parent constructor
-       OO.ui.InlineMenuWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
-       OO.ui.TitledElement.call( this, this.$label, config );
-
-       // Properties
-       this.menu = new OO.ui.MenuWidget( $.extend( { '$': this.$ }, config.menu ) );
-       this.$handle = this.$( '<span>' );
-
-       // Events
-       this.$element.on( { 'click': OO.ui.bind( this.onClick, this ) } );
-       this.menu.connect( this, { 'select': 'onMenuSelect' } );
-
-       // Initialization
-       this.$handle
-               .addClass( 'oo-ui-inlineMenuWidget-handle' )
-               .append( this.$icon, this.$label, this.$indicator );
-       this.$element
-               .addClass( 'oo-ui-inlineMenuWidget' )
-               .append( this.$handle, this.menu.$element );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.InlineMenuWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.TitledElement );
-
-/* Methods */
-
-/**
- * Get the menu.
- *
- * @return {OO.ui.MenuWidget} Menu of widget
- */
-OO.ui.InlineMenuWidget.prototype.getMenu = function () {
-       return this.menu;
-};
-
-/**
- * Handles menu select events.
- *
- * @method
- * @param {OO.ui.MenuItemWidget} item Selected menu item
- */
-OO.ui.InlineMenuWidget.prototype.onMenuSelect = function ( item ) {
-       var selectedLabel = item.getLabel();
-
-       // If the label is a DOM element, clone it, because setLabel will append() it
-       if ( selectedLabel instanceof jQuery ) {
-               selectedLabel = selectedLabel.clone();
-       }
-
-       this.setLabel( selectedLabel );
-};
-
-/**
- * Handles mouse click events.
- *
- * @method
- * @param {jQuery.Event} e Mouse click event
- */
-OO.ui.InlineMenuWidget.prototype.onClick = function ( e ) {
-       // Skip clicks within the menu
-       if ( $.contains( this.menu.$element[0], e.target ) ) {
-               return;
-       }
-
-       if ( !this.disabled ) {
-               if ( this.menu.isVisible() ) {
-                       this.menu.hide();
-               } else {
-                       this.menu.show();
-               }
-       }
-       return false;
-};
-/**
- * Creates an OO.ui.MenuSectionItemWidget object.
- *
- * @class
- * @extends OO.ui.OptionWidget
- *
- * @constructor
- * @param {Mixed} data Item data
- * @param {Object} [config] Configuration options
- */
-OO.ui.MenuSectionItemWidget = function OoUiMenuSectionItemWidget( data, config ) {
-       // Parent constructor
-       OO.ui.MenuSectionItemWidget.super.call( this, data, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-menuSectionItemWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.MenuSectionItemWidget, OO.ui.OptionWidget );
-
-OO.ui.MenuSectionItemWidget.static.selectable = false;
-
-OO.ui.MenuSectionItemWidget.static.highlightable = false;
-/**
- * Create an OO.ui.OutlineWidget object.
- *
- * @class
- * @extends OO.ui.SelectWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.OutlineWidget = function OoUiOutlineWidget( config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.OutlineWidget.super.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-outlineWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.OutlineWidget, OO.ui.SelectWidget );
-/**
- * Creates an OO.ui.OutlineControlsWidget object.
- *
- * @class
- *
- * @constructor
- * @param {OO.ui.OutlineWidget} outline Outline to control
- * @param {Object} [config] Configuration options
- */
-OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) {
-       // Configuration initialization
-       config = $.extend( { 'icon': 'add-item' }, config );
-
-       // Parent constructor
-       OO.ui.OutlineControlsWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
-       OO.ui.IconedElement.call( this, this.$( '<div>' ), config );
-
-       // Properties
-       this.outline = outline;
-       this.$movers = this.$( '<div>' );
-       this.upButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'collapse',
-               'title': OO.ui.msg( 'ooui-outline-control-move-up' )
-       } );
-       this.downButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'expand',
-               'title': OO.ui.msg( 'ooui-outline-control-move-down' )
-       } );
-       this.removeButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'remove',
-               'title': OO.ui.msg( 'ooui-outline-control-remove' )
-       } );
-
-       // Events
-       outline.connect( this, {
-               'select': 'onOutlineChange',
-               'add': 'onOutlineChange',
-               'remove': 'onOutlineChange'
-       } );
-       this.upButton.connect( this, { 'click': ['emit', 'move', -1] } );
-       this.downButton.connect( this, { 'click': ['emit', 'move', 1] } );
-       this.removeButton.connect( this, { 'click': ['emit', 'remove'] } );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-outlineControlsWidget' );
-       this.$group.addClass( 'oo-ui-outlineControlsWidget-adders' );
-       this.$movers
-               .addClass( 'oo-ui-outlineControlsWidget-movers' )
-               .append( this.removeButton.$element, this.upButton.$element, this.downButton.$element );
-       this.$element.append( this.$icon, this.$group, this.$movers );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.GroupElement );
-OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.IconedElement );
-
-/* Events */
-
-/**
- * @event move
- * @param {number} places Number of places to move
- */
-
-/**
- * @event remove
- */
-
-/* Methods */
-
-/**
- * Handle outline change events.
- *
- * @method
- */
-OO.ui.OutlineControlsWidget.prototype.onOutlineChange = function () {
-       var i, len, firstMovable, lastMovable,
-               items = this.outline.getItems(),
-               selectedItem = this.outline.getSelectedItem(),
-               movable = selectedItem && selectedItem.isMovable(),
-               removable = selectedItem && selectedItem.isRemovable();
-
-       if ( movable ) {
-               i = -1;
-               len = items.length;
-               while ( ++i < len ) {
-                       if ( items[i].isMovable() ) {
-                               firstMovable = items[i];
-                               break;
-                       }
-               }
-               i = len;
-               while ( i-- ) {
-                       if ( items[i].isMovable() ) {
-                               lastMovable = items[i];
-                               break;
-                       }
-               }
-       }
-       this.upButton.setDisabled( !movable || selectedItem === firstMovable );
-       this.downButton.setDisabled( !movable || selectedItem === lastMovable );
-       this.removeButton.setDisabled( !removable );
-};
-/**
- * Creates an OO.ui.OutlineItemWidget object.
- *
- * @class
- * @extends OO.ui.OptionWidget
- *
- * @constructor
- * @param {Mixed} data Item data
- * @param {Object} [config] Configuration options
- * @cfg {number} [level] Indentation level
- * @cfg {boolean} [movable] Allow modification from outline controls
- */
-OO.ui.OutlineItemWidget = function OoUiOutlineItemWidget( data, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.OutlineItemWidget.super.call( this, data, config );
-
-       // Properties
-       this.level = 0;
-       this.movable = !!config.movable;
-       this.removable = !!config.removable;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-outlineItemWidget' );
-       this.setLevel( config.level );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.OutlineItemWidget, OO.ui.OptionWidget );
-
-/* Static Properties */
-
-OO.ui.OutlineItemWidget.static.highlightable = false;
-
-OO.ui.OutlineItemWidget.static.scrollIntoViewOnSelect = true;
-
-OO.ui.OutlineItemWidget.static.levelClass = 'oo-ui-outlineItemWidget-level-';
-
-OO.ui.OutlineItemWidget.static.levels = 3;
-
-/* Methods */
-
-/**
- * Check if item is movable.
- *
- * Movablilty is used by outline controls.
- *
- * @returns {boolean} Item is movable
- */
-OO.ui.OutlineItemWidget.prototype.isMovable = function () {
-       return this.movable;
-};
-
-/**
- * Check if item is removable.
- *
- * Removablilty is used by outline controls.
- *
- * @returns {boolean} Item is removable
- */
-OO.ui.OutlineItemWidget.prototype.isRemovable = function () {
-       return this.removable;
-};
-
-/**
- * Get indentation level.
- *
- * @returns {number} Indentation level
- */
-OO.ui.OutlineItemWidget.prototype.getLevel = function () {
-       return this.level;
-};
-
-/**
- * Set movability.
- *
- * Movablilty is used by outline controls.
- *
- * @param {boolean} movable Item is movable
- * @chainable
- */
-OO.ui.OutlineItemWidget.prototype.setMovable = function ( movable ) {
-       this.movable = !!movable;
-       return this;
-};
-
-/**
- * Set removability.
- *
- * Removablilty is used by outline controls.
- *
- * @param {boolean} movable Item is removable
- * @chainable
- */
-OO.ui.OutlineItemWidget.prototype.setRemovable = function ( removable ) {
-       this.removable = !!removable;
-       return this;
-};
-
-/**
- * Set indentation level.
- *
- * @method
- * @param {number} [level=0] Indentation level, in the range of [0,#maxLevel]
- * @chainable
- */
-OO.ui.OutlineItemWidget.prototype.setLevel = function ( level ) {
-       var levels = this.constructor.static.levels,
-               levelClass = this.constructor.static.levelClass,
-               i = levels;
-
-       this.level = level ? Math.max( 0, Math.min( levels - 1, level ) ) : 0;
-       while ( i-- ) {
-               if ( this.level === i ) {
-                       this.$element.addClass( levelClass + i );
-               } else {
-                       this.$element.removeClass( levelClass + i );
-               }
-       }
-
-       return this;
-};
-/**
- * Create an OO.ui.ButtonOptionWidget object.
- *
- * @class
- * @extends OO.ui.OptionWidget
- * @mixins OO.ui.ButtonedElement
- * @mixins OO.ui.FlaggableElement
- *
- * @constructor
- * @param {Mixed} data Option data
- * @param {Object} [config] Configuration options
- */
-OO.ui.ButtonOptionWidget = function OoUiButtonOptionWidget( data, config ) {
-       // Parent constructor
-       OO.ui.ButtonOptionWidget.super.call( this, data, config );
-
-       // Mixin constructors
-       OO.ui.ButtonedElement.call( this, this.$( '<a>' ), config );
-       OO.ui.FlaggableElement.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-buttonOptionWidget' );
-       this.$button.append( this.$element.contents() );
-       this.$element.append( this.$button );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ButtonOptionWidget, OO.ui.OptionWidget );
-
-OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.ButtonedElement );
-OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.FlaggableElement );
-
-/* Methods */
-
-/**
- * @inheritdoc
- */
-OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
-       OO.ui.OptionWidget.prototype.setSelected.call( this, state );
-
-       this.setActive( state );
-
-       return this;
-};
-/**
- * Create an OO.ui.ButtonSelect object.
- *
- * @class
- * @extends OO.ui.SelectWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.ButtonSelectWidget = function OoUiButtonSelectWidget( config ) {
-       // Parent constructor
-       OO.ui.ButtonSelectWidget.super.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-buttonSelectWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ButtonSelectWidget, OO.ui.SelectWidget );
-/**
- * Creates an OO.ui.PopupWidget object.
- *
- * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.LabeledElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [tail=true] Show tail pointing to origin of popup
- * @cfg {string} [align='center'] Alignment of popup to origin
- * @cfg {jQuery} [$container] Container to prevent popup from rendering outside of
- * @cfg {boolean} [autoClose=false] Popup auto-closes when it loses focus
- * @cfg {jQuery} [$autoCloseIgnore] Elements to not auto close when clicked
- * @cfg {boolean} [head] Show label and close button at the top
- */
-OO.ui.PopupWidget = function OoUiPopupWidget( config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.PopupWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.LabeledElement.call( this, this.$( '<div>' ), config );
-       OO.ui.ClippableElement.call( this, this.$( '<div>' ), config );
-
-       // Properties
-       this.visible = false;
-       this.$popup = this.$( '<div>' );
-       this.$head = this.$( '<div>' );
-       this.$body = this.$clippable;
-       this.$tail = this.$( '<div>' );
-       this.$container = config.$container || this.$( 'body' );
-       this.autoClose = !!config.autoClose;
-       this.$autoCloseIgnore = config.$autoCloseIgnore;
-       this.transitionTimeout = null;
-       this.tail = false;
-       this.align = config.align || 'center';
-       this.closeButton = new OO.ui.ButtonWidget( { '$': this.$, 'frameless': true, 'icon': 'close' } );
-       this.onMouseDownHandler = OO.ui.bind( this.onMouseDown, this );
-
-       // Events
-       this.closeButton.connect( this, { 'click': 'onCloseButtonClick' } );
-
-       // Initialization
-       this.useTail( config.tail !== undefined ? !!config.tail : true );
-       this.$body.addClass( 'oo-ui-popupWidget-body' );
-       this.$tail.addClass( 'oo-ui-popupWidget-tail' );
-       this.$head
-               .addClass( 'oo-ui-popupWidget-head' )
-               .append( this.$label, this.closeButton.$element );
-       if ( !config.head ) {
-               this.$head.hide();
-       }
-       this.$popup
-               .addClass( 'oo-ui-popupWidget-popup' )
-               .append( this.$head, this.$body );
-       this.$element.hide()
-               .addClass( 'oo-ui-popupWidget' )
-               .append( this.$popup, this.$tail );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PopupWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.PopupWidget, OO.ui.LabeledElement );
-
-OO.mixinClass( OO.ui.PopupWidget, OO.ui.ClippableElement );
-
-/* Events */
-
-/**
- * @event hide
- */
-
-/**
- * @event show
- */
-
-/* Methods */
-
-/**
- * Handles mouse down events.
- *
- * @method
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.PopupWidget.prototype.onMouseDown = function ( e ) {
-       if (
-               this.visible &&
-               !$.contains( this.$element[0], e.target ) &&
-               ( !this.$autoCloseIgnore || !this.$autoCloseIgnore.has( e.target ).length )
-       ) {
-               this.hide();
-       }
-};
-
-/**
- * Bind mouse down listener
- *
- * @method
- */
-OO.ui.PopupWidget.prototype.bindMouseDownListener = function () {
-       // Capture clicks outside popup
-       this.getElementWindow().addEventListener( 'mousedown', this.onMouseDownHandler, true );
-};
-
-/**
- * Handles close button click events.
- *
- * @method
- */
-OO.ui.PopupWidget.prototype.onCloseButtonClick = function () {
-       if ( this.visible ) {
-               this.hide();
-       }
-};
-
-/**
- * Unbind mouse down listener
- *
- * @method
- */
-OO.ui.PopupWidget.prototype.unbindMouseDownListener = function () {
-       this.getElementWindow().removeEventListener( 'mousedown', this.onMouseDownHandler, true );
-};
-
-/**
- * Check if the popup is visible.
- *
- * @method
- * @returns {boolean} Popup is visible
- */
-OO.ui.PopupWidget.prototype.isVisible = function () {
-       return this.visible;
-};
-
-/**
- * Set whether to show a tail.
- *
- * @method
- * @returns {boolean} Make tail visible
- */
-OO.ui.PopupWidget.prototype.useTail = function ( value ) {
-       value = !!value;
-       if ( this.tail !== value ) {
-               this.tail = value;
-               if ( value ) {
-                       this.$element.addClass( 'oo-ui-popupWidget-tailed' );
-               } else {
-                       this.$element.removeClass( 'oo-ui-popupWidget-tailed' );
-               }
-       }
-};
-
-/**
- * Check if showing a tail.
- *
- * @method
- * @returns {boolean} tail is visible
- */
-OO.ui.PopupWidget.prototype.hasTail = function () {
-       return this.tail;
-};
-
-/**
- * Show the context.
- *
- * @method
- * @fires show
- * @chainable
- */
-OO.ui.PopupWidget.prototype.show = function () {
-       if ( !this.visible ) {
-               this.setClipping( true );
-               this.$element.show();
-               this.visible = true;
-               this.emit( 'show' );
-               if ( this.autoClose ) {
-                       this.bindMouseDownListener();
-               }
-       }
-       return this;
-};
-
-/**
- * Hide the context.
- *
- * @method
- * @fires hide
- * @chainable
- */
-OO.ui.PopupWidget.prototype.hide = function () {
-       if ( this.visible ) {
-               this.setClipping( false );
-               this.$element.hide();
-               this.visible = false;
-               this.emit( 'hide' );
-               if ( this.autoClose ) {
-                       this.unbindMouseDownListener();
-               }
-       }
-       return this;
-};
-
-/**
- * Updates the position and size.
- *
- * @method
- * @param {number} width Width
- * @param {number} height Height
- * @param {boolean} [transition=false] Use a smooth transition
- * @chainable
- */
-OO.ui.PopupWidget.prototype.display = function ( width, height, transition ) {
-       var padding = 10,
-               originOffset = Math.round( this.$element.offset().left ),
-               containerLeft = Math.round( this.$container.offset().left ),
-               containerWidth = this.$container.innerWidth(),
-               containerRight = containerLeft + containerWidth,
-               popupOffset = width * ( { 'left': 0, 'center': -0.5, 'right': -1 } )[this.align],
-               popupLeft = popupOffset - padding,
-               popupRight = popupOffset + padding + width + padding,
-               overlapLeft = ( originOffset + popupLeft ) - containerLeft,
-               overlapRight = containerRight - ( originOffset + popupRight );
-
-       // Prevent transition from being interrupted
-       clearTimeout( this.transitionTimeout );
-       if ( transition ) {
-               // Enable transition
-               this.$element.addClass( 'oo-ui-popupWidget-transitioning' );
-       }
-
-       if ( overlapRight < 0 ) {
-               popupOffset += overlapRight;
-       } else if ( overlapLeft < 0 ) {
-               popupOffset -= overlapLeft;
-       }
-
-       // Position body relative to anchor and resize
-       this.$popup.css( {
-               'left': popupOffset,
-               'width': width,
-               'height': height === undefined ? 'auto' : height
-       } );
-
-       if ( transition ) {
-               // Prevent transitioning after transition is complete
-               this.transitionTimeout = setTimeout( OO.ui.bind( function () {
-                       this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
-               }, this ), 200 );
-       } else {
-               // Prevent transitioning immediately
-               this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
-       }
-
-       return this;
-};
-/**
- * Button that shows and hides a popup.
- *
- * @class
- * @extends OO.ui.ButtonWidget
- * @mixins OO.ui.PopuppableElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.PopupButtonWidget = function OoUiPopupButtonWidget( config ) {
-       // Parent constructor
-       OO.ui.PopupButtonWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.PopuppableElement.call( this, config );
-
-       // Initialization
-       this.$element
-               .addClass( 'oo-ui-popupButtonWidget' )
-               .append( this.popup.$element );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PopupButtonWidget, OO.ui.ButtonWidget );
-
-OO.mixinClass( OO.ui.PopupButtonWidget, OO.ui.PopuppableElement );
-
-/* Methods */
-
-/**
- * Handles mouse click events.
- *
- * @method
- * @param {jQuery.Event} e Mouse click event
- */
-OO.ui.PopupButtonWidget.prototype.onClick = function ( e ) {
-       // Skip clicks within the popup
-       if ( $.contains( this.popup.$element[0], e.target ) ) {
-               return;
-       }
-
-       if ( !this.disabled ) {
-               if ( this.popup.isVisible() ) {
-                       this.hidePopup();
-               } else {
-                       this.showPopup();
-               }
-               OO.ui.ButtonWidget.prototype.onClick.call( this );
-       }
-       return false;
-};
-/**
- * Creates an OO.ui.SearchWidget object.
- *
- * @class
- * @extends OO.ui.Widget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string|jQuery} [placeholder] Placeholder text for query input
- * @cfg {string} [value] Initial query value
- */
-OO.ui.SearchWidget = function OoUiSearchWidget( config ) {
-       // Configuration intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.SearchWidget.super.call( this, config );
-
-       // Properties
-       this.query = new OO.ui.TextInputWidget( {
-               '$': this.$,
-               'icon': 'search',
-               'placeholder': config.placeholder,
-               'value': config.value
-       } );
-       this.results = new OO.ui.SelectWidget( { '$': this.$ } );
-       this.$query = this.$( '<div>' );
-       this.$results = this.$( '<div>' );
-
-       // Events
-       this.query.connect( this, {
-               'change': 'onQueryChange',
-               'enter': 'onQueryEnter'
-       } );
-       this.results.connect( this, {
-               'highlight': 'onResultsHighlight',
-               'select': 'onResultsSelect'
-       } );
-       this.query.$input.on( 'keydown', OO.ui.bind( this.onQueryKeydown, this ) );
-
-       // Initialization
-       this.$query
-               .addClass( 'oo-ui-searchWidget-query' )
-               .append( this.query.$element );
-       this.$results
-               .addClass( 'oo-ui-searchWidget-results' )
-               .append( this.results.$element );
-       this.$element
-               .addClass( 'oo-ui-searchWidget' )
-               .append( this.$results, this.$query );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.SearchWidget, OO.ui.Widget );
-
-/* Events */
-
-/**
- * @event highlight
- * @param {Object|null} item Item data or null if no item is highlighted
- */
-
-/**
- * @event select
- * @param {Object|null} item Item data or null if no item is selected
- */
-
-/* Methods */
-
-/**
- * Handle query key down events.
- *
- * @method
- * @param {jQuery.Event} e Key down event
- */
-OO.ui.SearchWidget.prototype.onQueryKeydown = function ( e ) {
-       var highlightedItem, nextItem,
-               dir = e.which === OO.ui.Keys.DOWN ? 1 : ( e.which === OO.ui.Keys.UP ? -1 : 0 );
-
-       if ( dir ) {
-               highlightedItem = this.results.getHighlightedItem();
-               if ( !highlightedItem ) {
-                       highlightedItem = this.results.getSelectedItem();
-               }
-               nextItem = this.results.getRelativeSelectableItem( highlightedItem, dir );
-               this.results.highlightItem( nextItem );
-               nextItem.scrollElementIntoView();
-       }
-};
-
-/**
- * Handle select widget select events.
- *
- * Clears existing results. Subclasses should repopulate items according to new query.
- *
- * @method
- * @param {string} value New value
- */
-OO.ui.SearchWidget.prototype.onQueryChange = function () {
-       // Reset
-       this.results.clearItems();
-};
-
-/**
- * Handle select widget enter key events.
- *
- * Selects highlighted item.
- *
- * @method
- * @param {string} value New value
- */
-OO.ui.SearchWidget.prototype.onQueryEnter = function () {
-       // Reset
-       this.results.selectItem( this.results.getHighlightedItem() );
-};
-
-/**
- * Handle select widget highlight events.
- *
- * @method
- * @param {OO.ui.OptionWidget} item Highlighted item
- * @fires highlight
- */
-OO.ui.SearchWidget.prototype.onResultsHighlight = function ( item ) {
-       this.emit( 'highlight', item ? item.getData() : null );
-};
-
-/**
- * Handle select widget select events.
- *
- * @method
- * @param {OO.ui.OptionWidget} item Selected item
- * @fires select
- */
-OO.ui.SearchWidget.prototype.onResultsSelect = function ( item ) {
-       this.emit( 'select', item ? item.getData() : null );
-};
-
-/**
- * Get the query input.
- *
- * @method
- * @returns {OO.ui.TextInputWidget} Query input
- */
-OO.ui.SearchWidget.prototype.getQuery = function () {
-       return this.query;
-};
-
-/**
- * Reset the widget to initial value.
- */
-OO.ui.SearchWidget.prototype.clear = function () {
-       this.query.setValue( '' );
-};
-
-/**
- * Get the results list.
- *
- * @method
- * @returns {OO.ui.SelectWidget} Select list
- */
-OO.ui.SearchWidget.prototype.getResults = function () {
-       return this.results;
-};
-/**
- * Creates an OO.ui.TextInputWidget object.
- *
- * @class
- * @extends OO.ui.InputWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string} [placeholder] Placeholder text
- * @cfg {string} [icon] Symbolic name of icon
- * @cfg {boolean} [multiline=false] Allow multiple lines of text
- * @cfg {boolean} [autosize=false] Automatically resize to fit content
- * @cfg {boolean} [maxRows=10] Maximum number of rows to make visible when autosizing
- */
-OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
-       config = $.extend( { 'maxRows': 10 }, config );
-
-       // Parent constructor
-       OO.ui.TextInputWidget.super.call( this, config );
-
-       // Properties
-       this.pending = 0;
-       this.multiline = !!config.multiline;
-       this.autosize = !!config.autosize;
-       this.maxRows = config.maxRows;
-
-       // Events
-       this.$input.on( 'keypress', OO.ui.bind( this.onKeyPress, this ) );
-       this.$element.on( 'DOMNodeInsertedIntoDocument', OO.ui.bind( this.onElementAttach, this ) );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-textInputWidget' );
-       if ( config.icon ) {
-               this.$element.addClass( 'oo-ui-textInputWidget-decorated' );
-               this.$element.append(
-                       this.$( '<span>' )
-                               .addClass( 'oo-ui-textInputWidget-icon oo-ui-icon-' + config.icon )
-                               .mousedown( OO.ui.bind( function () {
-                                       this.$input.focus();
-                                       return false;
-                               }, this ) )
-               );
-       }
-       if ( config.placeholder ) {
-               this.$input.attr( 'placeholder', config.placeholder );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.TextInputWidget, OO.ui.InputWidget );
-
-/* Events */
-
-/**
- * User presses enter inside the text box.
- *
- * Not called if input is multiline.
- *
- * @event enter
- */
-
-/* Methods */
-
-/**
- * Handles key press events.
- *
- * @param {jQuery.Event} e Key press event
- * @fires enter If enter key is pressed and input is not multiline
- */
-OO.ui.TextInputWidget.prototype.onKeyPress = function ( e ) {
-       if ( e.which === OO.ui.Keys.ENTER && !this.multiline ) {
-               this.emit( 'enter' );
-       }
-};
-
-/**
- * Handles element attach events.
- *
- * @param {jQuery.Event} e Element attach event
- */
-OO.ui.TextInputWidget.prototype.onElementAttach = function () {
-       this.adjustSize();
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.TextInputWidget.prototype.onEdit = function () {
-       this.adjustSize();
-
-       // Parent method
-       return OO.ui.InputWidget.prototype.onEdit.call( this );
-};
-
-/**
- * Automatically adjust the size of the text input.
- *
- * This only affects multi-line inputs that are auto-sized.
- *
- * @chainable
- */
-OO.ui.TextInputWidget.prototype.adjustSize = function () {
-       var $clone, scrollHeight, innerHeight, outerHeight, maxInnerHeight, idealHeight;
-
-       if ( this.multiline && this.autosize ) {
-               $clone = this.$input.clone()
-                       .val( this.$input.val() )
-                       .css( { 'height': 0 } )
-                       .insertAfter( this.$input );
-               // Set inline height property to 0 to measure scroll height
-               scrollHeight = $clone[0].scrollHeight;
-               // Remove inline height property to measure natural heights
-               $clone.css( 'height', '' );
-               innerHeight = $clone.innerHeight();
-               outerHeight = $clone.outerHeight();
-               // Measure max rows height
-               $clone.attr( 'rows', this.maxRows ).css( 'height', 'auto' );
-               maxInnerHeight = $clone.innerHeight();
-               $clone.removeAttr( 'rows' ).css( 'height', '' );
-               $clone.remove();
-               idealHeight = Math.min( maxInnerHeight, scrollHeight );
-               // Only apply inline height when expansion beyond natural height is needed
-               this.$input.css(
-                       'height',
-                       // Use the difference between the inner and outer height as a buffer
-                       idealHeight > outerHeight ? idealHeight + ( outerHeight - innerHeight ) : ''
-               );
-       }
-       return this;
-};
-
-/**
- * Get input element.
- *
- * @method
- * @param {Object} [config] Configuration options
- * @returns {jQuery} Input element
- */
-OO.ui.TextInputWidget.prototype.getInputElement = function ( config ) {
-       return config.multiline ? this.$( '<textarea>' ) : this.$( '<input type="text" />' );
-};
-
-/* Methods */
-
-/**
- * Checks if input supports multiple lines.
- *
- * @method
- * @returns {boolean} Input supports multiple lines
- */
-OO.ui.TextInputWidget.prototype.isMultiline = function () {
-       return !!this.multiline;
-};
-
-/**
- * Checks if input automatically adjusts its size.
- *
- * @method
- * @returns {boolean} Input automatically adjusts its size
- */
-OO.ui.TextInputWidget.prototype.isAutosizing = function () {
-       return !!this.autosize;
-};
-
-/**
- * Checks if input is pending.
- *
- * @method
- * @returns {boolean} Input is pending
- */
-OO.ui.TextInputWidget.prototype.isPending = function () {
-       return !!this.pending;
-};
-
-/**
- * Increases the pending stack.
- *
- * @method
- * @chainable
- */
-OO.ui.TextInputWidget.prototype.pushPending = function () {
-       this.pending++;
-       this.$element.addClass( 'oo-ui-textInputWidget-pending' );
-       this.$input.addClass( 'oo-ui-texture-pending' );
-       return this;
-};
-
-/**
- * Reduces the pending stack.
- *
- * Clamped at zero.
- *
- * @method
- * @chainable
- */
-OO.ui.TextInputWidget.prototype.popPending = function () {
-       this.pending = Math.max( 0, this.pending - 1 );
-       if ( !this.pending ) {
-               this.$element.removeClass( 'oo-ui-textInputWidget-pending' );
-               this.$input.removeClass( 'oo-ui-texture-pending' );
-       }
-       return this;
-};
-/**
- * Creates an OO.ui.TextInputMenuWidget object.
- *
- * @class
- * @extends OO.ui.MenuWidget
- *
- * @constructor
- * @param {OO.ui.TextInputWidget} input Text input widget to provide menu for
- * @param {Object} [config] Configuration options
- * @cfg {jQuery} [$container=input.$element] Element to render menu under
- */
-OO.ui.TextInputMenuWidget = function OoUiTextInputMenuWidget( input, config ) {
-       // Parent constructor
-       OO.ui.TextInputMenuWidget.super.call( this, config );
-
-       // Properties
-       this.input = input;
-       this.$container = config.$container || this.input.$element;
-       this.onWindowResizeHandler = OO.ui.bind( this.onWindowResize, this );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-textInputMenuWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.TextInputMenuWidget, OO.ui.MenuWidget );
-
-/* Methods */
-
-/**
- * Handle window resize event.
- *
- * @method
- * @param {jQuery.Event} e Window resize event
- */
-OO.ui.TextInputMenuWidget.prototype.onWindowResize = function () {
-       this.position();
-};
-
-/**
- * Shows the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.TextInputMenuWidget.prototype.show = function () {
-       // Parent method
-       OO.ui.MenuWidget.prototype.show.call( this );
-
-       this.position();
-       this.$( this.getElementWindow() ).on( 'resize', this.onWindowResizeHandler );
-       return this;
-};
-
-/**
- * Hides the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.TextInputMenuWidget.prototype.hide = function () {
-       // Parent method
-       OO.ui.MenuWidget.prototype.hide.call( this );
-
-       this.$( this.getElementWindow() ).off( 'resize', this.onWindowResizeHandler );
-       return this;
-};
-
-/**
- * Positions the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.TextInputMenuWidget.prototype.position = function () {
-       var frameOffset,
-               $container = this.$container,
-               dimensions = $container.offset();
-
-       // Position under input
-       dimensions.top += $container.height();
-
-       // Compensate for frame position if in a differnt frame
-       if ( this.input.$.frame && this.input.$.context !== this.$element[0].ownerDocument ) {
-               frameOffset = OO.ui.Element.getRelativePosition(
-                       this.input.$.frame.$element, this.$element.offsetParent()
-               );
-               dimensions.left += frameOffset.left;
-               dimensions.top += frameOffset.top;
-       } else {
-               // Fix for RTL (for some reason, no need to fix if the frameoffset is set)
-               if ( this.$element.css( 'direction' ) === 'rtl' ) {
-                       dimensions.right = this.$element.parent().position().left -
-                               dimensions.width - dimensions.left;
-                       // Erase the value for 'left':
-                       delete dimensions.left;
-               }
-       }
-
-       this.$element.css( dimensions );
-       this.setIdealSize( $container.width() );
-       return this;
-};
-/**
- * Mixin for widgets with a boolean state.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [value=false] Initial value
- */
-OO.ui.ToggleWidget = function OoUiToggleWidget( config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Properties
-       this.value = null;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-toggleWidget' );
-       this.setValue( !!config.value );
-};
-
-/* Events */
-
-/**
- * @event change
- * @param {boolean} value Changed value
- */
-
-/* Methods */
-
-/**
- * Get the value of the toggle.
- *
- * @method
- * @returns {boolean} Toggle value
- */
-OO.ui.ToggleWidget.prototype.getValue = function () {
-       return this.value;
-};
-
-/**
- * Set the value of the toggle.
- *
- * @method
- * @param {boolean} value New value
- * @fires change
- * @chainable
- */
-OO.ui.ToggleWidget.prototype.setValue = function ( value ) {
-       value = !!value;
-       if ( this.value !== value ) {
-               this.value = value;
-               this.emit( 'change', value );
-               this.$element.toggleClass( 'oo-ui-toggleWidget-on', value );
-               this.$element.toggleClass( 'oo-ui-toggleWidget-off', !value );
-       }
-       return this;
-};
-/**
- * @class
- * @extends OO.ui.ButtonWidget
- * @mixins OO.ui.ToggleWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [value=false] Initial value
- */
-OO.ui.ToggleButtonWidget = function OoUiToggleButtonWidget( config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.ToggleButtonWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.ToggleWidget.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-toggleButtonWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ToggleButtonWidget, OO.ui.ButtonWidget );
-
-OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.ToggleWidget );
-
-/* Methods */
-
-/**
- * @inheritdoc
- */
-OO.ui.ToggleButtonWidget.prototype.onClick = function () {
-       if ( !this.disabled ) {
-               this.setValue( !this.value );
-       }
-
-       // Parent method
-       return OO.ui.ButtonWidget.prototype.onClick.call( this );
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.ToggleButtonWidget.prototype.setValue = function ( value ) {
-       value = !!value;
-       if ( value !== this.value ) {
-               this.setActive( value );
-       }
-
-       // Parent method
-       OO.ui.ToggleWidget.prototype.setValue.call( this, value );
-
-       return this;
-};
-/**
- * @class
- * @abstract
- * @extends OO.ui.Widget
- * @mixins OO.ui.ToggleWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [value=false] Initial value
- */
-OO.ui.ToggleSwitchWidget = function OoUiToggleSwitchWidget( config ) {
-       // Parent constructor
-       OO.ui.ToggleSwitchWidget.super.call( this, config );
-
-       // Mixin constructors
-       OO.ui.ToggleWidget.call( this, config );
-
-       // Properties
-       this.dragging = false;
-       this.dragStart = null;
-       this.sliding = false;
-       this.$glow = this.$( '<span>' );
-       this.$grip = this.$( '<span>' );
-
-       // Events
-       this.$element.on( 'click', OO.ui.bind( this.onClick, this ) );
-
-       // Initialization
-       this.$glow.addClass( 'oo-ui-toggleSwitchWidget-glow' );
-       this.$grip.addClass( 'oo-ui-toggleSwitchWidget-grip' );
-       this.$element
-               .addClass( 'oo-ui-toggleSwitchWidget' )
-               .append( this.$glow, this.$grip );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ToggleSwitchWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.ToggleSwitchWidget, OO.ui.ToggleWidget );
-
-/* Methods */
-
-/**
- * Handles mouse down events.
- *
- * @method
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.ToggleSwitchWidget.prototype.onClick = function ( e ) {
-       if ( !this.disabled && e.which === 1 ) {
-               this.setValue( !this.value );
-       }
-};
-}( OO ) );
diff --git a/resources/oojs-ui/oojs-ui.svg.css b/resources/oojs-ui/oojs-ui.svg.css
deleted file mode 100644 (file)
index 58bbad0..0000000
+++ /dev/null
@@ -1,1230 +0,0 @@
-/*!
- * OOjs UI v0.1.0-pre (8986c46d35)
- * https://www.mediawiki.org/wiki/OOjs_UI
- *
- * Copyright 2011–2014 OOjs Team and other contributors.
- * Released under the MIT license
- * http://oojs.mit-license.org
- *
- * Date: Tue Apr 01 2014 19:33:39 GMT-0700 (PDT)
- */
-
-/* Textures */
-
-.oo-ui-texture-pending {
-  background-image: /* @embed */ url(images/textures/pending.gif);
-}
-
-.oo-ui-texture-transparency {
-  background-image: /* @embed */ url(images/textures/transparency.png);
-}
-
-/* RTL Definitions */
-
-/* @noflip */
-
-.oo-ui-rtl {
-  direction: rtl;
-}
-
-/* @noflip */
-
-.oo-ui-ltr {
-  direction: ltr;
-}
-
-.oo-ui-dialog {
-  position: fixed;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  padding: 1em;
-  line-height: 1em;
-  /* Fix for strange opacity-related rendering issues.
-          CAUTION: -webkit-backface-visibility: hidden; is EXTREMELY DANGEROUS.
-          If applied to a VE surface directly, it will break selection of
-          FocusableNodes, and in the past it's caused transparent PNGs to
-          render as opaque black images. For some reason applying it to the dialog
-          wrapper in the main document fixes opacity-related behavior in the iframe
-          document, but doesn't break the surface inside the iframe. */
-
-  -webkit-backface-visibility: hidden;
-          backface-visibility: hidden;
-}
-
-.oo-ui-dialog .oo-ui-window-frame {
-  position: fixed;
-  top: 1em;
-  right: 0;
-  bottom: 1em;
-  left: 0;
-  min-height: 12em;
-  margin: auto;
-  overflow: hidden;
-}
-
-.oo-ui-dialog-small .oo-ui-window-frame {
-  width: 400px;
-  max-height: 230px;
-}
-
-.oo-ui-dialog-medium .oo-ui-window-frame {
-  width: 600px;
-  max-height: 460px;
-}
-
-.oo-ui-dialog-large .oo-ui-window-frame {
-  width: 800px;
-  max-height: 690px;
-}
-
-.oo-ui-dialog .oo-ui-frame {
-  width: 100%;
-  height: 100%;
-}
-
-.oo-ui-dialog-content .oo-ui-window-head,
-.oo-ui-dialog-content .oo-ui-window-body,
-.oo-ui-dialog-content .oo-ui-window-foot {
-  position: absolute;
-  right: 0;
-  left: 0;
-  overflow: hidden;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-dialog-content .oo-ui-window-head {
-  top: 0;
-  height: 3.8em;
-  padding: 0.5em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-title {
-  line-height: 2.8em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-icon {
-  width: 2.4em;
-  height: 2.8em;
-  line-height: 2.8em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-closeButton {
-  float: right;
-  margin: 0.25em 0.25em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-body {
-  top: 3.8em;
-  bottom: 4.8em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot {
-  bottom: 0;
-  height: 4.8em;
-  padding: 1em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed {
-  float: left;
-  margin: 0.125em 0.25em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-primary,
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-constructive,
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-destructive {
-  float: right;
-}
-
-.oo-ui-dialog-content-footless .oo-ui-window-body {
-  bottom: 0;
-}
-
-.oo-ui-dialog-content-footless .oo-ui-window-foot {
-  display: none;
-}
-
-.oo-ui-frame {
-  padding: 0;
-  margin: 0;
-}
-
-.oo-ui-frame-body {
-  padding: 0;
-  margin: 0;
-  background: none;
-}
-
-.oo-ui-toolbar {
-  clear: both;
-}
-
-.oo-ui-toolbar-bar {
-  line-height: 1em;
-}
-
-.oo-ui-toolbar-bottom .oo-ui-toolbar-bar {
-  position: absolute;
-}
-
-.oo-ui-toolbar-actions {
-  float: right;
-}
-
-.oo-ui-toolbar-tools {
-  float: left;
-}
-
-.oo-ui-toolbar-tools,
-.oo-ui-toolbar-actions,
-.oo-ui-toolbar-shadow {
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-toolbar-actions .oo-ui-popupWidget {
-  -webkit-user-select: all;
-     -moz-user-select: all;
-      -ms-user-select: all;
-          user-select: all;
-  -webkit-touch-callout: default;
-}
-
-.oo-ui-toolbar-shadow {
-  position: absolute;
-  width: 100%;
-  pointer-events: none;
-  background-position: left top;
-  background-repeat: repeat-x;
-}
-
-.oo-ui-toolGroup {
-  display: inline-block;
-  margin: 0.3em;
-  vertical-align: middle;
-}
-
-.oo-ui-toolGroup-empty {
-  display: none;
-}
-
-.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-window-head {
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-window-icon {
-  float: left;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-window-title {
-  float: left;
-  white-space: nowrap;
-  cursor: default;
-}
-
-.oo-ui-window-overlay {
-  position: absolute;
-  top: 0;
-  left: 0;
-}
-
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button {
-  display: inline-block;
-  vertical-align: middle;
-  cursor: pointer;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  display: none;
-  margin-left: 0;
-}
-
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator {
-  display: none;
-  margin-right: -0.75em;
-}
-
-.oo-ui-buttonedElement.oo-ui-widget-disabled .oo-ui-buttonedElement-button {
-  cursor: default;
-}
-
-.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
-.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  display: inline-block;
-  vertical-align: middle;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-buttonedElement-frameless {
-  position: relative;
-  display: inline-block;
-}
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-  display: inline-block;
-  margin-left: 0.25em;
-  vertical-align: middle;
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-  display: inline-block;
-  padding: 0.2em 0.8em;
-  margin: 0.1em 0;
-  text-align: center;
-  vertical-align: top;
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-  display: inline-block;
-  line-height: 1.9em;
-  vertical-align: middle;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  margin-right: -0.5em;
-  margin-left: -0.5em;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-iconedElement.oo-ui-labeledElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-  margin-right: 0.3em;
-  margin-left: -0.5em;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
-  cursor: default;
-}
-
-.oo-ui-clippableElement-clippable {
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-bookletLayout-stackLayout.oo-ui-stackLayout-continuous .oo-ui-panelLayout-scrollable {
-  overflow-y: hidden;
-}
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
-  width: 100%;
-  padding: 1.5em;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-scrollable {
-  overflow-y: auto;
-}
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-padded {
-  padding: 2em;
-}
-
-.oo-ui-bookletLayout-outlinePanel-editable .oo-ui-outlineWidget {
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 3em;
-  left: 0;
-  overflow-y: auto;
-}
-
-.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
-  position: absolute;
-  right: 0;
-  bottom: 0;
-  left: 0;
-}
-
-.oo-ui-fieldLayout {
-  margin-bottom: 1em;
-}
-
-.oo-ui-fieldLayout:last-child {
-  margin-bottom: 0;
-}
-
-.oo-ui-fieldLayout:before,
-.oo-ui-fieldLayout:after {
-  display: table;
-  content: " ";
-}
-
-.oo-ui-fieldLayout:after {
-  clear: both;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labeledElement-label,
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labeledElement-label {
-  display: block;
-  float: left;
-  width: 35%;
-  padding-top: 0.5em;
-  margin-right: 5%;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
-  display: block;
-  float: left;
-  width: 60%;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labeledElement-label {
-  text-align: right;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labeledElement-label {
-  display: inline-block;
-  padding: 0.75em 0.5em 0.5em 0.5em;
-  vertical-align: middle;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
-  display: inline-block;
-  padding: 0.5em 0;
-  vertical-align: middle;
-}
-
-.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labeledElement-label {
-  padding: 0.5em 0;
-}
-
-.oo-ui-fieldsetLayout {
-  position: relative;
-  padding: 0;
-  margin: 0;
-}
-
-.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
-  margin-top: 2em;
-}
-
-.oo-ui-fieldsetLayout-labeled {
-  margin-top: -0.75em;
-}
-
-.oo-ui-fieldsetLayout > legend.oo-ui-labeledElement-label {
-  padding: 0.25em 0;
-  margin-bottom: 0.5em;
-}
-
-.oo-ui-fieldsetLayout.oo-ui-iconedElement > legend.oo-ui-labeledElement-label {
-  padding-left: 1.75em;
-}
-
-.oo-ui-fieldsetLayout.oo-ui-iconedElement > .oo-ui-iconedElement-icon {
-  position: absolute;
-  top: 0;
-  left: 0;
-  display: block;
-  width: 2em;
-  height: 2em;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-gridLayout {
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-}
-
-.oo-ui-labelWidget {
-  padding: 0.5em 0;
-}
-
-.oo-ui-panelLayout {
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-}
-
-.oo-ui-panelLayout-scrollable {
-  overflow-y: auto;
-}
-
-.oo-ui-panelLayout-padded {
-  padding: 2em;
-}
-
-.oo-ui-stackLayout > .oo-ui-panelLayout {
-  display: none;
-}
-
-.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
-  position: relative;
-  display: block;
-}
-
-.oo-ui-barToolGroup > .oo-ui-iconedElement-icon,
-.oo-ui-barToolGroup > .oo-ui-labeledElement-label {
-  display: none;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool {
-  position: relative;
-  display: inline-block;
-  vertical-align: top;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-link {
-  display: block;
-  height: 1.5em;
-  padding: 0.25em;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  display: block;
-  width: 1.5em;
-  height: 1.5em;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-tool-title {
-  display: none;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
-  cursor: default;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-title,
-.oo-ui-barToolGroup .oo-ui-tool-accel {
-  display: none;
-}
-
-.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool-link {
-  cursor: pointer;
-}
-
-.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
-  padding: 0.25em;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool {
-  display: inline-block;
-  width: 100%;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool-link {
-  display: block;
-  padding-right: 0.5em;
-  white-space: nowrap;
-  cursor: pointer;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
-  cursor: default;
-}
-
-.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
-  min-width: 8em;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool {
-  display: block;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-link {
-  display: block;
-  padding: 0.25em 1em 0.25em 0.25em;
-  white-space: nowrap;
-  cursor: pointer;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  background-image: none;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  background-image: /* @embed */ url(images/icons/check.png);
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
-  cursor: default;
-}
-
-.oo-ui-popupToolGroup {
-  position: relative;
-  height: 2em;
-  min-width: 2.5em;
-}
-
-.oo-ui-popupToolGroup.oo-ui-indicatedElement.oo-ui-iconedElement {
-  min-width: 3.5em;
-}
-
-.oo-ui-popupToolGroup-handle {
-  display: block;
-  cursor: pointer;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator,
-.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
-  position: absolute;
-  top: 0;
-  width: 2em;
-  height: 2em;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator {
-  right: 0;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
-  left: 0.25em;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-  margin: 0 1em;
-  font-size: 0.8em;
-  line-height: 2.6em;
-}
-
-.oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
-  cursor: default;
-}
-
-.oo-ui-popupToolGroup.oo-ui-iconedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-  margin-left: 3em;
-}
-
-.oo-ui-popupToolGroup.oo-ui-indicatedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-  margin-right: 2.25em;
-}
-
-.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
-  position: absolute;
-  top: 2em;
-  left: -1px;
-  z-index: 4;
-  display: none;
-}
-
-.oo-ui-popupToolGroup .oo-ui-toolGroup-tools .oo-ui-iconedElement-icon {
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-popupToolGroup-active.oo-ui-widget-enabled > .oo-ui-toolGroup-tools {
-  display: block;
-}
-
-.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-  display: inline-block;
-  width: 2em;
-  height: 2em;
-  margin-right: 0.25em;
-  vertical-align: middle;
-}
-
-.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
-  display: inline-block;
-  font-size: 0.8em;
-  line-height: 2em;
-  vertical-align: middle;
-}
-
-.oo-ui-popupToolGroup .oo-ui-tool-accel {
-  display: none;
-}
-
-.oo-ui-popupTool .oo-ui-popupWidget {
-  margin-left: 1.25em;
-  font-size: 0.8em;
-}
-
-.oo-ui-popupTool .oo-ui-popupWidget-popup,
-.oo-ui-popupTool .oo-ui-popupWidget-tail {
-  z-index: 4;
-}
-
-.oo-ui-iconWidget {
-  display: inline-block;
-  width: 1.9em;
-  height: 1.9em;
-  line-height: 2.5em;
-  vertical-align: middle;
-  background-position: center center;
-  background-repeat: no-repeat;
-  opacity: 0.8;
-}
-
-.oo-ui-iconWidget.oo-ui-widget-disabled {
-  opacity: 0.2;
-}
-
-.oo-ui-indicatorWidget {
-  display: inline-block;
-  width: 1.9em;
-  height: 1.9em;
-  line-height: 2.5em;
-  vertical-align: middle;
-  background-position: center center;
-  background-repeat: no-repeat;
-  opacity: 0.8;
-}
-
-.oo-ui-indicatorWidget.oo-ui-widget-disabled {
-  opacity: 0.2;
-}
-
-.oo-ui-selectWidget {
-  padding: 0;
-  margin: 0;
-  list-style: none;
-}
-
-.oo-ui-optionWidget {
-  position: relative;
-  display: block;
-  margin: 0;
-  list-style: none;
-  cursor: pointer;
-  border: none;
-}
-
-.oo-ui-optionWidget.oo-ui-widget-disabled {
-  cursor: default;
-}
-
-.oo-ui-optionWidget .oo-ui-labeledElement-label {
-  display: block;
-  overflow: hidden;
-  line-height: 1.5em;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.oo-ui-optionWidget .oo-ui-iconedElement-icon,
-.oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
-  position: absolute;
-  top: 50%;
-  width: 2em;
-  height: 2em;
-  margin-top: -1em;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-optionWidget .oo-ui-iconedElement-icon {
-  left: 0.5em;
-}
-
-.oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
-  right: 0.5em;
-}
-
-.oo-ui-menuWidget {
-  position: absolute;
-}
-
-.oo-ui-menuWidget input {
-  position: absolute;
-  width: 0;
-  height: 0;
-  overflow: hidden;
-  opacity: 0;
-}
-
-.oo-ui-popupWidget-popup {
-  position: absolute;
-  overflow: hidden;
-}
-
-.oo-ui-popupWidget-tail {
-  display: none;
-}
-
-.oo-ui-popupWidget-tailed .oo-ui-popupWidget-popup {
-  margin-top: 7px;
-}
-
-.oo-ui-popupWidget-tailed .oo-ui-popupWidget-tail {
-  position: absolute;
-  display: block;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-popupWidget-head {
-  height: 2.5em;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-popupWidget-head .oo-ui-buttonWidget {
-  float: right;
-  margin: 0.25em;
-}
-
-.oo-ui-popupWidget-head .oo-ui-labeledElement-label {
-  float: left;
-  margin: 0.75em 1em;
-  cursor: default;
-}
-
-.oo-ui-popupWidget-body {
-  clear: both;
-}
-
-.oo-ui-buttonGroupWidget {
-  border-radius: 0.3em;
-}
-
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-  margin-bottom: -1px;
-  margin-left: -1px;
-  border-radius: 0;
-}
-
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:first-child .oo-ui-buttonedElement-button {
-  margin-left: 0;
-  border-bottom-left-radius: 0.3em;
-  border-top-left-radius: 0.3em;
-}
-
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:last-child .oo-ui-buttonedElement-button {
-  border-top-right-radius: 0.3em;
-  border-bottom-right-radius: 0.3em;
-}
-
-.oo-ui-buttonOptionWidget {
-  display: inline-block;
-  background-color: transparent;
-}
-
-.oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
-  position: relative;
-  height: 1.9em;
-}
-
-.oo-ui-buttonOptionWidget.oo-ui-iconedElement .oo-ui-iconedElement-icon,
-.oo-ui-buttonOptionWidget.oo-ui-indicatedElement .oo-ui-indicatedElement-indicator {
-  position: static;
-  display: inline-block;
-  height: 1.9em;
-  margin-top: 0;
-  vertical-align: middle;
-}
-
-.oo-ui-buttonSelectWidget {
-  display: inline-block;
-  white-space: nowrap;
-}
-
-.oo-ui-buttonWidget {
-  display: inline-block;
-  vertical-align: middle;
-}
-
-.oo-ui-inlineMenuWidget {
-  position: relative;
-  display: inline-block;
-  min-width: 20em;
-  margin: 0.25em 0;
-}
-
-.oo-ui-inlineMenuWidget-handle {
-  display: inline-block;
-  width: 100%;
-  height: 2.5em;
-  cursor: pointer;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator,
-.oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
-  position: absolute;
-  top: 0;
-  width: 2.5em;
-  height: 2.5em;
-  background-position: center center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator {
-  right: 0;
-}
-
-.oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
-  left: 0.25em;
-}
-
-.oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
-  margin: 0 0.5em;
-  line-height: 2.5em;
-}
-
-.oo-ui-inlineMenuWidget.oo-ui-iconedElement .oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
-  margin-left: 3em;
-}
-
-.oo-ui-inlineMenuWidget.oo-ui-indicatedElement .oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
-  margin-right: 2em;
-}
-
-.oo-ui-inlineMenuWidget .oo-ui-menuWidget {
-  z-index: 1;
-  width: 100%;
-}
-
-.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle {
-  cursor: default;
-}
-
-.oo-ui-menuItemWidget {
-  position: relative;
-}
-
-.oo-ui-menuItemWidget .oo-ui-iconedElement-icon {
-  display: none;
-}
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
-  background-color: transparent;
-}
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-selected .oo-ui-iconedElement-icon {
-  display: block;
-}
-
-.oo-ui-menuSectionItemWidget {
-  cursor: default;
-}
-
-.oo-ui-outlineControlsWidget {
-  height: 3em;
-}
-
-.oo-ui-outlineControlsWidget-adders,
-.oo-ui-outlineControlsWidget-movers {
-  float: left;
-  height: 2em;
-  padding: 0;
-  margin: 0.5em;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-outlineControlsWidget > .oo-ui-iconedElement-icon {
-  float: left;
-  width: 1.5em;
-  height: 2em;
-  margin: 0.5em 0 0.5em 0.5em;
-  background-position: right center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-outlineControlsWidget-adders {
-  float: left;
-  margin-left: 0;
-}
-
-.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget {
-  float: left;
-}
-
-.oo-ui-outlineControlsWidget-movers {
-  float: right;
-}
-
-.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
-  float: right;
-}
-
-.oo-ui-outlineItemWidget {
-  position: relative;
-  padding: 0.75em;
-  cursor: pointer;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-popupButtonWidget {
-  position: relative;
-}
-
-.oo-ui-popupButtonWidget .oo-ui-popupWidget {
-  position: absolute;
-  left: 1em;
-  cursor: auto;
-}
-
-.oo-ui-searchWidget-query {
-  position: absolute;
-  top: 0;
-  right: 0;
-  left: 0;
-  height: 4em;
-  padding: 0 1em;
-}
-
-.oo-ui-searchWidget-query .oo-ui-textInputWidget {
-  width: 100%;
-  margin: 0.75em 0;
-}
-
-.oo-ui-searchWidget-results {
-  position: absolute;
-  top: 4em;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  padding: 1em;
-  overflow-x: hidden;
-  overflow-y: auto;
-  line-height: 0;
-}
-
-.oo-ui-textInputWidget {
-  position: relative;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-textInputWidget input,
-.oo-ui-textInputWidget textarea {
-  display: inline-block;
-  width: 100%;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-  resize: none;
-}
-
-.oo-ui-textInputWidget-icon {
-  position: absolute;
-  top: 0;
-  left: 0;
-  height: 100%;
-  background-position: right center;
-  background-repeat: no-repeat;
-}
-
-.oo-ui-toggleSwitchWidget {
-  position: relative;
-  display: inline-block;
-  width: 4em;
-  height: 2em;
-  overflow: hidden;
-  vertical-align: middle;
-  cursor: pointer;
-  -webkit-transform: translateZ(0);
-     -moz-transform: translateZ(0);
-      -ms-transform: translateZ(0);
-       -o-transform: translateZ(0);
-          transform: translateZ(0);
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
-  cursor: default;
-}
-
-.oo-ui-toggleSwitchWidget-grip {
-  position: absolute;
-  top: 0.25em;
-  left: 0.25em;
-  display: block;
-  width: 1.5em;
-  height: 1.5em;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-  -webkit-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-     -moz-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-      -ms-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-       -o-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-          transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-}
-
-.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  -webkit-transition: opacity 200ms ease-in-out;
-     -moz-transition: opacity 200ms ease-in-out;
-      -ms-transition: opacity 200ms ease-in-out;
-       -o-transition: opacity 200ms ease-in-out;
-          transition: opacity 200ms ease-in-out;
-  -webkit-user-select: none;
-     -moz-user-select: none;
-      -ms-user-select: none;
-          user-select: none;
-  -webkit-touch-callout: none;
-}
-
-.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
-  left: 2.25em;
-  margin-left: -2px;
-}
-
-.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
-  left: 0.25em;
-  margin-left: 0;
-}
-
-.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
-  display: none;
-}
-
-/* Icons */
-
-.oo-ui-icon-add-item {
-  background-image: /* @embed */ url(images/icons/add-item.svg);
-}
-
-.oo-ui-icon-advanced {
-  background-image: /* @embed */ url(images/icons/advanced.svg);
-}
-
-.oo-ui-icon-alert {
-  background-image: /* @embed */ url(images/icons/alert.svg);
-}
-
-.oo-ui-icon-check {
-  background-image: /* @embed */ url(images/icons/check.svg);
-}
-
-.oo-ui-icon-clear {
-  background-image: /* @embed */ url(images/icons/clear.svg);
-}
-
-.oo-ui-icon-close {
-  background-image: /* @embed */ url(images/icons/close.svg);
-}
-
-.oo-ui-icon-code {
-  background-image: /* @embed */ url(images/icons/code.svg);
-}
-
-.oo-ui-icon-collapse {
-  background-image: /* @embed */ url(images/icons/collapse.svg);
-}
-
-.oo-ui-icon-comment {
-  background-image: /* @embed */ url(images/icons/comment.svg);
-}
-
-.oo-ui-icon-expand {
-  background-image: /* @embed */ url(images/icons/expand.svg);
-}
-
-.oo-ui-icon-help {
-  background-image: /* @embed */ url(images/icons/help.svg);
-}
-
-.oo-ui-icon-link {
-  background-image: /* @embed */ url(images/icons/link.svg);
-}
-
-.oo-ui-icon-menu {
-  background-image: /* @embed */ url(images/icons/menu.svg);
-}
-
-.oo-ui-icon-next {
-  background-image: /* @embed */ url(images/icons/move-ltr.svg);
-}
-
-.oo-ui-icon-picture {
-  background-image: /* @embed */ url(images/icons/picture.svg);
-}
-
-.oo-ui-icon-previous {
-  background-image: /* @embed */ url(images/icons/move-rtl.svg);
-}
-
-.oo-ui-icon-redo {
-  background-image: /* @embed */ url(images/icons/arched-arrow-ltr.svg);
-}
-
-.oo-ui-icon-remove {
-  background-image: /* @embed */ url(images/icons/remove.svg);
-}
-
-.oo-ui-icon-search {
-  background-image: /* @embed */ url(images/icons/search.svg);
-}
-
-.oo-ui-icon-settings {
-  background-image: /* @embed */ url(images/icons/settings.svg);
-}
-
-.oo-ui-icon-tag {
-  background-image: /* @embed */ url(images/icons/tag.svg);
-}
-
-.oo-ui-icon-undo {
-  background-image: /* @embed */ url(images/icons/arched-arrow-rtl.svg);
-}
-
-.oo-ui-icon-window {
-  background-image: /* @embed */ url(images/icons/window.svg);
-}
-
-/* Indicators */
-
-.oo-ui-indicator-down {
-  background-image: /* @embed */ url(images/indicators/down.svg);
-}
-
-.oo-ui-indicator-required {
-  background-image: /* @embed */ url(images/indicators/required.svg);
-}
-
-.oo-ui-indicator-up {
-  background-image: /* @embed */ url(images/indicators/up.svg);
-}
\ No newline at end of file
diff --git a/resources/oojs-ui/update-oojs-ui.sh b/resources/oojs-ui/update-oojs-ui.sh
deleted file mode 100755 (executable)
index edc7425..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env bash
-
-# FIXME this script is duplicated from update-oojs.sh - factor this out
-
-# This script generates a commit that updates the oojs-ui distribution
-# ./bin/update-oojs-ui.sh path/to/repo/for/oojs-ui
-
-function oojsuihash() {
-       grep "OOjs UI v" resources/oojs-ui/oojs-ui.js \
-               | head -n 1 \
-               | grep -Eo '\([a-z0-9]+\)' \
-               | sed 's/^(//' \
-               | sed 's/)$//'
-}
-
-function oojsuitag() {
-       grep "OOjs UI v" resources/oojs-ui/oojs-ui.js \
-               | head -n 1 \
-               | grep -Eo '\bv[0-9a-z.-]+\b'
-}
-
-function oojsuiversion() {
-       grep "OOjs UI v" resources/oojs-ui/oojs-ui.js \
-               | head -n 1 \
-               | grep -Eo '\bv[0-9a-z.-]+\b.*$'
-}
-
-# cd to the VisualEditor directory
-cd $(cd $(dirname $0)/../..; pwd)
-
-if [ "x$1" == "x" ]
-then
-       echo >&2 "Usage: update-oojs-ui.sh path/to/repo/for/oojs-ui"
-       exit 1
-fi
-
-# Undo any changes in the oojs-ui directory
-git reset resources/oojs-ui/
-git checkout resources/oojs-ui/
-
-git fetch origin
-# Create a branch of MW if needed, and reset it to master
-git checkout -B update-oojsui origin/master
-
-# Get the old oojs-ui version
-OLDVERSION=$(oojsuihash)
-if [ "x$OLDVERSION" == "x" ]
-then
-       TAG=$(oojsuitag)
-fi
-
-# cd to the oojs-ui directory
-cd $1 || exit 1
-if [ "x$OLDVERSION" == "x" ]
-then
-       # Try the tag
-       OLDVERSION=$(git rev-parse $TAG)
-       if [ $? != 0 ]
-       then
-               echo Could not find OOjs UI version
-               cd -
-               exit 1
-       fi
-fi
-if [ "$(git rev-parse $OLDVERSION)" == "$(git rev-parse HEAD)" ]
-then
-       echo "No changes (already at $OLDVERSION)"
-       cd -
-       exit 0
-fi
-# Build the distribution
-npm install || exit 1
-grunt || exit 1
-# Get the list of changes
-NEWCHANGES=$(git log $OLDVERSION.. --oneline --no-merges --reverse --color=never)
-NEWCHANGESDISPLAY=$(git log $OLDVERSION.. --oneline --no-merges --reverse --color=always)
-# cd back to the VisualEditor directory
-cd -
-
-# Copy files from dist/ to resources/oojs-ui
-cp -a $1/dist/{oojs-ui.js,oojs-ui.svg.css,oojs-ui-apex.css,oojs-ui-agora.css,images,i18n} resources/oojs-ui/
-# Figure out what the new version is
-NEWVERSION=$(oojsuiversion)
-# Generate commit summary
-COMMITMSG=$(cat <<END
-Update OOjs UI to $NEWVERSION
-
-New changes:
-$NEWCHANGES
-END
-)
-# Commit
-git commit resources/oojs-ui/ -m "$COMMITMSG"
-cat >&2 <<END
-
-
-Created commit with changes:
-$NEWCHANGESDISPLAY
-END
diff --git a/resources/oojs/oojs.js b/resources/oojs/oojs.js
deleted file mode 100644 (file)
index f953878..0000000
+++ /dev/null
@@ -1,844 +0,0 @@
-/*!
- * OOjs v1.0.9
- * https://www.mediawiki.org/wiki/OOjs
- *
- * Copyright 2011-2014 OOjs Team and other contributors.
- * Released under the MIT license
- * http://oojs.mit-license.org
- *
- * Date: Wed Apr 02 2014 14:29:36 GMT-0700 (PDT)
- */
-( function ( global ) {
-
-'use strict';
-var
-       /**
-        * Namespace for all classes, static methods and static properties.
-        * @class OO
-        * @singleton
-        */
-       oo = {},
-       hasOwn = oo.hasOwnProperty,
-       toString = oo.toString;
-
-/* Class Methods */
-
-/**
- * Assert whether a value is a plain object or not.
- *
- * @param {Mixed} obj
- * @return {boolean}
- */
-oo.isPlainObject = function ( obj ) {
-       // Any object or value whose internal [[Class]] property is not "[object Object]"
-       if ( toString.call( obj ) !== '[object Object]' ) {
-               return false;
-       }
-
-       // The try/catch suppresses exceptions thrown when attempting to access
-       // the "constructor" property of certain host objects suich as window.location
-       // in Firefox < 20 (https://bugzilla.mozilla.org/814622)
-       try {
-               if ( obj.constructor &&
-                               !hasOwn.call( obj.constructor.prototype, 'isPrototypeOf' ) ) {
-                       return false;
-               }
-       } catch ( e ) {
-               return false;
-       }
-
-       return true;
-};
-
-/**
- * Utility to initialize a class for OO inheritance.
- *
- * Currently this just initializes an empty static object.
- *
- * @param {Function} fn
- */
-oo.initClass = function ( fn ) {
-       fn.static = fn.static || {};
-};
-
-/**
- * Utility for common usage of Object#create for inheriting from one
- * prototype to another.
- *
- * Beware: This redefines the prototype, call before setting your prototypes.
- * Beware: This redefines the prototype, can only be called once on a function.
- *  If called multiple times on the same function, the previous prototype is lost.
- *  This is how prototypal inheritance works, it can only be one straight chain
- *  (just like classical inheritance in PHP for example). If you need to work with
- *  multiple constructors consider storing an instance of the other constructor in a
- *  property instead, or perhaps use a mixin (see OO.mixinClass).
- *
- *     function Thing() {}
- *     Thing.prototype.exists = function () {};
- *
- *     function Person() {
- *         Person.super.apply( this, arguments );
- *     }
- *     OO.inheritClass( Person, Thing );
- *     Person.static.defaultEyeCount = 2;
- *     Person.prototype.walk = function () {};
- *
- *     function Jumper() {
- *         Jumper.super.apply( this, arguments );
- *     }
- *     OO.inheritClass( Jumper, Person );
- *     Jumper.prototype.jump = function () {};
- *
- *     Jumper.static.defaultEyeCount === 2;
- *     var x = new Jumper();
- *     x.jump();
- *     x.walk();
- *     x instanceof Thing && x instanceof Person && x instanceof Jumper;
- *
- * @param {Function} targetFn
- * @param {Function} originFn
- * @throws {Error} If target already inherits from origin
- */
-oo.inheritClass = function ( targetFn, originFn ) {
-       if ( targetFn.prototype instanceof originFn ) {
-               throw new Error( 'Target already inherits from origin' );
-       }
-
-       var targetConstructor = targetFn.prototype.constructor;
-
-       targetFn.super = originFn;
-       targetFn.prototype = Object.create( originFn.prototype, {
-               // Restore constructor property of targetFn
-               constructor: {
-                       value: targetConstructor,
-                       enumerable: false,
-                       writable: true,
-                       configurable: true
-               }
-       } );
-
-       // Extend static properties - always initialize both sides
-       oo.initClass( originFn );
-       targetFn.static = Object.create( originFn.static );
-};
-
-/**
- * Utility to copy over *own* prototype properties of a mixin.
- * The 'constructor' (whether implicit or explicit) is not copied over.
- *
- * This does not create inheritance to the origin. If inheritance is needed
- * use oo.inheritClass instead.
- *
- * Beware: This can redefine a prototype property, call before setting your prototypes.
- * Beware: Don't call before oo.inheritClass.
- *
- *     function Foo() {}
- *     function Context() {}
- *
- *     // Avoid repeating this code
- *     function ContextLazyLoad() {}
- *     ContextLazyLoad.prototype.getContext = function () {
- *         if ( !this.context ) {
- *             this.context = new Context();
- *         }
- *         return this.context;
- *     };
- *
- *     function FooBar() {}
- *     OO.inheritClass( FooBar, Foo );
- *     OO.mixinClass( FooBar, ContextLazyLoad );
- *
- * @param {Function} targetFn
- * @param {Function} originFn
- */
-oo.mixinClass = function ( targetFn, originFn ) {
-       var key;
-
-       // Copy prototype properties
-       for ( key in originFn.prototype ) {
-               if ( key !== 'constructor' && hasOwn.call( originFn.prototype, key ) ) {
-                       targetFn.prototype[key] = originFn.prototype[key];
-               }
-       }
-
-       // Copy static properties - always initialize both sides
-       oo.initClass( targetFn );
-       if ( originFn.static ) {
-               for ( key in originFn.static ) {
-                       if ( hasOwn.call( originFn.static, key ) ) {
-                               targetFn.static[key] = originFn.static[key];
-                       }
-               }
-       } else {
-               oo.initClass( originFn );
-       }
-};
-
-/* Object Methods */
-
-/**
- * Create a new object that is an instance of the same
- * constructor as the input, inherits from the same object
- * and contains the same own properties.
- *
- * This makes a shallow non-recursive copy of own properties.
- * To create a recursive copy of plain objects, use #copy.
- *
- *     var foo = new Person( mom, dad );
- *     foo.setAge( 21 );
- *     var foo2 = OO.cloneObject( foo );
- *     foo.setAge( 22 );
- *
- *     // Then
- *     foo2 !== foo; // true
- *     foo2 instanceof Person; // true
- *     foo2.getAge(); // 21
- *     foo.getAge(); // 22
- *
- * @param {Object} origin
- * @return {Object} Clone of origin
- */
-oo.cloneObject = function ( origin ) {
-       var key, r;
-
-       r = Object.create( origin.constructor.prototype );
-
-       for ( key in origin ) {
-               if ( hasOwn.call( origin, key ) ) {
-                       r[key] = origin[key];
-               }
-       }
-
-       return r;
-};
-
-/**
- * Get an array of all property values in an object.
- *
- * @param {Object} Object to get values from
- * @return {Array} List of object values
- */
-oo.getObjectValues = function ( obj ) {
-       var key, values;
-
-       if ( obj !== Object( obj ) ) {
-               throw new TypeError( 'Called on non-object' );
-       }
-
-       values = [];
-       for ( key in obj ) {
-               if ( hasOwn.call( obj, key ) ) {
-                       values[values.length] = obj[key];
-               }
-       }
-
-       return values;
-};
-
-/**
- * Recursively compares properties between two objects.
- *
- * A false result may be caused by property inequality or by properties in one object missing from
- * the other. An asymmetrical test may also be performed, which checks only that properties in the
- * first object are present in the second object, but not the inverse.
- *
- * @param {Object} a First object to compare
- * @param {Object} b Second object to compare
- * @param {boolean} [asymmetrical] Whether to check only that b contains values from a
- * @return {boolean} If the objects contain the same values as each other
- */
-oo.compare = function ( a, b, asymmetrical ) {
-       var aValue, bValue, aType, bType, k;
-
-       if ( a === b ) {
-               return true;
-       }
-
-       for ( k in a ) {
-               aValue = a[k];
-               bValue = b[k];
-               aType = typeof aValue;
-               bType = typeof bValue;
-               if ( aType !== bType ||
-                       ( ( aType === 'string' || aType === 'number' ) && aValue !== bValue ) ||
-                       ( aValue === Object( aValue ) && !oo.compare( aValue, bValue, asymmetrical ) ) ) {
-                       return false;
-               }
-       }
-       // If the check is not asymmetrical, recursing with the arguments swapped will verify our result
-       return asymmetrical ? true : oo.compare( b, a, true );
-};
-
-/**
- * Create a plain deep copy of any kind of object.
- *
- * Copies are deep, and will either be an object or an array depending on `source`.
- *
- * @param {Object} source Object to copy
- * @param {Function} [callback] Applied to leaf values before they added to the clone
- * @return {Object} Copy of source object
- */
-oo.copy = function ( source, callback ) {
-       var key, sourceValue, sourceType, destination;
-
-       if ( typeof source.clone === 'function' ) {
-               return source.clone();
-       }
-
-       destination = Array.isArray( source ) ? new Array( source.length ) : {};
-
-       for ( key in source ) {
-               sourceValue = source[key];
-               sourceType = typeof sourceValue;
-               if ( Array.isArray( sourceValue ) ) {
-                       // Array
-                       destination[key] = oo.copy( sourceValue, callback );
-               } else if ( sourceValue && typeof sourceValue.clone === 'function' ) {
-                       // Duck type object with custom clone method
-                       destination[key] = callback ?
-                               callback( sourceValue.clone() ) : sourceValue.clone();
-               } else if ( sourceValue && typeof sourceValue.cloneNode === 'function' ) {
-                       // DOM Node
-                       destination[key] = callback ?
-                               callback( sourceValue.cloneNode( true ) ) : sourceValue.cloneNode( true );
-               } else if ( oo.isPlainObject( sourceValue ) ) {
-                       // Plain objects
-                       destination[key] = oo.copy( sourceValue, callback );
-               } else {
-                       // Non-plain objects (incl. functions) and primitive values
-                       destination[key] = callback ? callback( sourceValue ) : sourceValue;
-               }
-       }
-
-       return destination;
-};
-
-/**
- * Generate a hash of an object based on its name and data.
- *
- * Performance optimization: <http://jsperf.com/ve-gethash-201208#/toJson_fnReplacerIfAoForElse>
- *
- * To avoid two objects with the same values generating different hashes, we utilize the replacer
- * argument of JSON.stringify and sort the object by key as it's being serialized. This may or may
- * not be the fastest way to do this; we should investigate this further.
- *
- * Objects and arrays are hashed recursively. When hashing an object that has a .getHash()
- * function, we call that function and use its return value rather than hashing the object
- * ourselves. This allows classes to define custom hashing.
- *
- * @param {Object} val Object to generate hash for
- * @return {string} Hash of object
- */
-oo.getHash = function ( val ) {
-       return JSON.stringify( val, oo.getHash.keySortReplacer );
-};
-
-/**
- * Helper function for OO.getHash which sorts objects by key.
- *
- * This is a callback passed into JSON.stringify.
- *
- * @method getHash_keySortReplacer
- * @param {string} key Property name of value being replaced
- * @param {Mixed} val Property value to replace
- * @return {Mixed} Replacement value
- */
-oo.getHash.keySortReplacer = function ( key, val ) {
-       var normalized, keys, i, len;
-       if ( val && typeof val.getHashObject === 'function' ) {
-               // This object has its own custom hash function, use it
-               val = val.getHashObject();
-       }
-       if ( !Array.isArray( val ) && Object( val ) === val ) {
-               // Only normalize objects when the key-order is ambiguous
-               // (e.g. any object not an array).
-               normalized = {};
-               keys = Object.keys( val ).sort();
-               i = 0;
-               len = keys.length;
-               for ( ; i < len; i += 1 ) {
-                       normalized[keys[i]] = val[keys[i]];
-               }
-               return normalized;
-
-       // Primitive values and arrays get stable hashes
-       // by default. Lets those be stringified as-is.
-       } else {
-               return val;
-       }
-};
-
-/**
- * Compute the union (duplicate-free merge) of a set of arrays.
- *
- * Arrays values must be convertable to object keys (strings).
- *
- * By building an object (with the values for keys) in parallel with
- * the array, a new item's existence in the union can be computed faster.
- *
- * @param {Array...} arrays Arrays to union
- * @return {Array} Union of the arrays
- */
-oo.simpleArrayUnion = function () {
-       var i, ilen, arr, j, jlen,
-               obj = {},
-               result = [];
-
-       for ( i = 0, ilen = arguments.length; i < ilen; i++ ) {
-               arr = arguments[i];
-               for ( j = 0, jlen = arr.length; j < jlen; j++ ) {
-                       if ( !obj[ arr[j] ] ) {
-                               obj[ arr[j] ] = true;
-                               result.push( arr[j] );
-                       }
-               }
-       }
-
-       return result;
-};
-
-/**
- * Combine arrays (intersection or difference).
- *
- * An intersection checks the item exists in 'b' while difference checks it doesn't.
- *
- * Arrays values must be convertable to object keys (strings).
- *
- * By building an object (with the values for keys) of 'b' we can
- * compute the result faster.
- *
- * @private
- * @param {Array} a First array
- * @param {Array} b Second array
- * @param {boolean} includeB Whether to items in 'b'
- * @return {Array} Combination (intersection or difference) of arrays
- */
-function simpleArrayCombine( a, b, includeB ) {
-       var i, ilen, isInB,
-               bObj = {},
-               result = [];
-
-       for ( i = 0, ilen = b.length; i < ilen; i++ ) {
-               bObj[ b[i] ] = true;
-       }
-
-       for ( i = 0, ilen = a.length; i < ilen; i++ ) {
-               isInB = !!bObj[ a[i] ];
-               if ( isInB === includeB ) {
-                       result.push( a[i] );
-               }
-       }
-
-       return result;
-}
-
-/**
- * Compute the intersection of two arrays (items in both arrays).
- *
- * Arrays values must be convertable to object keys (strings).
- *
- * @param {Array} a First array
- * @param {Array} b Second array
- * @return {Array} Intersection of arrays
- */
-oo.simpleArrayIntersection = function ( a, b ) {
-       return simpleArrayCombine( a, b, true );
-};
-
-/**
- * Compute the difference of two arrays (items in 'a' but not 'b').
- *
- * Arrays values must be convertable to object keys (strings).
- *
- * @param {Array} a First array
- * @param {Array} b Second array
- * @return {Array} Intersection of arrays
- */
-oo.simpleArrayDifference = function ( a, b ) {
-       return simpleArrayCombine( a, b, false );
-};
-/**
- * @class OO.EventEmitter
- *
- * @constructor
- */
-oo.EventEmitter = function OoEventEmitter() {
-       // Properties
-
-       /**
-        * Storage of bound event handlers by event name.
-        *
-        * @property
-        */
-       this.bindings = {};
-};
-
-/* Methods */
-
-/**
- * Add a listener to events of a specific event.
- *
- * If the callback/context are already bound to the event, they will not be bound again.
- *
- * @param {string} event Type of event to listen to
- * @param {Function} callback Function to call when event occurs
- * @param {Array} [args] Arguments to pass to listener, will be prepended to emitted arguments
- * @param {Object} [context=null] Object to use as context for callback function or call method on
- * @throws {Error} Listener argument is not a function or method name
- * @chainable
- */
-oo.EventEmitter.prototype.on = function ( event, callback, args, context ) {
-       var i, bindings, binding;
-
-       // Validate callback
-       if ( typeof callback !== 'function' ) {
-               throw new Error( 'Invalid callback. Function or method name expected.' );
-       }
-       // Fallback to null context
-       if ( arguments.length < 4 ) {
-               context = null;
-       }
-       if ( this.bindings.hasOwnProperty( event ) ) {
-               // Check for duplicate callback and context for this event
-               bindings = this.bindings[event];
-               i = bindings.length;
-               while ( i-- ) {
-                       binding = bindings[i];
-                       if ( bindings.callback === callback && bindings.context === context ) {
-                               return this;
-                       }
-               }
-       } else {
-               // Auto-initialize bindings list
-               bindings = this.bindings[event] = [];
-       }
-       // Add binding
-       bindings.push( {
-               callback: callback,
-               args: args,
-               context: context
-       } );
-       return this;
-};
-
-/**
- * Adds a one-time listener to a specific event.
- *
- * @param {string} event Type of event to listen to
- * @param {Function} listener Listener to call when event occurs
- * @chainable
- */
-oo.EventEmitter.prototype.once = function ( event, listener ) {
-       var eventEmitter = this;
-       return this.on( event, function listenerWrapper() {
-               eventEmitter.off( event, listenerWrapper );
-               listener.apply( eventEmitter, Array.prototype.slice.call( arguments, 0 ) );
-       } );
-};
-
-/**
- * Remove a specific listener from a specific event.
- *
- * @param {string} event Type of event to remove listener from
- * @param {Function} [callback] Listener to remove, omit to remove all
- * @param {Object} [context=null] Object used context for callback function or method
- * @chainable
- * @throws {Error} Listener argument is not a function
- */
-oo.EventEmitter.prototype.off = function ( event, callback, context ) {
-       var i, bindings;
-
-       if ( arguments.length === 1 ) {
-               // Remove all bindings for event
-               if ( event in this.bindings ) {
-                       delete this.bindings[event];
-               }
-       } else {
-               if ( typeof callback !== 'function' ) {
-                       throw new Error( 'Invalid callback. Function expected.' );
-               }
-               if ( !( event in this.bindings ) || !this.bindings[event].length ) {
-                       // No matching bindings
-                       return this;
-               }
-               // Fallback to null context
-               if ( arguments.length < 3 ) {
-                       context = null;
-               }
-               // Remove matching handlers
-               bindings = this.bindings[event];
-               i = bindings.length;
-               while ( i-- ) {
-                       if ( bindings[i].callback === callback && bindings[i].context === context ) {
-                               bindings.splice( i, 1 );
-                       }
-               }
-               // Cleanup if now empty
-               if ( bindings.length === 0 ) {
-                       delete this.bindings[event];
-               }
-       }
-       return this;
-};
-
-/**
- * Emit an event.
- *
- * TODO: Should this be chainable? What is the usefulness of the boolean
- * return value here?
- *
- * @param {string} event Type of event
- * @param {Mixed} args First in a list of variadic arguments passed to event handler (optional)
- * @return {boolean} If event was handled by at least one listener
- */
-oo.EventEmitter.prototype.emit = function ( event ) {
-       var i, len, binding, bindings, args;
-
-       if ( event in this.bindings ) {
-               // Slicing ensures that we don't get tripped up by event handlers that add/remove bindings
-               bindings = this.bindings[event].slice();
-               args = Array.prototype.slice.call( arguments, 1 );
-               for ( i = 0, len = bindings.length; i < len; i++ ) {
-                       binding = bindings[i];
-                       binding.callback.apply(
-                               binding.context,
-                               binding.args ? binding.args.concat( args ) : args
-                       );
-               }
-               return true;
-       }
-       return false;
-};
-
-/**
- * Connect event handlers to an object.
- *
- * @param {Object} context Object to call methods on when events occur
- * @param {Object.<string,string>|Object.<string,Function>|Object.<string,Array>} methods List of
- *  event bindings keyed by event name containing either method names, functions or arrays containing
- *  method name or function followed by a list of arguments to be passed to callback before emitted
- *  arguments
- * @chainable
- */
-oo.EventEmitter.prototype.connect = function ( context, methods ) {
-       var method, callback, args, event;
-
-       for ( event in methods ) {
-               method = methods[event];
-               // Allow providing additional args
-               if ( Array.isArray( method ) ) {
-                       args = method.slice( 1 );
-                       method = method[0];
-               } else {
-                       args = [];
-               }
-               // Allow callback to be a method name
-               if ( typeof method === 'string' ) {
-                       // Validate method
-                       if ( !context[method] || typeof context[method] !== 'function' ) {
-                               throw new Error( 'Method not found: ' + method );
-                       }
-                       // Resolve to function
-                       callback = context[method];
-               } else {
-                       callback = method;
-               }
-               // Add binding
-               this.on.apply( this, [ event, callback, args, context ] );
-       }
-       return this;
-};
-
-/**
- * Disconnect event handlers from an object.
- *
- * @param {Object} context Object to disconnect methods from
- * @param {Object.<string,string>|Object.<string,Function>|Object.<string,Array>} [methods] List of
- * event bindings keyed by event name containing either method names or functions
- * @chainable
- */
-oo.EventEmitter.prototype.disconnect = function ( context, methods ) {
-       var i, method, callback, event, bindings;
-
-       if ( methods ) {
-               // Remove specific connections to the context
-               for ( event in methods ) {
-                       method = methods[event];
-                       if ( typeof method === 'string' ) {
-                               // Validate method
-                               if ( !context[method] || typeof context[method] !== 'function' ) {
-                                       throw new Error( 'Method not found: ' + method );
-                               }
-                               // Resolve to function
-                               callback = context[method];
-                       } else {
-                               callback = method;
-                       }
-                       this.off( event, callback, context );
-               }
-       } else {
-               // Remove all connections to the context
-               for ( event in this.bindings ) {
-                       bindings = this.bindings[event];
-                       i = bindings.length;
-                       while ( i-- ) {
-                               if ( bindings[i].context === context ) {
-                                       this.off( event, bindings[i].callback, context );
-                               }
-                       }
-               }
-       }
-
-       return this;
-};
-/**
- * @class OO.Registry
- * @mixins OO.EventEmitter
- *
- * @constructor
- */
-oo.Registry = function OoRegistry() {
-       // Mixin constructors
-       oo.EventEmitter.call( this );
-
-       // Properties
-       this.registry = {};
-};
-
-/* Inheritance */
-
-oo.mixinClass( oo.Registry, oo.EventEmitter );
-
-/* Events */
-
-/**
- * @event register
- * @param {string} name
- * @param {Mixed} data
- */
-
-/* Methods */
-
-/**
- * Associate one or more symbolic names with some data.
- *
- * Only the base name will be registered, overriding any existing entry with the same base name.
- *
- * @param {string|string[]} name Symbolic name or list of symbolic names
- * @param {Mixed} data Data to associate with symbolic name
- * @fires register
- * @throws {Error} Name argument must be a string or array
- */
-oo.Registry.prototype.register = function ( name, data ) {
-       var i, len;
-       if ( typeof name === 'string' ) {
-               this.registry[name] = data;
-               this.emit( 'register', name, data );
-       } else if ( Array.isArray( name ) ) {
-               for ( i = 0, len = name.length; i < len; i++ ) {
-                       this.register( name[i], data );
-               }
-       } else {
-               throw new Error( 'Name must be a string or array, cannot be a ' + typeof name );
-       }
-};
-
-/**
- * Get data for a given symbolic name.
- *
- * Lookups are done using the base name.
- *
- * @param {string} name Symbolic name
- * @return {Mixed|undefined} Data associated with symbolic name
- */
-oo.Registry.prototype.lookup = function ( name ) {
-       return this.registry[name];
-};
-/**
- * @class OO.Factory
- * @extends OO.Registry
- *
- * @constructor
- */
-oo.Factory = function OoFactory() {
-       oo.Factory.super.call( this );
-
-       // Properties
-       this.entries = [];
-};
-
-/* Inheritance */
-
-oo.inheritClass( oo.Factory, oo.Registry );
-
-/* Methods */
-
-/**
- * Register a constructor with the factory.
- *
- * Classes must have a static `name` property to be registered.
- *
- *     function MyClass() {};
- *     OO.initClass( MyClass );
- *     // Adds a static property to the class defining a symbolic name
- *     MyClass.static.name = 'mine';
- *     // Registers class with factory, available via symbolic name 'mine'
- *     factory.register( MyClass );
- *
- * @param {Function} constructor Constructor to use when creating object
- * @throws {Error} Name must be a string and must not be empty
- * @throws {Error} Constructor must be a function
- */
-oo.Factory.prototype.register = function ( constructor ) {
-       var name;
-
-       if ( typeof constructor !== 'function' ) {
-               throw new Error( 'constructor must be a function, cannot be a ' + typeof constructor );
-       }
-       name = constructor.static && constructor.static.name;
-       if ( typeof name !== 'string' || name === '' ) {
-               throw new Error( 'Name must be a string and must not be empty' );
-       }
-       this.entries.push( name );
-
-       oo.Factory.super.prototype.register.call( this, name, constructor );
-};
-
-/**
- * Create an object based on a name.
- *
- * Name is used to look up the constructor to use, while all additional arguments are passed to the
- * constructor directly, so leaving one out will pass an undefined to the constructor.
- *
- * @param {string} name Object name
- * @param {Mixed...} [args] Arguments to pass to the constructor
- * @return {Object} The new object
- * @throws {Error} Unknown object name
- */
-oo.Factory.prototype.create = function ( name ) {
-       var args, obj, constructor;
-
-       if ( !this.registry.hasOwnProperty( name ) ) {
-               throw new Error( 'No class registered by that name: ' + name );
-       }
-       constructor = this.registry[name];
-
-       // Convert arguments to array and shift the first argument (name) off
-       args = Array.prototype.slice.call( arguments, 1 );
-
-       // We can't use the "new" operator with .apply directly because apply needs a
-       // context. So instead just do what "new" does: create an object that inherits from
-       // the constructor's prototype (which also makes it an "instanceof" the constructor),
-       // then invoke the constructor with the object as context, and return it (ignoring
-       // the constructor's return value).
-       obj = Object.create( constructor.prototype );
-       constructor.apply( obj, args );
-       return obj;
-};
-/*jshint node:true */
-if ( typeof module !== 'undefined' && module.exports ) {
-       module.exports = oo;
-} else {
-       global.OO = oo;
-}
-}( this ) );
diff --git a/resources/oojs/update-oojs.sh b/resources/oojs/update-oojs.sh
deleted file mode 100755 (executable)
index 57c7625..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env bash
-
-# FIXME this script is duplicated from update-oojs-ui.sh - factor this out
-
-# This script generates a commit that updates the oojs distribution
-# ./bin/update-oojs.sh path/to/repo/for/oojs
-
-function oojshash() {
-       grep "OOjs v" resources/oojs/oojs.js \
-               | head -n 1 \
-               | grep -Eo '\([a-z0-9]+\)' \
-               | sed 's/^(//' \
-               | sed 's/)$//'
-}
-
-function oojstag() {
-       grep "OOjs v" resources/oojs/oojs.js \
-               | head -n 1 \
-               | grep -Eo '\bv[0-9a-z.-]+\b'
-}
-
-function oojsversion() {
-       grep "OOjs v" resources/oojs/oojs.js \
-               | head -n 1 \
-               | grep -Eo '\bv[0-9a-z.-]+\b.*$'
-}
-
-# cd to the MW directory
-cd $(cd $(dirname $0)/../..; pwd)
-
-if [ "x$1" == "x" ]
-then
-       echo >&2 "Usage: update-oojs.sh path/to/repo/for/oojs"
-       exit 1
-fi
-
-# Undo any changes in the oojs directory
-git reset resources/oojs/
-git checkout resources/oojs/
-
-git fetch origin
-# Create a branch of MW if needed, and reset it to master
-git checkout -B update-oojs origin/master
-
-# Get the old oojs version
-OLDVERSION=$(oojshash)
-if [ "x$OLDVERSION" == "x" ]
-then
-       TAG=$(oojstag)
-fi
-
-# cd to the oojs directory
-cd $1 || exit 1
-if [ "x$OLDVERSION" == "x" ]
-then
-       # Try the tag
-       OLDVERSION=$(git rev-parse $TAG)
-       if [ $? != 0 ]
-       then
-               echo Could not find OOjs version
-               cd -
-               exit 1
-       fi
-fi
-if [ "$(git rev-parse $OLDVERSION)" == "$(git rev-parse HEAD)" ]
-then
-       echo "No changes (already at $OLDVERSION)"
-       cd -
-       exit 0
-fi
-# Build the distribution
-npm install || exit 1
-grunt || exit 1
-# Get the list of changes
-NEWCHANGES=$(git log $OLDVERSION.. --oneline --no-merges --reverse --color=never)
-NEWCHANGESDISPLAY=$(git log $OLDVERSION.. --oneline --no-merges --reverse --color=always)
-# cd back to the VisualEditor directory
-cd -
-
-# Copy files from dist/ to resources/oojs/
-cp -a $1/dist/* resources/oojs/
-# Figure out what the new version is
-NEWVERSION=$(oojsversion)
-# Generate commit summary
-COMMITMSG=$(cat <<END
-Update OOjs to $NEWVERSION
-
-New changes:
-$NEWCHANGES
-END
-)
-# Commit
-git commit resources/oojs/ -m "$COMMITMSG"
-cat >&2 <<END
-
-
-Created commit with changes:
-$NEWCHANGESDISPLAY
-END
diff --git a/resources/package.json b/resources/package.json
deleted file mode 100644 (file)
index a1722b5..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "name": "mediawiki-ui-dependencies",
-       "description": "Node.js dependencies used for KSS generation",
-       "version": "0.0.1",
-       "dependencies": {
-               "kss": ">=0.3.6"
-       },
-       "repository" : {
-               "type" : "git",
-               "url" : "https://gerrit.wikimedia.org/r/p/mediawiki/core.git"
-       }
-
-}
diff --git a/resources/scripts/nodecheck.sh b/resources/scripts/nodecheck.sh
deleted file mode 100755 (executable)
index 3ee0f83..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-if command -v npm > /dev/null ; then
-  npm install
-else
-  echo "You need to install Node.JS!"
-  echo "See http://nodejs.org/"
-  exit 1
-fi
diff --git a/resources/sinonjs/sinon-1.9.0.js b/resources/sinonjs/sinon-1.9.0.js
deleted file mode 100644 (file)
index 428b729..0000000
+++ /dev/null
@@ -1,4794 +0,0 @@
-/**
- * Sinon.JS 1.9.0, 2014/03/05
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
- *
- * (The BSD License)
- * 
- * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 
- *     * Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright notice,
- *       this list of conditions and the following disclaimer in the documentation
- *       and/or other materials provided with the distribution.
- *     * Neither the name of Christian Johansen nor the names of his contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-this.sinon = (function () {
-var samsam, formatio;
-function define(mod, deps, fn) { if (mod == "samsam") { samsam = deps(); } else { formatio = fn(samsam); } }
-define.amd = true;
-((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
- (typeof module === "object" &&
-      function (m) { module.exports = m(); }) || // Node
- function (m) { this.samsam = m(); } // Browser globals
-)(function () {
-    var o = Object.prototype;
-    var div = typeof document !== "undefined" && document.createElement("div");
-
-    function isNaN(value) {
-        // Unlike global isNaN, this avoids type coercion
-        // typeof check avoids IE host object issues, hat tip to
-        // lodash
-        var val = value; // JsLint thinks value !== value is "weird"
-        return typeof value === "number" && value !== val;
-    }
-
-    function getClass(value) {
-        // Returns the internal [[Class]] by calling Object.prototype.toString
-        // with the provided value as this. Return value is a string, naming the
-        // internal class, e.g. "Array"
-        return o.toString.call(value).split(/[ \]]/)[1];
-    }
-
-    /**
-     * @name samsam.isArguments
-     * @param Object object
-     *
-     * Returns ``true`` if ``object`` is an ``arguments`` object,
-     * ``false`` otherwise.
-     */
-    function isArguments(object) {
-        if (typeof object !== "object" || typeof object.length !== "number" ||
-                getClass(object) === "Array") {
-            return false;
-        }
-        if (typeof object.callee == "function") { return true; }
-        try {
-            object[object.length] = 6;
-            delete object[object.length];
-        } catch (e) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * @name samsam.isElement
-     * @param Object object
-     *
-     * Returns ``true`` if ``object`` is a DOM element node. Unlike
-     * Underscore.js/lodash, this function will return ``false`` if ``object``
-     * is an *element-like* object, i.e. a regular object with a ``nodeType``
-     * property that holds the value ``1``.
-     */
-    function isElement(object) {
-        if (!object || object.nodeType !== 1 || !div) { return false; }
-        try {
-            object.appendChild(div);
-            object.removeChild(div);
-        } catch (e) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * @name samsam.keys
-     * @param Object object
-     *
-     * Return an array of own property names.
-     */
-    function keys(object) {
-        var ks = [], prop;
-        for (prop in object) {
-            if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
-        }
-        return ks;
-    }
-
-    /**
-     * @name samsam.isDate
-     * @param Object value
-     *
-     * Returns true if the object is a ``Date``, or *date-like*. Duck typing
-     * of date objects work by checking that the object has a ``getTime``
-     * function whose return value equals the return value from the object's
-     * ``valueOf``.
-     */
-    function isDate(value) {
-        return typeof value.getTime == "function" &&
-            value.getTime() == value.valueOf();
-    }
-
-    /**
-     * @name samsam.isNegZero
-     * @param Object value
-     *
-     * Returns ``true`` if ``value`` is ``-0``.
-     */
-    function isNegZero(value) {
-        return value === 0 && 1 / value === -Infinity;
-    }
-
-    /**
-     * @name samsam.equal
-     * @param Object obj1
-     * @param Object obj2
-     *
-     * Returns ``true`` if two objects are strictly equal. Compared to
-     * ``===`` there are two exceptions:
-     *
-     *   - NaN is considered equal to NaN
-     *   - -0 and +0 are not considered equal
-     */
-    function identical(obj1, obj2) {
-        if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
-            return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
-        }
-    }
-
-
-    /**
-     * @name samsam.deepEqual
-     * @param Object obj1
-     * @param Object obj2
-     *
-     * Deep equal comparison. Two values are "deep equal" if:
-     *
-     *   - They are equal, according to samsam.identical
-     *   - They are both date objects representing the same time
-     *   - They are both arrays containing elements that are all deepEqual
-     *   - They are objects with the same set of properties, and each property
-     *     in ``obj1`` is deepEqual to the corresponding property in ``obj2``
-     *
-     * Supports cyclic objects.
-     */
-    function deepEqualCyclic(obj1, obj2) {
-
-        // used for cyclic comparison
-        // contain already visited objects
-        var objects1 = [],
-            objects2 = [],
-        // contain pathes (position in the object structure)
-        // of the already visited objects
-        // indexes same as in objects arrays
-            paths1 = [],
-            paths2 = [],
-        // contains combinations of already compared objects
-        // in the manner: { "$1['ref']$2['ref']": true }
-            compared = {};
-
-        /**
-         * used to check, if the value of a property is an object
-         * (cyclic logic is only needed for objects)
-         * only needed for cyclic logic
-         */
-        function isObject(value) {
-
-            if (typeof value === 'object' && value !== null &&
-                    !(value instanceof Boolean) &&
-                    !(value instanceof Date)    &&
-                    !(value instanceof Number)  &&
-                    !(value instanceof RegExp)  &&
-                    !(value instanceof String)) {
-
-                return true;
-            }
-
-            return false;
-        }
-
-        /**
-         * returns the index of the given object in the
-         * given objects array, -1 if not contained
-         * only needed for cyclic logic
-         */
-        function getIndex(objects, obj) {
-
-            var i;
-            for (i = 0; i < objects.length; i++) {
-                if (objects[i] === obj) {
-                    return i;
-                }
-            }
-
-            return -1;
-        }
-
-        // does the recursion for the deep equal check
-        return (function deepEqual(obj1, obj2, path1, path2) {
-            var type1 = typeof obj1;
-            var type2 = typeof obj2;
-
-            // == null also matches undefined
-            if (obj1 === obj2 ||
-                    isNaN(obj1) || isNaN(obj2) ||
-                    obj1 == null || obj2 == null ||
-                    type1 !== "object" || type2 !== "object") {
-
-                return identical(obj1, obj2);
-            }
-
-            // Elements are only equal if identical(expected, actual)
-            if (isElement(obj1) || isElement(obj2)) { return false; }
-
-            var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
-            if (isDate1 || isDate2) {
-                if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
-                    return false;
-                }
-            }
-
-            if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
-                if (obj1.toString() !== obj2.toString()) { return false; }
-            }
-
-            var class1 = getClass(obj1);
-            var class2 = getClass(obj2);
-            var keys1 = keys(obj1);
-            var keys2 = keys(obj2);
-
-            if (isArguments(obj1) || isArguments(obj2)) {
-                if (obj1.length !== obj2.length) { return false; }
-            } else {
-                if (type1 !== type2 || class1 !== class2 ||
-                        keys1.length !== keys2.length) {
-                    return false;
-                }
-            }
-
-            var key, i, l,
-                // following vars are used for the cyclic logic
-                value1, value2,
-                isObject1, isObject2,
-                index1, index2,
-                newPath1, newPath2;
-
-            for (i = 0, l = keys1.length; i < l; i++) {
-                key = keys1[i];
-                if (!o.hasOwnProperty.call(obj2, key)) {
-                    return false;
-                }
-
-                // Start of the cyclic logic
-
-                value1 = obj1[key];
-                value2 = obj2[key];
-
-                isObject1 = isObject(value1);
-                isObject2 = isObject(value2);
-
-                // determine, if the objects were already visited
-                // (it's faster to check for isObject first, than to
-                // get -1 from getIndex for non objects)
-                index1 = isObject1 ? getIndex(objects1, value1) : -1;
-                index2 = isObject2 ? getIndex(objects2, value2) : -1;
-
-                // determine the new pathes of the objects
-                // - for non cyclic objects the current path will be extended
-                //   by current property name
-                // - for cyclic objects the stored path is taken
-                newPath1 = index1 !== -1
-                    ? paths1[index1]
-                    : path1 + '[' + JSON.stringify(key) + ']';
-                newPath2 = index2 !== -1
-                    ? paths2[index2]
-                    : path2 + '[' + JSON.stringify(key) + ']';
-
-                // stop recursion if current objects are already compared
-                if (compared[newPath1 + newPath2]) {
-                    return true;
-                }
-
-                // remember the current objects and their pathes
-                if (index1 === -1 && isObject1) {
-                    objects1.push(value1);
-                    paths1.push(newPath1);
-                }
-                if (index2 === -1 && isObject2) {
-                    objects2.push(value2);
-                    paths2.push(newPath2);
-                }
-
-                // remember that the current objects are already compared
-                if (isObject1 && isObject2) {
-                    compared[newPath1 + newPath2] = true;
-                }
-
-                // End of cyclic logic
-
-                // neither value1 nor value2 is a cycle
-                // continue with next level
-                if (!deepEqual(value1, value2, newPath1, newPath2)) {
-                    return false;
-                }
-            }
-
-            return true;
-
-        }(obj1, obj2, '$1', '$2'));
-    }
-
-    var match;
-
-    function arrayContains(array, subset) {
-        if (subset.length === 0) { return true; }
-        var i, l, j, k;
-        for (i = 0, l = array.length; i < l; ++i) {
-            if (match(array[i], subset[0])) {
-                for (j = 0, k = subset.length; j < k; ++j) {
-                    if (!match(array[i + j], subset[j])) { return false; }
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * @name samsam.match
-     * @param Object object
-     * @param Object matcher
-     *
-     * Compare arbitrary value ``object`` with matcher.
-     */
-    match = function match(object, matcher) {
-        if (matcher && typeof matcher.test === "function") {
-            return matcher.test(object);
-        }
-
-        if (typeof matcher === "function") {
-            return matcher(object) === true;
-        }
-
-        if (typeof matcher === "string") {
-            matcher = matcher.toLowerCase();
-            var notNull = typeof object === "string" || !!object;
-            return notNull &&
-                (String(object)).toLowerCase().indexOf(matcher) >= 0;
-        }
-
-        if (typeof matcher === "number") {
-            return matcher === object;
-        }
-
-        if (typeof matcher === "boolean") {
-            return matcher === object;
-        }
-
-        if (getClass(object) === "Array" && getClass(matcher) === "Array") {
-            return arrayContains(object, matcher);
-        }
-
-        if (matcher && typeof matcher === "object") {
-            var prop;
-            for (prop in matcher) {
-                if (!match(object[prop], matcher[prop])) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        throw new Error("Matcher was not a string, a number, a " +
-                        "function, a boolean or an object");
-    };
-
-    return {
-        isArguments: isArguments,
-        isElement: isElement,
-        isDate: isDate,
-        isNegZero: isNegZero,
-        identical: identical,
-        deepEqual: deepEqualCyclic,
-        match: match,
-        keys: keys
-    };
-});
-((typeof define === "function" && define.amd && function (m) {
-    define("formatio", ["samsam"], m);
-}) || (typeof module === "object" && function (m) {
-    module.exports = m(require("samsam"));
-}) || function (m) { this.formatio = m(this.samsam); }
-)(function (samsam) {
-    
-    var formatio = {
-        excludeConstructors: ["Object", /^.$/],
-        quoteStrings: true
-    };
-
-    var hasOwn = Object.prototype.hasOwnProperty;
-
-    var specialObjects = [];
-    if (typeof global !== "undefined") {
-        specialObjects.push({ object: global, value: "[object global]" });
-    }
-    if (typeof document !== "undefined") {
-        specialObjects.push({
-            object: document,
-            value: "[object HTMLDocument]"
-        });
-    }
-    if (typeof window !== "undefined") {
-        specialObjects.push({ object: window, value: "[object Window]" });
-    }
-
-    function functionName(func) {
-        if (!func) { return ""; }
-        if (func.displayName) { return func.displayName; }
-        if (func.name) { return func.name; }
-        var matches = func.toString().match(/function\s+([^\(]+)/m);
-        return (matches && matches[1]) || "";
-    }
-
-    function constructorName(f, object) {
-        var name = functionName(object && object.constructor);
-        var excludes = f.excludeConstructors ||
-                formatio.excludeConstructors || [];
-
-        var i, l;
-        for (i = 0, l = excludes.length; i < l; ++i) {
-            if (typeof excludes[i] === "string" && excludes[i] === name) {
-                return "";
-            } else if (excludes[i].test && excludes[i].test(name)) {
-                return "";
-            }
-        }
-
-        return name;
-    }
-
-    function isCircular(object, objects) {
-        if (typeof object !== "object") { return false; }
-        var i, l;
-        for (i = 0, l = objects.length; i < l; ++i) {
-            if (objects[i] === object) { return true; }
-        }
-        return false;
-    }
-
-    function ascii(f, object, processed, indent) {
-        if (typeof object === "string") {
-            var qs = f.quoteStrings;
-            var quote = typeof qs !== "boolean" || qs;
-            return processed || quote ? '"' + object + '"' : object;
-        }
-
-        if (typeof object === "function" && !(object instanceof RegExp)) {
-            return ascii.func(object);
-        }
-
-        processed = processed || [];
-
-        if (isCircular(object, processed)) { return "[Circular]"; }
-
-        if (Object.prototype.toString.call(object) === "[object Array]") {
-            return ascii.array.call(f, object, processed);
-        }
-
-        if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
-        if (samsam.isElement(object)) { return ascii.element(object); }
-
-        if (typeof object.toString === "function" &&
-                object.toString !== Object.prototype.toString) {
-            return object.toString();
-        }
-
-        var i, l;
-        for (i = 0, l = specialObjects.length; i < l; i++) {
-            if (object === specialObjects[i].object) {
-                return specialObjects[i].value;
-            }
-        }
-
-        return ascii.object.call(f, object, processed, indent);
-    }
-
-    ascii.func = function (func) {
-        return "function " + functionName(func) + "() {}";
-    };
-
-    ascii.array = function (array, processed) {
-        processed = processed || [];
-        processed.push(array);
-        var i, l, pieces = [];
-        for (i = 0, l = array.length; i < l; ++i) {
-            pieces.push(ascii(this, array[i], processed));
-        }
-        return "[" + pieces.join(", ") + "]";
-    };
-
-    ascii.object = function (object, processed, indent) {
-        processed = processed || [];
-        processed.push(object);
-        indent = indent || 0;
-        var pieces = [], properties = samsam.keys(object).sort();
-        var length = 3;
-        var prop, str, obj, i, l;
-
-        for (i = 0, l = properties.length; i < l; ++i) {
-            prop = properties[i];
-            obj = object[prop];
-
-            if (isCircular(obj, processed)) {
-                str = "[Circular]";
-            } else {
-                str = ascii(this, obj, processed, indent + 2);
-            }
-
-            str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
-            length += str.length;
-            pieces.push(str);
-        }
-
-        var cons = constructorName(this, object);
-        var prefix = cons ? "[" + cons + "] " : "";
-        var is = "";
-        for (i = 0, l = indent; i < l; ++i) { is += " "; }
-
-        if (length + indent > 80) {
-            return prefix + "{\n  " + is + pieces.join(",\n  " + is) + "\n" +
-                is + "}";
-        }
-        return prefix + "{ " + pieces.join(", ") + " }";
-    };
-
-    ascii.element = function (element) {
-        var tagName = element.tagName.toLowerCase();
-        var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
-
-        for (i = 0, l = attrs.length; i < l; ++i) {
-            attr = attrs.item(i);
-            attrName = attr.nodeName.toLowerCase().replace("html:", "");
-            val = attr.nodeValue;
-            if (attrName !== "contenteditable" || val !== "inherit") {
-                if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
-            }
-        }
-
-        var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
-        var content = element.innerHTML;
-
-        if (content.length > 20) {
-            content = content.substr(0, 20) + "[...]";
-        }
-
-        var res = formatted + pairs.join(" ") + ">" + content +
-                "</" + tagName + ">";
-
-        return res.replace(/ contentEditable="inherit"/, "");
-    };
-
-    function Formatio(options) {
-        for (var opt in options) {
-            this[opt] = options[opt];
-        }
-    }
-
-    Formatio.prototype = {
-        functionName: functionName,
-
-        configure: function (options) {
-            return new Formatio(options);
-        },
-
-        constructorName: function (object) {
-            return constructorName(this, object);
-        },
-
-        ascii: function (object, processed, indent) {
-            return ascii(this, object, processed, indent);
-        }
-    };
-
-    return Formatio.prototype;
-});
-/*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
-/*global module, require, __dirname, document*/
-/**
- * Sinon core utilities. For internal use only.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-var sinon = (function (formatio) {
-    var div = typeof document != "undefined" && document.createElement("div");
-    var hasOwn = Object.prototype.hasOwnProperty;
-
-    function isDOMNode(obj) {
-        var success = false;
-
-        try {
-            obj.appendChild(div);
-            success = div.parentNode == obj;
-        } catch (e) {
-            return false;
-        } finally {
-            try {
-                obj.removeChild(div);
-            } catch (e) {
-                // Remove failed, not much we can do about that
-            }
-        }
-
-        return success;
-    }
-
-    function isElement(obj) {
-        return div && obj && obj.nodeType === 1 && isDOMNode(obj);
-    }
-
-    function isFunction(obj) {
-        return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
-    }
-
-    function mirrorProperties(target, source) {
-        for (var prop in source) {
-            if (!hasOwn.call(target, prop)) {
-                target[prop] = source[prop];
-            }
-        }
-    }
-
-    function isRestorable (obj) {
-        return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
-    }
-
-    var sinon = {
-        wrapMethod: function wrapMethod(object, property, method) {
-            if (!object) {
-                throw new TypeError("Should wrap property of object");
-            }
-
-            if (typeof method != "function") {
-                throw new TypeError("Method wrapper should be function");
-            }
-
-            var wrappedMethod = object[property],
-                error;
-
-            if (!isFunction(wrappedMethod)) {
-                error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
-                                    property + " as function");
-            }
-
-            if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
-                error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
-            }
-
-            if (wrappedMethod.calledBefore) {
-                var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
-                error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
-            }
-
-            if (error) {
-                if (wrappedMethod._stack) {
-                    error.stack += '\n--------------\n' + wrappedMethod._stack;
-                }
-                throw error;
-            }
-
-            // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
-            // when using hasOwn.call on objects from other frames.
-            var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
-            object[property] = method;
-            method.displayName = property;
-            // Set up a stack trace which can be used later to find what line of
-            // code the original method was created on.
-            method._stack = (new Error('Stack Trace for original')).stack;
-
-            method.restore = function () {
-                // For prototype properties try to reset by delete first.
-                // If this fails (ex: localStorage on mobile safari) then force a reset
-                // via direct assignment.
-                if (!owned) {
-                    delete object[property];
-                }
-                if (object[property] === method) {
-                    object[property] = wrappedMethod;
-                }
-            };
-
-            method.restore.sinon = true;
-            mirrorProperties(method, wrappedMethod);
-
-            return method;
-        },
-
-        extend: function extend(target) {
-            for (var i = 1, l = arguments.length; i < l; i += 1) {
-                for (var prop in arguments[i]) {
-                    if (arguments[i].hasOwnProperty(prop)) {
-                        target[prop] = arguments[i][prop];
-                    }
-
-                    // DONT ENUM bug, only care about toString
-                    if (arguments[i].hasOwnProperty("toString") &&
-                        arguments[i].toString != target.toString) {
-                        target.toString = arguments[i].toString;
-                    }
-                }
-            }
-
-            return target;
-        },
-
-        create: function create(proto) {
-            var F = function () {};
-            F.prototype = proto;
-            return new F();
-        },
-
-        deepEqual: function deepEqual(a, b) {
-            if (sinon.match && sinon.match.isMatcher(a)) {
-                return a.test(b);
-            }
-            if (typeof a != "object" || typeof b != "object") {
-                return a === b;
-            }
-
-            if (isElement(a) || isElement(b)) {
-                return a === b;
-            }
-
-            if (a === b) {
-                return true;
-            }
-
-            if ((a === null && b !== null) || (a !== null && b === null)) {
-                return false;
-            }
-
-            if (a instanceof RegExp && b instanceof RegExp) {
-              return (a.source === b.source) && (a.global === b.global) && 
-                (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
-            }
-
-            var aString = Object.prototype.toString.call(a);
-            if (aString != Object.prototype.toString.call(b)) {
-                return false;
-            }
-
-            if (aString == "[object Date]") {
-                return a.valueOf() === b.valueOf();
-            }
-
-            var prop, aLength = 0, bLength = 0;
-
-            if (aString == "[object Array]" && a.length !== b.length) {
-                return false;
-            }
-
-            for (prop in a) {
-                aLength += 1;
-
-                if (!deepEqual(a[prop], b[prop])) {
-                    return false;
-                }
-            }
-
-            for (prop in b) {
-                bLength += 1;
-            }
-
-            return aLength == bLength;
-        },
-
-        functionName: function functionName(func) {
-            var name = func.displayName || func.name;
-
-            // Use function decomposition as a last resort to get function
-            // name. Does not rely on function decomposition to work - if it
-            // doesn't debugging will be slightly less informative
-            // (i.e. toString will say 'spy' rather than 'myFunc').
-            if (!name) {
-                var matches = func.toString().match(/function ([^\s\(]+)/);
-                name = matches && matches[1];
-            }
-
-            return name;
-        },
-
-        functionToString: function toString() {
-            if (this.getCall && this.callCount) {
-                var thisValue, prop, i = this.callCount;
-
-                while (i--) {
-                    thisValue = this.getCall(i).thisValue;
-
-                    for (prop in thisValue) {
-                        if (thisValue[prop] === this) {
-                            return prop;
-                        }
-                    }
-                }
-            }
-
-            return this.displayName || "sinon fake";
-        },
-
-        getConfig: function (custom) {
-            var config = {};
-            custom = custom || {};
-            var defaults = sinon.defaultConfig;
-
-            for (var prop in defaults) {
-                if (defaults.hasOwnProperty(prop)) {
-                    config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
-                }
-            }
-
-            return config;
-        },
-
-        format: function (val) {
-            return "" + val;
-        },
-
-        defaultConfig: {
-            injectIntoThis: true,
-            injectInto: null,
-            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
-            useFakeTimers: true,
-            useFakeServer: true
-        },
-
-        timesInWords: function timesInWords(count) {
-            return count == 1 && "once" ||
-                count == 2 && "twice" ||
-                count == 3 && "thrice" ||
-                (count || 0) + " times";
-        },
-
-        calledInOrder: function (spies) {
-            for (var i = 1, l = spies.length; i < l; i++) {
-                if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
-                    return false;
-                }
-            }
-
-            return true;
-        },
-
-        orderByFirstCall: function (spies) {
-            return spies.sort(function (a, b) {
-                // uuid, won't ever be equal
-                var aCall = a.getCall(0);
-                var bCall = b.getCall(0);
-                var aId = aCall && aCall.callId || -1;
-                var bId = bCall && bCall.callId || -1;
-
-                return aId < bId ? -1 : 1;
-            });
-        },
-
-        log: function () {},
-
-        logError: function (label, err) {
-            var msg = label + " threw exception: ";
-            sinon.log(msg + "[" + err.name + "] " + err.message);
-            if (err.stack) { sinon.log(err.stack); }
-
-            setTimeout(function () {
-                err.message = msg + err.message;
-                throw err;
-            }, 0);
-        },
-
-        typeOf: function (value) {
-            if (value === null) {
-                return "null";
-            }
-            else if (value === undefined) {
-                return "undefined";
-            }
-            var string = Object.prototype.toString.call(value);
-            return string.substring(8, string.length - 1).toLowerCase();
-        },
-
-        createStubInstance: function (constructor) {
-            if (typeof constructor !== "function") {
-                throw new TypeError("The constructor should be a function.");
-            }
-            return sinon.stub(sinon.create(constructor.prototype));
-        },
-
-        restore: function (object) {
-            if (object !== null && typeof object === "object") {
-                for (var prop in object) {
-                    if (isRestorable(object[prop])) {
-                        object[prop].restore();
-                    }
-                }
-            }
-            else if (isRestorable(object)) {
-                object.restore();
-            }
-        }
-    };
-
-    var isNode = typeof module !== "undefined" && module.exports;
-    var isAMD = typeof define === 'function' && typeof define.amd === 'object' && define.amd;
-
-    if (isAMD) {
-        define(function(){
-            return sinon;
-        });
-    } else if (isNode) {
-        try {
-            formatio = require("formatio");
-        } catch (e) {}
-        module.exports = sinon;
-        module.exports.spy = require("./sinon/spy");
-        module.exports.spyCall = require("./sinon/call");
-        module.exports.behavior = require("./sinon/behavior");
-        module.exports.stub = require("./sinon/stub");
-        module.exports.mock = require("./sinon/mock");
-        module.exports.collection = require("./sinon/collection");
-        module.exports.assert = require("./sinon/assert");
-        module.exports.sandbox = require("./sinon/sandbox");
-        module.exports.test = require("./sinon/test");
-        module.exports.testCase = require("./sinon/test_case");
-        module.exports.assert = require("./sinon/assert");
-        module.exports.match = require("./sinon/match");
-    }
-
-    if (formatio) {
-        var formatter = formatio.configure({ quoteStrings: false });
-        sinon.format = function () {
-            return formatter.ascii.apply(formatter, arguments);
-        };
-    } else if (isNode) {
-        try {
-            var util = require("util");
-            sinon.format = function (value) {
-                return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
-            };
-        } catch (e) {
-            /* Node, but no util module - would be very old, but better safe than
-             sorry */
-        }
-    }
-
-    return sinon;
-}(typeof formatio == "object" && formatio));
-
-/* @depend ../sinon.js */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Match functions
- *
- * @author Maximilian Antoni (mail@maxantoni.de)
- * @license BSD
- *
- * Copyright (c) 2012 Maximilian Antoni
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function assertType(value, type, name) {
-        var actual = sinon.typeOf(value);
-        if (actual !== type) {
-            throw new TypeError("Expected type of " + name + " to be " +
-                type + ", but was " + actual);
-        }
-    }
-
-    var matcher = {
-        toString: function () {
-            return this.message;
-        }
-    };
-
-    function isMatcher(object) {
-        return matcher.isPrototypeOf(object);
-    }
-
-    function matchObject(expectation, actual) {
-        if (actual === null || actual === undefined) {
-            return false;
-        }
-        for (var key in expectation) {
-            if (expectation.hasOwnProperty(key)) {
-                var exp = expectation[key];
-                var act = actual[key];
-                if (match.isMatcher(exp)) {
-                    if (!exp.test(act)) {
-                        return false;
-                    }
-                } else if (sinon.typeOf(exp) === "object") {
-                    if (!matchObject(exp, act)) {
-                        return false;
-                    }
-                } else if (!sinon.deepEqual(exp, act)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    matcher.or = function (m2) {
-        if (!arguments.length) {
-            throw new TypeError("Matcher expected");
-        } else if (!isMatcher(m2)) {
-            m2 = match(m2);
-        }
-        var m1 = this;
-        var or = sinon.create(matcher);
-        or.test = function (actual) {
-            return m1.test(actual) || m2.test(actual);
-        };
-        or.message = m1.message + ".or(" + m2.message + ")";
-        return or;
-    };
-
-    matcher.and = function (m2) {
-        if (!arguments.length) {
-            throw new TypeError("Matcher expected");
-        } else if (!isMatcher(m2)) {
-            m2 = match(m2);
-        }
-        var m1 = this;
-        var and = sinon.create(matcher);
-        and.test = function (actual) {
-            return m1.test(actual) && m2.test(actual);
-        };
-        and.message = m1.message + ".and(" + m2.message + ")";
-        return and;
-    };
-
-    var match = function (expectation, message) {
-        var m = sinon.create(matcher);
-        var type = sinon.typeOf(expectation);
-        switch (type) {
-        case "object":
-            if (typeof expectation.test === "function") {
-                m.test = function (actual) {
-                    return expectation.test(actual) === true;
-                };
-                m.message = "match(" + sinon.functionName(expectation.test) + ")";
-                return m;
-            }
-            var str = [];
-            for (var key in expectation) {
-                if (expectation.hasOwnProperty(key)) {
-                    str.push(key + ": " + expectation[key]);
-                }
-            }
-            m.test = function (actual) {
-                return matchObject(expectation, actual);
-            };
-            m.message = "match(" + str.join(", ") + ")";
-            break;
-        case "number":
-            m.test = function (actual) {
-                return expectation == actual;
-            };
-            break;
-        case "string":
-            m.test = function (actual) {
-                if (typeof actual !== "string") {
-                    return false;
-                }
-                return actual.indexOf(expectation) !== -1;
-            };
-            m.message = "match(\"" + expectation + "\")";
-            break;
-        case "regexp":
-            m.test = function (actual) {
-                if (typeof actual !== "string") {
-                    return false;
-                }
-                return expectation.test(actual);
-            };
-            break;
-        case "function":
-            m.test = expectation;
-            if (message) {
-                m.message = message;
-            } else {
-                m.message = "match(" + sinon.functionName(expectation) + ")";
-            }
-            break;
-        default:
-            m.test = function (actual) {
-              return sinon.deepEqual(expectation, actual);
-            };
-        }
-        if (!m.message) {
-            m.message = "match(" + expectation + ")";
-        }
-        return m;
-    };
-
-    match.isMatcher = isMatcher;
-
-    match.any = match(function () {
-        return true;
-    }, "any");
-
-    match.defined = match(function (actual) {
-        return actual !== null && actual !== undefined;
-    }, "defined");
-
-    match.truthy = match(function (actual) {
-        return !!actual;
-    }, "truthy");
-
-    match.falsy = match(function (actual) {
-        return !actual;
-    }, "falsy");
-
-    match.same = function (expectation) {
-        return match(function (actual) {
-            return expectation === actual;
-        }, "same(" + expectation + ")");
-    };
-
-    match.typeOf = function (type) {
-        assertType(type, "string", "type");
-        return match(function (actual) {
-            return sinon.typeOf(actual) === type;
-        }, "typeOf(\"" + type + "\")");
-    };
-
-    match.instanceOf = function (type) {
-        assertType(type, "function", "type");
-        return match(function (actual) {
-            return actual instanceof type;
-        }, "instanceOf(" + sinon.functionName(type) + ")");
-    };
-
-    function createPropertyMatcher(propertyTest, messagePrefix) {
-        return function (property, value) {
-            assertType(property, "string", "property");
-            var onlyProperty = arguments.length === 1;
-            var message = messagePrefix + "(\"" + property + "\"";
-            if (!onlyProperty) {
-                message += ", " + value;
-            }
-            message += ")";
-            return match(function (actual) {
-                if (actual === undefined || actual === null ||
-                        !propertyTest(actual, property)) {
-                    return false;
-                }
-                return onlyProperty || sinon.deepEqual(value, actual[property]);
-            }, message);
-        };
-    }
-
-    match.has = createPropertyMatcher(function (actual, property) {
-        if (typeof actual === "object") {
-            return property in actual;
-        }
-        return actual[property] !== undefined;
-    }, "has");
-
-    match.hasOwn = createPropertyMatcher(function (actual, property) {
-        return actual.hasOwnProperty(property);
-    }, "hasOwn");
-
-    match.bool = match.typeOf("boolean");
-    match.number = match.typeOf("number");
-    match.string = match.typeOf("string");
-    match.object = match.typeOf("object");
-    match.func = match.typeOf("function");
-    match.array = match.typeOf("array");
-    match.regexp = match.typeOf("regexp");
-    match.date = match.typeOf("date");
-
-    if (commonJSModule) {
-        module.exports = match;
-    } else {
-        sinon.match = match;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
-  * @depend ../sinon.js
-  * @depend match.js
-  */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
-  * Spy calls
-  *
-  * @author Christian Johansen (christian@cjohansen.no)
-  * @author Maximilian Antoni (mail@maxantoni.de)
-  * @license BSD
-  *
-  * Copyright (c) 2010-2013 Christian Johansen
-  * Copyright (c) 2013 Maximilian Antoni
-  */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function throwYieldError(proxy, text, args) {
-        var msg = sinon.functionName(proxy) + text;
-        if (args.length) {
-            msg += " Received [" + slice.call(args).join(", ") + "]";
-        }
-        throw new Error(msg);
-    }
-
-    var slice = Array.prototype.slice;
-
-    var callProto = {
-        calledOn: function calledOn(thisValue) {
-            if (sinon.match && sinon.match.isMatcher(thisValue)) {
-                return thisValue.test(this.thisValue);
-            }
-            return this.thisValue === thisValue;
-        },
-
-        calledWith: function calledWith() {
-            for (var i = 0, l = arguments.length; i < l; i += 1) {
-                if (!sinon.deepEqual(arguments[i], this.args[i])) {
-                    return false;
-                }
-            }
-
-            return true;
-        },
-
-        calledWithMatch: function calledWithMatch() {
-            for (var i = 0, l = arguments.length; i < l; i += 1) {
-                var actual = this.args[i];
-                var expectation = arguments[i];
-                if (!sinon.match || !sinon.match(expectation).test(actual)) {
-                    return false;
-                }
-            }
-            return true;
-        },
-
-        calledWithExactly: function calledWithExactly() {
-            return arguments.length == this.args.length &&
-                this.calledWith.apply(this, arguments);
-        },
-
-        notCalledWith: function notCalledWith() {
-            return !this.calledWith.apply(this, arguments);
-        },
-
-        notCalledWithMatch: function notCalledWithMatch() {
-            return !this.calledWithMatch.apply(this, arguments);
-        },
-
-        returned: function returned(value) {
-            return sinon.deepEqual(value, this.returnValue);
-        },
-
-        threw: function threw(error) {
-            if (typeof error === "undefined" || !this.exception) {
-                return !!this.exception;
-            }
-
-            return this.exception === error || this.exception.name === error;
-        },
-
-        calledWithNew: function calledWithNew() {
-            return this.proxy.prototype && this.thisValue instanceof this.proxy;
-        },
-
-        calledBefore: function (other) {
-            return this.callId < other.callId;
-        },
-
-        calledAfter: function (other) {
-            return this.callId > other.callId;
-        },
-
-        callArg: function (pos) {
-            this.args[pos]();
-        },
-
-        callArgOn: function (pos, thisValue) {
-            this.args[pos].apply(thisValue);
-        },
-
-        callArgWith: function (pos) {
-            this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
-        },
-
-        callArgOnWith: function (pos, thisValue) {
-            var args = slice.call(arguments, 2);
-            this.args[pos].apply(thisValue, args);
-        },
-
-        "yield": function () {
-            this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
-        },
-
-        yieldOn: function (thisValue) {
-            var args = this.args;
-            for (var i = 0, l = args.length; i < l; ++i) {
-                if (typeof args[i] === "function") {
-                    args[i].apply(thisValue, slice.call(arguments, 1));
-                    return;
-                }
-            }
-            throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
-        },
-
-        yieldTo: function (prop) {
-            this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
-        },
-
-        yieldToOn: function (prop, thisValue) {
-            var args = this.args;
-            for (var i = 0, l = args.length; i < l; ++i) {
-                if (args[i] && typeof args[i][prop] === "function") {
-                    args[i][prop].apply(thisValue, slice.call(arguments, 2));
-                    return;
-                }
-            }
-            throwYieldError(this.proxy, " cannot yield to '" + prop +
-                "' since no callback was passed.", args);
-        },
-
-        toString: function () {
-            var callStr = this.proxy.toString() + "(";
-            var args = [];
-
-            for (var i = 0, l = this.args.length; i < l; ++i) {
-                args.push(sinon.format(this.args[i]));
-            }
-
-            callStr = callStr + args.join(", ") + ")";
-
-            if (typeof this.returnValue != "undefined") {
-                callStr += " => " + sinon.format(this.returnValue);
-            }
-
-            if (this.exception) {
-                callStr += " !" + this.exception.name;
-
-                if (this.exception.message) {
-                    callStr += "(" + this.exception.message + ")";
-                }
-            }
-
-            return callStr;
-        }
-    };
-
-    callProto.invokeCallback = callProto.yield;
-
-    function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
-        if (typeof id !== "number") {
-            throw new TypeError("Call id is not a number");
-        }
-        var proxyCall = sinon.create(callProto);
-        proxyCall.proxy = spy;
-        proxyCall.thisValue = thisValue;
-        proxyCall.args = args;
-        proxyCall.returnValue = returnValue;
-        proxyCall.exception = exception;
-        proxyCall.callId = id;
-
-        return proxyCall;
-    }
-    createSpyCall.toString = callProto.toString; // used by mocks
-
-    if (commonJSModule) {
-        module.exports = createSpyCall;
-    } else {
-        sinon.spyCall = createSpyCall;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-
-/**
-  * @depend ../sinon.js
-  * @depend call.js
-  */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
-  * Spy functions
-  *
-  * @author Christian Johansen (christian@cjohansen.no)
-  * @license BSD
-  *
-  * Copyright (c) 2010-2013 Christian Johansen
-  */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    var push = Array.prototype.push;
-    var slice = Array.prototype.slice;
-    var callId = 0;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function spy(object, property) {
-        if (!property && typeof object == "function") {
-            return spy.create(object);
-        }
-
-        if (!object && !property) {
-            return spy.create(function () { });
-        }
-
-        var method = object[property];
-        return sinon.wrapMethod(object, property, spy.create(method));
-    }
-
-    function matchingFake(fakes, args, strict) {
-        if (!fakes) {
-            return;
-        }
-
-        for (var i = 0, l = fakes.length; i < l; i++) {
-            if (fakes[i].matches(args, strict)) {
-                return fakes[i];
-            }
-        }
-    }
-
-    function incrementCallCount() {
-        this.called = true;
-        this.callCount += 1;
-        this.notCalled = false;
-        this.calledOnce = this.callCount == 1;
-        this.calledTwice = this.callCount == 2;
-        this.calledThrice = this.callCount == 3;
-    }
-
-    function createCallProperties() {
-        this.firstCall = this.getCall(0);
-        this.secondCall = this.getCall(1);
-        this.thirdCall = this.getCall(2);
-        this.lastCall = this.getCall(this.callCount - 1);
-    }
-
-    var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
-    function createProxy(func) {
-        // Retain the function length:
-        var p;
-        if (func.length) {
-            eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) +
-                ") { return p.invoke(func, this, slice.call(arguments)); });");
-        }
-        else {
-            p = function proxy() {
-                return p.invoke(func, this, slice.call(arguments));
-            };
-        }
-        return p;
-    }
-
-    var uuid = 0;
-
-    // Public API
-    var spyApi = {
-        reset: function () {
-            this.called = false;
-            this.notCalled = true;
-            this.calledOnce = false;
-            this.calledTwice = false;
-            this.calledThrice = false;
-            this.callCount = 0;
-            this.firstCall = null;
-            this.secondCall = null;
-            this.thirdCall = null;
-            this.lastCall = null;
-            this.args = [];
-            this.returnValues = [];
-            this.thisValues = [];
-            this.exceptions = [];
-            this.callIds = [];
-            if (this.fakes) {
-                for (var i = 0; i < this.fakes.length; i++) {
-                    this.fakes[i].reset();
-                }
-            }
-        },
-
-        create: function create(func) {
-            var name;
-
-            if (typeof func != "function") {
-                func = function () { };
-            } else {
-                name = sinon.functionName(func);
-            }
-
-            var proxy = createProxy(func);
-
-            sinon.extend(proxy, spy);
-            delete proxy.create;
-            sinon.extend(proxy, func);
-
-            proxy.reset();
-            proxy.prototype = func.prototype;
-            proxy.displayName = name || "spy";
-            proxy.toString = sinon.functionToString;
-            proxy._create = sinon.spy.create;
-            proxy.id = "spy#" + uuid++;
-
-            return proxy;
-        },
-
-        invoke: function invoke(func, thisValue, args) {
-            var matching = matchingFake(this.fakes, args);
-            var exception, returnValue;
-
-            incrementCallCount.call(this);
-            push.call(this.thisValues, thisValue);
-            push.call(this.args, args);
-            push.call(this.callIds, callId++);
-
-            try {
-                if (matching) {
-                    returnValue = matching.invoke(func, thisValue, args);
-                } else {
-                    returnValue = (this.func || func).apply(thisValue, args);
-                }
-
-                var thisCall = this.getCall(this.callCount - 1);
-                if (thisCall.calledWithNew() && typeof returnValue !== 'object') {
-                    returnValue = thisValue;
-                }
-            } catch (e) {
-                exception = e;
-            }
-
-            push.call(this.exceptions, exception);
-            push.call(this.returnValues, returnValue);
-
-            createCallProperties.call(this);
-
-            if (exception !== undefined) {
-                throw exception;
-            }
-
-            return returnValue;
-        },
-
-        getCall: function getCall(i) {
-            if (i < 0 || i >= this.callCount) {
-                return null;
-            }
-
-            return sinon.spyCall(this, this.thisValues[i], this.args[i],
-                                    this.returnValues[i], this.exceptions[i],
-                                    this.callIds[i]);
-        },
-
-        getCalls: function () {
-            var calls = [];
-            var i;
-
-            for (i = 0; i < this.callCount; i++) {
-                calls.push(this.getCall(i));
-            }
-
-            return calls;
-        },
-
-        calledBefore: function calledBefore(spyFn) {
-            if (!this.called) {
-                return false;
-            }
-
-            if (!spyFn.called) {
-                return true;
-            }
-
-            return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
-        },
-
-        calledAfter: function calledAfter(spyFn) {
-            if (!this.called || !spyFn.called) {
-                return false;
-            }
-
-            return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
-        },
-
-        withArgs: function () {
-            var args = slice.call(arguments);
-
-            if (this.fakes) {
-                var match = matchingFake(this.fakes, args, true);
-
-                if (match) {
-                    return match;
-                }
-            } else {
-                this.fakes = [];
-            }
-
-            var original = this;
-            var fake = this._create();
-            fake.matchingAguments = args;
-            fake.parent = this;
-            push.call(this.fakes, fake);
-
-            fake.withArgs = function () {
-                return original.withArgs.apply(original, arguments);
-            };
-
-            for (var i = 0; i < this.args.length; i++) {
-                if (fake.matches(this.args[i])) {
-                    incrementCallCount.call(fake);
-                    push.call(fake.thisValues, this.thisValues[i]);
-                    push.call(fake.args, this.args[i]);
-                    push.call(fake.returnValues, this.returnValues[i]);
-                    push.call(fake.exceptions, this.exceptions[i]);
-                    push.call(fake.callIds, this.callIds[i]);
-                }
-            }
-            createCallProperties.call(fake);
-
-            return fake;
-        },
-
-        matches: function (args, strict) {
-            var margs = this.matchingAguments;
-
-            if (margs.length <= args.length &&
-                sinon.deepEqual(margs, args.slice(0, margs.length))) {
-                return !strict || margs.length == args.length;
-            }
-        },
-
-        printf: function (format) {
-            var spy = this;
-            var args = slice.call(arguments, 1);
-            var formatter;
-
-            return (format || "").replace(/%(.)/g, function (match, specifyer) {
-                formatter = spyApi.formatters[specifyer];
-
-                if (typeof formatter == "function") {
-                    return formatter.call(null, spy, args);
-                } else if (!isNaN(parseInt(specifyer, 10))) {
-                    return sinon.format(args[specifyer - 1]);
-                }
-
-                return "%" + specifyer;
-            });
-        }
-    };
-
-    function delegateToCalls(method, matchAny, actual, notCalled) {
-        spyApi[method] = function () {
-            if (!this.called) {
-                if (notCalled) {
-                    return notCalled.apply(this, arguments);
-                }
-                return false;
-            }
-
-            var currentCall;
-            var matches = 0;
-
-            for (var i = 0, l = this.callCount; i < l; i += 1) {
-                currentCall = this.getCall(i);
-
-                if (currentCall[actual || method].apply(currentCall, arguments)) {
-                    matches += 1;
-
-                    if (matchAny) {
-                        return true;
-                    }
-                }
-            }
-
-            return matches === this.callCount;
-        };
-    }
-
-    delegateToCalls("calledOn", true);
-    delegateToCalls("alwaysCalledOn", false, "calledOn");
-    delegateToCalls("calledWith", true);
-    delegateToCalls("calledWithMatch", true);
-    delegateToCalls("alwaysCalledWith", false, "calledWith");
-    delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
-    delegateToCalls("calledWithExactly", true);
-    delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
-    delegateToCalls("neverCalledWith", false, "notCalledWith",
-        function () { return true; });
-    delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch",
-        function () { return true; });
-    delegateToCalls("threw", true);
-    delegateToCalls("alwaysThrew", false, "threw");
-    delegateToCalls("returned", true);
-    delegateToCalls("alwaysReturned", false, "returned");
-    delegateToCalls("calledWithNew", true);
-    delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
-    delegateToCalls("callArg", false, "callArgWith", function () {
-        throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
-    });
-    spyApi.callArgWith = spyApi.callArg;
-    delegateToCalls("callArgOn", false, "callArgOnWith", function () {
-        throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
-    });
-    spyApi.callArgOnWith = spyApi.callArgOn;
-    delegateToCalls("yield", false, "yield", function () {
-        throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
-    });
-    // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
-    spyApi.invokeCallback = spyApi.yield;
-    delegateToCalls("yieldOn", false, "yieldOn", function () {
-        throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
-    });
-    delegateToCalls("yieldTo", false, "yieldTo", function (property) {
-        throw new Error(this.toString() + " cannot yield to '" + property +
-            "' since it was not yet invoked.");
-    });
-    delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
-        throw new Error(this.toString() + " cannot yield to '" + property +
-            "' since it was not yet invoked.");
-    });
-
-    spyApi.formatters = {
-        "c": function (spy) {
-            return sinon.timesInWords(spy.callCount);
-        },
-
-        "n": function (spy) {
-            return spy.toString();
-        },
-
-        "C": function (spy) {
-            var calls = [];
-
-            for (var i = 0, l = spy.callCount; i < l; ++i) {
-                var stringifiedCall = "    " + spy.getCall(i).toString();
-                if (/\n/.test(calls[i - 1])) {
-                    stringifiedCall = "\n" + stringifiedCall;
-                }
-                push.call(calls, stringifiedCall);
-            }
-
-            return calls.length > 0 ? "\n" + calls.join("\n") : "";
-        },
-
-        "t": function (spy) {
-            var objects = [];
-
-            for (var i = 0, l = spy.callCount; i < l; ++i) {
-                push.call(objects, sinon.format(spy.thisValues[i]));
-            }
-
-            return objects.join(", ");
-        },
-
-        "*": function (spy, args) {
-            var formatted = [];
-
-            for (var i = 0, l = args.length; i < l; ++i) {
-                push.call(formatted, sinon.format(args[i]));
-            }
-
-            return formatted.join(", ");
-        }
-    };
-
-    sinon.extend(spy, spyApi);
-
-    spy.spyCall = sinon.spyCall;
-
-    if (commonJSModule) {
-        module.exports = spy;
-    } else {
-        sinon.spy = spy;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global module, require, sinon, process, setImmediate, setTimeout*/
-/**
- * Stub behavior
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Tim Fischbach (mail@timfischbach.de)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    var slice = Array.prototype.slice;
-    var join = Array.prototype.join;
-    var proto;
-
-    var nextTick = (function () {
-        if (typeof process === "object" && typeof process.nextTick === "function") {
-            return process.nextTick;
-        } else if (typeof setImmediate === "function") {
-            return setImmediate;
-        } else {
-            return function (callback) {
-                setTimeout(callback, 0);
-            };
-        }
-    })();
-
-    function throwsException(error, message) {
-        if (typeof error == "string") {
-            this.exception = new Error(message || "");
-            this.exception.name = error;
-        } else if (!error) {
-            this.exception = new Error("Error");
-        } else {
-            this.exception = error;
-        }
-
-        return this;
-    }
-
-    function getCallback(behavior, args) {
-        var callArgAt = behavior.callArgAt;
-
-        if (callArgAt < 0) {
-            var callArgProp = behavior.callArgProp;
-
-            for (var i = 0, l = args.length; i < l; ++i) {
-                if (!callArgProp && typeof args[i] == "function") {
-                    return args[i];
-                }
-
-                if (callArgProp && args[i] &&
-                    typeof args[i][callArgProp] == "function") {
-                    return args[i][callArgProp];
-                }
-            }
-
-            return null;
-        }
-
-        return args[callArgAt];
-    }
-
-    function getCallbackError(behavior, func, args) {
-        if (behavior.callArgAt < 0) {
-            var msg;
-
-            if (behavior.callArgProp) {
-                msg = sinon.functionName(behavior.stub) +
-                    " expected to yield to '" + behavior.callArgProp +
-                    "', but no object with such a property was passed.";
-            } else {
-                msg = sinon.functionName(behavior.stub) +
-                    " expected to yield, but no callback was passed.";
-            }
-
-            if (args.length > 0) {
-                msg += " Received [" + join.call(args, ", ") + "]";
-            }
-
-            return msg;
-        }
-
-        return "argument at index " + behavior.callArgAt + " is not a function: " + func;
-    }
-
-    function callCallback(behavior, args) {
-        if (typeof behavior.callArgAt == "number") {
-            var func = getCallback(behavior, args);
-
-            if (typeof func != "function") {
-                throw new TypeError(getCallbackError(behavior, func, args));
-            }
-
-            if (behavior.callbackAsync) {
-                nextTick(function() {
-                    func.apply(behavior.callbackContext, behavior.callbackArguments);
-                });
-            } else {
-                func.apply(behavior.callbackContext, behavior.callbackArguments);
-            }
-        }
-    }
-
-    proto = {
-        create: function(stub) {
-            var behavior = sinon.extend({}, sinon.behavior);
-            delete behavior.create;
-            behavior.stub = stub;
-
-            return behavior;
-        },
-
-        isPresent: function() {
-            return (typeof this.callArgAt == 'number' ||
-                    this.exception ||
-                    typeof this.returnArgAt == 'number' ||
-                    this.returnThis ||
-                    this.returnValueDefined);
-        },
-
-        invoke: function(context, args) {
-            callCallback(this, args);
-
-            if (this.exception) {
-                throw this.exception;
-            } else if (typeof this.returnArgAt == 'number') {
-                return args[this.returnArgAt];
-            } else if (this.returnThis) {
-                return context;
-            }
-
-            return this.returnValue;
-        },
-
-        onCall: function(index) {
-            return this.stub.onCall(index);
-        },
-
-        onFirstCall: function() {
-            return this.stub.onFirstCall();
-        },
-
-        onSecondCall: function() {
-            return this.stub.onSecondCall();
-        },
-
-        onThirdCall: function() {
-            return this.stub.onThirdCall();
-        },
-
-        withArgs: function(/* arguments */) {
-            throw new Error('Defining a stub by invoking "stub.onCall(...).withArgs(...)" is not supported. ' +
-                            'Use "stub.withArgs(...).onCall(...)" to define sequential behavior for calls with certain arguments.');
-        },
-
-        callsArg: function callsArg(pos) {
-            if (typeof pos != "number") {
-                throw new TypeError("argument index is not number");
-            }
-
-            this.callArgAt = pos;
-            this.callbackArguments = [];
-            this.callbackContext = undefined;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        callsArgOn: function callsArgOn(pos, context) {
-            if (typeof pos != "number") {
-                throw new TypeError("argument index is not number");
-            }
-            if (typeof context != "object") {
-                throw new TypeError("argument context is not an object");
-            }
-
-            this.callArgAt = pos;
-            this.callbackArguments = [];
-            this.callbackContext = context;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        callsArgWith: function callsArgWith(pos) {
-            if (typeof pos != "number") {
-                throw new TypeError("argument index is not number");
-            }
-
-            this.callArgAt = pos;
-            this.callbackArguments = slice.call(arguments, 1);
-            this.callbackContext = undefined;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        callsArgOnWith: function callsArgWith(pos, context) {
-            if (typeof pos != "number") {
-                throw new TypeError("argument index is not number");
-            }
-            if (typeof context != "object") {
-                throw new TypeError("argument context is not an object");
-            }
-
-            this.callArgAt = pos;
-            this.callbackArguments = slice.call(arguments, 2);
-            this.callbackContext = context;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        yields: function () {
-            this.callArgAt = -1;
-            this.callbackArguments = slice.call(arguments, 0);
-            this.callbackContext = undefined;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        yieldsOn: function (context) {
-            if (typeof context != "object") {
-                throw new TypeError("argument context is not an object");
-            }
-
-            this.callArgAt = -1;
-            this.callbackArguments = slice.call(arguments, 1);
-            this.callbackContext = context;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        yieldsTo: function (prop) {
-            this.callArgAt = -1;
-            this.callbackArguments = slice.call(arguments, 1);
-            this.callbackContext = undefined;
-            this.callArgProp = prop;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        yieldsToOn: function (prop, context) {
-            if (typeof context != "object") {
-                throw new TypeError("argument context is not an object");
-            }
-
-            this.callArgAt = -1;
-            this.callbackArguments = slice.call(arguments, 2);
-            this.callbackContext = context;
-            this.callArgProp = prop;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-
-        "throws": throwsException,
-        throwsException: throwsException,
-
-        returns: function returns(value) {
-            this.returnValue = value;
-            this.returnValueDefined = true;
-
-            return this;
-        },
-
-        returnsArg: function returnsArg(pos) {
-            if (typeof pos != "number") {
-                throw new TypeError("argument index is not number");
-            }
-
-            this.returnArgAt = pos;
-
-            return this;
-        },
-
-        returnsThis: function returnsThis() {
-            this.returnThis = true;
-
-            return this;
-        }
-    };
-
-    // create asynchronous versions of callsArg* and yields* methods
-    for (var method in proto) {
-        // need to avoid creating anotherasync versions of the newly added async methods
-        if (proto.hasOwnProperty(method) &&
-            method.match(/^(callsArg|yields)/) &&
-            !method.match(/Async/)) {
-            proto[method + 'Async'] = (function (syncFnName) {
-                return function () {
-                    var result = this[syncFnName].apply(this, arguments);
-                    this.callbackAsync = true;
-                    return result;
-                };
-            })(method);
-        }
-    }
-
-    if (commonJSModule) {
-        module.exports = proto;
-    } else {
-        sinon.behavior = proto;
-    }
-}(typeof sinon == "object" && sinon || null));
-/**
- * @depend ../sinon.js
- * @depend spy.js
- * @depend behavior.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global module, require, sinon*/
-/**
- * Stub functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function stub(object, property, func) {
-        if (!!func && typeof func != "function") {
-            throw new TypeError("Custom stub should be function");
-        }
-
-        var wrapper;
-
-        if (func) {
-            wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
-        } else {
-            wrapper = stub.create();
-        }
-
-        if (!object && typeof property === "undefined") {
-            return sinon.stub.create();
-        }
-
-        if (typeof property === "undefined" && typeof object == "object") {
-            for (var prop in object) {
-                if (typeof object[prop] === "function") {
-                    stub(object, prop);
-                }
-            }
-
-            return object;
-        }
-
-        return sinon.wrapMethod(object, property, wrapper);
-    }
-
-    function getDefaultBehavior(stub) {
-        return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub);
-    }
-
-    function getParentBehaviour(stub) {
-        return (stub.parent && getCurrentBehavior(stub.parent));
-    }
-
-    function getCurrentBehavior(stub) {
-        var behavior = stub.behaviors[stub.callCount - 1];
-        return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub);
-    }
-
-    var uuid = 0;
-
-    sinon.extend(stub, (function () {
-        var proto = {
-            create: function create() {
-                var functionStub = function () {
-                    return getCurrentBehavior(functionStub).invoke(this, arguments);
-                };
-
-                functionStub.id = "stub#" + uuid++;
-                var orig = functionStub;
-                functionStub = sinon.spy.create(functionStub);
-                functionStub.func = orig;
-
-                sinon.extend(functionStub, stub);
-                functionStub._create = sinon.stub.create;
-                functionStub.displayName = "stub";
-                functionStub.toString = sinon.functionToString;
-
-                functionStub.defaultBehavior = null;
-                functionStub.behaviors = [];
-
-                return functionStub;
-            },
-
-            resetBehavior: function () {
-                var i;
-
-                this.defaultBehavior = null;
-                this.behaviors = [];
-
-                delete this.returnValue;
-                delete this.returnArgAt;
-                this.returnThis = false;
-
-                if (this.fakes) {
-                    for (i = 0; i < this.fakes.length; i++) {
-                        this.fakes[i].resetBehavior();
-                    }
-                }
-            },
-
-            onCall: function(index) {
-                if (!this.behaviors[index]) {
-                    this.behaviors[index] = sinon.behavior.create(this);
-                }
-
-                return this.behaviors[index];
-            },
-
-            onFirstCall: function() {
-                return this.onCall(0);
-            },
-
-            onSecondCall: function() {
-                return this.onCall(1);
-            },
-
-            onThirdCall: function() {
-                return this.onCall(2);
-            }
-        };
-
-        for (var method in sinon.behavior) {
-            if (sinon.behavior.hasOwnProperty(method) &&
-                !proto.hasOwnProperty(method) &&
-                method != 'create' &&
-                method != 'withArgs' &&
-                method != 'invoke') {
-                proto[method] = (function(behaviorMethod) {
-                    return function() {
-                        this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
-                        this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
-                        return this;
-                    };
-                }(method));
-            }
-        }
-
-        return proto;
-    }()));
-
-    if (commonJSModule) {
-        module.exports = stub;
-    } else {
-        sinon.stub = stub;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- */
-/*jslint eqeqeq: false, onevar: false, nomen: false*/
-/*global module, require, sinon*/
-/**
- * Mock functions.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    var push = [].push;
-    var match;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    match = sinon.match;
-
-    if (!match && commonJSModule) {
-        match = require("./match");
-    }
-
-    function mock(object) {
-        if (!object) {
-            return sinon.expectation.create("Anonymous mock");
-        }
-
-        return mock.create(object);
-    }
-
-    sinon.mock = mock;
-
-    sinon.extend(mock, (function () {
-        function each(collection, callback) {
-            if (!collection) {
-                return;
-            }
-
-            for (var i = 0, l = collection.length; i < l; i += 1) {
-                callback(collection[i]);
-            }
-        }
-
-        return {
-            create: function create(object) {
-                if (!object) {
-                    throw new TypeError("object is null");
-                }
-
-                var mockObject = sinon.extend({}, mock);
-                mockObject.object = object;
-                delete mockObject.create;
-
-                return mockObject;
-            },
-
-            expects: function expects(method) {
-                if (!method) {
-                    throw new TypeError("method is falsy");
-                }
-
-                if (!this.expectations) {
-                    this.expectations = {};
-                    this.proxies = [];
-                }
-
-                if (!this.expectations[method]) {
-                    this.expectations[method] = [];
-                    var mockObject = this;
-
-                    sinon.wrapMethod(this.object, method, function () {
-                        return mockObject.invokeMethod(method, this, arguments);
-                    });
-
-                    push.call(this.proxies, method);
-                }
-
-                var expectation = sinon.expectation.create(method);
-                push.call(this.expectations[method], expectation);
-
-                return expectation;
-            },
-
-            restore: function restore() {
-                var object = this.object;
-
-                each(this.proxies, function (proxy) {
-                    if (typeof object[proxy].restore == "function") {
-                        object[proxy].restore();
-                    }
-                });
-            },
-
-            verify: function verify() {
-                var expectations = this.expectations || {};
-                var messages = [], met = [];
-
-                each(this.proxies, function (proxy) {
-                    each(expectations[proxy], function (expectation) {
-                        if (!expectation.met()) {
-                            push.call(messages, expectation.toString());
-                        } else {
-                            push.call(met, expectation.toString());
-                        }
-                    });
-                });
-
-                this.restore();
-
-                if (messages.length > 0) {
-                    sinon.expectation.fail(messages.concat(met).join("\n"));
-                } else {
-                    sinon.expectation.pass(messages.concat(met).join("\n"));
-                }
-
-                return true;
-            },
-
-            invokeMethod: function invokeMethod(method, thisValue, args) {
-                var expectations = this.expectations && this.expectations[method];
-                var length = expectations && expectations.length || 0, i;
-
-                for (i = 0; i < length; i += 1) {
-                    if (!expectations[i].met() &&
-                        expectations[i].allowsCall(thisValue, args)) {
-                        return expectations[i].apply(thisValue, args);
-                    }
-                }
-
-                var messages = [], available, exhausted = 0;
-
-                for (i = 0; i < length; i += 1) {
-                    if (expectations[i].allowsCall(thisValue, args)) {
-                        available = available || expectations[i];
-                    } else {
-                        exhausted += 1;
-                    }
-                    push.call(messages, "    " + expectations[i].toString());
-                }
-
-                if (exhausted === 0) {
-                    return available.apply(thisValue, args);
-                }
-
-                messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
-                    proxy: method,
-                    args: args
-                }));
-
-                sinon.expectation.fail(messages.join("\n"));
-            }
-        };
-    }()));
-
-    var times = sinon.timesInWords;
-
-    sinon.expectation = (function () {
-        var slice = Array.prototype.slice;
-        var _invoke = sinon.spy.invoke;
-
-        function callCountInWords(callCount) {
-            if (callCount == 0) {
-                return "never called";
-            } else {
-                return "called " + times(callCount);
-            }
-        }
-
-        function expectedCallCountInWords(expectation) {
-            var min = expectation.minCalls;
-            var max = expectation.maxCalls;
-
-            if (typeof min == "number" && typeof max == "number") {
-                var str = times(min);
-
-                if (min != max) {
-                    str = "at least " + str + " and at most " + times(max);
-                }
-
-                return str;
-            }
-
-            if (typeof min == "number") {
-                return "at least " + times(min);
-            }
-
-            return "at most " + times(max);
-        }
-
-        function receivedMinCalls(expectation) {
-            var hasMinLimit = typeof expectation.minCalls == "number";
-            return !hasMinLimit || expectation.callCount >= expectation.minCalls;
-        }
-
-        function receivedMaxCalls(expectation) {
-            if (typeof expectation.maxCalls != "number") {
-                return false;
-            }
-
-            return expectation.callCount == expectation.maxCalls;
-        }
-
-        function verifyMatcher(possibleMatcher, arg){
-            if (match && match.isMatcher(possibleMatcher)) {
-                return possibleMatcher.test(arg);
-            } else {
-                return true;
-            }
-        }
-
-        return {
-            minCalls: 1,
-            maxCalls: 1,
-
-            create: function create(methodName) {
-                var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
-                delete expectation.create;
-                expectation.method = methodName;
-
-                return expectation;
-            },
-
-            invoke: function invoke(func, thisValue, args) {
-                this.verifyCallAllowed(thisValue, args);
-
-                return _invoke.apply(this, arguments);
-            },
-
-            atLeast: function atLeast(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not number");
-                }
-
-                if (!this.limitsSet) {
-                    this.maxCalls = null;
-                    this.limitsSet = true;
-                }
-
-                this.minCalls = num;
-
-                return this;
-            },
-
-            atMost: function atMost(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not number");
-                }
-
-                if (!this.limitsSet) {
-                    this.minCalls = null;
-                    this.limitsSet = true;
-                }
-
-                this.maxCalls = num;
-
-                return this;
-            },
-
-            never: function never() {
-                return this.exactly(0);
-            },
-
-            once: function once() {
-                return this.exactly(1);
-            },
-
-            twice: function twice() {
-                return this.exactly(2);
-            },
-
-            thrice: function thrice() {
-                return this.exactly(3);
-            },
-
-            exactly: function exactly(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not a number");
-                }
-
-                this.atLeast(num);
-                return this.atMost(num);
-            },
-
-            met: function met() {
-                return !this.failed && receivedMinCalls(this);
-            },
-
-            verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
-                if (receivedMaxCalls(this)) {
-                    this.failed = true;
-                    sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
-                }
-
-                if ("expectedThis" in this && this.expectedThis !== thisValue) {
-                    sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
-                        this.expectedThis);
-                }
-
-                if (!("expectedArguments" in this)) {
-                    return;
-                }
-
-                if (!args) {
-                    sinon.expectation.fail(this.method + " received no arguments, expected " +
-                        sinon.format(this.expectedArguments));
-                }
-
-                if (args.length < this.expectedArguments.length) {
-                    sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
-                        "), expected " + sinon.format(this.expectedArguments));
-                }
-
-                if (this.expectsExactArgCount &&
-                    args.length != this.expectedArguments.length) {
-                    sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
-                        "), expected " + sinon.format(this.expectedArguments));
-                }
-
-                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
-
-                    if (!verifyMatcher(this.expectedArguments[i],args[i])) {
-                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
-                            ", didn't match " + this.expectedArguments.toString());
-                    }
-
-                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
-                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
-                            ", expected " + sinon.format(this.expectedArguments));
-                    }
-                }
-            },
-
-            allowsCall: function allowsCall(thisValue, args) {
-                if (this.met() && receivedMaxCalls(this)) {
-                    return false;
-                }
-
-                if ("expectedThis" in this && this.expectedThis !== thisValue) {
-                    return false;
-                }
-
-                if (!("expectedArguments" in this)) {
-                    return true;
-                }
-
-                args = args || [];
-
-                if (args.length < this.expectedArguments.length) {
-                    return false;
-                }
-
-                if (this.expectsExactArgCount &&
-                    args.length != this.expectedArguments.length) {
-                    return false;
-                }
-
-                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
-                    if (!verifyMatcher(this.expectedArguments[i],args[i])) {
-                        return false;
-                    }
-
-                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
-                        return false;
-                    }
-                }
-
-                return true;
-            },
-
-            withArgs: function withArgs() {
-                this.expectedArguments = slice.call(arguments);
-                return this;
-            },
-
-            withExactArgs: function withExactArgs() {
-                this.withArgs.apply(this, arguments);
-                this.expectsExactArgCount = true;
-                return this;
-            },
-
-            on: function on(thisValue) {
-                this.expectedThis = thisValue;
-                return this;
-            },
-
-            toString: function () {
-                var args = (this.expectedArguments || []).slice();
-
-                if (!this.expectsExactArgCount) {
-                    push.call(args, "[...]");
-                }
-
-                var callStr = sinon.spyCall.toString.call({
-                    proxy: this.method || "anonymous mock expectation",
-                    args: args
-                });
-
-                var message = callStr.replace(", [...", "[, ...") + " " +
-                    expectedCallCountInWords(this);
-
-                if (this.met()) {
-                    return "Expectation met: " + message;
-                }
-
-                return "Expected " + message + " (" +
-                    callCountInWords(this.callCount) + ")";
-            },
-
-            verify: function verify() {
-                if (!this.met()) {
-                    sinon.expectation.fail(this.toString());
-                } else {
-                    sinon.expectation.pass(this.toString());
-                }
-
-                return true;
-            },
-
-            pass: function(message) {
-              sinon.assert.pass(message);
-            },
-            fail: function (message) {
-                var exception = new Error(message);
-                exception.name = "ExpectationError";
-
-                throw exception;
-            }
-        };
-    }());
-
-    if (commonJSModule) {
-        module.exports = mock;
-    } else {
-        sinon.mock = mock;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- * @depend mock.js
- */
-/*jslint eqeqeq: false, onevar: false, forin: true*/
-/*global module, require, sinon*/
-/**
- * Collections of stubs, spies and mocks.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    var push = [].push;
-    var hasOwnProperty = Object.prototype.hasOwnProperty;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function getFakes(fakeCollection) {
-        if (!fakeCollection.fakes) {
-            fakeCollection.fakes = [];
-        }
-
-        return fakeCollection.fakes;
-    }
-
-    function each(fakeCollection, method) {
-        var fakes = getFakes(fakeCollection);
-
-        for (var i = 0, l = fakes.length; i < l; i += 1) {
-            if (typeof fakes[i][method] == "function") {
-                fakes[i][method]();
-            }
-        }
-    }
-
-    function compact(fakeCollection) {
-        var fakes = getFakes(fakeCollection);
-        var i = 0;
-        while (i < fakes.length) {
-          fakes.splice(i, 1);
-        }
-    }
-
-    var collection = {
-        verify: function resolve() {
-            each(this, "verify");
-        },
-
-        restore: function restore() {
-            each(this, "restore");
-            compact(this);
-        },
-
-        verifyAndRestore: function verifyAndRestore() {
-            var exception;
-
-            try {
-                this.verify();
-            } catch (e) {
-                exception = e;
-            }
-
-            this.restore();
-
-            if (exception) {
-                throw exception;
-            }
-        },
-
-        add: function add(fake) {
-            push.call(getFakes(this), fake);
-            return fake;
-        },
-
-        spy: function spy() {
-            return this.add(sinon.spy.apply(sinon, arguments));
-        },
-
-        stub: function stub(object, property, value) {
-            if (property) {
-                var original = object[property];
-
-                if (typeof original != "function") {
-                    if (!hasOwnProperty.call(object, property)) {
-                        throw new TypeError("Cannot stub non-existent own property " + property);
-                    }
-
-                    object[property] = value;
-
-                    return this.add({
-                        restore: function () {
-                            object[property] = original;
-                        }
-                    });
-                }
-            }
-            if (!property && !!object && typeof object == "object") {
-                var stubbedObj = sinon.stub.apply(sinon, arguments);
-
-                for (var prop in stubbedObj) {
-                    if (typeof stubbedObj[prop] === "function") {
-                        this.add(stubbedObj[prop]);
-                    }
-                }
-
-                return stubbedObj;
-            }
-
-            return this.add(sinon.stub.apply(sinon, arguments));
-        },
-
-        mock: function mock() {
-            return this.add(sinon.mock.apply(sinon, arguments));
-        },
-
-        inject: function inject(obj) {
-            var col = this;
-
-            obj.spy = function () {
-                return col.spy.apply(col, arguments);
-            };
-
-            obj.stub = function () {
-                return col.stub.apply(col, arguments);
-            };
-
-            obj.mock = function () {
-                return col.mock.apply(col, arguments);
-            };
-
-            return obj;
-        }
-    };
-
-    if (commonJSModule) {
-        module.exports = collection;
-    } else {
-        sinon.collection = collection;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
-/*global module, require, window*/
-/**
- * Fake timer API
- * setTimeout
- * setInterval
- * clearTimeout
- * clearInterval
- * tick
- * reset
- * Date
- *
- * Inspired by jsUnitMockTimeOut from JsUnit
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    var sinon = {};
-}
-
-(function (global) {
-    var id = 1;
-
-    function addTimer(args, recurring) {
-        if (args.length === 0) {
-            throw new Error("Function requires at least 1 parameter");
-        }
-
-        if (typeof args[0] === "undefined") {
-            throw new Error("Callback must be provided to timer calls");
-        }
-
-        var toId = id++;
-        var delay = args[1] || 0;
-
-        if (!this.timeouts) {
-            this.timeouts = {};
-        }
-
-        this.timeouts[toId] = {
-            id: toId,
-            func: args[0],
-            callAt: this.now + delay,
-            invokeArgs: Array.prototype.slice.call(args, 2)
-        };
-
-        if (recurring === true) {
-            this.timeouts[toId].interval = delay;
-        }
-
-        return toId;
-    }
-
-    function parseTime(str) {
-        if (!str) {
-            return 0;
-        }
-
-        var strings = str.split(":");
-        var l = strings.length, i = l;
-        var ms = 0, parsed;
-
-        if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
-            throw new Error("tick only understands numbers and 'h:m:s'");
-        }
-
-        while (i--) {
-            parsed = parseInt(strings[i], 10);
-
-            if (parsed >= 60) {
-                throw new Error("Invalid time " + str);
-            }
-
-            ms += parsed * Math.pow(60, (l - i - 1));
-        }
-
-        return ms * 1000;
-    }
-
-    function createObject(object) {
-        var newObject;
-
-        if (Object.create) {
-            newObject = Object.create(object);
-        } else {
-            var F = function () {};
-            F.prototype = object;
-            newObject = new F();
-        }
-
-        newObject.Date.clock = newObject;
-        return newObject;
-    }
-
-    sinon.clock = {
-        now: 0,
-
-        create: function create(now) {
-            var clock = createObject(this);
-
-            if (typeof now == "number") {
-                clock.now = now;
-            }
-
-            if (!!now && typeof now == "object") {
-                throw new TypeError("now should be milliseconds since UNIX epoch");
-            }
-
-            return clock;
-        },
-
-        setTimeout: function setTimeout(callback, timeout) {
-            return addTimer.call(this, arguments, false);
-        },
-
-        clearTimeout: function clearTimeout(timerId) {
-            if (!this.timeouts) {
-                this.timeouts = [];
-            }
-
-            if (timerId in this.timeouts) {
-                delete this.timeouts[timerId];
-            }
-        },
-
-        setInterval: function setInterval(callback, timeout) {
-            return addTimer.call(this, arguments, true);
-        },
-
-        clearInterval: function clearInterval(timerId) {
-            this.clearTimeout(timerId);
-        },
-
-        setImmediate: function setImmediate(callback) {
-            var passThruArgs = Array.prototype.slice.call(arguments, 1);
-
-            return addTimer.call(this, [callback, 0].concat(passThruArgs), false);
-        },
-
-        clearImmediate: function clearImmediate(timerId) {
-            this.clearTimeout(timerId);
-        },
-
-        tick: function tick(ms) {
-            ms = typeof ms == "number" ? ms : parseTime(ms);
-            var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
-            var timer = this.firstTimerInRange(tickFrom, tickTo);
-
-            var firstException;
-            while (timer && tickFrom <= tickTo) {
-                if (this.timeouts[timer.id]) {
-                    tickFrom = this.now = timer.callAt;
-                    try {
-                      this.callTimer(timer);
-                    } catch (e) {
-                      firstException = firstException || e;
-                    }
-                }
-
-                timer = this.firstTimerInRange(previous, tickTo);
-                previous = tickFrom;
-            }
-
-            this.now = tickTo;
-
-            if (firstException) {
-              throw firstException;
-            }
-
-            return this.now;
-        },
-
-        firstTimerInRange: function (from, to) {
-            var timer, smallest = null, originalTimer;
-
-            for (var id in this.timeouts) {
-                if (this.timeouts.hasOwnProperty(id)) {
-                    if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
-                        continue;
-                    }
-
-                    if (smallest === null || this.timeouts[id].callAt < smallest) {
-                        originalTimer = this.timeouts[id];
-                        smallest = this.timeouts[id].callAt;
-
-                        timer = {
-                            func: this.timeouts[id].func,
-                            callAt: this.timeouts[id].callAt,
-                            interval: this.timeouts[id].interval,
-                            id: this.timeouts[id].id,
-                            invokeArgs: this.timeouts[id].invokeArgs
-                        };
-                    }
-                }
-            }
-
-            return timer || null;
-        },
-
-        callTimer: function (timer) {
-            if (typeof timer.interval == "number") {
-                this.timeouts[timer.id].callAt += timer.interval;
-            } else {
-                delete this.timeouts[timer.id];
-            }
-
-            try {
-                if (typeof timer.func == "function") {
-                    timer.func.apply(null, timer.invokeArgs);
-                } else {
-                    eval(timer.func);
-                }
-            } catch (e) {
-              var exception = e;
-            }
-
-            if (!this.timeouts[timer.id]) {
-                if (exception) {
-                  throw exception;
-                }
-                return;
-            }
-
-            if (exception) {
-              throw exception;
-            }
-        },
-
-        reset: function reset() {
-            this.timeouts = {};
-        },
-
-        Date: (function () {
-            var NativeDate = Date;
-
-            function ClockDate(year, month, date, hour, minute, second, ms) {
-                // Defensive and verbose to avoid potential harm in passing
-                // explicit undefined when user does not pass argument
-                switch (arguments.length) {
-                case 0:
-                    return new NativeDate(ClockDate.clock.now);
-                case 1:
-                    return new NativeDate(year);
-                case 2:
-                    return new NativeDate(year, month);
-                case 3:
-                    return new NativeDate(year, month, date);
-                case 4:
-                    return new NativeDate(year, month, date, hour);
-                case 5:
-                    return new NativeDate(year, month, date, hour, minute);
-                case 6:
-                    return new NativeDate(year, month, date, hour, minute, second);
-                default:
-                    return new NativeDate(year, month, date, hour, minute, second, ms);
-                }
-            }
-
-            return mirrorDateProperties(ClockDate, NativeDate);
-        }())
-    };
-
-    function mirrorDateProperties(target, source) {
-        if (source.now) {
-            target.now = function now() {
-                return target.clock.now;
-            };
-        } else {
-            delete target.now;
-        }
-
-        if (source.toSource) {
-            target.toSource = function toSource() {
-                return source.toSource();
-            };
-        } else {
-            delete target.toSource;
-        }
-
-        target.toString = function toString() {
-            return source.toString();
-        };
-
-        target.prototype = source.prototype;
-        target.parse = source.parse;
-        target.UTC = source.UTC;
-        target.prototype.toUTCString = source.prototype.toUTCString;
-
-        for (var prop in source) {
-            if (source.hasOwnProperty(prop)) {
-                target[prop] = source[prop];
-            }
-        }
-
-        return target;
-    }
-
-    var methods = ["Date", "setTimeout", "setInterval",
-                   "clearTimeout", "clearInterval"];
-
-    if (typeof global.setImmediate !== "undefined") {
-        methods.push("setImmediate");
-    }
-
-    if (typeof global.clearImmediate !== "undefined") {
-        methods.push("clearImmediate");
-    }
-
-    function restore() {
-        var method;
-
-        for (var i = 0, l = this.methods.length; i < l; i++) {
-            method = this.methods[i];
-
-            if (global[method].hadOwnProperty) {
-                global[method] = this["_" + method];
-            } else {
-                try {
-                    delete global[method];
-                } catch (e) {}
-            }
-        }
-
-        // Prevent multiple executions which will completely remove these props
-        this.methods = [];
-    }
-
-    function stubGlobal(method, clock) {
-        clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(global, method);
-        clock["_" + method] = global[method];
-
-        if (method == "Date") {
-            var date = mirrorDateProperties(clock[method], global[method]);
-            global[method] = date;
-        } else {
-            global[method] = function () {
-                return clock[method].apply(clock, arguments);
-            };
-
-            for (var prop in clock[method]) {
-                if (clock[method].hasOwnProperty(prop)) {
-                    global[method][prop] = clock[method][prop];
-                }
-            }
-        }
-
-        global[method].clock = clock;
-    }
-
-    sinon.useFakeTimers = function useFakeTimers(now) {
-        var clock = sinon.clock.create(now);
-        clock.restore = restore;
-        clock.methods = Array.prototype.slice.call(arguments,
-                                                   typeof now == "number" ? 1 : 0);
-
-        if (clock.methods.length === 0) {
-            clock.methods = methods;
-        }
-
-        for (var i = 0, l = clock.methods.length; i < l; i++) {
-            stubGlobal(clock.methods[i], clock);
-        }
-
-        return clock;
-    };
-}(typeof global != "undefined" && typeof global !== "function" ? global : this));
-
-sinon.timers = {
-    setTimeout: setTimeout,
-    clearTimeout: clearTimeout,
-    setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
-    clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
-    setInterval: setInterval,
-    clearInterval: clearInterval,
-    Date: Date
-};
-
-if (typeof module !== 'undefined' && module.exports) {
-    module.exports = sinon;
-}
-
-/*jslint eqeqeq: false, onevar: false*/
-/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
-/**
- * Minimal Event interface implementation
- *
- * Original implementation by Sven Fuchs: https://gist.github.com/995028
- * Modifications and tests by Christian Johansen.
- *
- * @author Sven Fuchs (svenfuchs@artweb-design.de)
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2011 Sven Fuchs, Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    this.sinon = {};
-}
-
-(function () {
-    var push = [].push;
-
-    sinon.Event = function Event(type, bubbles, cancelable, target) {
-        this.initEvent(type, bubbles, cancelable, target);
-    };
-
-    sinon.Event.prototype = {
-        initEvent: function(type, bubbles, cancelable, target) {
-            this.type = type;
-            this.bubbles = bubbles;
-            this.cancelable = cancelable;
-            this.target = target;
-        },
-
-        stopPropagation: function () {},
-
-        preventDefault: function () {
-            this.defaultPrevented = true;
-        }
-    };
-
-    sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
-        this.initEvent(type, false, false, target);
-        this.loaded = progressEventRaw.loaded || null;
-        this.total = progressEventRaw.total || null;
-    };
-
-    sinon.ProgressEvent.prototype = new sinon.Event();
-
-    sinon.ProgressEvent.prototype.constructor =  sinon.ProgressEvent;
-
-    sinon.CustomEvent = function CustomEvent(type, customData, target) {
-        this.initEvent(type, false, false, target);
-        this.detail = customData.detail || null;
-    };
-
-    sinon.CustomEvent.prototype = new sinon.Event();
-
-    sinon.CustomEvent.prototype.constructor =  sinon.CustomEvent;
-
-    sinon.EventTarget = {
-        addEventListener: function addEventListener(event, listener) {
-            this.eventListeners = this.eventListeners || {};
-            this.eventListeners[event] = this.eventListeners[event] || [];
-            push.call(this.eventListeners[event], listener);
-        },
-
-        removeEventListener: function removeEventListener(event, listener) {
-            var listeners = this.eventListeners && this.eventListeners[event] || [];
-
-            for (var i = 0, l = listeners.length; i < l; ++i) {
-                if (listeners[i] == listener) {
-                    return listeners.splice(i, 1);
-                }
-            }
-        },
-
-        dispatchEvent: function dispatchEvent(event) {
-            var type = event.type;
-            var listeners = this.eventListeners && this.eventListeners[type] || [];
-
-            for (var i = 0; i < listeners.length; i++) {
-                if (typeof listeners[i] == "function") {
-                    listeners[i].call(this, event);
-                } else {
-                    listeners[i].handleEvent(event);
-                }
-            }
-
-            return !!event.defaultPrevented;
-        }
-    };
-}());
-
-/**
- * @depend ../../sinon.js
- * @depend event.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
-/**
- * Fake XMLHttpRequest object
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-// wrapper for global
-(function(global) {
-    if (typeof sinon === "undefined") {
-        global.sinon = {};
-    }
-
-    var supportsProgress = typeof ProgressEvent !== "undefined";
-    var supportsCustomEvent = typeof CustomEvent !== "undefined";
-    sinon.xhr = { XMLHttpRequest: global.XMLHttpRequest };
-    var xhr = sinon.xhr;
-    xhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
-    xhr.GlobalActiveXObject = global.ActiveXObject;
-    xhr.supportsActiveX = typeof xhr.GlobalActiveXObject != "undefined";
-    xhr.supportsXHR = typeof xhr.GlobalXMLHttpRequest != "undefined";
-    xhr.workingXHR = xhr.supportsXHR ? xhr.GlobalXMLHttpRequest : xhr.supportsActiveX
-                                     ? function() { return new xhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
-    xhr.supportsCORS = 'withCredentials' in (new sinon.xhr.GlobalXMLHttpRequest());
-
-    /*jsl:ignore*/
-    var unsafeHeaders = {
-        "Accept-Charset": true,
-        "Accept-Encoding": true,
-        "Connection": true,
-        "Content-Length": true,
-        "Cookie": true,
-        "Cookie2": true,
-        "Content-Transfer-Encoding": true,
-        "Date": true,
-        "Expect": true,
-        "Host": true,
-        "Keep-Alive": true,
-        "Referer": true,
-        "TE": true,
-        "Trailer": true,
-        "Transfer-Encoding": true,
-        "Upgrade": true,
-        "User-Agent": true,
-        "Via": true
-    };
-    /*jsl:end*/
-
-    function FakeXMLHttpRequest() {
-        this.readyState = FakeXMLHttpRequest.UNSENT;
-        this.requestHeaders = {};
-        this.requestBody = null;
-        this.status = 0;
-        this.statusText = "";
-        this.upload = new UploadProgress();
-        if (sinon.xhr.supportsCORS) {
-            this.withCredentials = false;
-        }
-
-
-        var xhr = this;
-        var events = ["loadstart", "load", "abort", "loadend"];
-
-        function addEventListener(eventName) {
-            xhr.addEventListener(eventName, function (event) {
-                var listener = xhr["on" + eventName];
-
-                if (listener && typeof listener == "function") {
-                    listener.call(this, event);
-                }
-            });
-        }
-
-        for (var i = events.length - 1; i >= 0; i--) {
-            addEventListener(events[i]);
-        }
-
-        if (typeof FakeXMLHttpRequest.onCreate == "function") {
-            FakeXMLHttpRequest.onCreate(this);
-        }
-    }
-
-    // An upload object is created for each
-    // FakeXMLHttpRequest and allows upload
-    // events to be simulated using uploadProgress
-    // and uploadError.
-    function UploadProgress() {
-        this.eventListeners = {
-            "progress": [],
-            "load": [],
-            "abort": [],
-            "error": []
-        }
-    }
-
-    UploadProgress.prototype.addEventListener = function(event, listener) {
-        this.eventListeners[event].push(listener);
-    };
-
-    UploadProgress.prototype.removeEventListener = function(event, listener) {
-        var listeners = this.eventListeners[event] || [];
-
-        for (var i = 0, l = listeners.length; i < l; ++i) {
-            if (listeners[i] == listener) {
-                return listeners.splice(i, 1);
-            }
-        }
-    };
-
-    UploadProgress.prototype.dispatchEvent = function(event) {
-        var listeners = this.eventListeners[event.type] || [];
-
-        for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
-            listener(event);
-        }
-    };
-
-    function verifyState(xhr) {
-        if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
-            throw new Error("INVALID_STATE_ERR");
-        }
-
-        if (xhr.sendFlag) {
-            throw new Error("INVALID_STATE_ERR");
-        }
-    }
-
-    // filtering to enable a white-list version of Sinon FakeXhr,
-    // where whitelisted requests are passed through to real XHR
-    function each(collection, callback) {
-        if (!collection) return;
-        for (var i = 0, l = collection.length; i < l; i += 1) {
-            callback(collection[i]);
-        }
-    }
-    function some(collection, callback) {
-        for (var index = 0; index < collection.length; index++) {
-            if(callback(collection[index]) === true) return true;
-        }
-        return false;
-    }
-    // largest arity in XHR is 5 - XHR#open
-    var apply = function(obj,method,args) {
-        switch(args.length) {
-        case 0: return obj[method]();
-        case 1: return obj[method](args[0]);
-        case 2: return obj[method](args[0],args[1]);
-        case 3: return obj[method](args[0],args[1],args[2]);
-        case 4: return obj[method](args[0],args[1],args[2],args[3]);
-        case 5: return obj[method](args[0],args[1],args[2],args[3],args[4]);
-        }
-    };
-
-    FakeXMLHttpRequest.filters = [];
-    FakeXMLHttpRequest.addFilter = function(fn) {
-        this.filters.push(fn)
-    };
-    var IE6Re = /MSIE 6/;
-    FakeXMLHttpRequest.defake = function(fakeXhr,xhrArgs) {
-        var xhr = new sinon.xhr.workingXHR();
-        each(["open","setRequestHeader","send","abort","getResponseHeader",
-              "getAllResponseHeaders","addEventListener","overrideMimeType","removeEventListener"],
-             function(method) {
-                 fakeXhr[method] = function() {
-                   return apply(xhr,method,arguments);
-                 };
-             });
-
-        var copyAttrs = function(args) {
-            each(args, function(attr) {
-              try {
-                fakeXhr[attr] = xhr[attr]
-              } catch(e) {
-                if(!IE6Re.test(navigator.userAgent)) throw e;
-              }
-            });
-        };
-
-        var stateChange = function() {
-            fakeXhr.readyState = xhr.readyState;
-            if(xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                copyAttrs(["status","statusText"]);
-            }
-            if(xhr.readyState >= FakeXMLHttpRequest.LOADING) {
-                copyAttrs(["responseText"]);
-            }
-            if(xhr.readyState === FakeXMLHttpRequest.DONE) {
-                copyAttrs(["responseXML"]);
-            }
-            if(fakeXhr.onreadystatechange) fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
-        };
-        if(xhr.addEventListener) {
-          for(var event in fakeXhr.eventListeners) {
-              if(fakeXhr.eventListeners.hasOwnProperty(event)) {
-                  each(fakeXhr.eventListeners[event],function(handler) {
-                      xhr.addEventListener(event, handler);
-                  });
-              }
-          }
-          xhr.addEventListener("readystatechange",stateChange);
-        } else {
-          xhr.onreadystatechange = stateChange;
-        }
-        apply(xhr,"open",xhrArgs);
-    };
-    FakeXMLHttpRequest.useFilters = false;
-
-    function verifyRequestOpened(xhr) {
-        if (xhr.readyState != FakeXMLHttpRequest.OPENED) {
-            throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
-        }
-    }
-
-    function verifyRequestSent(xhr) {
-        if (xhr.readyState == FakeXMLHttpRequest.DONE) {
-            throw new Error("Request done");
-        }
-    }
-
-    function verifyHeadersReceived(xhr) {
-        if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
-            throw new Error("No headers received");
-        }
-    }
-
-    function verifyResponseBodyType(body) {
-        if (typeof body != "string") {
-            var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
-                                 body + ", which is not a string.");
-            error.name = "InvalidBodyException";
-            throw error;
-        }
-    }
-
-    sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
-        async: true,
-
-        open: function open(method, url, async, username, password) {
-            this.method = method;
-            this.url = url;
-            this.async = typeof async == "boolean" ? async : true;
-            this.username = username;
-            this.password = password;
-            this.responseText = null;
-            this.responseXML = null;
-            this.requestHeaders = {};
-            this.sendFlag = false;
-            if(sinon.FakeXMLHttpRequest.useFilters === true) {
-                var xhrArgs = arguments;
-                var defake = some(FakeXMLHttpRequest.filters,function(filter) {
-                    return filter.apply(this,xhrArgs)
-                });
-                if (defake) {
-                  return sinon.FakeXMLHttpRequest.defake(this,arguments);
-                }
-            }
-            this.readyStateChange(FakeXMLHttpRequest.OPENED);
-        },
-
-        readyStateChange: function readyStateChange(state) {
-            this.readyState = state;
-
-            if (typeof this.onreadystatechange == "function") {
-                try {
-                    this.onreadystatechange();
-                } catch (e) {
-                    sinon.logError("Fake XHR onreadystatechange handler", e);
-                }
-            }
-
-            this.dispatchEvent(new sinon.Event("readystatechange"));
-
-            switch (this.readyState) {
-                case FakeXMLHttpRequest.DONE:
-                    this.dispatchEvent(new sinon.Event("load", false, false, this));
-                    this.dispatchEvent(new sinon.Event("loadend", false, false, this));
-                    this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
-                    if (supportsProgress) {
-                        this.upload.dispatchEvent(new sinon.ProgressEvent('progress', {loaded: 100, total: 100}));
-                    }
-                    break;
-            }
-        },
-
-        setRequestHeader: function setRequestHeader(header, value) {
-            verifyState(this);
-
-            if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
-                throw new Error("Refused to set unsafe header \"" + header + "\"");
-            }
-
-            if (this.requestHeaders[header]) {
-                this.requestHeaders[header] += "," + value;
-            } else {
-                this.requestHeaders[header] = value;
-            }
-        },
-
-        // Helps testing
-        setResponseHeaders: function setResponseHeaders(headers) {
-            verifyRequestOpened(this);
-            this.responseHeaders = {};
-
-            for (var header in headers) {
-                if (headers.hasOwnProperty(header)) {
-                    this.responseHeaders[header] = headers[header];
-                }
-            }
-
-            if (this.async) {
-                this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
-            } else {
-                this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
-            }
-        },
-
-        // Currently treats ALL data as a DOMString (i.e. no Document)
-        send: function send(data) {
-            verifyState(this);
-
-            if (!/^(get|head)$/i.test(this.method)) {
-                if (this.requestHeaders["Content-Type"]) {
-                    var value = this.requestHeaders["Content-Type"].split(";");
-                    this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
-                } else {
-                    this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
-                }
-
-                this.requestBody = data;
-            }
-
-            this.errorFlag = false;
-            this.sendFlag = this.async;
-            this.readyStateChange(FakeXMLHttpRequest.OPENED);
-
-            if (typeof this.onSend == "function") {
-                this.onSend(this);
-            }
-
-            this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
-        },
-
-        abort: function abort() {
-            this.aborted = true;
-            this.responseText = null;
-            this.errorFlag = true;
-            this.requestHeaders = {};
-
-            if (this.readyState > sinon.FakeXMLHttpRequest.UNSENT && this.sendFlag) {
-                this.readyStateChange(sinon.FakeXMLHttpRequest.DONE);
-                this.sendFlag = false;
-            }
-
-            this.readyState = sinon.FakeXMLHttpRequest.UNSENT;
-
-            this.dispatchEvent(new sinon.Event("abort", false, false, this));
-
-            this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
-
-            if (typeof this.onerror === "function") {
-                this.onerror();
-            }
-        },
-
-        getResponseHeader: function getResponseHeader(header) {
-            if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                return null;
-            }
-
-            if (/^Set-Cookie2?$/i.test(header)) {
-                return null;
-            }
-
-            header = header.toLowerCase();
-
-            for (var h in this.responseHeaders) {
-                if (h.toLowerCase() == header) {
-                    return this.responseHeaders[h];
-                }
-            }
-
-            return null;
-        },
-
-        getAllResponseHeaders: function getAllResponseHeaders() {
-            if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                return "";
-            }
-
-            var headers = "";
-
-            for (var header in this.responseHeaders) {
-                if (this.responseHeaders.hasOwnProperty(header) &&
-                    !/^Set-Cookie2?$/i.test(header)) {
-                    headers += header + ": " + this.responseHeaders[header] + "\r\n";
-                }
-            }
-
-            return headers;
-        },
-
-        setResponseBody: function setResponseBody(body) {
-            verifyRequestSent(this);
-            verifyHeadersReceived(this);
-            verifyResponseBodyType(body);
-
-            var chunkSize = this.chunkSize || 10;
-            var index = 0;
-            this.responseText = "";
-
-            do {
-                if (this.async) {
-                    this.readyStateChange(FakeXMLHttpRequest.LOADING);
-                }
-
-                this.responseText += body.substring(index, index + chunkSize);
-                index += chunkSize;
-            } while (index < body.length);
-
-            var type = this.getResponseHeader("Content-Type");
-
-            if (this.responseText &&
-                (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
-                try {
-                    this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
-                } catch (e) {
-                    // Unable to parse XML - no biggie
-                }
-            }
-
-            if (this.async) {
-                this.readyStateChange(FakeXMLHttpRequest.DONE);
-            } else {
-                this.readyState = FakeXMLHttpRequest.DONE;
-            }
-        },
-
-        respond: function respond(status, headers, body) {
-            this.status = typeof status == "number" ? status : 200;
-            this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
-            this.setResponseHeaders(headers || {});
-            this.setResponseBody(body || "");
-        },
-
-        uploadProgress: function uploadProgress(progressEventRaw) {
-            if (supportsProgress) {
-                this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
-            }
-        },
-
-        uploadError: function uploadError(error) {
-            if (supportsCustomEvent) {
-                this.upload.dispatchEvent(new sinon.CustomEvent("error", {"detail": error}));
-            }
-        }
-    });
-
-    sinon.extend(FakeXMLHttpRequest, {
-        UNSENT: 0,
-        OPENED: 1,
-        HEADERS_RECEIVED: 2,
-        LOADING: 3,
-        DONE: 4
-    });
-
-    // Borrowed from JSpec
-    FakeXMLHttpRequest.parseXML = function parseXML(text) {
-        var xmlDoc;
-
-        if (typeof DOMParser != "undefined") {
-            var parser = new DOMParser();
-            xmlDoc = parser.parseFromString(text, "text/xml");
-        } else {
-            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
-            xmlDoc.async = "false";
-            xmlDoc.loadXML(text);
-        }
-
-        return xmlDoc;
-    };
-
-    FakeXMLHttpRequest.statusCodes = {
-        100: "Continue",
-        101: "Switching Protocols",
-        200: "OK",
-        201: "Created",
-        202: "Accepted",
-        203: "Non-Authoritative Information",
-        204: "No Content",
-        205: "Reset Content",
-        206: "Partial Content",
-        300: "Multiple Choice",
-        301: "Moved Permanently",
-        302: "Found",
-        303: "See Other",
-        304: "Not Modified",
-        305: "Use Proxy",
-        307: "Temporary Redirect",
-        400: "Bad Request",
-        401: "Unauthorized",
-        402: "Payment Required",
-        403: "Forbidden",
-        404: "Not Found",
-        405: "Method Not Allowed",
-        406: "Not Acceptable",
-        407: "Proxy Authentication Required",
-        408: "Request Timeout",
-        409: "Conflict",
-        410: "Gone",
-        411: "Length Required",
-        412: "Precondition Failed",
-        413: "Request Entity Too Large",
-        414: "Request-URI Too Long",
-        415: "Unsupported Media Type",
-        416: "Requested Range Not Satisfiable",
-        417: "Expectation Failed",
-        422: "Unprocessable Entity",
-        500: "Internal Server Error",
-        501: "Not Implemented",
-        502: "Bad Gateway",
-        503: "Service Unavailable",
-        504: "Gateway Timeout",
-        505: "HTTP Version Not Supported"
-    };
-
-    sinon.useFakeXMLHttpRequest = function () {
-        sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
-            if (xhr.supportsXHR) {
-                global.XMLHttpRequest = xhr.GlobalXMLHttpRequest;
-            }
-
-            if (xhr.supportsActiveX) {
-                global.ActiveXObject = xhr.GlobalActiveXObject;
-            }
-
-            delete sinon.FakeXMLHttpRequest.restore;
-
-            if (keepOnCreate !== true) {
-                delete sinon.FakeXMLHttpRequest.onCreate;
-            }
-        };
-        if (xhr.supportsXHR) {
-            global.XMLHttpRequest = sinon.FakeXMLHttpRequest;
-        }
-
-        if (xhr.supportsActiveX) {
-            global.ActiveXObject = function ActiveXObject(objId) {
-                if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
-
-                    return new sinon.FakeXMLHttpRequest();
-                }
-
-                return new xhr.GlobalActiveXObject(objId);
-            };
-        }
-
-        return sinon.FakeXMLHttpRequest;
-    };
-
-    sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
-
-})(typeof global === "object" ? global : this);
-
-if (typeof module !== 'undefined' && module.exports) {
-    module.exports = sinon;
-}
-
-/**
- * @depend fake_xml_http_request.js
- */
-/*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/
-/*global module, require, window*/
-/**
- * The Sinon "server" mimics a web server that receives requests from
- * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
- * both synchronously and asynchronously. To respond synchronuously, canned
- * answers have to be provided upfront.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    var sinon = {};
-}
-
-sinon.fakeServer = (function () {
-    var push = [].push;
-    function F() {}
-
-    function create(proto) {
-        F.prototype = proto;
-        return new F();
-    }
-
-    function responseArray(handler) {
-        var response = handler;
-
-        if (Object.prototype.toString.call(handler) != "[object Array]") {
-            response = [200, {}, handler];
-        }
-
-        if (typeof response[2] != "string") {
-            throw new TypeError("Fake server response body should be string, but was " +
-                                typeof response[2]);
-        }
-
-        return response;
-    }
-
-    var wloc = typeof window !== "undefined" ? window.location : {};
-    var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
-
-    function matchOne(response, reqMethod, reqUrl) {
-        var rmeth = response.method;
-        var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
-        var url = response.url;
-        var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
-
-        return matchMethod && matchUrl;
-    }
-
-    function match(response, request) {
-        var requestUrl = request.url;
-
-        if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
-            requestUrl = requestUrl.replace(rCurrLoc, "");
-        }
-
-        if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
-            if (typeof response.response == "function") {
-                var ru = response.url;
-                var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []);
-                return response.response.apply(response, args);
-            }
-
-            return true;
-        }
-
-        return false;
-    }
-
-    function log(response, request) {
-        var str;
-
-        str =  "Request:\n"  + sinon.format(request)  + "\n\n";
-        str += "Response:\n" + sinon.format(response) + "\n\n";
-
-        sinon.log(str);
-    }
-
-    return {
-        create: function () {
-            var server = create(this);
-            this.xhr = sinon.useFakeXMLHttpRequest();
-            server.requests = [];
-
-            this.xhr.onCreate = function (xhrObj) {
-                server.addRequest(xhrObj);
-            };
-
-            return server;
-        },
-
-        addRequest: function addRequest(xhrObj) {
-            var server = this;
-            push.call(this.requests, xhrObj);
-
-            xhrObj.onSend = function () {
-                server.handleRequest(this);
-
-                if (server.autoRespond && !server.responding) {
-                    setTimeout(function () {
-                        server.responding = false;
-                        server.respond();
-                    }, server.autoRespondAfter || 10);
-
-                    server.responding = true;
-                }
-            };
-        },
-
-        getHTTPMethod: function getHTTPMethod(request) {
-            if (this.fakeHTTPMethods && /post/i.test(request.method)) {
-                var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
-                return !!matches ? matches[1] : request.method;
-            }
-
-            return request.method;
-        },
-
-        handleRequest: function handleRequest(xhr) {
-            if (xhr.async) {
-                if (!this.queue) {
-                    this.queue = [];
-                }
-
-                push.call(this.queue, xhr);
-            } else {
-                this.processRequest(xhr);
-            }
-        },
-
-        respondWith: function respondWith(method, url, body) {
-            if (arguments.length == 1 && typeof method != "function") {
-                this.response = responseArray(method);
-                return;
-            }
-
-            if (!this.responses) { this.responses = []; }
-
-            if (arguments.length == 1) {
-                body = method;
-                url = method = null;
-            }
-
-            if (arguments.length == 2) {
-                body = url;
-                url = method;
-                method = null;
-            }
-
-            push.call(this.responses, {
-                method: method,
-                url: url,
-                response: typeof body == "function" ? body : responseArray(body)
-            });
-        },
-
-        respond: function respond() {
-            if (arguments.length > 0) this.respondWith.apply(this, arguments);
-            var queue = this.queue || [];
-            var requests = queue.splice(0);
-            var request;
-
-            while(request = requests.shift()) {
-                this.processRequest(request);
-            }
-        },
-
-        processRequest: function processRequest(request) {
-            try {
-                if (request.aborted) {
-                    return;
-                }
-
-                var response = this.response || [404, {}, ""];
-
-                if (this.responses) {
-                    for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
-                        if (match.call(this, this.responses[i], request)) {
-                            response = this.responses[i].response;
-                            break;
-                        }
-                    }
-                }
-
-                if (request.readyState != 4) {
-                    log(response, request);
-
-                    request.respond(response[0], response[1], response[2]);
-                }
-            } catch (e) {
-                sinon.logError("Fake server request processing", e);
-            }
-        },
-
-        restore: function restore() {
-            return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
-        }
-    };
-}());
-
-if (typeof module !== 'undefined' && module.exports) {
-    module.exports = sinon;
-}
-
-/**
- * @depend fake_server.js
- * @depend fake_timers.js
- */
-/*jslint browser: true, eqeqeq: false, onevar: false*/
-/*global sinon*/
-/**
- * Add-on for sinon.fakeServer that automatically handles a fake timer along with
- * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
- * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
- * it polls the object for completion with setInterval. Dispite the direct
- * motivation, there is nothing jQuery-specific in this file, so it can be used
- * in any environment where the ajax implementation depends on setInterval or
- * setTimeout.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function () {
-    function Server() {}
-    Server.prototype = sinon.fakeServer;
-
-    sinon.fakeServerWithClock = new Server();
-
-    sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
-        if (xhr.async) {
-            if (typeof setTimeout.clock == "object") {
-                this.clock = setTimeout.clock;
-            } else {
-                this.clock = sinon.useFakeTimers();
-                this.resetClock = true;
-            }
-
-            if (!this.longestTimeout) {
-                var clockSetTimeout = this.clock.setTimeout;
-                var clockSetInterval = this.clock.setInterval;
-                var server = this;
-
-                this.clock.setTimeout = function (fn, timeout) {
-                    server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
-
-                    return clockSetTimeout.apply(this, arguments);
-                };
-
-                this.clock.setInterval = function (fn, timeout) {
-                    server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
-
-                    return clockSetInterval.apply(this, arguments);
-                };
-            }
-        }
-
-        return sinon.fakeServer.addRequest.call(this, xhr);
-    };
-
-    sinon.fakeServerWithClock.respond = function respond() {
-        var returnVal = sinon.fakeServer.respond.apply(this, arguments);
-
-        if (this.clock) {
-            this.clock.tick(this.longestTimeout || 0);
-            this.longestTimeout = 0;
-
-            if (this.resetClock) {
-                this.clock.restore();
-                this.resetClock = false;
-            }
-        }
-
-        return returnVal;
-    };
-
-    sinon.fakeServerWithClock.restore = function restore() {
-        if (this.clock) {
-            this.clock.restore();
-        }
-
-        return sinon.fakeServer.restore.apply(this, arguments);
-    };
-}());
-
-/**
- * @depend ../sinon.js
- * @depend collection.js
- * @depend util/fake_timers.js
- * @depend util/fake_server_with_clock.js
- */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global require, module*/
-/**
- * Manages fake collections as well as fake utilities such as Sinon's
- * timers and fake XHR implementation in one convenient object.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-if (typeof module !== 'undefined' && module.exports) {
-    var sinon = require("../sinon");
-    sinon.extend(sinon, require("./util/fake_timers"));
-}
-
-(function () {
-    var push = [].push;
-
-    function exposeValue(sandbox, config, key, value) {
-        if (!value) {
-            return;
-        }
-
-        if (config.injectInto && !(key in config.injectInto)) {
-            config.injectInto[key] = value;
-            sandbox.injectedKeys.push(key);
-        } else {
-            push.call(sandbox.args, value);
-        }
-    }
-
-    function prepareSandboxFromConfig(config) {
-        var sandbox = sinon.create(sinon.sandbox);
-
-        if (config.useFakeServer) {
-            if (typeof config.useFakeServer == "object") {
-                sandbox.serverPrototype = config.useFakeServer;
-            }
-
-            sandbox.useFakeServer();
-        }
-
-        if (config.useFakeTimers) {
-            if (typeof config.useFakeTimers == "object") {
-                sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
-            } else {
-                sandbox.useFakeTimers();
-            }
-        }
-
-        return sandbox;
-    }
-
-    sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
-        useFakeTimers: function useFakeTimers() {
-            this.clock = sinon.useFakeTimers.apply(sinon, arguments);
-
-            return this.add(this.clock);
-        },
-
-        serverPrototype: sinon.fakeServer,
-
-        useFakeServer: function useFakeServer() {
-            var proto = this.serverPrototype || sinon.fakeServer;
-
-            if (!proto || !proto.create) {
-                return null;
-            }
-
-            this.server = proto.create();
-            return this.add(this.server);
-        },
-
-        inject: function (obj) {
-            sinon.collection.inject.call(this, obj);
-
-            if (this.clock) {
-                obj.clock = this.clock;
-            }
-
-            if (this.server) {
-                obj.server = this.server;
-                obj.requests = this.server.requests;
-            }
-
-            return obj;
-        },
-
-        restore: function () {
-            sinon.collection.restore.apply(this, arguments);
-            this.restoreContext();
-        },
-
-        restoreContext: function () {
-            if (this.injectedKeys) {
-                for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
-                    delete this.injectInto[this.injectedKeys[i]];
-                }
-                this.injectedKeys = [];
-            }
-        },
-
-        create: function (config) {
-            if (!config) {
-                return sinon.create(sinon.sandbox);
-            }
-
-            var sandbox = prepareSandboxFromConfig(config);
-            sandbox.args = sandbox.args || [];
-            sandbox.injectedKeys = [];
-            sandbox.injectInto = config.injectInto;
-            var prop, value, exposed = sandbox.inject({});
-
-            if (config.properties) {
-                for (var i = 0, l = config.properties.length; i < l; i++) {
-                    prop = config.properties[i];
-                    value = exposed[prop] || prop == "sandbox" && sandbox;
-                    exposeValue(sandbox, config, prop, value);
-                }
-            } else {
-                exposeValue(sandbox, config, "sandbox", value);
-            }
-
-            return sandbox;
-        }
-    });
-
-    sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
-
-    if (typeof module !== 'undefined' && module.exports) {
-        module.exports = sinon.sandbox;
-    }
-}());
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- * @depend mock.js
- * @depend sandbox.js
- */
-/*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Test function, sandboxes fakes
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function test(callback) {
-        var type = typeof callback;
-
-        if (type != "function") {
-            throw new TypeError("sinon.test needs to wrap a test function, got " + type);
-        }
-
-        return function () {
-            var config = sinon.getConfig(sinon.config);
-            config.injectInto = config.injectIntoThis && this || config.injectInto;
-            var sandbox = sinon.sandbox.create(config);
-            var exception, result;
-            var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
-
-            try {
-                result = callback.apply(this, args);
-            } catch (e) {
-                exception = e;
-            }
-
-            if (typeof exception !== "undefined") {
-                sandbox.restore();
-                throw exception;
-            }
-            else {
-                sandbox.verifyAndRestore();
-            }
-
-            return result;
-        };
-    }
-
-    test.config = {
-        injectIntoThis: true,
-        injectInto: null,
-        properties: ["spy", "stub", "mock", "clock", "server", "requests"],
-        useFakeTimers: true,
-        useFakeServer: true
-    };
-
-    if (commonJSModule) {
-        module.exports = test;
-    } else {
-        sinon.test = test;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend test.js
- */
-/*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
-/*global module, require, sinon*/
-/**
- * Test case, sandboxes all test functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon || !Object.prototype.hasOwnProperty) {
-        return;
-    }
-
-    function createTest(property, setUp, tearDown) {
-        return function () {
-            if (setUp) {
-                setUp.apply(this, arguments);
-            }
-
-            var exception, result;
-
-            try {
-                result = property.apply(this, arguments);
-            } catch (e) {
-                exception = e;
-            }
-
-            if (tearDown) {
-                tearDown.apply(this, arguments);
-            }
-
-            if (exception) {
-                throw exception;
-            }
-
-            return result;
-        };
-    }
-
-    function testCase(tests, prefix) {
-        /*jsl:ignore*/
-        if (!tests || typeof tests != "object") {
-            throw new TypeError("sinon.testCase needs an object with test functions");
-        }
-        /*jsl:end*/
-
-        prefix = prefix || "test";
-        var rPrefix = new RegExp("^" + prefix);
-        var methods = {}, testName, property, method;
-        var setUp = tests.setUp;
-        var tearDown = tests.tearDown;
-
-        for (testName in tests) {
-            if (tests.hasOwnProperty(testName)) {
-                property = tests[testName];
-
-                if (/^(setUp|tearDown)$/.test(testName)) {
-                    continue;
-                }
-
-                if (typeof property == "function" && rPrefix.test(testName)) {
-                    method = property;
-
-                    if (setUp || tearDown) {
-                        method = createTest(property, setUp, tearDown);
-                    }
-
-                    methods[testName] = sinon.test(method);
-                } else {
-                    methods[testName] = tests[testName];
-                }
-            }
-        }
-
-        return methods;
-    }
-
-    if (commonJSModule) {
-        module.exports = testCase;
-    } else {
-        sinon.testCase = testCase;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- */
-/*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Assertions matching the test spy retrieval interface.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon, global) {
-    var commonJSModule = typeof module !== "undefined" && module.exports;
-    var slice = Array.prototype.slice;
-    var assert;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function verifyIsStub() {
-        var method;
-
-        for (var i = 0, l = arguments.length; i < l; ++i) {
-            method = arguments[i];
-
-            if (!method) {
-                assert.fail("fake is not a spy");
-            }
-
-            if (typeof method != "function") {
-                assert.fail(method + " is not a function");
-            }
-
-            if (typeof method.getCall != "function") {
-                assert.fail(method + " is not stubbed");
-            }
-        }
-    }
-
-    function failAssertion(object, msg) {
-        object = object || global;
-        var failMethod = object.fail || assert.fail;
-        failMethod.call(object, msg);
-    }
-
-    function mirrorPropAsAssertion(name, method, message) {
-        if (arguments.length == 2) {
-            message = method;
-            method = name;
-        }
-
-        assert[name] = function (fake) {
-            verifyIsStub(fake);
-
-            var args = slice.call(arguments, 1);
-            var failed = false;
-
-            if (typeof method == "function") {
-                failed = !method(fake);
-            } else {
-                failed = typeof fake[method] == "function" ?
-                    !fake[method].apply(fake, args) : !fake[method];
-            }
-
-            if (failed) {
-                failAssertion(this, fake.printf.apply(fake, [message].concat(args)));
-            } else {
-                assert.pass(name);
-            }
-        };
-    }
-
-    function exposedName(prefix, prop) {
-        return !prefix || /^fail/.test(prop) ? prop :
-            prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
-    }
-
-    assert = {
-        failException: "AssertError",
-
-        fail: function fail(message) {
-            var error = new Error(message);
-            error.name = this.failException || assert.failException;
-
-            throw error;
-        },
-
-        pass: function pass(assertion) {},
-
-        callOrder: function assertCallOrder() {
-            verifyIsStub.apply(null, arguments);
-            var expected = "", actual = "";
-
-            if (!sinon.calledInOrder(arguments)) {
-                try {
-                    expected = [].join.call(arguments, ", ");
-                    var calls = slice.call(arguments);
-                    var i = calls.length;
-                    while (i) {
-                        if (!calls[--i].called) {
-                            calls.splice(i, 1);
-                        }
-                    }
-                    actual = sinon.orderByFirstCall(calls).join(", ");
-                } catch (e) {
-                    // If this fails, we'll just fall back to the blank string
-                }
-
-                failAssertion(this, "expected " + expected + " to be " +
-                              "called in order but were called as " + actual);
-            } else {
-                assert.pass("callOrder");
-            }
-        },
-
-        callCount: function assertCallCount(method, count) {
-            verifyIsStub(method);
-
-            if (method.callCount != count) {
-                var msg = "expected %n to be called " + sinon.timesInWords(count) +
-                    " but was called %c%C";
-                failAssertion(this, method.printf(msg));
-            } else {
-                assert.pass("callCount");
-            }
-        },
-
-        expose: function expose(target, options) {
-            if (!target) {
-                throw new TypeError("target is null or undefined");
-            }
-
-            var o = options || {};
-            var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
-            var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
-
-            for (var method in this) {
-                if (method != "export" && (includeFail || !/^(fail)/.test(method))) {
-                    target[exposedName(prefix, method)] = this[method];
-                }
-            }
-
-            return target;
-        },
-
-        match: function match(actual, expectation) {
-            var matcher = sinon.match(expectation);
-            if (matcher.test(actual)) {
-                assert.pass("match");
-            } else {
-                var formatted = [
-                    "expected value to match",
-                    "    expected = " + sinon.format(expectation),
-                    "    actual = " + sinon.format(actual)
-                ]
-                failAssertion(this, formatted.join("\n"));
-            }
-        }
-    };
-
-    mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
-    mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
-                          "expected %n to not have been called but was called %c%C");
-    mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
-    mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
-    mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
-    mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
-    mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
-    mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
-    mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
-    mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
-    mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
-    mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
-    mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
-    mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
-    mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
-    mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
-    mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
-    mirrorPropAsAssertion("threw", "%n did not throw exception%C");
-    mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
-
-    if (commonJSModule) {
-        module.exports = assert;
-    } else {
-        sinon.assert = assert;
-    }
-}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
-
-return sinon;}.call(typeof window != 'undefined' && window || {}));
diff --git a/resources/sinonjs/sinon-ie-1.9.0.js b/resources/sinonjs/sinon-ie-1.9.0.js
deleted file mode 100644 (file)
index c9fbd9d..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Sinon.JS 1.9.0, 2014/03/05
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
- *
- * (The BSD License)
- * 
- * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 
- *     * Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright notice,
- *       this list of conditions and the following disclaimer in the documentation
- *       and/or other materials provided with the distribution.
- *     * Neither the name of Christian Johansen nor the names of his contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*global sinon, setTimeout, setInterval, clearTimeout, clearInterval, Date*/
-/**
- * Helps IE run the fake timers. By defining global functions, IE allows
- * them to be overwritten at a later point. If these are not defined like
- * this, overwriting them will result in anything from an exception to browser
- * crash.
- *
- * If you don't require fake timers to work in IE, don't include this file.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-function setTimeout() {}
-function clearTimeout() {}
-function setImmediate() {}
-function clearImmediate() {}
-function setInterval() {}
-function clearInterval() {}
-function Date() {}
-
-// Reassign the original functions. Now their writable attribute
-// should be true. Hackish, I know, but it works.
-setTimeout = sinon.timers.setTimeout;
-clearTimeout = sinon.timers.clearTimeout;
-setImmediate = sinon.timers.setImmediate;
-clearImmediate = sinon.timers.clearImmediate;
-setInterval = sinon.timers.setInterval;
-clearInterval = sinon.timers.clearInterval;
-Date = sinon.timers.Date;
-
-/*global sinon*/
-/**
- * Helps IE run the fake XMLHttpRequest. By defining global functions, IE allows
- * them to be overwritten at a later point. If these are not defined like
- * this, overwriting them will result in anything from an exception to browser
- * crash.
- *
- * If you don't require fake XHR to work in IE, don't include this file.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-function XMLHttpRequest() {}
-
-// Reassign the original function. Now its writable attribute
-// should be true. Hackish, I know, but it works.
-XMLHttpRequest = sinon.xhr.XMLHttpRequest || undefined;
diff --git a/resources/src/jquery.tipsy/images/tipsy.png b/resources/src/jquery.tipsy/images/tipsy.png
new file mode 100644 (file)
index 0000000..ef17cc3
Binary files /dev/null and b/resources/src/jquery.tipsy/images/tipsy.png differ
diff --git a/resources/src/jquery.tipsy/jquery.tipsy.css b/resources/src/jquery.tipsy/jquery.tipsy.css
new file mode 100644 (file)
index 0000000..3680fbe
--- /dev/null
@@ -0,0 +1,75 @@
+.tipsy {
+       padding: 5px;
+       position: absolute;
+       z-index: 100000;
+       cursor: default;
+}
+.tipsy-inner {
+       padding: 5px 8px 4px 8px;
+       /*background-color: #e8f2f8;*/
+       background-color: #ffffff;
+       border: solid 1px #a7d7f9;
+       color: black;
+       max-width: 15em;
+       border-radius: 4px;
+       -moz-border-radius: 4px;
+       -webkit-border-radius: 4px;
+       /*
+       -moz-box-shadow: 0px 2px 8px #cccccc;
+       -webkit-box-shadow: 0px 2px 8px #cccccc;
+       box-shadow: 0px 2px 8px #cccccc;
+       -ms-filter: "progid:DXImageTransform.Microsoft.DropShadow(OffX=0, OffY=2, Strength=6, Direction=90, Color='#cccccc')";
+       filter: progid:DXImageTransform.Microsoft.DropShadow(OffX=0, OffY=2, Strength=6, Direction=90, Color='#cccccc');
+       */
+}
+.tipsy-arrow {
+       position: absolute;
+       /* @embed */
+       background: url('images/tipsy.png') no-repeat top left;
+       width: 11px;
+       height: 6px;
+}
+/* @noflip */ .tipsy-n .tipsy-arrow {
+       top: 0px;
+       left: 50%;
+       margin-left: -5px;
+}
+/* @noflip */ .tipsy-nw .tipsy-arrow {
+       top: 1px;
+       left: 10px;
+}
+/* @noflip */ .tipsy-ne .tipsy-arrow {
+       top: 1px;
+       right: 10px;
+}
+/* @noflip */ .tipsy-s .tipsy-arrow {
+       bottom: 0px;
+       left: 50%;
+       margin-left: -5px;
+       background-position: bottom left;
+}
+/* @noflip */ .tipsy-sw .tipsy-arrow {
+       bottom: 0px;
+       left: 10px;
+       background-position: bottom left;
+}
+/* @noflip */ .tipsy-se .tipsy-arrow {
+       bottom: 0px;
+       right: 10px;
+       background-position: bottom left;
+}
+/* @noflip */ .tipsy-e .tipsy-arrow {
+       top: 50%;
+       margin-top: -5px;
+       right: 1px;
+       width: 5px;
+       height: 11px;
+       background-position: top right;
+}
+/* @noflip */ .tipsy-w .tipsy-arrow {
+       top: 50%;
+       margin-top: -5px;
+       left: 0px;
+       width: 6px;
+       height: 11px;
+}
\ No newline at end of file
diff --git a/resources/src/jquery.tipsy/jquery.tipsy.js b/resources/src/jquery.tipsy/jquery.tipsy.js
new file mode 100644 (file)
index 0000000..f920e8b
--- /dev/null
@@ -0,0 +1,223 @@
+// tipsy, facebook style tooltips for jquery
+// version 1.0.0a*
+// (c) 2008-2010 jason frame [jason@onehackoranother.com]
+// released under the MIT license
+
+// * This installation of tipsy includes several local modifications to both Javascript and CSS.
+//   Please be careful when upgrading.
+
+(function($) {
+
+    function maybeCall(thing, ctx) {
+        return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
+    }
+
+    function fixTitle($ele) {
+        if ($ele.attr('title') || typeof($ele.attr('original-title')) != 'string') {
+            $ele.attr('original-title', $ele.attr('title') || '').removeAttr('title');
+        }
+    }
+
+    function Tipsy(element, options) {
+        this.$element = $(element);
+        this.options = options;
+        this.enabled = true;
+        fixTitle(this.$element);
+    }
+
+    Tipsy.prototype = {
+        show: function() {
+            var title = this.getTitle();
+            if (title && this.enabled) {
+                var $tip = this.tip();
+
+                $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
+                $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
+                if (this.options.className) {
+                    $tip.addClass(maybeCall(this.options.className, this.$element[0]));
+                }
+                $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);
+
+                var pos = $.extend({}, this.$element.offset(), {
+                    width: this.$element[0].offsetWidth,
+                    height: this.$element[0].offsetHeight
+                });
+
+                var gravity = (typeof this.options.gravity == 'function')
+                                ? this.options.gravity.call(this.$element[0])
+                                : this.options.gravity;
+
+                // Attach css classes before checking height/width so they
+                // can be applied.
+                $tip.addClass('tipsy-' + gravity);
+                if (this.options.className) {
+                    $tip.addClass(maybeCall(this.options.className, this.$element[0]));
+                }
+
+                var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight;
+                var tp;
+                switch (gravity.charAt(0)) {
+                    case 'n':
+                        tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
+                        break;
+                    case 's':
+                        tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
+                        break;
+                    case 'e':
+                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
+                        break;
+                    case 'w':
+                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
+                        break;
+                }
+
+                if (gravity.length == 2) {
+                    if (gravity.charAt(1) == 'w') {
+                        if (this.options.center) {
+                            tp.left = pos.left + pos.width / 2 - 15;
+                        } else {
+                            tp.left = pos.left;
+                        }
+                    } else {
+                        if (this.options.center) {
+                            tp.left = pos.left + pos.width / 2 - actualWidth + 15;
+                        } else {
+                            tp.left = pos.left + pos.width;
+                        }
+                    }
+                }
+                $tip.css(tp);
+
+                if (this.options.fade) {
+                    $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity}, 100);
+                } else {
+                    $tip.css({visibility: 'visible', opacity: this.options.opacity});
+                }
+            }
+        },
+
+        hide: function() {
+            if (this.options.fade) {
+                this.tip().stop().fadeOut(100, function() { $(this).remove(); });
+            } else {
+                this.tip().remove();
+            }
+        },
+
+        getTitle: function() {
+            var title, $e = this.$element, o = this.options;
+            fixTitle($e);
+            if (typeof o.title == 'string') {
+                title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
+            } else if (typeof o.title == 'function') {
+                title = o.title.call($e[0]);
+            }
+            title = ('' + title).replace(/(^\s*|\s*$)/, "");
+            return title || o.fallback;
+        },
+
+        tip: function() {
+            if (!this.$tip) {
+                this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"/></div>');
+            }
+            return this.$tip;
+        },
+
+        validate: function() {
+            if (!this.$element[0].parentNode) {
+                this.hide();
+                this.$element = null;
+                this.options = null;
+            }
+        },
+
+        enable: function() { this.enabled = true; },
+        disable: function() { this.enabled = false; },
+        toggleEnabled: function() { this.enabled = !this.enabled; }
+    };
+
+    $.fn.tipsy = function(options) {
+
+        if (options === true) {
+            return this.data('tipsy');
+        } else if (typeof options == 'string') {
+            return this.data('tipsy')[options]();
+        }
+
+        options = $.extend({}, $.fn.tipsy.defaults, options);
+
+        function get(ele) {
+            var tipsy = $.data(ele, 'tipsy');
+            if (!tipsy) {
+                tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
+                $.data(ele, 'tipsy', tipsy);
+            }
+            return tipsy;
+        }
+
+        function enter() {
+            var tipsy = get(this);
+            tipsy.hoverState = 'in';
+            if (options.delayIn == 0) {
+                tipsy.show();
+            } else {
+                setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
+            }
+        };
+
+        function leave() {
+            var tipsy = get(this);
+            tipsy.hoverState = 'out';
+            if (options.delayOut == 0) {
+                tipsy.hide();
+            } else {
+                setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
+            }
+        };
+
+        if (!options.live) this.each(function() { get(this); });
+
+        if (options.trigger != 'manual') {
+            var binder   = options.live ? 'live' : 'bind',
+                eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus',
+                eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
+            this[binder](eventIn, enter)[binder](eventOut, leave);
+        }
+
+        return this;
+
+    };
+
+    $.fn.tipsy.defaults = {
+        className: null,
+        delayIn: 0,
+        delayOut: 0,
+        fade: true,
+        fallback: '',
+        gravity: 'n',
+        center: true,
+        html: false,
+        live: false,
+        offset: 0,
+        opacity: 1.0,
+        title: 'title',
+        trigger: 'hover'
+    };
+
+    // Overwrite this method to provide options on a per-element basis.
+    // For example, you could store the gravity in a 'tipsy-gravity' attribute:
+    // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
+    // (remember - do not modify 'options' in place!)
+    $.fn.tipsy.elementOptions = function(ele, options) {
+        return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
+    };
+
+    $.fn.tipsy.autoNS = function() {
+        return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
+    };
+
+    $.fn.tipsy.autoWE = function() {
+        return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
+    };
+
+})(jQuery);
diff --git a/resources/src/jquery.ui-themes/vector/images/close.png b/resources/src/jquery.ui-themes/vector/images/close.png
new file mode 100644 (file)
index 0000000..ef0dd9e
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/close.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/titlebar-fade.png b/resources/src/jquery.ui-themes/vector/images/titlebar-fade.png
new file mode 100644 (file)
index 0000000..12a80c8
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/titlebar-fade.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-anim_basic_16x16.gif b/resources/src/jquery.ui-themes/vector/images/ui-anim_basic_16x16.gif
new file mode 100644 (file)
index 0000000..085ccae
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-anim_basic_16x16.gif differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png
new file mode 100644 (file)
index 0000000..09de537
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_15_cd0a0a_40x100.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_70_000000_40x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_70_000000_40x100.png
new file mode 100644 (file)
index 0000000..c06dd56
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-bg_flat_70_000000_40x100.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png
new file mode 100644 (file)
index 0000000..5308b46
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png
new file mode 100644 (file)
index 0000000..0c8997f
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png
new file mode 100644 (file)
index 0000000..3149255
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png
new file mode 100644 (file)
index 0000000..09b2376
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_100_ffffff_1x100.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png
new file mode 100644 (file)
index 0000000..66627c1
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-bg_highlight-soft_25_ffef8f_1x100.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png b/resources/src/jquery.ui-themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png
new file mode 100644 (file)
index 0000000..ccb6dc0
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-bg_inset-hard_100_f0f0f0_1x100.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_2694e8_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_2694e8_256x240.png
new file mode 100644 (file)
index 0000000..998ac3b
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-icons_2694e8_256x240.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_2e83ff_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_2e83ff_256x240.png
new file mode 100644 (file)
index 0000000..34e38d1
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-icons_2e83ff_256x240.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_3d80b3_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_3d80b3_256x240.png
new file mode 100644 (file)
index 0000000..ec129a8
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-icons_3d80b3_256x240.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_666666_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_666666_256x240.png
new file mode 100644 (file)
index 0000000..a32c57d
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-icons_666666_256x240.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_72a7cf_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_72a7cf_256x240.png
new file mode 100644 (file)
index 0000000..88fad1a
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-icons_72a7cf_256x240.png differ
diff --git a/resources/src/jquery.ui-themes/vector/images/ui-icons_ffffff_256x240.png b/resources/src/jquery.ui-themes/vector/images/ui-icons_ffffff_256x240.png
new file mode 100644 (file)
index 0000000..29ba7d2
Binary files /dev/null and b/resources/src/jquery.ui-themes/vector/images/ui-icons_ffffff_256x240.png differ
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.accordion.css b/resources/src/jquery.ui-themes/vector/jquery.ui.accordion.css
new file mode 100644 (file)
index 0000000..8d8a1a6
--- /dev/null
@@ -0,0 +1,12 @@
+/* Accordion
+----------------------------------*/
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
+/* IE7-/Win - Fix extra vertical space in lists */
+.ui-accordion a { zoom: 1; }
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
+.ui-accordion .ui-accordion-content-active { display: block; }
\ No newline at end of file
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.autocomplete.css b/resources/src/jquery.ui-themes/vector/jquery.ui.autocomplete.css
new file mode 100644 (file)
index 0000000..c06fd18
--- /dev/null
@@ -0,0 +1,40 @@
+/* Autocomplete
+----------------------------------*/
+.ui-autocomplete { position: absolute; cursor: default; }      
+.ui-autocomplete-loading { /* @embed */ background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; }
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/* Menu
+----------------------------------*/
+.ui-menu {
+       list-style:none;
+       padding: 2px;
+       margin: 0;
+       display:block;
+       float: left;
+}
+.ui-menu .ui-menu {
+       margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+       margin:0;
+       padding: 0;
+       zoom: 1;
+       float: left;
+       clear: left;
+       width: 100%;
+}
+.ui-menu .ui-menu-item a {
+       text-decoration:none;
+       display:block;
+       padding:.2em .4em;
+       line-height:1.5;
+       zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+       font-weight: normal;
+       margin: -1px;
+}
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.button.css b/resources/src/jquery.ui-themes/vector/jquery.ui.button.css
new file mode 100644 (file)
index 0000000..ea14723
--- /dev/null
@@ -0,0 +1,379 @@
+/* Button
+----------------------------------*/
+
+.ui-button {
+       display: inline-block;
+       position: relative;
+       padding: 0;
+       margin-right: .1em;
+       text-decoration: none !important;
+       cursor: pointer;
+       text-align: center;
+       zoom: 1;
+       overflow: visible; /* the overflow property removes extra width in IE */
+}
+
+/*button text element */
+.ui-button .ui-button-text {
+       display: block;
+       line-height: 1.4;
+       text-shadow: 0 1px 1px #fff;
+}
+.ui-button-text-only .ui-button-text {
+       padding: 0.3em 1em 0.25em 1em;
+}
+.ui-button-icon-only .ui-button-text,
+.ui-button-icons-only .ui-button-text {
+       padding: 0.3em;
+       text-indent: -9999999px;
+}
+.ui-button-text-icon-primary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+       padding: 0.3em 1em 0.25em 2.1em;
+}
+.ui-button-text-icon-secondary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+       padding: 0.3em 2.1em 0.25em 1em;
+}
+.ui-button-text-icons .ui-button-text {
+       padding-left: 2.1em;
+       padding-right: 2.1em;
+}
+
+/* no icon support for input elements, provide padding by default */
+input.ui-button {
+       padding: 0.3em 1em;
+}
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon,
+.ui-button-text-icon-primary .ui-icon,
+.ui-button-text-icon-secondary .ui-icon,
+.ui-button-text-icons .ui-icon,
+.ui-button-text-icon .ui-icon,
+.ui-button-icons-only .ui-icon {
+       position: absolute;
+       top: 50%;
+       margin-top: -9px;
+}
+.ui-button-icon-only .ui-icon {
+       left: 50%;
+       margin-left: -8px;
+}
+.ui-button-text-icon-primary .ui-button-icon-primary,
+.ui-button-text-icon .ui-button-icon-primary,
+.ui-button-text-icons .ui-button-icon-primary,
+.ui-button-icons-only .ui-button-icon-primary {
+       left: 0.5em;
+}
+.ui-button-text-icon-secondary .ui-button-icon-secondary,
+.ui-button-text-icon .ui-button-icon-secondary,
+.ui-button-text-icons .ui-button-icon-secondary,
+.ui-button-icons-only .ui-button-icon-secondary {
+       right: 0.5em;
+}
+
+/*button sets*/
+.ui-buttonset {
+       margin-right: 7px;
+}
+.ui-buttonset .ui-button {
+       margin-left: 0;
+       margin-right: -.4em;
+}
+
+/* workarounds */
+button.ui-button::-moz-focus-inner {
+       border: 0;
+       padding: 0; /* reset extra padding in Firefox */
+}
+/* Disables the annoying dashed border Firefox puts on active buttons */
+body button.ui-button::-moz-focus-inner {
+       border: 0;
+}
+/* Give large buttons some extra padding */
+body .ui-button-large {
+       padding: 5px;
+}
+/* Use white icons for colored buttons */
+.ui-button-green .ui-icon,
+.ui-button-blue .ui-icon,
+.ui-button-red .ui-icon,
+.ui-button-orange .ui-icon {
+       /* @embed */
+       background-image: url(images/ui-icons_ffffff_256x240.png) !important;
+}
+
+/* Corner radius */
+/* This is normally handled in jquery.ui.theme.css, but in our case, the corner
+   styling of our buttons doesn't match our default widget corner styling */
+.ui-button.ui-corner-all,
+.ui-button.ui-corner-top,
+.ui-button.ui-corner-left,
+.ui-button.ui-corner-tl {
+       -moz-border-radius-topleft: 4px;
+       -webkit-border-top-left-radius: 4px;
+       border-top-left-radius: 4px;
+}
+.ui-button.ui-corner-all,
+.ui-button.ui-corner-top,
+
+.ui-button.ui-corner-right,
+.ui-button.ui-corner-tr {
+       -moz-border-radius-topright: 4px;
+       -webkit-border-top-right-radius: 4px;
+       border-top-right-radius: 4px;
+}
+.ui-button.ui-corner-all,
+.ui-button.ui-corner-bottom,
+.ui-button.ui-corner-left,
+.ui-button.ui-corner-bl {
+       -moz-border-radius-bottomleft: 4px;
+       -webkit-border-bottom-left-radius: 4px;
+       border-bottom-left-radius: 4px;
+}
+.ui-button.ui-corner-all,
+.ui-button.ui-corner-bottom,
+.ui-button.ui-corner-right,
+.ui-button.ui-corner-br {
+       -moz-border-radius-bottomright: 4px;
+       -webkit-border-bottom-right-radius: 4px;
+       border-bottom-right-radius: 4px;
+}
+
+body .ui-button {
+       color: #2779aa;
+       margin: 0.5em 0 0.5em 0.4em;
+       border: 1px solid #aaa !important;
+       background: #f0f0f0 !important;
+       background: -moz-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #fff 0%, #ddd 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #fff 0%, #ddd 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#dddddd', GradientType=0); /* IE6-8 */
+       cursor: pointer;
+       font-size: 1em;
+       line-height: 1.4em;
+       width: auto;
+       overflow: visible;
+       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.2);
+       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.2);
+       box-shadow: 0 1px 3px rgba(0,0,0,.2);
+}
+
+body .ui-button-icon-only {
+       width: 2.2em;
+}
+
+body .ui-button-icons-only {
+       width: 3.4em;
+}
+
+body .ui-button:hover {
+       color: #2779aa;
+       border-color: #bbb !important;
+       background: #fff !important;
+       background: -moz-linear-gradient(top, #fff 0%, #eee 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #fff 0%, #eee 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #fff 0%, #eee 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #fff 0%, #eee 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #fff 0%, #eee 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); /* IE6-8 */
+       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.1);
+       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.1);
+       box-shadow: 0 1px 3px rgba(0,0,0,.1);
+}
+body .ui-button:active,
+body .ui-button:focus {
+       border-color: #8ad !important;
+       -webkit-box-shadow: 0 0 1px 1px rgba(167,215,249,.5);
+       -moz-box-shadow: 0 0 1px 1px rgba(167,215,249,.5);
+       box-shadow: 0 0 1px 1px rgba(167,215,249,.5);
+}
+body .ui-button:active {
+       background: #e0e0e0 !important;
+       background: -moz-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #f0f0f0 0%, #d0d0d0 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #f0f0f0 0%, #d0d0d0 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f0f0f0', endColorstr='#d0d0d0', GradientType=0); /* IE6-8 */
+}
+
+/* Green buttons */
+body .ui-button-green,
+body .ui-button-green .ui-button-text {
+       color: white;
+       text-shadow: 0 -1px 1px #072;
+}
+body .ui-button.ui-button-green {
+       border-color: #294 !important;
+       background: #295 !important;
+       background: -moz-linear-gradient(top, #3c8 0%, #295 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #3c8 0%, #295 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #3c8 0%, #295 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #3c8 0%, #295 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #3c8 0%, #295 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#33cc88', endColorstr='#229955', GradientType=0); /* IE6-8 */
+       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.3);
+       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.3);
+       box-shadow: 0 1px 3px rgba(0,0,0,.3);
+}
+body .ui-button.ui-button-green:hover {
+       background: #33a055 !important;
+       background: -moz-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #44d388 0%, #33a055 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #44d388 0%, #33a055 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#44d388', endColorstr='#33a055', GradientType=0); /* IE6-8 */
+       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.25);
+       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.25);
+       box-shadow: 0 1px 3px rgba(0,0,0,.25);
+}
+body .ui-button.ui-button-green:active,
+body .ui-button.ui-button-green:focus {
+       border-color: #172 !important;
+       -webkit-box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
+       -moz-box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
+       box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
+}
+body .ui-button.ui-button-green:active {
+       background: #338855 !important;
+       background: -moz-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #30c080 0%, #338855 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #30c080 0%, #338855 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#30c080', endColorstr='#338855', GradientType=0); /* IE6-8 */
+}
+
+/* Blue buttons */
+body .ui-button-blue,
+body .ui-button-blue .ui-button-text {
+       color: white;
+       text-shadow: 0 -1px 1px #037;
+}
+body .ui-button.ui-button-blue {
+       border-color: #468 !important;
+       background: #36b !important;
+       background: -moz-linear-gradient(top, #48e 0%, #36b 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #48e 0%, #36b 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #48e 0%, #36b 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #48e 0%, #36b 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #48e 0%, #36b 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4488ee', endColorstr='#3366bb', GradientType=0); /* IE6-8 */
+       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.35);
+       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.35);
+       box-shadow: 0 1px 3px rgba(0,0,0,.35);
+}
+body .ui-button.ui-button-blue:hover {
+       background: #36c !important;
+       background: -moz-linear-gradient(top, #59e 0%, #36c 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #59e 0%, #36c 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #59e 0%, #36c 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #59e 0%, #36c 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #59e 0%, #36c 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5599ee', endColorstr='#3366cc', GradientType=0); /* IE6-8 */
+}
+body .ui-button.ui-button-blue:active,
+body .ui-button.ui-button-blue:focus {
+       border-color: #357 !important;
+       -webkit-box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
+       -moz-box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
+       box-shadow: 0 0 2px 2px rgba(167,215,249,.75);
+}
+body .ui-button.ui-button-blue:active {
+       background: #3060a0 !important;
+       background: -moz-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #4080e0 0%, #3060a0 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #4080e0 0%, #3060a0 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4080e0', endColorstr='#3060a0', GradientType=0); /* IE6-8 */
+}
+
+/* Red buttons */
+body .ui-button-red,
+body .ui-button-red .ui-button-text {
+       color: white;
+       text-shadow: 0 -1px 1px #700;
+}
+body .ui-button.ui-button-red {
+       border-color: #944 !important;
+       background: #a22 !important;
+       background: -moz-linear-gradient(top, #d44 0%, #a22 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #d44 0%, #a22 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #d44 0%, #a22 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #d44 0%, #a22 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #d44 0%, #a22 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dd4444', endColorstr='#aa2222', GradientType=0); /* IE6-8 */
+       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.35);
+       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.35);
+       box-shadow: 0 1px 3px rgba(0,0,0,.35);
+}
+body .ui-button.ui-button-red:hover {
+       border-color: #a44 !important;
+       background: #b03333 !important;
+       background: -moz-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #ee4646 0%, #b03333 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #ee4646 0%, #b03333 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee4646', endColorstr='#b03333', GradientType=0); /* IE6-8 */
+       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.3);
+       -moz-box-shadow: 0 1px 3px rgba(0,0,0,.3);
+       box-shadow: 0 1px 3px rgba(0,0,0,.3);
+}
+body .ui-button.ui-button-red:active,
+body .ui-button.ui-button-red:focus {
+       border-color: #747 !important;
+       -webkit-box-shadow: 0 0 2px 2px rgba(167,215,249,.7);
+       -moz-box-shadow: 0 0 2px 2px rgba(167,215,249,.7);
+       box-shadow: 0 0 2px 2px rgba(167,215,249,.7);
+}
+body .ui-button.ui-button-red:active {
+       background: #952020 !important;
+       background: -moz-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #d04545 0%, #952020 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #d04545 0%, #952020 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#d04545', endColorstr='#952020', GradientType=0); /* IE6-8 */
+}
+
+/* Disabled buttons */
+body .ui-button-green.disabled,
+body .ui-button-green.disabled:hover,
+body .ui-button-green.disabled:active,
+body .ui-button-green.disabled:focus,
+body .ui-button-blue.disabled,
+body .ui-button-blue.disabled:hover,
+body .ui-button-blue.disabled:active,
+body .ui-button-blue.disabled:focus,
+body .ui-button-red.disabled,
+body .ui-button-red.disabled:hover,
+body .ui-button-red.disabled:active,
+body .ui-button-red.disabled:focus,
+body .ui-button.disabled,
+body .ui-button.disabled:hover {
+       color: #aaa;
+       border-color: #ccc !important;
+       background: #eee !important;
+       background: -moz-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* FF3.6+ */
+       background: -webkit-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* Chrome10+, Safari5.1+ */
+       background: -o-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* Opera 11.10+ */
+       background: -ms-linear-gradient(top, #f6f6f6 0%, #eee 90%) !important; /* IE10+ */
+       background: linear-gradient(to bottom, #f6f6f6 0%, #eee 90%) !important;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6f6f6', endColorstr='#eeeeee', GradientType=0); /* IE6-8 */
+       -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0);
+       -moz-box-shadow: 0 1px 3px rgba(0,0,0,0);
+       box-shadow: 0 1px 3px rgba(0,0,0,0);
+}
+body .ui-button-green.disabled .ui-button-text,
+body .ui-button-blue.disabled .ui-button-text,
+body .ui-button-red.disabled .ui-button-text {
+       color: #aaa;
+       text-shadow: 0 1px 1px #fff;
+}
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.core.css b/resources/src/jquery.ui-themes/vector/jquery.ui.core.css
new file mode 100644 (file)
index 0000000..b3e8193
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+*/
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.datepicker.css b/resources/src/jquery.ui-themes/vector/jquery.ui.datepicker.css
new file mode 100644 (file)
index 0000000..871bf69
--- /dev/null
@@ -0,0 +1,61 @@
+/* Datepicker
+----------------------------------*/
+.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; padding:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month, 
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .2em 0 0 0; padding: 0 .2em; border-top: 1px solid #DDDDDD; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; }
+
+/* RTL support */
+/* @noflip */ .ui-datepicker-rtl { direction: rtl; }
+/* @noflip */ .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+/* @noflip */ .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+/* @noflip */ .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+/* @noflip */ .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+/* @noflip */ .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+/* @noflip */ .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+/* @noflip */ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+/* @noflip */ .ui-datepicker-rtl .ui-datepicker-group { float:right; }
+/* @noflip */ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+/* @noflip */ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+    display: none; /*sorry for IE5*/
+    display/**/: block; /*sorry for IE5*/
+    position: absolute; /*must have*/
+    z-index: -1; /*must have*/
+    filter: mask(); /*must have*/
+    top: -4px; /*must have*/
+    left: -4px; /*must have*/
+    width: 200px; /*must have*/
+    height: 200px; /*must have*/
+}
\ No newline at end of file
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.dialog.css b/resources/src/jquery.ui-themes/vector/jquery.ui.dialog.css
new file mode 100644 (file)
index 0000000..cd85f14
--- /dev/null
@@ -0,0 +1,37 @@
+/* Dialog
+----------------------------------*/
+.ui-dialog { position: absolute; padding: 0; width: 300px; }
+.ui-dialog .ui-dialog-titlebar { padding: .75em; position: relative;  }
+.ui-dialog .ui-dialog-title { float: left; margin: 0; } 
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .75em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/* Customizations */
+body .ui-dialog .ui-dialog-titlebar-close:hover {
+       text-decoration: none;
+}
+body .ui-dialog .ui-dialog-content .status-invalid input {
+       border: 2px solid red;
+       padding: 2px 1px;
+}
+body .ui-dialog .ui-dialog-titlebar {
+       padding: 0.9em 1.4em 0.6em !important;
+}
+body .ui-dialog .ui-widget-header {
+       /* @embed */
+       background: #f0f0f0 url(images/titlebar-fade.png) repeat-x scroll 50% 100% !important;
+}
+/* FIXME: Should just update the icon sprite if we're keeping this X */
+body .ui-dialog .ui-icon-closethick {
+       /* @embed */
+       background: url(images/close.png) no-repeat 50% 50% !important;
+}
+body .ui-dialog .ui-dialog-buttonpane {
+       margin-top: 0 !important;
+       padding:0.3em 1.4em 0.5em 1.4em !important;
+}
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.progressbar.css b/resources/src/jquery.ui-themes/vector/jquery.ui.progressbar.css
new file mode 100644 (file)
index 0000000..bc0939e
--- /dev/null
@@ -0,0 +1,4 @@
+/* Progressbar
+----------------------------------*/
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.resizable.css b/resources/src/jquery.ui-themes/vector/jquery.ui.resizable.css
new file mode 100644 (file)
index 0000000..f1bd7c5
--- /dev/null
@@ -0,0 +1,19 @@
+/* Resizable
+----------------------------------*/
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+/* @noflip */
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+/* @noflip */
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+/* @noflip */
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+/* @noflip */
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+/* @noflip */
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+/* @noflip */
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
\ No newline at end of file
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.selectable.css b/resources/src/jquery.ui-themes/vector/jquery.ui.selectable.css
new file mode 100644 (file)
index 0000000..c5d46ce
--- /dev/null
@@ -0,0 +1,3 @@
+/* Selectable
+----------------------------------*/
+.ui-selectable-helper { border:1px dotted black }
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.slider.css b/resources/src/jquery.ui-themes/vector/jquery.ui.slider.css
new file mode 100644 (file)
index 0000000..07c6f4e
--- /dev/null
@@ -0,0 +1,17 @@
+/* Slider
+----------------------------------*/
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }
\ No newline at end of file
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.tabs.css b/resources/src/jquery.ui-themes/vector/jquery.ui.tabs.css
new file mode 100644 (file)
index 0000000..99e16db
--- /dev/null
@@ -0,0 +1,11 @@
+/* Tabs
+----------------------------------*/
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.theme.css b/resources/src/jquery.ui-themes/vector/jquery.ui.theme.css
new file mode 100644 (file)
index 0000000..e39371d
--- /dev/null
@@ -0,0 +1,248 @@
+
+
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=sans-serif&fwDefault=normal&fsDefault=1.0em&cornerRadius=3px&bgColorHeader=ffffff&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=100&borderColorHeader=aed0ea&fcHeader=222222&iconColorHeader=72a7cf&bgColorContent=f2f5f7&bgTextureContent=04_highlight_hard.png&bgImgOpacityContent=100&borderColorContent=cccccc&fcContent=362b36&iconColorContent=72a7cf&bgColorDefault=d7ebf9&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=80&borderColorDefault=aed0ea&fcDefault=2779aa&iconColorDefault=3d80b3&bgColorHover=e4f1fb&bgTextureHover=03_highlight_soft.png&bgImgOpacityHover=100&borderColorHover=74b2e2&fcHover=0070a3&iconColorHover=2694e8&bgColorActive=f0f0f0&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=cccccc&fcActive=000000&iconColorActive=666666&bgColorHighlight=ffef8f&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=25&borderColorHighlight=f9dd34&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=cd0a0a&bgTextureError=01_flat.png&bgImgOpacityError=15&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffffff&bgColorOverlay=000000&bgTextureOverlay=21_glow_ball.png&bgImgOpacityOverlay=100&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=70&opacityShadow=20&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px
+*/
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: sans-serif; font-size: 0.8em; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #cccccc; /* @embed */ background: #f2f5f7 url(images/ui-bg_highlight-hard_100_f2f5f7_1x100.png) 50% top repeat-x; color: #362b36; }
+.ui-widget-content a { color: #362b36; }
+.ui-widget-header { border-bottom: 1px solid #bbbbbb; line-height: 1em; /* @embed */ background: #ffffff url(images/ui-bg_highlight-soft_100_ffffff_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
+.ui-widget-header a { color: #222222; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #aed0ea; /* @embed */ background: #d7ebf9 url(images/ui-bg_highlight-hard_80_d7ebf9_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #2779aa; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2779aa; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #74b2e2; /* @embed */ background: #e4f1fb url(images/ui-bg_highlight-soft_100_e4f1fb_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #0070a3; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #0070a3; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #cccccc; background: #f0f0f0 /* @embed */ url(images/ui-bg_inset-hard_100_f0f0f0_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #000000; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #000000; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #f9dd34; background: #ffef8f /* @embed */ url(images/ui-bg_highlight-soft_25_ffef8f_1x100.png) 50% top repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #cd0a0a /* @embed */ url(images/ui-bg_flat_15_cd0a0a_40x100.png) 50% 50% repeat-x; color: #ffffff; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; }
+.ui-icon, .ui-widget-content .ui-icon, .ui-widget-header .ui-icon { /* @embed */ background-image: url(images/ui-icons_72a7cf_256x240.png); }
+.ui-state-default .ui-icon { /* @embed */ background-image: url(images/ui-icons_3d80b3_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon { /* @embed */ background-image: url(images/ui-icons_2694e8_256x240.png); }
+.ui-state-active .ui-icon { /* @embed */ background-image: url(images/ui-icons_666666_256x240.png); }
+.ui-state-highlight .ui-icon { /* @embed */ background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon { /* @embed */ background-image: url(images/ui-icons_ffffff_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 0; -webkit-border-top-left-radius: 0; }
+.ui-corner-tr { -moz-border-radius-topright: 0; -webkit-border-top-right-radius: 0; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 0; -webkit-border-bottom-left-radius: 0; }
+.ui-corner-br { -moz-border-radius-bottomright: 0; -webkit-border-bottom-right-radius: 0; }
+.ui-corner-top { -moz-border-radius-topleft: 0; -webkit-border-top-left-radius: 0; -moz-border-radius-topright: 0; -webkit-border-top-right-radius: 0; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 0; -webkit-border-bottom-left-radius: 0; -moz-border-radius-bottomright: 0; -webkit-border-bottom-right-radius: 0; }
+.ui-corner-right {  -moz-border-radius-topright: 0; -webkit-border-top-right-radius: 0; -moz-border-radius-bottomright: 0; -webkit-border-bottom-right-radius: 0; }
+.ui-corner-left { -moz-border-radius-topleft: 0; -webkit-border-top-left-radius: 0; -moz-border-radius-bottomleft: 0; -webkit-border-bottom-left-radius: 0; }
+.ui-corner-all { -moz-border-radius: 0; -webkit-border-radius: 0; }
+
+/* Overlays */
+.ui-widget-overlay { background: #000000; opacity: .75;filter:Alpha(Opacity=75); }
+.ui-widget-shadow { margin: -7px 0 0 -7px; padding: 7px; /* @embed */ background: #000000 url(images/ui-bg_flat_70_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
\ No newline at end of file
diff --git a/resources/src/jquery/images/jquery.arrowSteps.divider-ltr.png b/resources/src/jquery/images/jquery.arrowSteps.divider-ltr.png
new file mode 100644 (file)
index 0000000..84ed2a2
Binary files /dev/null and b/resources/src/jquery/images/jquery.arrowSteps.divider-ltr.png differ
diff --git a/resources/src/jquery/images/jquery.arrowSteps.divider-rtl.png b/resources/src/jquery/images/jquery.arrowSteps.divider-rtl.png
new file mode 100644 (file)
index 0000000..7cfbfeb
Binary files /dev/null and b/resources/src/jquery/images/jquery.arrowSteps.divider-rtl.png differ
diff --git a/resources/src/jquery/images/jquery.arrowSteps.head-ltr.png b/resources/src/jquery/images/jquery.arrowSteps.head-ltr.png
new file mode 100644 (file)
index 0000000..eb07028
Binary files /dev/null and b/resources/src/jquery/images/jquery.arrowSteps.head-ltr.png differ
diff --git a/resources/src/jquery/images/jquery.arrowSteps.head-rtl.png b/resources/src/jquery/images/jquery.arrowSteps.head-rtl.png
new file mode 100644 (file)
index 0000000..7ea2fdb
Binary files /dev/null and b/resources/src/jquery/images/jquery.arrowSteps.head-rtl.png differ
diff --git a/resources/src/jquery/images/jquery.arrowSteps.tail-ltr.png b/resources/src/jquery/images/jquery.arrowSteps.tail-ltr.png
new file mode 100644 (file)
index 0000000..3ad990b
Binary files /dev/null and b/resources/src/jquery/images/jquery.arrowSteps.tail-ltr.png differ
diff --git a/resources/src/jquery/images/jquery.arrowSteps.tail-rtl.png b/resources/src/jquery/images/jquery.arrowSteps.tail-rtl.png
new file mode 100644 (file)
index 0000000..1d3048e
Binary files /dev/null and b/resources/src/jquery/images/jquery.arrowSteps.tail-rtl.png differ
diff --git a/resources/src/jquery/images/marker.png b/resources/src/jquery/images/marker.png
new file mode 100644 (file)
index 0000000..19efb6c
Binary files /dev/null and b/resources/src/jquery/images/marker.png differ
diff --git a/resources/src/jquery/images/mask.png b/resources/src/jquery/images/mask.png
new file mode 100644 (file)
index 0000000..fe08de0
Binary files /dev/null and b/resources/src/jquery/images/mask.png differ
diff --git a/resources/src/jquery/images/sort_both.gif b/resources/src/jquery/images/sort_both.gif
new file mode 100644 (file)
index 0000000..50ad15a
Binary files /dev/null and b/resources/src/jquery/images/sort_both.gif differ
diff --git a/resources/src/jquery/images/sort_down.gif b/resources/src/jquery/images/sort_down.gif
new file mode 100644 (file)
index 0000000..ec4f41b
Binary files /dev/null and b/resources/src/jquery/images/sort_down.gif differ
diff --git a/resources/src/jquery/images/sort_none.gif b/resources/src/jquery/images/sort_none.gif
new file mode 100644 (file)
index 0000000..edd07e5
Binary files /dev/null and b/resources/src/jquery/images/sort_none.gif differ
diff --git a/resources/src/jquery/images/sort_up.gif b/resources/src/jquery/images/sort_up.gif
new file mode 100644 (file)
index 0000000..8018918
Binary files /dev/null and b/resources/src/jquery/images/sort_up.gif differ
diff --git a/resources/src/jquery/images/spinner-large.gif b/resources/src/jquery/images/spinner-large.gif
new file mode 100644 (file)
index 0000000..72203fd
Binary files /dev/null and b/resources/src/jquery/images/spinner-large.gif differ
diff --git a/resources/src/jquery/images/spinner.gif b/resources/src/jquery/images/spinner.gif
new file mode 100644 (file)
index 0000000..6146be4
Binary files /dev/null and b/resources/src/jquery/images/spinner.gif differ
diff --git a/resources/src/jquery/images/wheel.png b/resources/src/jquery/images/wheel.png
new file mode 100644 (file)
index 0000000..7e53103
Binary files /dev/null and b/resources/src/jquery/images/wheel.png differ
diff --git a/resources/src/jquery/jquery.arrowSteps.css b/resources/src/jquery/jquery.arrowSteps.css
new file mode 100644 (file)
index 0000000..f8f6e95
--- /dev/null
@@ -0,0 +1,45 @@
+.arrowSteps {
+       list-style-type: none;
+       list-style-image: none;
+       border: 1px solid #666666;
+       position: relative;
+}
+
+.arrowSteps li {
+       float: left;
+       padding: 0px;
+       margin: 0px;
+       border: 0 none;
+}
+
+.arrowSteps li div {
+       padding: 0.5em;
+       text-align: center;
+       white-space: nowrap;
+       overflow: hidden;
+}
+
+.arrowSteps li.arrow div {
+       /* @embed */
+       background: url(images/jquery.arrowSteps.divider-ltr.png) no-repeat right center;
+}
+
+/* applied to the element preceding the highlighted step */
+.arrowSteps li.arrow.tail div {
+       /* @embed */
+       background: url(images/jquery.arrowSteps.tail-ltr.png) no-repeat right center;
+}
+
+/* this applies to all highlighted, including the last */
+.arrowSteps li.head div {
+       /* @embed */
+       background: url(images/jquery.arrowSteps.head-ltr.png) no-repeat left center;
+       font-weight: bold;
+}
+
+/* this applies to all highlighted arrows except the last */
+.arrowSteps li.arrow.head div {
+       /* TODO: eliminate duplication of jquery.arrowSteps.head.png embedding */
+       /* @embed */
+       background: url(images/jquery.arrowSteps.head-ltr.png) no-repeat right center;
+}
diff --git a/resources/src/jquery/jquery.arrowSteps.js b/resources/src/jquery/jquery.arrowSteps.js
new file mode 100644 (file)
index 0000000..c44e7c5
--- /dev/null
@@ -0,0 +1,92 @@
+/*!
+ * jQuery arrowSteps plugin
+ * Copyright Neil Kandalgaonkar, 2010
+ *
+ * This work is licensed under the terms of the GNU General Public License,
+ * version 2 or later.
+ * (see http://www.fsf.org/licensing/licenses/gpl.html).
+ * Derivative works and later versions of the code must be free software
+ * licensed under the same or a compatible license.
+ */
+
+/**
+ * @class jQuery.plugin.arrowSteps
+ */
+( function ( $ ) {
+       /**
+        * Show users their progress through a series of steps, via a row of items that fit
+        * together like arrows. One item can be highlighted at a time.
+        *
+        *     <ul id="robin-hood-daffy">
+        *       <li id="guard"><div>Guard!</div></li>
+        *       <li id="turn"><div>Turn!</div></li>
+        *       <li id="parry"><div>Parry!</div></li>
+        *       <li id="dodge"><div>Dodge!</div></li>
+        *       <li id="spin"><div>Spin!</div></li>
+        *       <li id="ha"><div>Ha!</div></li>
+        *       <li id="thrust"><div>Thrust!</div></li>
+        *     </ul>
+        *
+        *     <script>
+        *       $( '#robin-hood-daffy' ).arrowSteps();
+        *     </script>
+        *
+        * @return {jQuery}
+        * @chainable
+        */
+       $.fn.arrowSteps = function () {
+               var $steps, width, arrowWidth,
+                       paddingSide = $( 'body' ).hasClass( 'rtl' ) ? 'padding-left' : 'padding-right';
+
+               this.addClass( 'arrowSteps' );
+               $steps = this.find( 'li' );
+
+               width = parseInt( 100 / $steps.length, 10 );
+               $steps.css( 'width', width + '%' );
+
+               // Every step except the last one has an arrow pointing forward:
+               // at the right hand side in LTR languages, and at the left hand side in RTL.
+               // Also add in the padding for the calculated arrow width.
+               arrowWidth = parseInt( this.outerHeight(), 10 );
+               $steps.filter( ':not(:last-child)' ).addClass( 'arrow' )
+                     .find( 'div' ).css( paddingSide, arrowWidth.toString() + 'px' );
+
+               this.data( 'arrowSteps', $steps );
+               return this;
+       };
+
+       /**
+        * Highlights the element selected by the selector.
+        *
+        *       $( '#robin-hood-daffy' ).arrowStepsHighlight( '#guard' );
+        *       // 'Guard!' is highlighted.
+        *
+        *       // ... user completes the 'guard' step ...
+        *
+        *       $( '#robin-hood-daffy' ).arrowStepsHighlight( '#turn' );
+        *       // 'Turn!' is highlighted.
+        *
+        * @param {string} selector
+        */
+       $.fn.arrowStepsHighlight = function ( selector ) {
+               var $previous,
+                       $steps = this.data( 'arrowSteps' );
+               $.each( $steps, function ( i, step ) {
+                       var $step = $( step );
+                       if ( $step.is( selector ) ) {
+                               if ($previous) {
+                                       $previous.addClass( 'tail' );
+                               }
+                               $step.addClass( 'head' );
+                       } else {
+                               $step.removeClass( 'head tail lasthead' );
+                       }
+                       $previous = $step;
+               } );
+       };
+
+       /**
+        * @class jQuery
+        * @mixins jQuery.plugin.arrowSteps
+        */
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.autoEllipsis.js b/resources/src/jquery/jquery.autoEllipsis.js
new file mode 100644 (file)
index 0000000..57d8f94
--- /dev/null
@@ -0,0 +1,168 @@
+/**
+ * @class jQuery.plugin.autoEllipsis
+ */
+( function ( $ ) {
+
+var
+       // Cache ellipsed substrings for every string-width-position combination
+       cache = {},
+
+       // Use a separate cache when match highlighting is enabled
+       matchTextCache = {};
+
+/**
+ * Automatically truncate the plain text contents of an element and add an ellipsis
+ *
+ * @param {Object} options
+ * @param {'center'|'left'|'right'} [options.position='center'] Where to remove text.
+ * @param {boolean} [options.tooltip=false] Whether to show a tooltip with the remainder
+ * of the text.
+ * @param {boolean} [options.restoreText=false] Whether to save the text for restoring
+ * later.
+ * @param {boolean} [options.hasSpan=false] Whether the element is already a container,
+ * or if the library should create a new container for it.
+ * @param {string|null} [options.matchText=null] Text to highlight, e.g. search terms.
+ * @return {jQuery}
+ * @chainable
+ */
+$.fn.autoEllipsis = function ( options ) {
+       options = $.extend( {
+               position: 'center',
+               tooltip: false,
+               restoreText: false,
+               hasSpan: false,
+               matchText: null
+       }, options );
+
+       return this.each( function () {
+               var $trimmableText,
+                       text, trimmableText, w, pw,
+                       l, r, i, side, m,
+                       // container element - used for measuring against
+                       $container = $(this);
+
+               if ( options.restoreText ) {
+                       if ( !$container.data( 'autoEllipsis.originalText' ) ) {
+                               $container.data( 'autoEllipsis.originalText', $container.text() );
+                       } else {
+                               $container.text( $container.data( 'autoEllipsis.originalText' ) );
+                       }
+               }
+
+               // trimmable text element - only the text within this element will be trimmed
+               if ( options.hasSpan ) {
+                       $trimmableText = $container.children( options.selector );
+               } else {
+                       $trimmableText = $( '<span>' )
+                               .css( 'whiteSpace', 'nowrap' )
+                               .text( $container.text() );
+                       $container
+                               .empty()
+                               .append( $trimmableText );
+               }
+
+               text = $container.text();
+               trimmableText = $trimmableText.text();
+               w = $container.width();
+               pw = 0;
+
+               // Try cache
+               if ( options.matchText ) {
+                       if ( !( text in matchTextCache ) ) {
+                               matchTextCache[text] = {};
+                       }
+                       if ( !( options.matchText in matchTextCache[text] ) ) {
+                               matchTextCache[text][options.matchText] = {};
+                       }
+                       if ( !( w in matchTextCache[text][options.matchText] ) ) {
+                               matchTextCache[text][options.matchText][w] = {};
+                       }
+                       if ( options.position in matchTextCache[text][options.matchText][w] ) {
+                               $container.html( matchTextCache[text][options.matchText][w][options.position] );
+                               if ( options.tooltip ) {
+                                       $container.attr( 'title', text );
+                               }
+                               return;
+                       }
+               } else {
+                       if ( !( text in cache ) ) {
+                               cache[text] = {};
+                       }
+                       if ( !( w in cache[text] ) ) {
+                               cache[text][w] = {};
+                       }
+                       if ( options.position in cache[text][w] ) {
+                               $container.html( cache[text][w][options.position] );
+                               if ( options.tooltip ) {
+                                       $container.attr( 'title', text );
+                               }
+                               return;
+                       }
+               }
+
+               if ( $trimmableText.width() + pw > w ) {
+                       switch ( options.position ) {
+                               case 'right':
+                                       // Use binary search-like technique for efficiency
+                                       l = 0;
+                                       r = trimmableText.length;
+                                       do {
+                                               m = Math.ceil( ( l + r ) / 2 );
+                                               $trimmableText.text( trimmableText.substr( 0, m ) + '...' );
+                                               if ( $trimmableText.width() + pw > w ) {
+                                                       // Text is too long
+                                                       r = m - 1;
+                                               } else {
+                                                       l = m;
+                                               }
+                                       } while ( l < r );
+                                       $trimmableText.text( trimmableText.substr( 0, l ) + '...' );
+                                       break;
+                               case 'center':
+                                       // TODO: Use binary search like for 'right'
+                                       i = [Math.round( trimmableText.length / 2 ), Math.round( trimmableText.length / 2 )];
+                                       // Begin with making the end shorter
+                                       side = 1;
+                                       while ( $trimmableText.outerWidth() + pw > w && i[0] > 0 ) {
+                                               $trimmableText.text( trimmableText.substr( 0, i[0] ) + '...' + trimmableText.substr( i[1] ) );
+                                               // Alternate between trimming the end and begining
+                                               if ( side === 0 ) {
+                                                       // Make the begining shorter
+                                                       i[0]--;
+                                                       side = 1;
+                                               } else {
+                                                       // Make the end shorter
+                                                       i[1]++;
+                                                       side = 0;
+                                               }
+                                       }
+                                       break;
+                               case 'left':
+                                       // TODO: Use binary search like for 'right'
+                                       r = 0;
+                                       while ( $trimmableText.outerWidth() + pw > w && r < trimmableText.length ) {
+                                               $trimmableText.text( '...' + trimmableText.substr( r ) );
+                                               r++;
+                                       }
+                                       break;
+                       }
+               }
+               if ( options.tooltip ) {
+                       $container.attr( 'title', text );
+               }
+               if ( options.matchText ) {
+                       $container.highlightText( options.matchText );
+                       matchTextCache[text][options.matchText][w][options.position] = $container.html();
+               } else {
+                       cache[text][w][options.position] = $container.html();
+               }
+
+       } );
+};
+
+/**
+ * @class jQuery
+ * @mixins jQuery.plugin.autoEllipsis
+ */
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.badge.css b/resources/src/jquery/jquery.badge.css
new file mode 100644 (file)
index 0000000..f313663
--- /dev/null
@@ -0,0 +1,37 @@
+.mw-badge {
+       min-width: 7px;
+       border-radius: 2px;
+       padding: 1px 4px;
+       text-align: center;
+       font-size: 12px;
+       line-height: 12px;
+       background-color: #d2d2d2;
+       cursor: pointer;
+}
+
+.mw-badge-content {
+       font-weight: bold;
+       color: white;
+       vertical-align: baseline;
+       text-shadow: 0 1px rgba(0, 0, 0, 0.4);
+}
+
+.mw-badge-inline {
+       margin-left: 3px;
+       display: inline-block;
+       /* Hack for IE6 and IE7 (bug 47926) */
+       zoom: 1;
+       *display: inline;
+
+}
+.mw-badge-overlay {
+       position: absolute;
+       bottom: -1px;
+       right: -3px;
+       z-index: 50;
+}
+
+.mw-badge-important {
+       background-color: #cc0000;
+}
+
diff --git a/resources/src/jquery/jquery.badge.js b/resources/src/jquery/jquery.badge.js
new file mode 100644 (file)
index 0000000..023b6e2
--- /dev/null
@@ -0,0 +1,88 @@
+/*!
+ * jQuery Badge plugin
+ *
+ * @license MIT
+ *
+ * @author Ryan Kaldari <rkaldari@wikimedia.org>, 2012
+ * @author Andrew Garrett <agarrett@wikimedia.org>, 2012
+ * @author Marius Hoch <hoo@online.de>, 2012
+ *
+ * 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.
+ *
+ * This program is distributed WITHOUT ANY WARRANTY.
+ */
+
+/**
+ * @class jQuery.plugin.badge
+ */
+( function ( $, mw ) {
+       /**
+        * Put a badge on an item on the page. The badge container will be appended to the selected element(s).
+        *
+        *     $element.badge( text );
+        *     $element.badge( 5 );
+        *     $element.badge( '100+' );
+        *     $element.badge( text, inline );
+        *     $element.badge( 'New', true );
+        *
+        * @param {number|string} text The value to display in the badge. If the value is falsey (0,
+        *  null, false, '', etc.), any existing badge will be removed.
+        * @param {boolean} [inline=true] True if the badge should be displayed inline, false
+        *  if the badge should overlay the parent element.
+        * @param {boolean} [displayZero=false] True if the number zero should be displayed,
+        *  false if the number zero should result in the badge being hidden
+        * @return {jQuery}
+        * @chainable
+        */
+       $.fn.badge = function ( text, inline, displayZero ) {
+               var $badge = this.find( '.mw-badge' ),
+                       badgeStyleClass = 'mw-badge-' + ( inline ? 'inline' : 'overlay' ),
+                       isImportant = true, displayBadge = true;
+
+               // If we're displaying zero, ensure style to be non-important
+               if ( mw.language.convertNumber( text, true ) === 0 ) {
+                       isImportant = false;
+                       if ( !displayZero ) {
+                               displayBadge = false;
+                       }
+               // If text is falsey (besides 0), hide the badge
+               } else if ( !text ) {
+                       displayBadge = false;
+               }
+
+               if ( displayBadge ) {
+                       // If a badge already exists, reuse it
+                       if ( $badge.length ) {
+                               $badge
+                                       .toggleClass( 'mw-badge-important', isImportant )
+                                       .find( '.mw-badge-content' )
+                                               .text( text );
+                       } else {
+                               // Otherwise, create a new badge with the specified text and style
+                               $badge = $( '<div class="mw-badge"></div>' )
+                                       .addClass( badgeStyleClass )
+                                       .toggleClass( 'mw-badge-important', isImportant )
+                                       .append(
+                                               $( '<span class="mw-badge-content"></span>' ).text( text )
+                                       )
+                                       .appendTo( this );
+                       }
+               } else {
+                       $badge.remove();
+               }
+               return this;
+       };
+
+       /**
+        * @class jQuery
+        * @mixins jQuery.plugin.badge
+        */
+}( jQuery, mediaWiki ) );
diff --git a/resources/src/jquery/jquery.byteLength.js b/resources/src/jquery/jquery.byteLength.js
new file mode 100644 (file)
index 0000000..398937e
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * jQuery.byteLength
+ *
+ * Calculate the byte length of a string (accounting for UTF-8).
+ *
+ * @author Jan Paul Posma, 2011
+ * @author Timo Tijhof, 2012
+ * @author David Chan, 2013
+ */
+jQuery.byteLength = function ( str ) {
+
+       // This basically figures out how many bytes a UTF-16 string (which is what js sees)
+       // will take in UTF-8 by replacing a 2 byte character with 2 *'s, etc, and counting that.
+       // Note, surrogate (\uD800-\uDFFF) characters are counted as 2 bytes, since there's two of them
+       // and the actual character takes 4 bytes in UTF-8 (2*2=4). Might not work perfectly in
+       // edge cases such as illegal sequences, but that should never happen.
+
+       // https://en.wikipedia.org/wiki/UTF-8#Description
+       // The mapping from UTF-16 code units to UTF-8 bytes is as follows:
+       // > Range 0000-007F: codepoints that become 1 byte of UTF-8
+       // > Range 0080-07FF: codepoints that become 2 bytes of UTF-8
+       // > Range 0800-D7FF: codepoints that become 3 bytes of UTF-8
+       // > Range D800-DFFF: Surrogates (each pair becomes 4 bytes of UTF-8)
+       // > Range E000-FFFF: codepoints that become 3 bytes of UTF-8 (continued)
+
+       return str
+               .replace( /[\u0080-\u07FF\uD800-\uDFFF]/g, '**' )
+               .replace( /[\u0800-\uD7FF\uE000-\uFFFF]/g, '***' )
+               .length;
+
+};
diff --git a/resources/src/jquery/jquery.byteLimit.js b/resources/src/jquery/jquery.byteLimit.js
new file mode 100644 (file)
index 0000000..17c1821
--- /dev/null
@@ -0,0 +1,235 @@
+/**
+ * @class jQuery.plugin.byteLimit
+ */
+( function ( $ ) {
+
+       /**
+        * Utility function to trim down a string, based on byteLimit
+        * and given a safe start position. It supports insertion anywhere
+        * in the string, so "foo" to "fobaro" if limit is 4 will result in
+        * "fobo", not "foba". Basically emulating the native maxlength by
+        * reconstructing where the insertion occured.
+        *
+        * @private
+        * @param {string} safeVal Known value that was previously returned by this
+        * function, if none, pass empty string.
+        * @param {string} newVal New value that may have to be trimmed down.
+        * @param {number} byteLimit Number of bytes the value may be in size.
+        * @param {Function} [fn] See jQuery.byteLimit.
+        * @return {Object}
+        * @return {string} return.newVal
+        * @return {boolean} return.trimmed
+        */
+       function trimValForByteLength( safeVal, newVal, byteLimit, fn ) {
+               var startMatches, endMatches, matchesLen, inpParts,
+                       oldVal = safeVal;
+
+               // Run the hook if one was provided, but only on the length
+               // assessment. The value itself is not to be affected by the hook.
+               if ( $.byteLength( fn ? fn( newVal ) : newVal ) <= byteLimit ) {
+                       // Limit was not reached, just remember the new value
+                       // and let the user continue.
+                       return {
+                               newVal: newVal,
+                               trimmed: false
+                       };
+               }
+
+               // Current input is longer than the active limit.
+               // Figure out what was added and limit the addition.
+               startMatches = 0;
+               endMatches = 0;
+
+               // It is important that we keep the search within the range of
+               // the shortest string's length.
+               // Imagine a user adds text that matches the end of the old value
+               // (e.g. "foo" -> "foofoo"). startMatches would be 3, but without
+               // limiting both searches to the shortest length, endMatches would
+               // also be 3.
+               matchesLen = Math.min( newVal.length, oldVal.length );
+
+               // Count same characters from the left, first.
+               // (if "foo" -> "foofoo", assume addition was at the end).
+               while (
+                       startMatches < matchesLen &&
+                       oldVal.charAt( startMatches ) === newVal.charAt( startMatches )
+               ) {
+                       startMatches += 1;
+               }
+
+               while (
+                       endMatches < ( matchesLen - startMatches ) &&
+                       oldVal.charAt( oldVal.length - 1 - endMatches ) === newVal.charAt( newVal.length - 1 - endMatches )
+               ) {
+                       endMatches += 1;
+               }
+
+               inpParts = [
+                       // Same start
+                       newVal.substring( 0, startMatches ),
+                       // Inserted content
+                       newVal.substring( startMatches, newVal.length - endMatches ),
+                       // Same end
+                       newVal.substring( newVal.length - endMatches )
+               ];
+
+               // Chop off characters from the end of the "inserted content" string
+               // until the limit is statisfied.
+               if ( fn ) {
+                       // stop, when there is nothing to slice - bug 41450
+                       while ( $.byteLength( fn( inpParts.join( '' ) ) ) > byteLimit && inpParts[1].length > 0 ) {
+                               inpParts[1] = inpParts[1].slice( 0, -1 );
+                       }
+               } else {
+                       while ( $.byteLength( inpParts.join( '' ) ) > byteLimit ) {
+                               inpParts[1] = inpParts[1].slice( 0, -1 );
+                       }
+               }
+
+               newVal = inpParts.join( '' );
+
+               return {
+                       newVal: newVal,
+                       trimmed: true
+               };
+       }
+
+       var eventKeys = [
+               'keyup.byteLimit',
+               'keydown.byteLimit',
+               'change.byteLimit',
+               'mouseup.byteLimit',
+               'cut.byteLimit',
+               'paste.byteLimit',
+               'focus.byteLimit',
+               'blur.byteLimit'
+       ].join( ' ' );
+
+       /**
+        * Enforces a byte limit on an input field, so that UTF-8 entries are counted as well,
+        * when, for example, a database field has a byte limit rather than a character limit.
+        * Plugin rationale: Browser has native maxlength for number of characters, this plugin
+        * exists to limit number of bytes instead.
+        *
+        * Can be called with a custom limit (to use that limit instead of the maxlength attribute
+        * value), a filter function (in case the limit should apply to something other than the
+        * exact input value), or both. Order of parameters is important!
+        *
+        * @param {number} [limit] Limit to enforce, fallsback to maxLength-attribute,
+        *  called with fetched value as argument.
+        * @param {Function} [fn] Function to call on the string before assessing the length.
+        * @return {jQuery}
+        * @chainable
+        */
+       $.fn.byteLimit = function ( limit, fn ) {
+               // If the first argument is the function,
+               // set fn to the first argument's value and ignore the second argument.
+               if ( $.isFunction( limit ) ) {
+                       fn = limit;
+                       limit = undefined;
+               // Either way, verify it is a function so we don't have to call
+               // isFunction again after this.
+               } else if ( !fn || !$.isFunction( fn ) ) {
+                       fn = undefined;
+               }
+
+               // The following is specific to each element in the collection.
+               return this.each( function ( i, el ) {
+                       var $el, elLimit, prevSafeVal;
+
+                       $el = $( el );
+
+                       // If no limit was passed to byteLimit(), use the maxlength value.
+                       // Can't re-use 'limit' variable because it's in the higher scope
+                       // that would affect the next each() iteration as well.
+                       // Note that we use attribute to read the value instead of property,
+                       // because in Chrome the maxLength property by default returns the
+                       // highest supported value (no indication that it is being enforced
+                       // by choice). We don't want to bind all of this for some ridiculously
+                       // high default number, unless it was explicitly set in the HTML.
+                       // Also cast to a (primitive) number (most commonly because the maxlength
+                       // attribute contains a string, but theoretically the limit parameter
+                       // could be something else as well).
+                       elLimit = Number( limit === undefined ? $el.attr( 'maxlength' ) : limit );
+
+                       // If there is no (valid) limit passed or found in the property,
+                       // skip this. The < 0 check is required for Firefox, which returns
+                       // -1  (instead of undefined) for maxLength if it is not set.
+                       if ( !elLimit || elLimit < 0 ) {
+                               return;
+                       }
+
+                       if ( fn ) {
+                               // Save function for reference
+                               $el.data( 'byteLimit.callback', fn );
+                       }
+
+                       // Remove old event handlers (if there are any)
+                       $el.off( '.byteLimit' );
+
+                       if ( fn ) {
+                               // Disable the native maxLength (if there is any), because it interferes
+                               // with the (differently calculated) byte limit.
+                               // Aside from being differently calculated (average chars with byteLimit
+                               // is lower), we also support a callback which can make it to allow longer
+                               // values (e.g. count "Foo" from "User:Foo").
+                               // maxLength is a strange property. Removing or setting the property to
+                               // undefined directly doesn't work. Instead, it can only be unset internally
+                               // by the browser when removing the associated attribute (Firefox/Chrome).
+                               // http://code.google.com/p/chromium/issues/detail?id=136004
+                               $el.removeAttr( 'maxlength' );
+
+                       } else {
+                               // If we don't have a callback the bytelimit can only be lower than the charlimit
+                               // (that is, there are no characters less than 1 byte in size). So lets (re-)enforce
+                               // the native limit for efficiency when possible (it will make the while-loop below
+                               // faster by there being less left to interate over).
+                               $el.attr( 'maxlength', elLimit );
+                       }
+
+                       // Safe base value, used to determine the path between the previous state
+                       // and the state that triggered the event handler below - and enforce the
+                       // limit approppiately (e.g. don't chop from the end if text was inserted
+                       // at the beginning of the string).
+                       prevSafeVal = '';
+
+                       // We need to listen to after the change has already happened because we've
+                       // learned that trying to guess the new value and canceling the event
+                       // accordingly doesn't work because the new value is not always as simple as:
+                       // oldValue + String.fromCharCode( e.which ); because of cut, paste, select-drag
+                       // replacements, and custom input methods and what not.
+                       // Even though we only trim input after it was changed (never prevent it), we do
+                       // listen on events that input text, because there are cases where the text has
+                       // changed while text is being entered and keyup/change will not be fired yet
+                       // (such as holding down a single key, fires keydown, and after each keydown,
+                       // we can trim the previous one).
+                       // See http://www.w3.org/TR/DOM-Level-3-Events/#events-keyboard-event-order for
+                       // the order and characteristics of the key events.
+                       $el.on( eventKeys, function () {
+                               var res = trimValForByteLength(
+                                       prevSafeVal,
+                                       this.value,
+                                       elLimit,
+                                       fn
+                               );
+
+                               // Only set value property if it was trimmed, because whenever the
+                               // value property is set, the browser needs to re-initiate the text context,
+                               // which moves the cursor at the end the input, moving it away from wherever it was.
+                               // This is a side-effect of limiting after the fact.
+                               if ( res.trimmed === true ) {
+                                       this.value = res.newVal;
+                               }
+                               // Always adjust prevSafeVal to reflect the input value. Not doing this could cause
+                               // trimValForByteLength to compare the new value to an empty string instead of the
+                               // old value, resulting in trimming always from the end (bug 40850).
+                               prevSafeVal = res.newVal;
+                       } );
+               } );
+       };
+
+       /**
+        * @class jQuery
+        * @mixins jQuery.plugin.byteLimit
+        */
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.checkboxShiftClick.js b/resources/src/jquery/jquery.checkboxShiftClick.js
new file mode 100644 (file)
index 0000000..b206566
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * jQuery checkboxShiftClick
+ *
+ * This will enable checkboxes to be checked or unchecked in a row by clicking one,
+ * holding shift and clicking another one.
+ *
+ * @author Timo Tijhof, 2011 - 2012
+ * @license GPL v2
+ */
+( function ( $ ) {
+       $.fn.checkboxShiftClick = function () {
+               var prevCheckbox = null,
+                       $box = this;
+               // When our boxes are clicked..
+               $box.click( function ( e ) {
+                       // And one has been clicked before...
+                       if ( prevCheckbox !== null && e.shiftKey ) {
+                               // Check or uncheck this one and all in-between checkboxes,
+                               // except for disabled ones
+                               $box
+                                       .slice(
+                                               Math.min( $box.index( prevCheckbox ), $box.index( e.target ) ),
+                                               Math.max( $box.index( prevCheckbox ), $box.index( e.target ) ) + 1
+                                       )
+                                       .filter( function () {
+                                               return !this.disabled;
+                                       } )
+                                       .prop( 'checked', !!e.target.checked );
+                       }
+                       // Either way, update the prevCheckbox variable to the one clicked now
+                       prevCheckbox = e.target;
+               } );
+               return $box;
+       };
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.client.js b/resources/src/jquery/jquery.client.js
new file mode 100644 (file)
index 0000000..6689b7c
--- /dev/null
@@ -0,0 +1,299 @@
+/**
+ * User-agent detection
+ */
+( function ( $ ) {
+
+       /* Private Members */
+
+       /**
+        * @var {Object} profileCache Keyed by userAgent string,
+        * value is the parsed $.client.profile object for that user agent.
+        */
+       var profileCache = {};
+
+       /* Public Methods */
+
+       $.client = {
+
+               /**
+                * Get an object containing information about the client.
+                *
+                * @param {Object} nav An object with atleast a 'userAgent' and 'platform' key.
+                * Defaults to the global Navigator object.
+                * @return {Object} The resulting client object will be in the following format:
+                *  {
+                *   'name': 'firefox',
+                *   'layout': 'gecko',
+                *   'layoutVersion': 20101026,
+                *   'platform': 'linux'
+                *   'version': '3.5.1',
+                *   'versionBase': '3',
+                *   'versionNumber': 3.5,
+                *  }
+                */
+               profile: function ( nav ) {
+                       /*jshint boss: true */
+
+                       if ( nav === undefined ) {
+                               nav = window.navigator;
+                       }
+
+                       // Use the cached version if possible
+                       if ( profileCache[ nav.userAgent + '|' + nav.platform ] !== undefined ) {
+                               return profileCache[ nav.userAgent + '|' + nav.platform ];
+                       }
+
+                       var
+                               versionNumber,
+                               key = nav.userAgent + '|' + nav.platform,
+
+                               /* Configuration */
+
+                               // Name of browsers or layout engines we don't recognize
+                               uk = 'unknown',
+                               // Generic version digit
+                               x = 'x',
+                               // Strings found in user agent strings that need to be conformed
+                               wildUserAgents = ['Opera', 'Navigator', 'Minefield', 'KHTML', 'Chrome', 'PLAYSTATION 3', 'Iceweasel'],
+                               // Translations for conforming user agent strings
+                               userAgentTranslations = [
+                                       // Tons of browsers lie about being something they are not
+                                       [/(Firefox|MSIE|KHTML,?\slike\sGecko|Konqueror)/, ''],
+                                       // Chrome lives in the shadow of Safari still
+                                       ['Chrome Safari', 'Chrome'],
+                                       // KHTML is the layout engine not the browser - LIES!
+                                       ['KHTML', 'Konqueror'],
+                                       // Firefox nightly builds
+                                       ['Minefield', 'Firefox'],
+                                       // This helps keep different versions consistent
+                                       ['Navigator', 'Netscape'],
+                                       // This prevents version extraction issues, otherwise translation would happen later
+                                       ['PLAYSTATION 3', 'PS3']
+                               ],
+                               // Strings which precede a version number in a user agent string - combined and used as
+                               // match 1 in version detection
+                               versionPrefixes = [
+                                       'camino', 'chrome', 'firefox', 'iceweasel', 'netscape', 'netscape6', 'opera', 'version', 'konqueror',
+                                       'lynx', 'msie', 'safari', 'ps3', 'android'
+                               ],
+                               // Used as matches 2, 3 and 4 in version extraction - 3 is used as actual version number
+                               versionSuffix = '(\\/|\\;?\\s|)([a-z0-9\\.\\+]*?)(\\;|dev|rel|\\)|\\s|$)',
+                               // Names of known browsers
+                               names = [
+                                       'camino', 'chrome', 'firefox', 'iceweasel', 'netscape', 'konqueror', 'lynx', 'msie', 'opera',
+                                       'safari', 'ipod', 'iphone', 'blackberry', 'ps3', 'rekonq', 'android'
+                               ],
+                               // Tanslations for conforming browser names
+                               nameTranslations = [],
+                               // Names of known layout engines
+                               layouts = ['gecko', 'konqueror', 'msie', 'trident', 'opera', 'webkit'],
+                               // Translations for conforming layout names
+                               layoutTranslations = [ ['konqueror', 'khtml'], ['msie', 'trident'], ['opera', 'presto'] ],
+                               // Names of supported layout engines for version number
+                               layoutVersions = ['applewebkit', 'gecko', 'trident'],
+                               // Names of known operating systems
+                               platforms = ['win', 'wow64', 'mac', 'linux', 'sunos', 'solaris', 'iphone'],
+                               // Translations for conforming operating system names
+                               platformTranslations = [ ['sunos', 'solaris'], ['wow64', 'win'] ],
+
+                               /* Methods */
+
+                               /**
+                                * Performs multiple replacements on a string
+                                */
+                               translate = function ( source, translations ) {
+                                       var i;
+                                       for ( i = 0; i < translations.length; i++ ) {
+                                               source = source.replace( translations[i][0], translations[i][1] );
+                                       }
+                                       return source;
+                               },
+
+                               /* Pre-processing */
+
+                               ua = nav.userAgent,
+                               match,
+                               name = uk,
+                               layout = uk,
+                               layoutversion = uk,
+                               platform = uk,
+                               version = x;
+
+                       if ( match = new RegExp( '(' + wildUserAgents.join( '|' ) + ')' ).exec( ua ) ) {
+                               // Takes a userAgent string and translates given text into something we can more easily work with
+                               ua = translate( ua, userAgentTranslations );
+                       }
+                       // Everything will be in lowercase from now on
+                       ua = ua.toLowerCase();
+
+                       /* Extraction */
+
+                       if ( match = new RegExp( '(' + names.join( '|' ) + ')' ).exec( ua ) ) {
+                               name = translate( match[1], nameTranslations );
+                       }
+                       if ( match = new RegExp( '(' + layouts.join( '|' ) + ')' ).exec( ua ) ) {
+                               layout = translate( match[1], layoutTranslations );
+                       }
+                       if ( match = new RegExp( '(' + layoutVersions.join( '|' ) + ')\\\/(\\d+)').exec( ua ) ) {
+                               layoutversion = parseInt( match[2], 10 );
+                       }
+                       if ( match = new RegExp( '(' + platforms.join( '|' ) + ')' ).exec( nav.platform.toLowerCase() ) ) {
+                               platform = translate( match[1], platformTranslations );
+                       }
+                       if ( match = new RegExp( '(' + versionPrefixes.join( '|' ) + ')' + versionSuffix ).exec( ua ) ) {
+                               version = match[3];
+                       }
+
+                       /* Edge Cases -- did I mention about how user agent string lie? */
+
+                       // Decode Safari's crazy 400+ version numbers
+                       if ( name === 'safari' && version > 400 ) {
+                               version = '2.0';
+                       }
+                       // Expose Opera 10's lies about being Opera 9.8
+                       if ( name === 'opera' && version >= 9.8 ) {
+                               match = ua.match( /\bversion\/([0-9\.]*)/ );
+                               if ( match && match[1] ) {
+                                       version = match[1];
+                               } else {
+                                       version = '10';
+                               }
+                       }
+                       // And Opera 15's lies about being Chrome
+                       if ( name === 'chrome' && ( match = ua.match( /\bopr\/([0-9\.]*)/ ) ) ) {
+                               if ( match[1] ) {
+                                       name = 'opera';
+                                       version = match[1];
+                               }
+                       }
+                       // And IE 11's lies about being not being IE
+                       if ( layout === 'trident' && layoutversion >= 7 && ( match = ua.match( /\brv[ :\/]([0-9\.]*)/ ) ) ) {
+                               if ( match[1] ) {
+                                       name = 'msie';
+                                       version = match[1];
+                               }
+                       }
+                       // And Amazon Silk's lies about being Android on mobile or Safari on desktop
+                       if ( match = ua.match( /\bsilk\/([0-9.\-_]*)/ ) ) {
+                               if ( match[1] ) {
+                                       name = 'silk';
+                                       version = match[1];
+                               }
+                       }
+
+                       versionNumber = parseFloat( version, 10 ) || 0.0;
+
+                       /* Caching */
+
+                       return profileCache[ key  ] = {
+                               name: name,
+                               layout: layout,
+                               layoutVersion: layoutversion,
+                               platform: platform,
+                               version: version,
+                               versionBase: ( version !== x ? Math.floor( versionNumber ).toString() : x ),
+                               versionNumber: versionNumber
+                       };
+               },
+
+               /**
+                * Checks the current browser against a support map object.
+                *
+                * Version numbers passed as numeric values will be compared like numbers (1.2 > 1.11).
+                * Version numbers passed as string values will be compared using a simple component-wise
+                * algorithm, similar to PHP's version_compare ('1.2' < '1.11').
+                *
+                * A browser map is in the following format:
+                * {
+                *   // Multiple rules with configurable operators
+                *   'msie': [['>=', 7], ['!=', 9]],
+                *    // Match no versions
+                *   'iphone': false,
+                *    // Match any version
+                *   'android': null
+                * }
+                *
+                * It can optionally be split into ltr/rtl sections:
+                * {
+                *   'ltr': {
+                *     'android': null,
+                *     'iphone': false
+                *   },
+                *   'rtl': {
+                *     'android': false,
+                *     // rules are not inherited from ltr
+                *     'iphone': false
+                *   }
+                * }
+                *
+                * @param {Object} map Browser support map
+                * @param {Object} [profile] A client-profile object
+                * @param {boolean} [exactMatchOnly=false] Only return true if the browser is matched, otherwise
+                * returns true if the browser is not found.
+                *
+                * @return {boolean} The current browser is in the support map
+                */
+               test: function ( map, profile, exactMatchOnly ) {
+                       /*jshint evil: true */
+
+                       var conditions, dir, i, op, val, j, pieceVersion, pieceVal, compare;
+                       profile = $.isPlainObject( profile ) ? profile : $.client.profile();
+                       if ( map.ltr && map.rtl ) {
+                               dir = $( 'body' ).is( '.rtl' ) ? 'rtl' : 'ltr';
+                               map = map[dir];
+                       }
+                       // Check over each browser condition to determine if we are running in a compatible client
+                       if ( typeof map !== 'object' || map[profile.name] === undefined ) {
+                               // Not found, return true if exactMatchOnly not set, false otherwise
+                               return !exactMatchOnly;
+                       }
+                       conditions = map[profile.name];
+                       if ( conditions === false ) {
+                               // Match no versions
+                               return false;
+                       }
+                       if ( conditions === null ) {
+                               // Match all versions
+                               return true;
+                       }
+                       for ( i = 0; i < conditions.length; i++ ) {
+                               op = conditions[i][0];
+                               val = conditions[i][1];
+                               if ( typeof val === 'string' ) {
+                                       // Perform a component-wise comparison of versions, similar to PHP's version_compare
+                                       // but simpler. '1.11' is larger than '1.2'.
+                                       pieceVersion = profile.version.toString().split( '.' );
+                                       pieceVal = val.split( '.' );
+                                       // Extend with zeroes to equal length
+                                       while ( pieceVersion.length < pieceVal.length ) {
+                                               pieceVersion.push( '0' );
+                                       }
+                                       while ( pieceVal.length < pieceVersion.length ) {
+                                               pieceVal.push( '0' );
+                                       }
+                                       // Compare components
+                                       compare = 0;
+                                       for ( j = 0; j < pieceVersion.length; j++ ) {
+                                               if ( Number( pieceVersion[j] ) < Number( pieceVal[j] ) ) {
+                                                       compare = -1;
+                                                       break;
+                                               } else if ( Number( pieceVersion[j] ) > Number( pieceVal[j] ) ) {
+                                                       compare = 1;
+                                                       break;
+                                               }
+                                       }
+                                       // compare will be -1, 0 or 1, depending on comparison result
+                                       if ( !( eval( '' + compare + op + '0' ) ) ) {
+                                               return false;
+                                       }
+                               } else if ( typeof val === 'number' ) {
+                                       if ( !( eval( 'profile.versionNumber' + op + val ) ) ) {
+                                               return false;
+                                       }
+                               }
+                       }
+
+                       return true;
+               }
+       };
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.color.js b/resources/src/jquery/jquery.color.js
new file mode 100644 (file)
index 0000000..04f8047
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ * jQuery Color Animations
+ *
+ * @author John Resig, 2007
+ * @author Krinkle, 2011
+ * Released under the MIT and GPL licenses.
+ *
+ * - 2011-01-05: Forked for MediaWiki. See also jQuery.colorUtil plugin
+ */
+( function ( $ ) {
+
+       function getColor( elem, attr ) {
+               /*jshint boss:true */
+               var color;
+
+               do {
+                       color = $.css( elem, attr );
+
+                       // Keep going until we find an element that has color, or we hit the body
+                       if ( color !== '' && color !== 'transparent' || $.nodeName( elem, 'body' ) ) {
+                               break;
+                       }
+
+                       attr = 'backgroundColor';
+               } while ( elem = elem.parentNode );
+
+               return $.colorUtil.getRGB( color );
+       }
+
+       // We override the animation for all of these color styles
+       $.each([
+               'backgroundColor',
+               'borderBottomColor',
+               'borderLeftColor',
+               'borderRightColor',
+               'borderTopColor',
+               'color',
+               'outlineColor'
+       ], function ( i, attr ) {
+               $.fx.step[attr] = function ( fx ) {
+                       if ( !fx.colorInit ) {
+                               fx.start = getColor( fx.elem, attr );
+                               fx.end = $.colorUtil.getRGB( fx.end );
+                               fx.colorInit = true;
+                       }
+
+                       fx.elem.style[attr] = 'rgb(' + [
+                               Math.max( Math.min( parseInt( (fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10 ), 255 ), 0 ),
+                               Math.max( Math.min( parseInt( (fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10 ), 255 ), 0 ),
+                               Math.max( Math.min( parseInt( (fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10 ), 255 ), 0 )
+                       ].join( ',' ) + ')';
+               };
+       } );
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.colorUtil.js b/resources/src/jquery/jquery.colorUtil.js
new file mode 100644 (file)
index 0000000..37bf176
--- /dev/null
@@ -0,0 +1,219 @@
+/**
+ * jQuery Color Utilities
+ * Written by Krinkle in 2011
+ * Released under the MIT and GPL licenses.
+ * Mostly based on other plugins and functions (linted and optimized a little).
+ * Sources cited inline.
+ */
+( function ( $ ) {
+       $.colorUtil = {
+
+               // Color Conversion function from highlightFade
+               // By Blair Mitchelmore
+               // http://jquery.offput.ca/highlightFade/
+               // Parse strings looking for color tuples [255,255,255]
+               getRGB: function ( color ) {
+                       /*jshint boss:true */
+                       var result;
+
+                       // Check if we're already dealing with an array of colors
+                       if ( color && $.isArray( color ) && color.length === 3 ) {
+                               return color;
+                       }
+
+                       // Look for rgb(num,num,num)
+                       if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) {
+                               return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
+                       }
+
+                       // Look for rgb(num%,num%,num%)
+                       if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) {
+                               return [parseFloat(result[1],10) * 2.55, parseFloat(result[2],10) * 2.55, parseFloat(result[3]) * 2.55];
+                       }
+
+                       // Look for #a0b1c2
+                       if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) {
+                               return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
+                       }
+
+                       // Look for #fff
+                       if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) {
+                               return [parseInt(result[1] + result[1],16), parseInt(result[2] + result[2],16), parseInt(result[3] + result[3],16)];
+                       }
+
+                       // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
+                       if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) {
+                               return $.colorUtil.colors.transparent;
+                       }
+
+                       // Otherwise, we're most likely dealing with a named color
+                       return $.colorUtil.colors[$.trim(color).toLowerCase()];
+               },
+
+               // Some named colors to work with
+               // From Interface by Stefan Petre
+               // http://interface.eyecon.ro/
+               colors: {
+                       aqua: [0,255,255],
+                       azure: [240,255,255],
+                       beige: [245,245,220],
+                       black: [0,0,0],
+                       blue: [0,0,255],
+                       brown: [165,42,42],
+                       cyan: [0,255,255],
+                       darkblue: [0,0,139],
+                       darkcyan: [0,139,139],
+                       darkgrey: [169,169,169],
+                       darkgreen: [0,100,0],
+                       darkkhaki: [189,183,107],
+                       darkmagenta: [139,0,139],
+                       darkolivegreen: [85,107,47],
+                       darkorange: [255,140,0],
+                       darkorchid: [153,50,204],
+                       darkred: [139,0,0],
+                       darksalmon: [233,150,122],
+                       darkviolet: [148,0,211],
+                       fuchsia: [255,0,255],
+                       gold: [255,215,0],
+                       green: [0,128,0],
+                       indigo: [75,0,130],
+                       khaki: [240,230,140],
+                       lightblue: [173,216,230],
+                       lightcyan: [224,255,255],
+                       lightgreen: [144,238,144],
+                       lightgrey: [211,211,211],
+                       lightpink: [255,182,193],
+                       lightyellow: [255,255,224],
+                       lime: [0,255,0],
+                       magenta: [255,0,255],
+                       maroon: [128,0,0],
+                       navy: [0,0,128],
+                       olive: [128,128,0],
+                       orange: [255,165,0],
+                       pink: [255,192,203],
+                       purple: [128,0,128],
+                       violet: [128,0,128],
+                       red: [255,0,0],
+                       silver: [192,192,192],
+                       white: [255,255,255],
+                       yellow: [255,255,0],
+                       transparent: [255,255,255]
+               },
+
+               /**
+                * http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
+                * Converts an RGB color value to HSL. Conversion formula
+                * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
+                * Assumes r, g, and b are contained in the set [0, 255] and
+                * returns h, s, and l in the set [0, 1].
+                *
+                * @param       Number  R               The red color value
+                * @param       Number  G               The green color value
+                * @param       Number  B               The blue color value
+                * @return      Array                   The HSL representation
+                */
+               rgbToHsl: function ( R, G, B ) {
+                       var d,
+                               r = R / 255,
+                               g = G / 255,
+                               b = B / 255,
+                               max = Math.max( r, g, b ), min = Math.min( r, g, b ),
+                               h,
+                               s,
+                               l = (max + min) / 2;
+
+                       if ( max === min ) {
+                               // achromatic
+                               h = s = 0;
+                       } else {
+                               d = max - min;
+                               s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
+                               switch ( max ) {
+                                       case r:
+                                               h = (g - b) / d + (g < b ? 6 : 0);
+                                               break;
+                                       case g:
+                                               h = (b - r) / d + 2;
+                                               break;
+                                       case b:
+                                               h = (r - g) / d + 4;
+                                               break;
+                               }
+                               h /= 6;
+                       }
+
+                       return [h, s, l];
+               },
+
+               /**
+                * http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
+                * Converts an HSL color value to RGB. Conversion formula
+                * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
+                * Assumes h, s, and l are contained in the set [0, 1] and
+                * returns r, g, and b in the set [0, 255].
+                *
+                * @param       Number  h               The hue
+                * @param       Number  s               The saturation
+                * @param       Number  l               The lightness
+                * @return      Array                   The RGB representation
+                */
+               hslToRgb: function ( h, s, l ) {
+                       var r, g, b, hue2rgb, q, p;
+
+                       if ( s === 0 ) {
+                               r = g = b = l; // achromatic
+                       } else {
+                               hue2rgb = function ( p, q, t ) {
+                                       if ( t < 0 ) {
+                                               t += 1;
+                                       }
+                                       if ( t > 1 ) {
+                                               t -= 1;
+                                       }
+                                       if ( t < 1 / 6 ) {
+                                               return p + (q - p) * 6 * t;
+                                       }
+                                       if ( t < 1 / 2 ) {
+                                               return q;
+                                       }
+                                       if ( t < 2 / 3 ) {
+                                               return p + (q - p) * (2 / 3 - t) * 6;
+                                       }
+                                       return p;
+                               };
+
+                               q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+                               p = 2 * l - q;
+                               r = hue2rgb( p, q, h + 1 / 3 );
+                               g = hue2rgb( p, q, h );
+                               b = hue2rgb( p, q, h - 1 / 3 );
+                       }
+
+                       return [r * 255, g * 255, b * 255];
+               },
+
+               /**
+                * Get's a brighter or darker rgb() value string.
+                *
+                * @author Krinkle
+                *
+                * @example     getCSSColorMod( 'red', +0.1 )
+                * @example     getCSSColorMod( 'rgb(200,50,50)', -0.2 )
+                *
+                * @param       Mixed   currentColor current value in css
+                * @param       Number  mod wanted brightness modification between -1 and 1
+                * @return      String 'rgb(r,g,b)'
+                */
+               getColorBrightness: function ( currentColor, mod ) {
+                       var rgbArr = $.colorUtil.getRGB( currentColor ),
+                               hslArr = $.colorUtil.rgbToHsl(rgbArr[0], rgbArr[1], rgbArr[2] );
+                       rgbArr = $.colorUtil.hslToRgb(hslArr[0], hslArr[1], hslArr[2] + mod);
+
+                       return 'rgb(' +
+                               [parseInt( rgbArr[0], 10), parseInt( rgbArr[1], 10 ), parseInt( rgbArr[2], 10 )].join( ',' ) +
+                               ')';
+               }
+
+       };
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.delayedBind.js b/resources/src/jquery/jquery.delayedBind.js
new file mode 100644 (file)
index 0000000..874c111
--- /dev/null
@@ -0,0 +1,83 @@
+( function ( mw, $ ) {
+/**
+ * Function that escapes spaces in event names. This is needed because
+ * "_delayedBind-foo bar-1000" refers to two events
+ */
+function encodeEvent( event ) {
+       return event.replace( /-/g, '--' ).replace( / /g, '-' );
+}
+
+$.fn.extend( {
+       /**
+        * Bind a callback to an event in a delayed fashion.
+        * In detail, this means that the callback will be called a certain
+        * time after the event fires, but the timer is reset every time
+        * the event fires.
+        * @param timeout Number of milliseconds to wait
+        * @param event Name of the event (string)
+        * @param data Data to pass to the event handler (optional)
+        * @param callback Function to call
+        */
+       delayedBind: function ( timeout, event, data, callback ) {
+               if ( arguments.length === 3 ) {
+                       // Shift optional parameter down
+                       callback = data;
+                       data = undefined;
+               }
+               var encEvent = encodeEvent( event );
+               return this.each( function () {
+                       var that = this;
+                       // Bind the top half
+                       // Do this only once for every (event, timeout) pair
+                       if (  !( $(this).data( '_delayedBindBound-' + encEvent + '-' + timeout ) ) ) {
+                               $(this).data( '_delayedBindBound-' + encEvent + '-' + timeout, true );
+                               $(this).bind( event, function () {
+                                       var timerID = $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout );
+                                       // Cancel the running timer
+                                       if ( timerID !== null ) {
+                                               clearTimeout( timerID );
+                                       }
+                                       timerID = setTimeout( function () {
+                                               $(that).trigger( '_delayedBind-' + encEvent + '-' + timeout );
+                                       }, timeout );
+                                       $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout, timerID );
+                               } );
+                       }
+
+                       // Bottom half
+                       $(this).bind( '_delayedBind-' + encEvent + '-' + timeout, data, callback );
+               } );
+       },
+
+       /**
+        * Cancel the timers for delayed events on the selected elements.
+        */
+       delayedBindCancel: function ( timeout, event ) {
+               var encEvent = encodeEvent( event );
+               return this.each( function () {
+                       var timerID = $(this).data( '_delayedBindTimerID-' + encEvent + '-' + timeout );
+                       if ( timerID !== null ) {
+                               clearTimeout( timerID );
+                       }
+               } );
+       },
+
+       /**
+        * Unbind an event bound with delayedBind()
+        */
+       delayedBindUnbind: function ( timeout, event, callback ) {
+               var encEvent = encodeEvent( event );
+               return this.each( function () {
+                       $(this).unbind( '_delayedBind-' + encEvent + '-' + timeout, callback );
+               } );
+       }
+} );
+
+mw.log.deprecate( $.fn, 'delayedBind', $.fn.delayedBind,
+       'Use the jquery.throttle-debounce module instead' );
+mw.log.deprecate( $.fn, 'delayedBindCancel', $.fn.delayedBindCancel,
+       'Use the jquery.throttle-debounce module instead' );
+mw.log.deprecate( $.fn, 'delayedBindUnbind', $.fn.delayedBindUnbind,
+       'Use the jquery.throttle-debounce module instead' );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/jquery/jquery.expandableField.js b/resources/src/jquery/jquery.expandableField.js
new file mode 100644 (file)
index 0000000..732cc6e
--- /dev/null
@@ -0,0 +1,140 @@
+/**
+ * This plugin provides functionality to expand a text box on focus to double it's current width
+ *
+ * Usage:
+ *
+ * Set options:
+ *             $('#textbox').expandableField( { option1: value1, option2: value2 } );
+ *             $('#textbox').expandableField( option, value );
+ * Get option:
+ *             value = $('#textbox').expandableField( option );
+ * Initialize:
+ *             $('#textbox').expandableField();
+ *
+ * Options:
+ *
+ */
+( function ( $ ) {
+
+       $.expandableField = {
+               /**
+                * Expand the field, make the callback
+                */
+               expandField: function ( e, context ) {
+                       context.config.beforeExpand.call( context.data.$field, context );
+                       context.data.$field
+                               .animate( { 'width': context.data.expandedWidth }, 'fast', function () {
+                                       context.config.afterExpand.call( this, context );
+                               } );
+               },
+               /**
+                * Condense the field, make the callback
+                */
+               condenseField: function ( e, context ) {
+                       context.config.beforeCondense.call( context.data.$field, context );
+                       context.data.$field
+                               .animate( { 'width': context.data.condensedWidth }, 'fast', function () {
+                                       context.config.afterCondense.call( this, context );
+                               } );
+               },
+               /**
+                * Sets the value of a property, and updates the widget accordingly
+                * @param property String Name of property
+                * @param value Mixed Value to set property with
+                */
+               configure: function ( context, property, value ) {
+                       // TODO: Validate creation using fallback values
+                       context.config[property] = value;
+               }
+
+       };
+
+       $.fn.expandableField = function () {
+
+               // Multi-context fields
+               var returnValue,
+                       args = arguments;
+
+               $( this ).each( function () {
+                       var key, context, timeout;
+
+                       /* Construction / Loading */
+
+                       context = $( this ).data( 'expandableField-context' );
+
+                       // TODO: Do we need to check both null and undefined?
+                       if ( context === undefined || context === null ) {
+                               context = {
+                                       config: {
+                                               // callback function for before collapse
+                                               beforeCondense: function () {},
+
+                                               // callback function for before expand
+                                               beforeExpand: function () {},
+
+                                               // callback function for after collapse
+                                               afterCondense: function () {},
+
+                                               // callback function for after expand
+                                               afterExpand: function () {},
+
+                                               // Whether the field should expand to the left or the right -- defaults to left
+                                               expandToLeft: true
+                                       }
+                               };
+                       }
+
+                       /* API */
+                       // Handle various calling styles
+                       if ( args.length > 0 ) {
+                               if ( typeof args[0] === 'object' ) {
+                                       // Apply set of properties
+                                       for ( key in args[0] ) {
+                                               $.expandableField.configure( context, key, args[0][key] );
+                                       }
+                               } else if ( typeof args[0] === 'string' ) {
+                                       if ( args.length > 1 ) {
+                                               // Set property values
+                                               $.expandableField.configure( context, args[0], args[1] );
+
+                                       // TODO: Do we need to check both null and undefined?
+                                       } else if ( returnValue === null || returnValue === undefined ) {
+                                               // Get property values, but don't give access to internal data - returns only the first
+                                               returnValue = ( args[0] in context.config ? undefined : context.config[args[0]] );
+                                       }
+                               }
+                       }
+
+                       /* Initialization */
+
+                       if ( context.data === undefined ) {
+                               context.data = {
+                                       // The width of the field in it's condensed state
+                                       condensedWidth: $( this ).width(),
+
+                                       // The width of the field in it's expanded state
+                                       expandedWidth: $( this ).width() * 2,
+
+                                       // Reference to the field
+                                       $field: $( this )
+                               };
+
+                               $( this )
+                                       .addClass( 'expandableField' )
+                                       .focus( function ( e ) {
+                                               clearTimeout( timeout );
+                                               $.expandableField.expandField( e, context );
+                                       } )
+                                       .blur( function ( e ) {
+                                               timeout = setTimeout( function () {
+                                                       $.expandableField.condenseField( e, context );
+                                               }, 250 );
+                                       } );
+                       }
+                       // Store the context for next time
+                       $( this ).data( 'expandableField-context', context );
+               } );
+               return returnValue !== undefined ? returnValue : $(this);
+       };
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.farbtastic.css b/resources/src/jquery/jquery.farbtastic.css
new file mode 100644 (file)
index 0000000..1c6428f
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * Farbtastic Color Picker 1.2
+ * © 2008 Steven Wittens
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+.farbtastic {
+       position: relative;
+}
+.farbtastic * {
+       position: absolute;
+       cursor: crosshair;
+}
+.farbtastic, .farbtastic .wheel {
+       width: 195px;
+       height: 195px;
+}
+.farbtastic .color, .farbtastic .overlay {
+       top: 47px;
+       left: 47px;
+       width: 101px;
+       height: 101px;
+}
+.farbtastic .wheel {
+       /* @embed */
+       background: url(images/wheel.png) no-repeat;
+       width: 195px;
+       height: 195px;
+}
+.farbtastic .overlay {
+       /* @embed */
+       background: url(images/mask.png) no-repeat;
+}
+.farbtastic .marker {
+       width: 17px;
+       height: 17px;
+       margin: -8px 0 0 -8px;
+       overflow: hidden;
+       /* @embed */
+       background: url(images/marker.png) no-repeat;
+}
+
diff --git a/resources/src/jquery/jquery.farbtastic.js b/resources/src/jquery/jquery.farbtastic.js
new file mode 100644 (file)
index 0000000..1881085
--- /dev/null
@@ -0,0 +1,286 @@
+/**
+ * Farbtastic Color Picker 1.2
+ * © 2008 Steven Wittens
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//Adapted to uniform style with jQuery UI widgets and slightly change behavior
+//TODO:
+// - remove duplicated code by replacing it with jquery.colorUtils and modern jQuery
+// - uniform code style
+
+jQuery.fn.farbtastic = function (callback) {
+       $.farbtastic(this, callback);
+       return this;
+};
+
+jQuery.farbtastic = function (container, callback) {
+       var container = $(container).get(0);
+       return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback));
+}
+
+jQuery._farbtastic = function (container, callback) {
+       // Store farbtastic object
+       var fb = this;
+
+       // Insert markup
+       $(container).html('<div class="farbtastic ui-widget-content"><div class="color"></div><div class="wheel"></div><div class="overlay"></div><div class="h-marker marker"></div><div class="sl-marker marker"></div></div>');
+       $(container).addClass('ui-widget');
+       var e = $('.farbtastic', container);
+       fb.wheel = $('.wheel', container).get(0);
+       // Dimensions
+       fb.radius = 84;
+       fb.square = 100;
+       fb.width = 194;
+
+       // Fix background PNGs in IE6
+       if (navigator.appVersion.match(/MSIE [0-6]\./)) {
+               $('*', e).each(function () {
+                       if (this.currentStyle.backgroundImage != 'none') {
+                               var image = this.currentStyle.backgroundImage;
+                               image = this.currentStyle.backgroundImage.substring(5, image.length - 2);
+                               $(this).css({
+                                       'backgroundImage': 'none',
+                                       'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
+                               });
+                       }
+               });
+       }
+
+       /**
+        * Link to the given element(s) or callback.
+        */
+       fb.linkTo = function (callback) {
+               // Unbind previous nodes
+               if (typeof fb.callback == 'object') {
+                       $(fb.callback).unbind('keyup', fb.updateValue);
+               }
+
+               // Reset color
+               fb.color = null;
+
+               // Bind callback or elements
+               if (typeof callback == 'function') {
+                       fb.callback = callback;
+               }
+               else if (typeof callback == 'object' || typeof callback == 'string') {
+                       fb.callback = $(callback);
+                       fb.callback.bind('keyup', fb.updateValue);
+                       if (fb.callback.get(0).value) {
+                               fb.setColor(fb.callback.get(0).value);
+                       }
+               }
+               return this;
+       }
+       fb.updateValue = function (event) {
+               if (this.value != fb.color) {
+                       fb.setColor(this.value);
+               }
+       }
+
+       /**
+        * Change color with HTML syntax #123456
+        */
+       fb.setColor = function (color) {
+               var rgb = $.colorUtil.getRGB( color );
+               if (fb.color != color && rgb) {
+                       rgb = rgb.slice( 0 ); //make a clone
+                       //TODO: rewrite code so that this is not needed
+                       rgb[0] /= 255;
+                       rgb[1] /= 255;
+                       rgb[2] /= 255;
+                       fb.color = color;
+                       fb.rgb = rgb;
+                       fb.hsl = fb.RGBToHSL(fb.rgb);
+                       fb.updateDisplay();
+               }
+               return this;
+       }
+
+       /**
+        * Change color with HSL triplet [0..1, 0..1, 0..1]
+        */
+       fb.setHSL = function (hsl) {
+               fb.hsl = hsl;
+               fb.rgb = fb.HSLToRGB(hsl);
+               fb.color = fb.pack(fb.rgb);
+               fb.updateDisplay();
+               return this;
+       }
+
+       /////////////////////////////////////////////////////
+
+       /**
+        * Retrieve the coordinates of the given event relative to the center
+        * of the widget.
+        */
+       fb.widgetCoords = function (event) {
+               var ref = $( fb.wheel ).offset();
+               return {
+                       x: event.pageX - ref.left - fb.width / 2,
+                       y: event.pageY - ref.top - fb.width / 2
+               };
+       }
+
+       /**
+        * Mousedown handler
+        */
+       fb.mousedown = function (event) {
+               // Capture mouse
+               if (!document.dragging) {
+                       $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup);
+                       document.dragging = true;
+               }
+
+               // Check which area is being dragged
+               var pos = fb.widgetCoords(event);
+               fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square;
+
+               // Process
+               fb.mousemove(event);
+               return false;
+       }
+
+       /**
+        * Mousemove handler
+        */
+       fb.mousemove = function (event) {
+               // Get coordinates relative to color picker center
+               var pos = fb.widgetCoords(event);
+
+               // Set new HSL parameters
+               if (fb.circleDrag) {
+                       var hue = Math.atan2(pos.x, -pos.y) / 6.28;
+                       if (hue < 0) hue += 1;
+                       fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]);
+               }
+               else {
+                       var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5));
+                       var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5));
+                       fb.setHSL([fb.hsl[0], sat, lum]);
+               }
+               return false;
+       }
+
+       /**
+        * Mouseup handler
+        */
+       fb.mouseup = function () {
+               // Uncapture mouse
+               $(document).unbind('mousemove', fb.mousemove);
+               $(document).unbind('mouseup', fb.mouseup);
+               document.dragging = false;
+       }
+
+       /**
+        * Update the markers and styles
+        */
+       fb.updateDisplay = function () {
+               // Markers
+               var angle = fb.hsl[0] * 6.28;
+               $('.h-marker', e).css({
+                       left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px',
+                       top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px'
+               });
+
+               $('.sl-marker', e).css({
+                       left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px',
+                       top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px'
+               });
+
+               // Saturation/Luminance gradient
+               $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5])));
+
+               // Linked elements or callback
+               if (typeof fb.callback == 'object') {
+                       // Set background/foreground color
+                       $(fb.callback).css({
+                               backgroundColor: fb.color,
+                               color: fb.hsl[2] > 0.5 ? '#000' : '#fff'
+                       });
+
+                       // Change linked value
+                       $(fb.callback).each(function() {
+                               if ( $( this ).val() != fb.color) {
+                                       $( this ).val( fb.color ).change();
+                               }
+                       });
+               }
+               else if (typeof fb.callback == 'function') {
+                       fb.callback.call(fb, fb.color);
+               }
+       }
+
+       /* Various color utility functions */
+       fb.pack = function (rgb) {
+               var r = Math.round(rgb[0] * 255);
+               var g = Math.round(rgb[1] * 255);
+               var b = Math.round(rgb[2] * 255);
+               return '#' + (r < 16 ? '0' : '') + r.toString(16) +
+                                        (g < 16 ? '0' : '') + g.toString(16) +
+                                        (b < 16 ? '0' : '') + b.toString(16);
+       }
+
+       fb.HSLToRGB = function (hsl) {
+               var m1, m2, r, g, b;
+               var h = hsl[0], s = hsl[1], l = hsl[2];
+               m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s;
+               m1 = l * 2 - m2;
+               return [this.hueToRGB(m1, m2, h+0.33333),
+                               this.hueToRGB(m1, m2, h),
+                               this.hueToRGB(m1, m2, h-0.33333)];
+       }
+
+       fb.hueToRGB = function (m1, m2, h) {
+               h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
+               if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
+               if (h * 2 < 1) return m2;
+               if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
+               return m1;
+       }
+
+       fb.RGBToHSL = function (rgb) {
+               var min, max, delta, h, s, l;
+               var r = rgb[0], g = rgb[1], b = rgb[2];
+               min = Math.min(r, Math.min(g, b));
+               max = Math.max(r, Math.max(g, b));
+               delta = max - min;
+               l = (min + max) / 2;
+               s = 0;
+               if (l > 0 && l < 1) {
+                       s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
+               }
+               h = 0;
+               if (delta > 0) {
+                       if (max == r && max != g) h += (g - b) / delta;
+                       if (max == g && max != b) h += (2 + (b - r) / delta);
+                       if (max == b && max != r) h += (4 + (r - g) / delta);
+                       h /= 6;
+               }
+               return [h, s, l];
+       }
+
+       // Install mousedown handler (the others are set on the document on-demand)
+       $('*', e).mousedown(fb.mousedown);
+
+               // Init color
+       fb.setColor('#000000');
+
+       // Set linked elements/callback
+       if (callback) {
+               fb.linkTo(callback);
+       }
+}
diff --git a/resources/src/jquery/jquery.footHovzer.css b/resources/src/jquery/jquery.footHovzer.css
new file mode 100644 (file)
index 0000000..77d9514
--- /dev/null
@@ -0,0 +1,6 @@
+#jquery-foot-hovzer {
+       position: fixed;
+       bottom: 0;
+       width: 100%;
+       z-index: 1000;
+}
diff --git a/resources/src/jquery/jquery.footHovzer.js b/resources/src/jquery/jquery.footHovzer.js
new file mode 100644 (file)
index 0000000..56fc32d
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * Utility to stack stuff in an overlay fixed on the bottom of the page.
+ *
+ * Usage:
+ * <code>
+ *     var hovzer = $.getFootHovzer();
+ *     hovzer.$.append( $myCollection );
+ *     hovzer.update();
+ * </code>
+ *
+ * @author Timo Tijhof, 2012
+ */
+( function ( $ ) {
+       var $hovzer, footHovzer, prevHeight, newHeight;
+
+       function getHovzer() {
+               if ( $hovzer === undefined ) {
+                       $hovzer = $( '<div id="jquery-foot-hovzer"></div>' ).appendTo( 'body' );
+               }
+               return $hovzer;
+       }
+
+       footHovzer = {
+               update: function () {
+                       var $body;
+
+                       $body = $( 'body' );
+                       if ( prevHeight === undefined ) {
+                               prevHeight = getHovzer().outerHeight( /*includeMargin=*/true );
+                               $body.css( 'paddingBottom', '+=' + prevHeight + 'px' );
+                       } else {
+                               newHeight = getHovzer().outerHeight( true );
+                               $body.css( 'paddingBottom', ( parseFloat( $body.css( 'paddingBottom' ) ) - prevHeight ) + newHeight );
+
+                               prevHeight = newHeight;
+                       }
+               }
+       };
+
+       $.getFootHovzer = function () {
+               footHovzer.$ = getHovzer();
+               return footHovzer;
+       };
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.getAttrs.js b/resources/src/jquery/jquery.getAttrs.js
new file mode 100644 (file)
index 0000000..25b806b
--- /dev/null
@@ -0,0 +1,24 @@
+/**
+ * Utility to get all attributes of an element directy as an object.
+ *
+ * @author Timo Tijhof, 2011
+ */
+jQuery.fn.getAttrs = function ( all ) {
+       var map = this[0].attributes,
+               attrs = {},
+               len = map.length,
+               i, v;
+
+       for ( i = 0; i < len; i++ ) {
+               // IE6 includes *all* allowed attributes for thew element (including those
+               // not set). Those have values like undefined, null, 0, false, "" or "inherit".
+               // However there may be genuine attributes set to that. If you need them,
+               // set all to true. They are excluded by default.
+               v = map[i].nodeValue;
+               if ( all || ( v && v !== 'inherit' ) ) {
+                       attrs[ map[i].nodeName ] = v;
+               }
+       }
+
+       return attrs;
+};
diff --git a/resources/src/jquery/jquery.hidpi.js b/resources/src/jquery/jquery.hidpi.js
new file mode 100644 (file)
index 0000000..eb29db9
--- /dev/null
@@ -0,0 +1,115 @@
+/**
+ * Responsive images based on 'srcset' and 'window.devicePixelRatio' emulation where needed.
+ *
+ * Call $().hidpi() on a document or part of a document to replace image srcs in that section.
+ *
+ * $.devicePixelRatio() can be used to supplement window.devicePixelRatio with support on
+ * some additional browsers.
+ */
+( function ( $ ) {
+
+/**
+ * Detect reported or approximate device pixel ratio.
+ * 1.0 means 1 CSS pixel is 1 hardware pixel
+ * 2.0 means 1 CSS pixel is 2 hardware pixels
+ * etc
+ *
+ * Uses window.devicePixelRatio if available, or CSS media queries on IE.
+ *
+ * @return {number} Device pixel ratio
+ */
+$.devicePixelRatio = function () {
+       if ( window.devicePixelRatio !== undefined ) {
+               // Most web browsers:
+               // * WebKit (Safari, Chrome, Android browser, etc)
+               // * Opera
+               // * Firefox 18+
+               return window.devicePixelRatio;
+       } else if ( window.msMatchMedia !== undefined ) {
+               // Windows 8 desktops / tablets, probably Windows Phone 8
+               //
+               // IE 10 doesn't report pixel ratio directly, but we can get the
+               // screen DPI and divide by 96. We'll bracket to [1, 1.5, 2.0] for
+               // simplicity, but you may get different values depending on zoom
+               // factor, size of screen and orientation in Metro IE.
+               if ( window.msMatchMedia( '(min-resolution: 192dpi)' ).matches ) {
+                       return 2;
+               } else if ( window.msMatchMedia( '(min-resolution: 144dpi)' ).matches ) {
+                       return 1.5;
+               } else {
+                       return 1;
+               }
+       } else {
+               // Legacy browsers...
+               // Assume 1 if unknown.
+               return 1;
+       }
+};
+
+/**
+ * Implement responsive images based on srcset attributes, if browser has no
+ * native srcset support.
+ *
+ * @return {jQuery} This selection
+ */
+$.fn.hidpi = function () {
+       var $target = this,
+               // @todo add support for dpi media query checks on Firefox, IE
+               devicePixelRatio = $.devicePixelRatio(),
+               testImage = new Image();
+
+       if ( devicePixelRatio > 1 && testImage.srcset === undefined ) {
+               // No native srcset support.
+               $target.find( 'img' ).each( function () {
+                       var $img = $( this ),
+                               srcset = $img.attr( 'srcset' ),
+                               match;
+                       if ( typeof srcset === 'string' && srcset !== '' ) {
+                               match = $.matchSrcSet( devicePixelRatio, srcset );
+                               if (match !== null ) {
+                                       $img.attr( 'src', match );
+                               }
+                       }
+               });
+       }
+
+       return $target;
+};
+
+/**
+ * Match a srcset entry for the given device pixel ratio
+ *
+ * Exposed for testing.
+ *
+ * @param {number} devicePixelRatio
+ * @param {string} srcset
+ * @return {mixed} null or the matching src string
+ */
+$.matchSrcSet = function ( devicePixelRatio, srcset ) {
+       var candidates,
+               candidate,
+               bits,
+               src,
+               i,
+               ratioStr,
+               ratio,
+               selectedRatio = 1,
+               selectedSrc = null;
+       candidates = srcset.split( / *, */ );
+       for ( i = 0; i < candidates.length; i++ ) {
+               candidate = candidates[i];
+               bits = candidate.split( / +/ );
+               src = bits[0];
+               if ( bits.length > 1 && bits[1].charAt( bits[1].length - 1 ) === 'x' ) {
+                       ratioStr = bits[1].substr( 0, bits[1].length - 1 );
+                       ratio = parseFloat( ratioStr );
+                       if ( ratio <= devicePixelRatio && ratio > selectedRatio ) {
+                               selectedRatio = ratio;
+                               selectedSrc = src;
+                       }
+               }
+       }
+       return selectedSrc;
+};
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.highlightText.js b/resources/src/jquery/jquery.highlightText.js
new file mode 100644 (file)
index 0000000..0408151
--- /dev/null
@@ -0,0 +1,68 @@
+/**
+ * Plugin that highlights matched word partials in a given element.
+ * TODO: Add a function for restoring the previous text.
+ * TODO: Accept mappings for converting shortcuts like WP: to Wikipedia:.
+ */
+( function ( $ ) {
+
+       $.highlightText = {
+
+               // Split our pattern string at spaces and run our highlight function on the results
+               splitAndHighlight: function ( node, pat ) {
+                       var i,
+                               patArray = pat.split( ' ' );
+                       for ( i = 0; i < patArray.length; i++ ) {
+                               if ( patArray[i].length === 0 ) {
+                                       continue;
+                               }
+                               $.highlightText.innerHighlight( node, patArray[i] );
+                       }
+                       return node;
+               },
+
+               // scans a node looking for the pattern and wraps a span around each match
+               innerHighlight: function ( node, pat ) {
+                       var i, match, pos, spannode, middlebit, middleclone;
+                       // if this is a text node
+                       if ( node.nodeType === 3 ) {
+                               // TODO - need to be smarter about the character matching here.
+                               // non latin characters can make regex think a new word has begun: do not use \b
+                               // http://stackoverflow.com/questions/3787072/regex-wordwrap-with-utf8-characters-in-js
+                               // look for an occurrence of our pattern and store the starting position
+                               match = node.data.match( new RegExp( '(^|\\s)' + $.escapeRE( pat ), 'i' ) );
+                               if ( match ) {
+                                       pos = match.index + match[1].length; // include length of any matched spaces
+                                       // create the span wrapper for the matched text
+                                       spannode = document.createElement( 'span' );
+                                       spannode.className = 'highlight';
+                                       // shave off the characters preceding the matched text
+                                       middlebit = node.splitText( pos );
+                                       // shave off any unmatched text off the end
+                                       middlebit.splitText( pat.length );
+                                       // clone for appending to our span
+                                       middleclone = middlebit.cloneNode( true );
+                                       // append the matched text node to the span
+                                       spannode.appendChild( middleclone );
+                                       // replace the matched node, with our span-wrapped clone of the matched node
+                                       middlebit.parentNode.replaceChild( spannode, middlebit );
+                               }
+                       // if this is an element with childnodes, and not a script, style or an element we created
+                       } else if ( node.nodeType === 1 && node.childNodes && !/(script|style)/i.test( node.tagName )
+                                       && !( node.tagName.toLowerCase() === 'span' && node.className.match( /\bhighlight/ ) ) ) {
+                               for ( i = 0; i < node.childNodes.length; ++i ) {
+                                       // call the highlight function for each child node
+                                       $.highlightText.innerHighlight( node.childNodes[i], pat );
+                               }
+                       }
+               }
+       };
+
+       $.fn.highlightText = function ( matchString ) {
+               return this.each( function () {
+                       var $el = $( this );
+                       $el.data( 'highlightText', { originalText: $el.text() } );
+                       $.highlightText.splitAndHighlight( this, matchString );
+               } );
+       };
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.localize.js b/resources/src/jquery/jquery.localize.js
new file mode 100644 (file)
index 0000000..f499e10
--- /dev/null
@@ -0,0 +1,170 @@
+/**
+ * @class jQuery.plugin.localize
+ */
+( function ( $, mw ) {
+
+/**
+ * Gets a localized message, using parameters from options if present.
+ * @ignore
+ *
+ * @param {Object} options
+ * @param {string} key
+ * @return {string} Localized message
+ */
+function msg( options, key ) {
+       var args = options.params[key] || [];
+       // Format: mw.msg( key [, p1, p2, ...] )
+       args.unshift( options.prefix + ( options.keys[key] || key ) );
+       return mw.msg.apply( mw, args );
+}
+
+/**
+ * Localizes a DOM selection by replacing <html:msg /> elements with localized text and adding
+ * localized title and alt attributes to elements with title-msg and alt-msg attributes
+ * respectively.
+ *
+ * Call on a selection of HTML which contains `<html:msg key="message-key" />` elements or elements
+ * with title-msg="message-key", alt-msg="message-key" or placeholder-msg="message-key" attributes.
+ * `<html:msg />` elements will be replaced with localized text, *-msg attributes will be replaced
+ * with attributes that do not have the "-msg" suffix and contain a localized message.
+ *
+ * Example:
+ *     // Messages: { 'title': 'Awesome', 'desc': 'Cat doing backflip' 'search' contains 'Search' }
+ *     var html = '\
+ *         <p>\
+ *             <html:msg key="title" />\
+ *             <img src="something.jpg" title-msg="title" alt-msg="desc" />\
+ *             <input type="text" placeholder-msg="search" />\
+ *         </p>';
+ *     $( 'body' ).append( $( html ).localize() );
+ *
+ * Appends something like this to the body...
+ *     <p>
+ *         Awesome
+ *         <img src="something.jpg" title="Awesome" alt="Cat doing backflip" />
+ *         <input type="text" placeholder="Search" />
+ *     </p>
+ *
+ * Arguments can be passed into uses of a message using the params property of the options object
+ * given to .localize(). Multiple messages can be given parameters, because the params property is
+ * an object keyed by the message key to apply the parameters to, each containing an array of
+ * parameters to use. The limitation is that you can not use different parameters to individual uses
+ * of a message in the same selection being localized - they will all recieve the same parameters.
+ *
+ * Example:
+ *     // Messages: { 'easy-as': 'Easy as $1 $2 $3.' }
+ *     var html = '<p><html:msg key="easy-as" /></p>';
+ *     $( 'body' ).append( $( html ).localize( { 'params': { 'easy-as': ['a', 'b', 'c'] } } ) );
+ *
+ * Appends something like this to the body...
+ *     <p>Easy as a, b, c</p>
+ *
+ * Raw HTML content can be used, instead of it being escaped as text. To do this, just use the raw
+ * attribute on a msg element.
+ *
+ * Example:
+ *     // Messages: { 'hello': '<b><i>Hello</i> $1!</b>' }
+ *     var html = '\
+ *         <p>\
+ *             <!-- escaped: --><html:msg key="hello" />\
+ *             <!-- raw: --><html:msg key="hello" raw />\
+ *         </p>';
+ *     $( 'body' ).append( $( html ).localize( { 'params': { 'hello': ['world'] } } ) );
+ *
+ * Appends something like this to the body...
+ *     <p>
+ *         <!-- escaped: -->&lt;b&gt;&lt;i&gt;Hello&lt;/i&gt; world!&lt;/b&gt;
+ *         <!-- raw: --><b><i>Hello</i> world!</b>
+ *     </p>
+ *
+ * Message keys can also be remapped, allowing the same generic template to be used with a variety
+ * of messages. This is important for improving re-usability of templates.
+ *
+ * Example:
+ *     // Messages: { 'good-afternoon': 'Good afternoon' }
+ *     var html = '<p><html:msg key="greeting" /></p>';
+ *     $( 'body' ).append( $( html ).localize( { 'keys': { 'greeting': 'good-afternoon' } } ) );
+ *
+ * Appends something like this to the body...
+ *     <p>Good afternoon</p>
+ *
+ * Message keys can also be prefixed globally, which is handy when writing extensions, where by
+ * convention all messages are prefixed with the extension's name.
+ *
+ * Example:
+ *     // Messages: { 'teleportation-warning': 'You may not get there all in one piece.' }
+ *     var html = '<p><html:msg key="warning" /></p>';
+ *     $( 'body' ).append( $( html ).localize( { 'prefix': 'teleportation-' } ) );
+ *
+ * Appends something like this to the body...
+ *     <p>You may not get there all in one piece.</p>
+ *
+ * @param {Object} options Map of options to be used while localizing
+ * @param {string} options.prefix String to prepend to all message keys
+ * @param {Object} options.keys Message key aliases, used for remapping keys to a template
+ * @param {Object} options.params Lists of parameters to use with certain message keys
+ * @return {jQuery}
+ * @chainable
+ */
+$.fn.localize = function ( options ) {
+       var $target = this,
+               attributes = ['title', 'alt', 'placeholder'];
+
+       // Extend options
+       options = $.extend( {
+               prefix: '',
+               keys: {},
+               params: {}
+       }, options );
+
+       // Elements
+       // Ok, so here's the story on this selector. In IE 6/7, searching for 'msg' turns up the
+       // 'html:msg', but searching for 'html:msg' doesn't. In later IE and other browsers, searching
+       // for 'html:msg' turns up the 'html:msg', but searching for 'msg' doesn't. So searching for
+       // both 'msg' and 'html:msg' seems to get the job done. This feels pretty icky, though.
+       $target.find( 'msg,html\\:msg' ).each( function () {
+               var $el = $(this);
+               // Escape by default
+               if ( $el.attr( 'raw' ) ) {
+                       $el.html( msg( options, $el.attr( 'key' ) ) );
+               } else {
+                       $el.text( msg( options, $el.attr( 'key' ) ) );
+               }
+               // Remove wrapper
+               $el.replaceWith( $el.html() );
+       } );
+
+       // Attributes
+       // Note: there's no way to prevent escaping of values being injected into attributes, this is
+       // on purpose, not a design flaw.
+       $.each( attributes, function ( i, attr ) {
+               var msgAttr = attr + '-msg';
+               $target.find( '[' + msgAttr + ']' ).each( function () {
+                       var $el = $(this);
+                       $el.attr( attr, msg( options, $el.attr( msgAttr ) ) ).removeAttr( msgAttr );
+               } );
+       } );
+
+       // HTML, Text for elements which cannot have children e.g. OPTION
+       $target.find( '[data-msg-text]' ).each( function () {
+               var $el = $( this );
+               $el.text( msg( options, $el.attr( 'data-msg-text' ) ) );
+       } );
+
+       $target.find( '[data-msg-html]' ).each( function () {
+               var $el = $( this );
+               $el.html( msg( options, $el.attr( 'data-msg-html' ) ) );
+       } );
+
+       return $target;
+};
+
+// Let IE know about the msg tag before it's used...
+document.createElement( 'msg' );
+
+/**
+ * @class jQuery
+ * @mixins jQuery.plugin.localize
+ */
+
+}( jQuery, mediaWiki ) );
diff --git a/resources/src/jquery/jquery.makeCollapsible.css b/resources/src/jquery/jquery.makeCollapsible.css
new file mode 100644 (file)
index 0000000..55ea7c9
--- /dev/null
@@ -0,0 +1,23 @@
+/* See also jquery.makeCollapsible.js */
+.mw-collapsible-toggle {
+       float: right;
+       -moz-user-select: none;
+       -webkit-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+/* collapse links in captions should be inline */
+caption .mw-collapsible-toggle {
+       float: none;
+}
+
+/* list-items go as wide as their parent element, don't float them inside list items */
+li .mw-collapsible-toggle {
+       float: none;
+}
+
+/* the added list item should have no list-style */
+.mw-collapsible-toggle-li {
+       list-style: none;
+}
diff --git a/resources/src/jquery/jquery.makeCollapsible.js b/resources/src/jquery/jquery.makeCollapsible.js
new file mode 100644 (file)
index 0000000..01fde4c
--- /dev/null
@@ -0,0 +1,394 @@
+/**
+ * jQuery makeCollapsible
+ *
+ * This will enable collapsible-functionality on all passed elements.
+ * - Will prevent binding twice to the same element.
+ * - Initial state is expanded by default, this can be overriden by adding class
+ *   "mw-collapsed" to the "mw-collapsible" element.
+ * - Elements made collapsible have jQuery data "mw-made-collapsible" set to true.
+ * - The inner content is wrapped in a "div.mw-collapsible-content" (except for tables and lists).
+ *
+ * @author Krinkle, 2011-2012
+ *
+ * Dual license:
+ * @license CC BY 3.0 <http://creativecommons.org/licenses/by/3.0>
+ * @license GPL2 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
+ */
+( function ( $, mw ) {
+       /**
+        * Handler for a click on a collapsible toggler.
+        *
+        * @param {jQuery} $collapsible
+        * @param {string} action The action this function will take ('expand' or 'collapse').
+        * @param {jQuery|null} [optional] $defaultToggle
+        * @param {Object|undefined} options
+        */
+       function toggleElement( $collapsible, action, $defaultToggle, options ) {
+               var $collapsibleContent, $containers, hookCallback;
+               options = options || {};
+
+               // Validate parameters
+
+               // $collapsible must be an instance of jQuery
+               if ( !$collapsible.jquery ) {
+                       return;
+               }
+               if ( action !== 'expand' && action !== 'collapse' ) {
+                       // action must be string with 'expand' or 'collapse'
+                       return;
+               }
+               if ( $defaultToggle === undefined ) {
+                       $defaultToggle = null;
+               }
+               if ( $defaultToggle !== null && !$defaultToggle.jquery ) {
+                       // is optional (may be undefined), but if defined it must be an instance of jQuery.
+                       // If it's not, abort right away.
+                       // After this $defaultToggle is either null or a valid jQuery instance.
+                       return;
+               }
+
+               // Trigger a custom event to allow callers to hook to the collapsing/expanding,
+               // allowing the module to be testable, and making it possible to
+               // e.g. implement persistence via cookies
+               $collapsible.trigger( action === 'expand' ? 'beforeExpand.mw-collapsible' : 'beforeCollapse.mw-collapsible' );
+               hookCallback = function () {
+                       $collapsible.trigger( action === 'expand' ? 'afterExpand.mw-collapsible' : 'afterCollapse.mw-collapsible' );
+               };
+
+               // Handle different kinds of elements
+
+               if ( !options.plainMode && $collapsible.is( 'table' ) ) {
+                       // Tables
+                       // If there is a caption, hide all rows; otherwise, only hide body rows
+                       if ( $collapsible.find( '> caption' ).length ) {
+                               $containers = $collapsible.find( '> * > tr' );
+                       } else {
+                               $containers = $collapsible.find( '> tbody > tr' );
+                       }
+                       if ( $defaultToggle ) {
+                               // Exclude table row containing togglelink
+                               $containers = $containers.not( $defaultToggle.closest( 'tr' ) );
+                       }
+
+                       if ( action === 'collapse' ) {
+                               // Hide all table rows of this table
+                               // Slide doesn't work with tables, but fade does as of jQuery 1.1.3
+                               // http://stackoverflow.com/questions/467336#920480
+                               if ( options.instantHide ) {
+                                       $containers.hide();
+                                       hookCallback();
+                               } else {
+                                       $containers.stop( true, true ).fadeOut().promise().done( hookCallback );
+                               }
+                       } else {
+                               $containers.stop( true, true ).fadeIn().promise().done( hookCallback );
+                       }
+
+               } else if ( !options.plainMode && ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) ) {
+                       // Lists
+                       $containers = $collapsible.find( '> li' );
+                       if ( $defaultToggle ) {
+                               // Exclude list-item containing togglelink
+                               $containers = $containers.not( $defaultToggle.parent() );
+                       }
+
+                       if ( action === 'collapse' ) {
+                               if ( options.instantHide ) {
+                                       $containers.hide();
+                                       hookCallback();
+                               } else {
+                                       $containers.stop( true, true ).slideUp().promise().done( hookCallback );
+                               }
+                       } else {
+                               $containers.stop( true, true ).slideDown().promise().done( hookCallback );
+                       }
+
+               } else {
+                       // Everything else: <div>, <p> etc.
+                       $collapsibleContent = $collapsible.find( '> .mw-collapsible-content' );
+
+                       // If a collapsible-content is defined, act on it
+                       if ( !options.plainMode && $collapsibleContent.length ) {
+                               if ( action === 'collapse' ) {
+                                       if ( options.instantHide ) {
+                                               $collapsibleContent.hide();
+                                               hookCallback();
+                                       } else {
+                                               $collapsibleContent.slideUp().promise().done( hookCallback );
+                                       }
+                               } else {
+                                       $collapsibleContent.slideDown().promise().done( hookCallback );
+                               }
+
+                       // Otherwise assume this is a customcollapse with a remote toggle
+                       // .. and there is no collapsible-content because the entire element should be toggled
+                       } else {
+                               if ( action === 'collapse' ) {
+                                       if ( options.instantHide ) {
+                                               $collapsible.hide();
+                                               hookCallback();
+                                       } else {
+                                               if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
+                                                       $collapsible.fadeOut().promise().done( hookCallback );
+                                               } else {
+                                                       $collapsible.slideUp().promise().done( hookCallback );
+                                               }
+                                       }
+                               } else {
+                                       if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
+                                               $collapsible.fadeIn().promise().done( hookCallback );
+                                       } else {
+                                               $collapsible.slideDown().promise().done( hookCallback );
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Handles clicking/keypressing on the collapsible element toggle and other
+        * situations where a collapsible element is toggled (e.g. the initial
+        * toggle for collapsed ones).
+        *
+        * @param {jQuery} $toggle the clickable toggle itself
+        * @param {jQuery} $collapsible the collapsible element
+        * @param {jQuery.Event|null} e either the event or null if unavailable
+        * @param {Object|undefined} options
+        */
+       function togglingHandler( $toggle, $collapsible, e, options ) {
+               var wasCollapsed, $textContainer, collapseText, expandText;
+
+               if ( options === undefined ) {
+                       options = {};
+               }
+
+               if ( e ) {
+                       if ( e.type === 'click' && options.linksPassthru && $.nodeName( e.target, 'a' ) ) {
+                               // Don't fire if a link was clicked, if requested  (for premade togglers by default)
+                               return;
+                       } else if ( e.type === 'keypress' && e.which !== 13 && e.which !== 32 ) {
+                               // Only handle keypresses on the "Enter" or "Space" keys
+                               return;
+                       } else {
+                               e.preventDefault();
+                               e.stopPropagation();
+                       }
+               }
+
+               // This allows the element to be hidden on initial toggle without fiddling with the class
+               if ( options.wasCollapsed !== undefined ) {
+                       wasCollapsed = options.wasCollapsed;
+               } else {
+                       wasCollapsed = $collapsible.hasClass( 'mw-collapsed' );
+               }
+
+               // Toggle the state of the collapsible element (that is, expand or collapse)
+               $collapsible.toggleClass( 'mw-collapsed', !wasCollapsed );
+
+               // Toggle the mw-collapsible-toggle classes, if requested (for default and premade togglers by default)
+               if ( options.toggleClasses ) {
+                       $toggle
+                               .toggleClass( 'mw-collapsible-toggle-collapsed', !wasCollapsed )
+                               .toggleClass( 'mw-collapsible-toggle-expanded', wasCollapsed );
+               }
+
+               // Toggle the text ("Show"/"Hide"), if requested (for default togglers by default)
+               if ( options.toggleText ) {
+                       collapseText = options.toggleText.collapseText;
+                       expandText = options.toggleText.expandText;
+
+                       $textContainer = $toggle.find( '> a' );
+                       if ( !$textContainer.length ) {
+                               $textContainer = $toggle;
+                       }
+                       $textContainer.text( wasCollapsed ? collapseText : expandText );
+               }
+
+               // And finally toggle the element state itself
+               toggleElement( $collapsible, wasCollapsed ? 'expand' : 'collapse', $toggle, options );
+       }
+
+       /**
+        * Make any element collapsible.
+        *
+        * Supported options:
+        * - collapseText: text to be used for the toggler when clicking it would
+        *   collapse the element. Default: the 'data-collapsetext' attribute of
+        *   the collapsible element or the content of 'collapsible-collapse'
+        *   message.
+        * - expandText: text to be used for the toggler when clicking it would
+        *   expand the element. Default: the 'data-expandtext' attribute of
+        *   the collapsible element or the content of 'collapsible-expand'
+        *   message.
+        * - collapsed: boolean, whether to collapse immediately. By default
+        *   collapse only if the elements has the 'mw-collapsible' class.
+        * - $customTogglers: jQuerified list of elements to be used as togglers
+        *   for this collapsible element. By default, if the collapsible element
+        *   has an id attribute like 'mw-customcollapsible-XXX', elements with a
+        *   *class* of 'mw-customtoggle-XXX' are made togglers for it.
+        * - plainMode: boolean, whether to use a "plain mode" when making the
+        *   element collapsible - that is, hide entire tables and lists (instead
+        *   of hiding only all rows but first of tables, and hiding each list
+        *   item separately for lists) and don't wrap other elements in
+        *   div.mw-collapsible-content. May only be used with custom togglers.
+        */
+       $.fn.makeCollapsible = function ( options ) {
+               if ( options === undefined ) {
+                       options = {};
+               }
+
+               return this.each( function () {
+                       var $collapsible, collapseText, expandText, $caption, $toggle, actionHandler, buildDefaultToggleLink,
+                               premadeToggleHandler, $toggleLink, $firstItem, collapsibleId, $customTogglers, firstval;
+
+                       // Ensure class "mw-collapsible" is present in case .makeCollapsible()
+                       // is called on element(s) that don't have it yet.
+                       $collapsible = $( this ).addClass( 'mw-collapsible' );
+
+                       // Return if it has been enabled already.
+                       if ( $collapsible.data( 'mw-made-collapsible' ) ) {
+                               return;
+                       } else {
+                               $collapsible.data( 'mw-made-collapsible', true );
+                       }
+
+                       // Use custom text or default?
+                       collapseText = options.collapseText || $collapsible.attr( 'data-collapsetext' ) || mw.msg( 'collapsible-collapse' );
+                       expandText = options.expandText || $collapsible.attr( 'data-expandtext' ) || mw.msg( 'collapsible-expand' );
+
+                       // Default click/keypress handler and toggle link to use when none is present
+                       actionHandler = function ( e, opts ) {
+                               var defaultOpts = {
+                                       toggleClasses: true,
+                                       toggleText: { collapseText: collapseText, expandText: expandText }
+                               };
+                               opts = $.extend( defaultOpts, options, opts );
+                               togglingHandler( $( this ), $collapsible, e, opts );
+                       };
+                       // Default toggle link. Only build it when needed to avoid jQuery memory leaks (event data).
+                       buildDefaultToggleLink = function () {
+                               return $( '<a href="#"></a>' )
+                                       .text( collapseText )
+                                       .wrap( '<span class="mw-collapsible-toggle"></span>' )
+                                               .parent()
+                                               .prepend( '&nbsp;[' )
+                                               .append( ']&nbsp;' )
+                                               .on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                       };
+
+                       // Default handler for clicking on premade toggles
+                       premadeToggleHandler = function ( e, opts ) {
+                               var defaultOpts = { toggleClasses: true, linksPassthru: true };
+                               opts = $.extend( defaultOpts, options, opts );
+                               togglingHandler( $( this ), $collapsible, e, opts );
+                       };
+
+                       // Check if this element has a custom position for the toggle link
+                       // (ie. outside the container or deeper inside the tree)
+                       if ( options.$customTogglers ) {
+                               $customTogglers = $( options.$customTogglers );
+                       } else {
+                               collapsibleId = $collapsible.attr( 'id' ) || '';
+                               if ( collapsibleId.indexOf( 'mw-customcollapsible-' ) === 0 ) {
+                                       $customTogglers = $( '.' + collapsibleId.replace( 'mw-customcollapsible', 'mw-customtoggle' ) );
+                               }
+                       }
+
+                       // Add event handlers to custom togglers or create our own ones
+                       if ( $customTogglers && $customTogglers.length ) {
+                               actionHandler = function ( e, opts ) {
+                                       var defaultOpts = {};
+                                       opts = $.extend( defaultOpts, options, opts );
+                                       togglingHandler( $( this ), $collapsible, e, opts );
+                               };
+
+                               $toggleLink = $customTogglers;
+                               $toggleLink.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+
+                       } else {
+                               // If this is not a custom case, do the default: wrap the
+                               // contents and add the toggle link. Different elements are
+                               // treated differently.
+                               if ( $collapsible.is( 'table' ) ) {
+
+                                       // If the table has a caption, collapse to the caption
+                                       // as opposed to the first row
+                                       $caption = $collapsible.find( '> caption' );
+                                       if ( $caption.length ) {
+                                               $toggle = $caption.find( '> .mw-collapsible-toggle' );
+
+                                               // If there is no toggle link, add it to the end of the caption
+                                               if ( !$toggle.length ) {
+                                                       $toggleLink = buildDefaultToggleLink().appendTo( $caption );
+                                               } else {
+                                                       actionHandler = premadeToggleHandler;
+                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                               }
+                                       } else {
+                                               // The toggle-link will be in one the the cells (td or th) of the first row
+                                               $firstItem = $collapsible.find( 'tr:first th, tr:first td' );
+                                               $toggle = $firstItem.find( '> .mw-collapsible-toggle' );
+
+                                               // If theres no toggle link, add it to the last cell
+                                               if ( !$toggle.length ) {
+                                                       $toggleLink = buildDefaultToggleLink().prependTo( $firstItem.eq( -1 ) );
+                                               } else {
+                                                       actionHandler = premadeToggleHandler;
+                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                               }
+                                       }
+
+                               } else if ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) {
+                                       // The toggle-link will be in the first list-item
+                                       $firstItem = $collapsible.find( 'li:first' );
+                                       $toggle = $firstItem.find( '> .mw-collapsible-toggle' );
+
+                                       // If theres no toggle link, add it
+                                       if ( !$toggle.length ) {
+                                               // Make sure the numeral order doesn't get messed up, force the first (soon to be second) item
+                                               // to be "1". Except if the value-attribute is already used.
+                                               // If no value was set WebKit returns "", Mozilla returns '-1', others return 0, null or undefined.
+                                               firstval = $firstItem.attr( 'value' );
+                                               if ( firstval === undefined || !firstval || firstval === '-1' || firstval === -1 ) {
+                                                       $firstItem.attr( 'value', '1' );
+                                               }
+                                               $toggleLink = buildDefaultToggleLink();
+                                               $toggleLink.wrap( '<li class="mw-collapsible-toggle-li"></li>' ).parent().prependTo( $collapsible );
+                                       } else {
+                                               actionHandler = premadeToggleHandler;
+                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                       }
+
+                               } else { // <div>, <p> etc.
+
+                                       // The toggle-link will be the first child of the element
+                                       $toggle = $collapsible.find( '> .mw-collapsible-toggle' );
+
+                                       // If a direct child .content-wrapper does not exists, create it
+                                       if ( !$collapsible.find( '> .mw-collapsible-content' ).length ) {
+                                               $collapsible.wrapInner( '<div class="mw-collapsible-content"></div>' );
+                                       }
+
+                                       // If theres no toggle link, add it
+                                       if ( !$toggle.length ) {
+                                               $toggleLink = buildDefaultToggleLink().prependTo( $collapsible );
+                                       } else {
+                                               actionHandler = premadeToggleHandler;
+                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                       }
+                               }
+                       }
+
+                       // Attributes for accessibility. This isn't necessary when the toggler is already
+                       // an <a> or a <button> etc., but it doesn't hurt either, and it's consistent.
+                       $toggleLink.prop( 'tabIndex', 0 );
+
+                       // Initial state
+                       if ( options.collapsed || $collapsible.hasClass( 'mw-collapsed' ) ) {
+                               // One toggler can hook to multiple elements, and one element can have
+                               // multiple togglers. This is the sanest way to handle that.
+                               actionHandler.call( $toggleLink.get( 0 ), null, { instantHide: true, wasCollapsed: false } );
+                       }
+               } );
+       };
+}( jQuery, mediaWiki ) );
diff --git a/resources/src/jquery/jquery.mw-jump.js b/resources/src/jquery/jquery.mw-jump.js
new file mode 100644 (file)
index 0000000..e286834
--- /dev/null
@@ -0,0 +1,15 @@
+/**
+ * JavaScript to show jump links to motor-impaired users when they are focused.
+ */
+jQuery( function ( $ ) {
+
+       $( '.mw-jump' ).on( 'focus blur', 'a', function ( e ) {
+               // Confusingly jQuery leaves e.type as focusout for delegated blur events
+               if ( e.type === 'blur' || e.type === 'focusout' ) {
+                       $( this ).closest( '.mw-jump' ).css({ height: 0 });
+               } else {
+                       $( this ).closest( '.mw-jump' ).css({ height: 'auto' });
+               }
+       } );
+
+} );
diff --git a/resources/src/jquery/jquery.mwExtension.js b/resources/src/jquery/jquery.mwExtension.js
new file mode 100644 (file)
index 0000000..03c1c85
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * JavaScript backwards-compatibility alternatives and other convenience functions
+ */
+( function ( $ ) {
+
+       $.extend({
+               trimLeft: function ( str ) {
+                       return str === null ? '' : str.toString().replace( /^\s+/, '' );
+               },
+               trimRight: function ( str ) {
+                       return str === null ?
+                                       '' : str.toString().replace( /\s+$/, '' );
+               },
+               ucFirst: function ( str ) {
+                       return str.charAt( 0 ).toUpperCase() + str.substr( 1 );
+               },
+               escapeRE: function ( str ) {
+                       return str.replace ( /([\\{}()|.?*+\-\^$\[\]])/g, '\\$1' );
+               },
+               isDomElement: function ( el ) {
+                       return !!el && !!el.nodeType;
+               },
+               isEmpty: function ( v ) {
+                       var key;
+                       if ( v === '' || v === 0 || v === '0' || v === null
+                               || v === false || v === undefined )
+                       {
+                               return true;
+                       }
+                       // the for-loop could potentially contain prototypes
+                       // to avoid that we check it's length first
+                       if ( v.length === 0 ) {
+                               return true;
+                       }
+                       if ( typeof v === 'object' ) {
+                               for ( key in v ) {
+                                       return false;
+                               }
+                               return true;
+                       }
+                       return false;
+               },
+               compareArray: function ( arrThis, arrAgainst ) {
+                       if ( arrThis.length !== arrAgainst.length ) {
+                               return false;
+                       }
+                       for ( var i = 0; i < arrThis.length; i++ ) {
+                               if ( $.isArray( arrThis[i] ) ) {
+                                       if ( !$.compareArray( arrThis[i], arrAgainst[i] ) ) {
+                                               return false;
+                                       }
+                               } else if ( arrThis[i] !== arrAgainst[i] ) {
+                                       return false;
+                               }
+                       }
+                       return true;
+               },
+               compareObject: function ( objectA, objectB ) {
+                       var prop, type;
+
+                       // Do a simple check if the types match
+                       if ( typeof objectA === typeof objectB ) {
+
+                               // Only loop over the contents if it really is an object
+                               if ( typeof objectA === 'object' ) {
+                                       // If they are aliases of the same object (ie. mw and mediaWiki) return now
+                                       if ( objectA === objectB ) {
+                                               return true;
+                                       } else {
+                                               // Iterate over each property
+                                               for ( prop in objectA ) {
+                                                       // Check if this property is also present in the other object
+                                                       if ( prop in objectB ) {
+                                                               // Compare the types of the properties
+                                                               type = typeof objectA[prop];
+                                                               if ( type === typeof objectB[prop] ) {
+                                                                       // Recursively check objects inside this one
+                                                                       switch ( type ) {
+                                                                               case 'object' :
+                                                                                       if ( !$.compareObject( objectA[prop], objectB[prop] ) ) {
+                                                                                               return false;
+                                                                                       }
+                                                                                       break;
+                                                                               case 'function' :
+                                                                                       // Functions need to be strings to compare them properly
+                                                                                       if ( objectA[prop].toString() !== objectB[prop].toString() ) {
+                                                                                               return false;
+                                                                                       }
+                                                                                       break;
+                                                                               default:
+                                                                                       // Strings, numbers
+                                                                                       if ( objectA[prop] !== objectB[prop] ) {
+                                                                                               return false;
+                                                                                       }
+                                                                                       break;
+                                                                       }
+                                                               } else {
+                                                                       return false;
+                                                               }
+                                                       } else {
+                                                               return false;
+                                                       }
+                                               }
+                                               // Check for properties in B but not in A
+                                               // This is about 15% faster (tested in Safari 5 and Firefox 3.6)
+                                               // ...than incrementing a count variable in the above and below loops
+                                               // See also: https://www.mediawiki.org/wiki/ResourceLoader/Default_modules/compareObject_test#Results
+                                               for ( prop in objectB ) {
+                                                       if ( !( prop in objectA ) ) {
+                                                               return false;
+                                                       }
+                                               }
+                                       }
+                               }
+                       } else {
+                               return false;
+                       }
+                       return true;
+               }
+       });
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.placeholder.js b/resources/src/jquery/jquery.placeholder.js
new file mode 100644 (file)
index 0000000..6f7ada3
--- /dev/null
@@ -0,0 +1,229 @@
+/**
+ * HTML5 placeholder emulation for jQuery plugin
+ *
+ * This will automatically use the HTML5 placeholder attribute if supported, or emulate this behavior if not.
+ *
+ * This is a fork from Mathias Bynens' jquery.placeholder as of this commit
+ * https://github.com/mathiasbynens/jquery-placeholder/blob/47f05d400e2dd16b59d144141a2cf54a9a77c502/jquery.placeholder.js
+ *
+ * @author Mathias Bynens <http://mathiasbynens.be/>
+ * @author Trevor Parscal <tparscal@wikimedia.org>, 2012
+ * @author Krinkle <krinklemail@gmail.com>, 2012
+ * @author Alex Ivanov <alexivanov97@gmail.com>, 2013
+ * @version 2.1.0
+ * @license MIT
+ */
+(function ($) {
+
+       var isInputSupported = 'placeholder' in document.createElement('input'),
+               isTextareaSupported = 'placeholder' in document.createElement('textarea'),
+               prototype = $.fn,
+               valHooks = $.valHooks,
+               propHooks = $.propHooks,
+               hooks,
+               placeholder;
+
+       if (isInputSupported && isTextareaSupported) {
+
+               placeholder = prototype.placeholder = function (text) {
+                       var hasArgs = arguments.length;
+
+                       if (hasArgs) {
+                               changePlaceholder.call(this, text);
+                       }
+
+                       return this;
+               };
+
+               placeholder.input = placeholder.textarea = true;
+
+       } else {
+
+               placeholder = prototype.placeholder = function (text) {
+                       var $this = this,
+                               hasArgs = arguments.length;
+
+                       if (hasArgs) {
+                               changePlaceholder.call(this, text);
+                       }
+
+                       $this
+                               .filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')
+                               .filter(function () {
+                                       return !$(this).data('placeholder-enabled');
+                               })
+                               .bind({
+                                       'focus.placeholder drop.placeholder': clearPlaceholder,
+                                       'blur.placeholder': setPlaceholder
+                               })
+                               .data('placeholder-enabled', true)
+                               .trigger('blur.placeholder');
+                       return $this;
+               };
+
+               placeholder.input = isInputSupported;
+               placeholder.textarea = isTextareaSupported;
+
+               hooks = {
+                       'get': function (element) {
+                               var $element = $(element),
+                                       $passwordInput = $element.data('placeholder-password');
+                               if ($passwordInput) {
+                                       return $passwordInput[0].value;
+                               }
+
+                               return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value;
+                       },
+                       'set': function (element, value) {
+                               var $element = $(element),
+                                       $passwordInput = $element.data('placeholder-password');
+                               if ($passwordInput) {
+                                       $passwordInput[0].value = value;
+                                       return value;
+                               }
+
+                               if (!$element.data('placeholder-enabled')) {
+                                       element.value = value;
+                                       return value;
+                               }
+                               if (!value) {
+                                       element.value = value;
+                                       // Issue #56: Setting the placeholder causes problems if the element continues to have focus.
+                                       if (element !== safeActiveElement()) {
+                                               // We can't use `triggerHandler` here because of dummy text/password inputs :(
+                                               setPlaceholder.call(element);
+                                       }
+                               } else if ($element.hasClass('placeholder')) {
+                                       if (!clearPlaceholder.call(element, true, value)) {
+                                               element.value = value;
+                                       }
+                               } else {
+                                       element.value = value;
+                               }
+                               // `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
+                               return $element;
+                       }
+               };
+
+               if (!isInputSupported) {
+                       valHooks.input = hooks;
+                       propHooks.value = hooks;
+               }
+               if (!isTextareaSupported) {
+                       valHooks.textarea = hooks;
+                       propHooks.value = hooks;
+               }
+
+               $(function () {
+                       // Look for forms
+                       $(document).delegate('form', 'submit.placeholder', function () {
+                               // Clear the placeholder values so they don't get submitted
+                               var $inputs = $('.placeholder', this).each(clearPlaceholder);
+                               setTimeout(function () {
+                                       $inputs.each(setPlaceholder);
+                               }, 10);
+                       });
+               });
+
+               // Clear placeholder values upon page reload
+               $(window).bind('beforeunload.placeholder', function () {
+                       $('.placeholder').each(function () {
+                               this.value = '';
+                       });
+               });
+
+       }
+
+       function args(elem) {
+               // Return an object of element attributes
+               var newAttrs = {},
+                       rinlinejQuery = /^jQuery\d+$/;
+               $.each(elem.attributes, function (i, attr) {
+                       if (attr.specified && !rinlinejQuery.test(attr.name)) {
+                               newAttrs[attr.name] = attr.value;
+                       }
+               });
+               return newAttrs;
+       }
+
+       function clearPlaceholder(event, value) {
+               var input = this,
+                       $input = $(input);
+               if (input.value === $input.attr('placeholder') && $input.hasClass('placeholder')) {
+                       if ($input.data('placeholder-password')) {
+                               $input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id'));
+                               // If `clearPlaceholder` was called from `$.valHooks.input.set`
+                               if (event === true) {
+                                       $input[0].value = value;
+                                       return value;
+                               }
+                               $input.focus();
+                       } else {
+                               input.value = '';
+                               $input.removeClass('placeholder');
+                               if (input === safeActiveElement()) {
+                                       input.select();
+                               }
+                       }
+               }
+       }
+
+       function setPlaceholder() {
+               var $replacement,
+                       input = this,
+                       $input = $(input),
+                       id = this.id;
+               if (!input.value) {
+                       if (input.type === 'password') {
+                               if (!$input.data('placeholder-textinput')) {
+                                       try {
+                                               $replacement = $input.clone().attr({ 'type': 'text' });
+                                       } catch(e) {
+                                               $replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' }));
+                                       }
+                                       $replacement
+                                               .removeAttr('name')
+                                               .data({
+                                                       'placeholder-password': $input,
+                                                       'placeholder-id': id
+                                               })
+                                               .bind('focus.placeholder drop.placeholder', clearPlaceholder);
+                                       $input
+                                               .data({
+                                                       'placeholder-textinput': $replacement,
+                                                       'placeholder-id': id
+                                               })
+                                               .before($replacement);
+                               }
+                               $input = $input.removeAttr('id').hide().prev().attr('id', id).show();
+                               // Note: `$input[0] != input` now!
+                       }
+                       $input.addClass('placeholder');
+                       $input[0].value = $input.attr('placeholder');
+               } else {
+                       $input.removeClass('placeholder');
+               }
+       }
+
+       function safeActiveElement() {
+               // Avoid IE9 `document.activeElement` of death
+               // https://github.com/mathiasbynens/jquery-placeholder/pull/99
+               try {
+                       return document.activeElement;
+               } catch (err) {}
+       }
+
+       function changePlaceholder(text) {
+               var hasArgs = arguments.length,
+                       $input = this;
+               if (hasArgs) {
+                       if ($input.attr('placeholder') !== text) {
+                               $input.prop('placeholder', text);
+                               if ($input.hasClass('placeholder')) {
+                                       $input[0].value = text;
+                               }
+                       }
+               }
+       }
+
+}(jQuery));
diff --git a/resources/src/jquery/jquery.qunit.completenessTest.js b/resources/src/jquery/jquery.qunit.completenessTest.js
new file mode 100644 (file)
index 0000000..86fcaea
--- /dev/null
@@ -0,0 +1,359 @@
+/**
+ * jQuery QUnit CompletenessTest 0.4
+ *
+ * Tests the completeness of test suites for object oriented javascript
+ * libraries. Written to be used in environments with jQuery and QUnit.
+ * Requires jQuery 1.7.2 or higher.
+ *
+ * Built for and tested with:
+ * - Chrome 19
+ * - Firefox 4
+ * - Safari 5
+ *
+ * @author Timo Tijhof, 2011-2012
+ */
+( function ( $ ) {
+       'use strict';
+
+       var util,
+               hasOwn = Object.prototype.hasOwnProperty,
+               log = (window.console && window.console.log)
+                       ? function () { return window.console.log.apply(window.console, arguments); }
+                       : function () {};
+
+       // Simplified version of a few jQuery methods, except that they don't
+       // call other jQuery methods. Required to be able to run the CompletenessTest
+       // on jQuery itself as well.
+       util = {
+               keys: Object.keys || function ( object ) {
+                       var key, keys = [];
+                       for ( key in object ) {
+                               if ( hasOwn.call( object, key ) ) {
+                                       keys.push( key );
+                               }
+                       }
+                       return keys;
+               },
+               extend: function () {
+                       var options, name, src, copy,
+                               target = arguments[0] || {},
+                               i = 1,
+                               length = arguments.length;
+
+                       for ( ; i < length; i++ ) {
+                               options = arguments[ i ];
+                               // Only deal with non-null/undefined values
+                               if ( options !== null && options !== undefined ) {
+                                       // Extend the base object
+                                       for ( name in options ) {
+                                               src = target[ name ];
+                                               copy = options[ name ];
+
+                                               // Prevent never-ending loop
+                                               if ( target === copy ) {
+                                                       continue;
+                                               }
+
+                                               if ( copy !== undefined ) {
+                                                       target[ name ] = copy;
+                                               }
+                                       }
+                               }
+                       }
+
+                       // Return the modified object
+                       return target;
+               },
+               each: function ( object, callback ) {
+                       var name;
+                       for ( name in object ) {
+                               if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+                                       break;
+                               }
+                       }
+               },
+               // $.type and $.isEmptyObject are safe as is, they don't call
+               // other $.* methods. Still need to be derefenced into `util`
+               // since the CompletenessTest will overload them with spies.
+               type: $.type,
+               isEmptyObject: $.isEmptyObject
+       };
+
+       /**
+        * CompletenessTest
+        * @constructor
+        *
+        * @example
+        *  var myTester = new CompletenessTest( myLib );
+        * @param masterVariable {Object} The root variable that contains all object
+        *  members. CompletenessTest will recursively traverse objects and keep track
+        *  of all methods.
+        * @param ignoreFn {Function} Optionally pass a function to filter out certain
+        *  methods. Example: You may want to filter out instances of jQuery or some
+        *  other constructor. Otherwise "missingTests" will include all methods that
+        *  were not called from that instance.
+        */
+       function CompletenessTest( masterVariable, ignoreFn ) {
+
+               // Keep track in these objects. Keyed by strings with the
+               // method names (ie. 'my.foo', 'my.bar', etc.) values are boolean true.
+               this.injectionTracker = {};
+               this.methodCallTracker = {};
+               this.missingTests = {};
+
+               this.ignoreFn = undefined === ignoreFn ? function () { return false; } : ignoreFn;
+
+               // Lazy limit in case something weird happends (like recurse (part of) ourself).
+               this.lazyLimit = 2000;
+               this.lazyCounter = 0;
+
+               var that = this;
+
+               // Bind begin and end to QUnit.
+               QUnit.begin( function () {
+                       that.walkTheObject( null, masterVariable, masterVariable, [], CompletenessTest.ACTION_INJECT );
+                       log( 'CompletenessTest/walkTheObject/ACTION_INJECT', that );
+               });
+
+               QUnit.done( function () {
+                       that.populateMissingTests();
+                       log( 'CompletenessTest/populateMissingTests', that );
+
+                       var toolbar, testResults, cntTotal, cntCalled, cntMissing;
+
+                       cntTotal = util.keys( that.injectionTracker ).length;
+                       cntCalled = util.keys( that.methodCallTracker ).length;
+                       cntMissing = util.keys( that.missingTests ).length;
+
+                       function makeTestResults( blob, title, style ) {
+                               var elOutputWrapper, elTitle, elContainer, elList, elFoot;
+
+                               elTitle = document.createElement( 'strong' );
+                               elTitle.textContent = title || 'Values';
+
+                               elList = document.createElement( 'ul' );
+                               util.each( blob, function ( key ) {
+                                       var elItem = document.createElement( 'li' );
+                                       elItem.textContent = key;
+                                       elList.appendChild( elItem );
+                               });
+
+                               elFoot = document.createElement( 'p' );
+                               elFoot.innerHTML = '<em>&mdash; CompletenessTest</em>';
+
+                               elContainer = document.createElement( 'div' );
+                               elContainer.appendChild( elTitle );
+                               elContainer.appendChild( elList );
+                               elContainer.appendChild( elFoot );
+
+                               elOutputWrapper = document.getElementById( 'qunit-completenesstest' );
+                               if ( !elOutputWrapper ) {
+                                       elOutputWrapper = document.createElement( 'div' );
+                                       elOutputWrapper.id = 'qunit-completenesstest';
+                               }
+                               elOutputWrapper.appendChild( elContainer );
+
+                               util.each( style, function ( key, value ) {
+                                       elOutputWrapper.style[key] = value;
+                               });
+                               return elOutputWrapper;
+                       }
+
+                       if ( cntMissing === 0 ) {
+                               // Good
+                               testResults = makeTestResults(
+                                       {},
+                                       'Detected calls to ' + cntCalled + '/' + cntTotal + ' methods. No missing tests!',
+                                       {
+                                               backgroundColor: '#D2E0E6',
+                                               color: '#366097',
+                                               paddingTop: '1em',
+                                               paddingRight: '1em',
+                                               paddingBottom: '1em',
+                                               paddingLeft: '1em'
+                                       }
+                               );
+                       } else {
+                               // Bad
+                               testResults = makeTestResults(
+                                       that.missingTests,
+                                       'Detected calls to ' + cntCalled + '/' + cntTotal + ' methods. ' + cntMissing + ' methods not covered:',
+                                       {
+                                               backgroundColor: '#EE5757',
+                                               color: 'black',
+                                               paddingTop: '1em',
+                                               paddingRight: '1em',
+                                               paddingBottom: '1em',
+                                               paddingLeft: '1em'
+                                       }
+                               );
+                       }
+
+                       toolbar = document.getElementById( 'qunit-testrunner-toolbar' );
+                       if ( toolbar ) {
+                               toolbar.insertBefore( testResults, toolbar.firstChild );
+                       }
+               });
+
+               return this;
+       }
+
+       /* Static members */
+       CompletenessTest.ACTION_INJECT = 500;
+       CompletenessTest.ACTION_CHECK = 501;
+
+       /* Public methods */
+       CompletenessTest.fn = CompletenessTest.prototype = {
+
+               /**
+                * CompletenessTest.fn.walkTheObject
+                *
+                * This function recursively walks through the given object, calling itself as it goes.
+                * Depending on the action it either injects our listener into the methods, or
+                * reads from our tracker and records which methods have not been called by the test suite.
+                *
+                * @param currName {String|Null} Name of the given object member (Initially this is null).
+                * @param currVar {mixed} The variable to check (initially an object,
+                *  further down it could be anything).
+                * @param masterVariable {Object} Throughout our interation, always keep track of the master/root.
+                *  Initially this is the same as currVar.
+                * @param parentPathArray {Array} Array of names that indicate our breadcrumb path starting at
+                *  masterVariable. Not including currName.
+                * @param action {Number} What is this function supposed to do (ACTION_INJECT or ACTION_CHECK)
+                */
+               walkTheObject: function ( currName, currVar, masterVariable, parentPathArray, action ) {
+
+                       var key, value, tmpPathArray,
+                               type = util.type( currVar ),
+                               that = this;
+
+                       // Hard ignores
+                       if ( this.ignoreFn( currVar, that, parentPathArray ) ) {
+                               return null;
+                       }
+
+                       // Handle the lazy limit
+                       this.lazyCounter++;
+                       if ( this.lazyCounter > this.lazyLimit ) {
+                               log( 'CompletenessTest.fn.walkTheObject> Limit reached: ' + this.lazyCounter, parentPathArray );
+                               return null;
+                       }
+
+                       // Functions
+                       if ( type === 'function' ) {
+
+                               if ( !currVar.prototype || util.isEmptyObject( currVar.prototype ) ) {
+
+                                       if ( action === CompletenessTest.ACTION_INJECT ) {
+
+                                               that.injectionTracker[ parentPathArray.join( '.' ) ] = true;
+                                               that.injectCheck( masterVariable, parentPathArray, function () {
+                                                       that.methodCallTracker[ parentPathArray.join( '.' ) ] = true;
+                                               } );
+                                       }
+
+                               // We don't support checking object constructors yet...
+                               // ...we can check the prototypes fine, though.
+                               } else {
+                                       if ( action === CompletenessTest.ACTION_INJECT ) {
+
+                                               for ( key in currVar.prototype ) {
+                                                       if ( hasOwn.call( currVar.prototype, key ) ) {
+                                                               value = currVar.prototype[key];
+                                                               if ( key === 'constructor' ) {
+                                                                       continue;
+                                                               }
+
+                                                               // Clone and break reference to parentPathArray
+                                                               tmpPathArray = util.extend( [], parentPathArray );
+                                                               tmpPathArray.push( 'prototype' );
+                                                               tmpPathArray.push( key );
+
+                                                               that.walkTheObject( key, value, masterVariable, tmpPathArray, action );
+                                                       }
+                                               }
+
+                                       }
+                               }
+
+                       }
+
+                       // Recursively. After all, this is the *completeness* test
+                       if ( type === 'function' || type === 'object' ) {
+                               for ( key in currVar ) {
+                                       if ( hasOwn.call( currVar, key ) ) {
+                                               value = currVar[key];
+
+                                               // Clone and break reference to parentPathArray
+                                               tmpPathArray = util.extend( [], parentPathArray );
+                                               tmpPathArray.push( key );
+
+                                               that.walkTheObject( key, value, masterVariable, tmpPathArray, action );
+                                       }
+                               }
+                       }
+               },
+
+               populateMissingTests: function () {
+                       var ct = this;
+                       util.each( ct.injectionTracker, function ( key ) {
+                               ct.hasTest( key );
+                       });
+               },
+
+               /**
+                * CompletenessTest.fn.hasTest
+                *
+                * Checks if the given method name (ie. 'my.foo.bar')
+                * was called during the test suite (as far as the tracker knows).
+                * If not it adds it to missingTests.
+                *
+                * @param fnName {String}
+                * @return {Boolean}
+                */
+               hasTest: function ( fnName ) {
+                       if ( !( fnName in this.methodCallTracker ) ) {
+                               this.missingTests[fnName] = true;
+                               return false;
+                       }
+                       return true;
+               },
+
+               /**
+                * CompletenessTest.fn.injectCheck
+                *
+                * Injects a function (such as a spy that updates methodCallTracker when
+                * it's called) inside another function.
+                *
+                * @param masterVariable {Object}
+                * @param objectPathArray {Array}
+                * @param injectFn {Function}
+                */
+               injectCheck: function ( masterVariable, objectPathArray, injectFn ) {
+                       var i, len, prev, memberName, lastMember,
+                               curr = masterVariable;
+
+                       // Get the object in question through the path from the master variable,
+                       // We can't pass the value directly because we need to re-define the object
+                       // member and keep references to the parent object, member name and member
+                       // value at all times.
+                       for ( i = 0, len = objectPathArray.length; i < len; i++ ) {
+                               memberName = objectPathArray[i];
+
+                               prev = curr;
+                               curr = prev[memberName];
+                               lastMember = memberName;
+                       }
+
+                       // Objects are by reference, members (unless objects) are not.
+                       prev[lastMember] = function () {
+                               injectFn();
+                               return curr.apply( this, arguments );
+                       };
+               }
+       };
+
+       /* Expose */
+       window.CompletenessTest = CompletenessTest;
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.spinner.css b/resources/src/jquery/jquery.spinner.css
new file mode 100644 (file)
index 0000000..a9e06db
--- /dev/null
@@ -0,0 +1,40 @@
+.mw-spinner {
+       background-color: transparent;
+       background-position: center center;
+       background-repeat: no-repeat;
+}
+
+.mw-spinner-small {
+       /* @embed */
+       background-image: url(images/spinner.gif);
+       height: 20px;
+       width: 20px;
+       /* Avoid issues with .mw-spinner-block when floated without width. */
+       min-width: 20px;
+}
+
+.mw-spinner-large {
+       /* @embed */
+       background-image: url(images/spinner-large.gif);
+       height: 32px;
+       width: 32px;
+       /* Avoid issues with .mw-spinner-block when floated without width. */
+       min-width: 32px;
+}
+
+.mw-spinner-block {
+       display: block;
+       /* This overrides width from .mw-spinner-large / .mw-spinner-small,
+        * This is where the min-width kicks in.
+        */
+       width: 100%;
+}
+
+.mw-spinner-inline {
+       display: inline-block;
+       vertical-align: middle;
+
+       /* IE < 8 */
+       zoom: 1;
+       *display: inline;
+}
diff --git a/resources/src/jquery/jquery.spinner.js b/resources/src/jquery/jquery.spinner.js
new file mode 100644 (file)
index 0000000..073fb3d
--- /dev/null
@@ -0,0 +1,112 @@
+/**
+ * jQuery Spinner
+ *
+ * Simple jQuery plugin to create, inject and remove spinners.
+ *
+ * @class jQuery.plugin.spinner
+ */
+( function ( $ ) {
+
+       // Default options for new spinners,
+       // stored outside the function to share between calls.
+       var defaults = {
+               id: undefined,
+               size: 'small',
+               type: 'inline'
+       };
+
+       $.extend({
+               /**
+                * Create a spinner element
+                *
+                * The argument is an object with options used to construct the spinner (see below).
+                *
+                * It is a good practice to keep a reference to the created spinner to be able to remove it
+                * later. Alternatively, one can use the 'id' option and #removeSpinner (but make sure to choose
+                * an id that's unlikely to cause conflicts, e.g. with extensions, gadgets or user scripts).
+                *
+                * CSS classes used:
+                *
+                * - .mw-spinner for every spinner
+                * - .mw-spinner-small / .mw-spinner-large for size
+                * - .mw-spinner-block / .mw-spinner-inline for display types
+                *
+                * Example:
+                *
+                *     // Create a large spinner reserving all available horizontal space.
+                *     var $spinner = $.createSpinner({ size: 'large', type: 'block' });
+                *     // Insert above page content.
+                *     $( '#mw-content-text' ).prepend( $spinner );
+                *
+                *     // Place a small inline spinner next to the "Save" button
+                *     var $spinner = $.createSpinner({ size: 'small', type: 'inline' });
+                *     // Alternatively, just `$.createSpinner();` as these are the default options.
+                *     $( '#wpSave' ).after( $spinner );
+                *
+                *     // The following two are equivalent:
+                *     $.createSpinner( 'magic' );
+                *     $.createSpinner({ id: 'magic' });
+                *
+                * @static
+                * @inheritable
+                * @param {Object|string} [opts] Options. If a string is given, it will be treated as the value
+                *   of the `id` option. If an object is given, the possible option keys are:
+                * @param {string} [opts.id] If given, spinner will be given an id of "mw-spinner-{id}".
+                * @param {string} [opts.size='small'] 'small' or 'large' for a 20-pixel or 32-pixel spinner.
+                * @param {string} [opts.type='inline'] 'inline' or 'block'. Inline creates an inline-block with
+                *   width and height equal to spinner size. Block is a block-level element with width 100%,
+                *   height equal to spinner size.
+                * @return {jQuery}
+                */
+               createSpinner: function ( opts ) {
+                       if ( opts !== undefined && $.type( opts ) !== 'object' ) {
+                               opts = {
+                                       id: opts
+                               };
+                       }
+
+                       opts = $.extend( {}, defaults, opts );
+
+                       var $spinner = $( '<div>', { 'class': 'mw-spinner', 'title': '...' } );
+                       if ( opts.id !== undefined ) {
+                               $spinner.attr( 'id', 'mw-spinner-' + opts.id );
+                       }
+
+                       $spinner.addClass( opts.size === 'large' ? 'mw-spinner-large' : 'mw-spinner-small' );
+                       $spinner.addClass( opts.type === 'block' ? 'mw-spinner-block' : 'mw-spinner-inline' );
+
+                       return $spinner;
+               },
+
+               /**
+                * Remove a spinner element
+                *
+                * @static
+                * @inheritable
+                * @param {string} id Id of the spinner, as passed to #createSpinner
+                * @return {jQuery} The (now detached) spinner element
+                */
+               removeSpinner: function ( id ) {
+                       return $( '#mw-spinner-' + id ).remove();
+               }
+       });
+
+       /**
+        * Inject a spinner after each element in the collection
+        *
+        * Inserts spinner as siblings (not children) of the target elements.
+        * Collection contents remain unchanged.
+        *
+        * @param {Object|string} [opts] See #createSpinner
+        * @return {jQuery}
+        */
+       $.fn.injectSpinner = function ( opts ) {
+               return this.after( $.createSpinner( opts ) );
+       };
+
+       /**
+        * @class jQuery
+        * @mixins jQuery.plugin.spinner
+        */
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.suggestions.css b/resources/src/jquery/jquery.suggestions.css
new file mode 100644 (file)
index 0000000..ea65946
--- /dev/null
@@ -0,0 +1,81 @@
+/* suggestions plugin */
+
+.suggestions {
+       overflow: hidden;
+       position: absolute;
+       top: 0;
+       left: 0;
+       width: 0;
+       border: none;
+       z-index: 1099;
+       padding: 0;
+       margin: -1px -1px 0 0;
+}
+
+/* IGNORED BY IE6 */
+html > body .suggestions {
+       margin: -1px 0 0 0;
+}
+
+.suggestions-special {
+       position: relative;
+       background-color: white;
+       cursor: pointer;
+       border: solid 1px #aaaaaa;
+       padding: 0;
+       margin: 0;
+       margin-top: -2px;
+       display: none;
+       padding: 0.25em 0.25em;
+       line-height: 1.25em;
+}
+
+.suggestions-results {
+       background-color: white;
+       cursor: pointer;
+       border: solid 1px #aaaaaa;
+       padding: 0;
+       margin: 0;
+}
+
+.suggestions-result {
+       color: black;
+       margin: 0;
+       line-height: 1.5em;
+       padding: 0.01em 0.25em;
+       text-align: left;
+       /* Apply ellipsis to suggestions */
+       overflow: hidden;
+       -o-text-overflow: ellipsis; /* Opera 9 to 10 */
+       text-overflow: ellipsis;
+       white-space: nowrap;
+}
+
+.suggestions-result-current {
+       background-color: #4C59A6;
+       color: white;
+}
+
+.suggestions-special .special-label {
+       color: gray;
+       text-align: left;
+}
+
+.suggestions-special .special-query {
+       color: black;
+       font-style: italic;
+       text-align: left;
+}
+
+.suggestions-special .special-hover {
+       background-color: silver;
+}
+
+.suggestions-result-current .special-label,
+.suggestions-result-current .special-query {
+       color: white;
+}
+
+.highlight {
+       font-weight: bold;
+}
diff --git a/resources/src/jquery/jquery.suggestions.js b/resources/src/jquery/jquery.suggestions.js
new file mode 100644 (file)
index 0000000..29be239
--- /dev/null
@@ -0,0 +1,617 @@
+/**
+ * This plugin provides a generic way to add suggestions to a text box.
+ *
+ * Usage:
+ *
+ * Set options:
+ *             $( '#textbox' ).suggestions( { option1: value1, option2: value2 } );
+ *             $( '#textbox' ).suggestions( option, value );
+ * Get option:
+ *             value = $( '#textbox' ).suggestions( option );
+ * Initialize:
+ *             $( '#textbox' ).suggestions();
+ *
+ * Options:
+ *
+ * fetch(query): Callback that should fetch suggestions and set the suggestions property.
+ *      Executed in the context of the textbox
+ *             Type: Function
+ * cancel: Callback function to call when any pending asynchronous suggestions fetches
+ *      should be canceled. Executed in the context of the textbox
+ *             Type: Function
+ * special: Set of callbacks for rendering and selecting
+ *             Type: Object of Functions 'render' and 'select'
+ * result: Set of callbacks for rendering and selecting
+ *             Type: Object of Functions 'render' and 'select'
+ * $region: jQuery selection of element to place the suggestions below and match width of
+ *             Type: jQuery Object, Default: $(this)
+ * suggestions: Suggestions to display
+ *             Type: Array of strings
+ * maxRows: Maximum number of suggestions to display at one time
+ *             Type: Number, Range: 1 - 100, Default: 7
+ * delay: Number of ms to wait for the user to stop typing
+ *             Type: Number, Range: 0 - 1200, Default: 120
+ * submitOnClick: Whether to submit the form containing the textbox when a suggestion is clicked
+ *             Type: Boolean, Default: false
+ * maxExpandFactor: Maximum suggestions box width relative to the textbox width. If set
+ *      to e.g. 2, the suggestions box will never be grown beyond 2 times the width of the textbox.
+ *             Type: Number, Range: 1 - infinity, Default: 3
+ * expandFrom: Which direction to offset the suggestion box from.
+ *      Values 'start' and 'end' translate to left and right respectively depending on the
+ *      directionality of the current document, according to $( 'html' ).css( 'direction' ).
+ *      Type: String, default: 'auto', options: 'left', 'right', 'start', 'end', 'auto'.
+ * positionFromLeft: Sets expandFrom=left, for backwards compatibility
+ *             Type: Boolean, Default: true
+ * highlightInput: Whether to hightlight matched portions of the input or not
+ *             Type: Boolean, Default: false
+ */
+( function ( $ ) {
+
+$.suggestions = {
+       /**
+        * Cancel any delayed maybeFetch() call and callback the context so
+        * they can cancel any async fetching if they use AJAX or something.
+        */
+       cancel: function ( context ) {
+               if ( context.data.timerID !== null ) {
+                       clearTimeout( context.data.timerID );
+               }
+               if ( $.isFunction( context.config.cancel ) ) {
+                       context.config.cancel.call( context.data.$textbox );
+               }
+       },
+
+       /**
+        * Hide the element with suggestions and clean up some state.
+        */
+       hide: function ( context ) {
+               // Remove any highlights, including on "special" items
+               context.data.$container.find( '.suggestions-result-current' ).removeClass( 'suggestions-result-current' );
+               // Hide the container
+               context.data.$container.hide();
+       },
+
+       /**
+        * Restore the text the user originally typed in the textbox, before it
+        * was overwritten by highlight(). This restores the value the currently
+        * displayed suggestions are based on, rather than the value just before
+        * highlight() overwrote it; the former is arguably slightly more sensible.
+        */
+       restore: function ( context ) {
+               context.data.$textbox.val( context.data.prevText );
+       },
+
+       /**
+        * Ask the user-specified callback for new suggestions. Any previous delayed
+        * call to this function still pending will be canceled. If the value in the
+        * textbox is empty or hasn't changed since the last time suggestions were fetched,
+        * this function does nothing.
+        * @param {Boolean} delayed Whether or not to delay this by the currently configured amount of time
+        */
+       update: function ( context, delayed ) {
+               // Only fetch if the value in the textbox changed and is not empty, or if the results were hidden
+               // if the textbox is empty then clear the result div, but leave other settings intouched
+               function maybeFetch() {
+                       if ( context.data.$textbox.val().length === 0 ) {
+                               $.suggestions.hide( context );
+                               context.data.prevText = '';
+                       } else if (
+                               context.data.$textbox.val() !== context.data.prevText ||
+                               !context.data.$container.is( ':visible' )
+                       ) {
+                               if ( typeof context.config.fetch === 'function' ) {
+                                       context.data.prevText = context.data.$textbox.val();
+                                       context.config.fetch.call( context.data.$textbox, context.data.$textbox.val() );
+                               }
+                       }
+               }
+
+               // Cancels any delayed maybeFetch call, and invokes context.config.cancel.
+               $.suggestions.cancel( context );
+
+               if ( delayed ) {
+                       // To avoid many started/aborted requests while typing, we're gonna take a short
+                       // break before trying to fetch data.
+                       context.data.timerID = setTimeout( maybeFetch, context.config.delay );
+               } else {
+                       maybeFetch();
+               }
+               $.suggestions.special( context );
+       },
+
+       special: function ( context ) {
+               // Allow custom rendering - but otherwise don't do any rendering
+               if ( typeof context.config.special.render === 'function' ) {
+                       // Wait for the browser to update the value
+                       setTimeout( function () {
+                               // Render special
+                               var $special = context.data.$container.find( '.suggestions-special' );
+                               context.config.special.render.call( $special, context.data.$textbox.val(), context );
+                       }, 1 );
+               }
+       },
+
+       /**
+        * Sets the value of a property, and updates the widget accordingly
+        * @param property String Name of property
+        * @param value Mixed Value to set property with
+        */
+       configure: function ( context, property, value ) {
+               var newCSS,
+                       $result, $results, childrenWidth,
+                       i, expWidth, maxWidth, text;
+
+               // Validate creation using fallback values
+               switch ( property ) {
+                       case 'fetch':
+                       case 'cancel':
+                       case 'special':
+                       case 'result':
+                       case '$region':
+                       case 'expandFrom':
+                               context.config[property] = value;
+                               break;
+                       case 'suggestions':
+                               context.config[property] = value;
+                               // Update suggestions
+                               if ( context.data !== undefined ) {
+                                       if ( context.data.$textbox.val().length === 0 ) {
+                                               // Hide the div when no suggestion exist
+                                               $.suggestions.hide( context );
+                                       } else {
+                                               // Rebuild the suggestions list
+                                               context.data.$container.show();
+                                               // Update the size and position of the list
+                                               newCSS = {
+                                                       top: context.config.$region.offset().top + context.config.$region.outerHeight(),
+                                                       bottom: 'auto',
+                                                       width: context.config.$region.outerWidth(),
+                                                       height: 'auto'
+                                               };
+
+                                               // Process expandFrom, after this it is set to left or right.
+                                               context.config.expandFrom = ( function ( expandFrom ) {
+                                                       var regionWidth, docWidth, regionCenter, docCenter,
+                                                               docDir = $( document.documentElement ).css( 'direction' ),
+                                                               $region = context.config.$region;
+
+                                                       // Backwards compatible
+                                                       if ( context.config.positionFromLeft ) {
+                                                               expandFrom = 'left';
+
+                                                       // Catch invalid values, default to 'auto'
+                                                       } else if ( $.inArray( expandFrom, ['left', 'right', 'start', 'end', 'auto'] ) === -1 ) {
+                                                               expandFrom = 'auto';
+                                                       }
+
+                                                       if ( expandFrom === 'auto' ) {
+                                                               if ( $region.data( 'searchsuggest-expand-dir' ) ) {
+                                                                       // If the markup explicitly contains a direction, use it.
+                                                                       expandFrom = $region.data( 'searchsuggest-expand-dir' );
+                                                               } else {
+                                                                       regionWidth = $region.outerWidth();
+                                                                       docWidth = $( document ).width();
+                                                                       if ( ( regionWidth / docWidth  ) > 0.85 ) {
+                                                                               // If the input size takes up more than 85% of the document horizontally
+                                                                               // expand the suggestions to the writing direction's native end.
+                                                                               expandFrom = 'start';
+                                                                       } else {
+                                                                               // Calculate the center points of the input and document
+                                                                               regionCenter = $region.offset().left + regionWidth / 2;
+                                                                               docCenter = docWidth / 2;
+                                                                               if ( Math.abs( regionCenter - docCenter ) / docCenter < 0.10 ) {
+                                                                                       // If the input's center is within 10% of the document center
+                                                                                       // use the writing direction's native end.
+                                                                                       expandFrom = 'start';
+                                                                               } else {
+                                                                                       // Otherwise expand the input from the closest side of the page,
+                                                                                       // towards the side of the page with the most free open space
+                                                                                       expandFrom = regionCenter > docCenter ? 'right' : 'left';
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+
+                                                       if ( expandFrom === 'start' ) {
+                                                               expandFrom = docDir === 'rtl' ? 'right': 'left';
+
+                                                       } else if ( expandFrom === 'end' ) {
+                                                               expandFrom = docDir === 'rtl' ? 'left': 'right';
+                                                       }
+
+                                                       return expandFrom;
+
+                                               }( context.config.expandFrom ) );
+
+                                               if ( context.config.expandFrom === 'left' ) {
+                                                       // Expand from left
+                                                       newCSS.left = context.config.$region.offset().left;
+                                                       newCSS.right = 'auto';
+                                               } else {
+                                                       // Expand from right
+                                                       newCSS.left = 'auto';
+                                                       newCSS.right = $( document ).width() - ( context.config.$region.offset().left + context.config.$region.outerWidth() );
+                                               }
+
+                                               context.data.$container.css( newCSS );
+                                               $results = context.data.$container.children( '.suggestions-results' );
+                                               $results.empty();
+                                               expWidth = -1;
+                                               for ( i = 0; i < context.config.suggestions.length; i++ ) {
+                                                       /*jshint loopfunc:true */
+                                                       text = context.config.suggestions[i];
+                                                       $result = $( '<div>' )
+                                                               .addClass( 'suggestions-result' )
+                                                               .attr( 'rel', i )
+                                                               .data( 'text', context.config.suggestions[i] )
+                                                               .mousemove( function () {
+                                                                       context.data.selectedWithMouse = true;
+                                                                       $.suggestions.highlight(
+                                                                               context,
+                                                                               $(this).closest( '.suggestions-results .suggestions-result' ),
+                                                                               false
+                                                                       );
+                                                               } )
+                                                               .appendTo( $results );
+                                                       // Allow custom rendering
+                                                       if ( typeof context.config.result.render === 'function' ) {
+                                                               context.config.result.render.call( $result, context.config.suggestions[i], context );
+                                                       } else {
+                                                               $result.text( text );
+                                                       }
+
+                                                       if ( context.config.highlightInput ) {
+                                                               $result.highlightText( context.data.prevText );
+                                                       }
+
+                                                       // Widen results box if needed
+                                                       // New width is only calculated here, applied later
+                                                       childrenWidth = $result.children().outerWidth();
+                                                       if ( childrenWidth > $result.width() && childrenWidth > expWidth ) {
+                                                               // factor in any padding, margin, or border space on the parent
+                                                               expWidth = childrenWidth + ( context.data.$container.width() - $result.width() );
+                                                       }
+                                               }
+
+                                               // Apply new width for results box, if any
+                                               if ( expWidth > context.data.$container.width() ) {
+                                                       maxWidth = context.config.maxExpandFactor * context.data.$textbox.width();
+                                                       context.data.$container.width( Math.min( expWidth, maxWidth ) );
+                                               }
+                                       }
+                               }
+                               break;
+                       case 'maxRows':
+                               context.config[property] = Math.max( 1, Math.min( 100, value ) );
+                               break;
+                       case 'delay':
+                               context.config[property] = Math.max( 0, Math.min( 1200, value ) );
+                               break;
+                       case 'maxExpandFactor':
+                               context.config[property] = Math.max( 1, value );
+                               break;
+                       case 'submitOnClick':
+                       case 'positionFromLeft':
+                       case 'highlightInput':
+                               context.config[property] = value ? true : false;
+                               break;
+               }
+       },
+
+       /**
+        * Highlight a result in the results table
+        * @param result <tr> to highlight: jQuery object, or 'prev' or 'next'
+        * @param updateTextbox If true, put the suggestion in the textbox
+        */
+       highlight: function ( context, result, updateTextbox ) {
+               var selected = context.data.$container.find( '.suggestions-result-current' );
+               if ( !result.get || selected.get( 0 ) !== result.get( 0 ) ) {
+                       if ( result === 'prev' ) {
+                               if( selected.hasClass( 'suggestions-special' ) ) {
+                                       result = context.data.$container.find( '.suggestions-result:last' );
+                               } else {
+                                       result = selected.prev();
+                                       if ( !( result.length && result.hasClass( 'suggestions-result' ) ) ) {
+                                               // there is something in the DOM between selected element and the wrapper, bypass it
+                                               result = selected.parents( '.suggestions-results > *' ).prev().find( '.suggestions-result' ).eq(0);
+                                       }
+
+                                       if ( selected.length === 0 ) {
+                                               // we are at the beginning, so lets jump to the last item
+                                               if ( context.data.$container.find( '.suggestions-special' ).html() !== '' ) {
+                                                       result = context.data.$container.find( '.suggestions-special' );
+                                               } else {
+                                                       result = context.data.$container.find( '.suggestions-results .suggestions-result:last' );
+                                               }
+                                       }
+                               }
+                       } else if ( result === 'next' ) {
+                               if ( selected.length === 0 ) {
+                                       // No item selected, go to the first one
+                                       result = context.data.$container.find( '.suggestions-results .suggestions-result:first' );
+                                       if ( result.length === 0 && context.data.$container.find( '.suggestions-special' ).html() !== '' ) {
+                                               // No suggestion exists, go to the special one directly
+                                               result = context.data.$container.find( '.suggestions-special' );
+                                       }
+                               } else {
+                                       result = selected.next();
+                                       if ( !( result.length && result.hasClass( 'suggestions-result' ) ) ) {
+                                               // there is something in the DOM between selected element and the wrapper, bypass it
+                                               result = selected.parents( '.suggestions-results > *' ).next().find( '.suggestions-result' ).eq(0);
+                                       }
+
+                                       if ( selected.hasClass( 'suggestions-special' ) ) {
+                                               result = $( [] );
+                                       } else if (
+                                               result.length === 0 &&
+                                               context.data.$container.find( '.suggestions-special' ).html() !== ''
+                                       ) {
+                                               // We were at the last item, jump to the specials!
+                                               result = context.data.$container.find( '.suggestions-special' );
+                                       }
+                               }
+                       }
+                       selected.removeClass( 'suggestions-result-current' );
+                       result.addClass( 'suggestions-result-current' );
+               }
+               if ( updateTextbox ) {
+                       if ( result.length === 0 || result.is( '.suggestions-special' ) ) {
+                               $.suggestions.restore( context );
+                       } else {
+                               context.data.$textbox.val( result.data( 'text' ) );
+                               // .val() doesn't call any event handlers, so
+                               // let the world know what happened
+                               context.data.$textbox.change();
+                       }
+                       context.data.$textbox.trigger( 'change' );
+               }
+       },
+
+       /**
+        * Respond to keypress event
+        * @param key Integer Code of key pressed
+        */
+       keypress: function ( e, context, key ) {
+               var selected,
+                       wasVisible = context.data.$container.is( ':visible' ),
+                       preventDefault = false;
+
+               switch ( key ) {
+                       // Arrow down
+                       case 40:
+                               if ( wasVisible ) {
+                                       $.suggestions.highlight( context, 'next', true );
+                                       context.data.selectedWithMouse = false;
+                               } else {
+                                       $.suggestions.update( context, false );
+                               }
+                               preventDefault = true;
+                               break;
+                       // Arrow up
+                       case 38:
+                               if ( wasVisible ) {
+                                       $.suggestions.highlight( context, 'prev', true );
+                                       context.data.selectedWithMouse = false;
+                               }
+                               preventDefault = wasVisible;
+                               break;
+                       // Escape
+                       case 27:
+                               $.suggestions.hide( context );
+                               $.suggestions.restore( context );
+                               $.suggestions.cancel( context );
+                               context.data.$textbox.trigger( 'change' );
+                               preventDefault = wasVisible;
+                               break;
+                       // Enter
+                       case 13:
+                               preventDefault = wasVisible;
+                               selected = context.data.$container.find( '.suggestions-result-current' );
+                               $.suggestions.hide( context );
+                               if ( selected.length === 0 || context.data.selectedWithMouse ) {
+                                       // If nothing is selected or if something was selected with the mouse
+                                       // cancel any current requests and allow the form to be submitted
+                                       // (simply don't prevent default behavior).
+                                       $.suggestions.cancel( context );
+                                       preventDefault = false;
+                               } else if ( selected.is( '.suggestions-special' ) ) {
+                                       if ( typeof context.config.special.select === 'function' ) {
+                                               // Allow the callback to decide whether to prevent default or not
+                                               if ( context.config.special.select.call( selected, context.data.$textbox ) === true ) {
+                                                       preventDefault = false;
+                                               }
+                                       }
+                               } else {
+                                       $.suggestions.highlight( context, selected, true );
+
+                                       if ( typeof context.config.result.select === 'function' ) {
+                                               // Allow the callback to decide whether to prevent default or not
+                                               if ( context.config.result.select.call( selected, context.data.$textbox ) === true ) {
+                                                       preventDefault = false;
+                                               }
+                                       }
+                               }
+                               break;
+                       default:
+                               $.suggestions.update( context, true );
+                               break;
+               }
+               if ( preventDefault ) {
+                       e.preventDefault();
+                       e.stopPropagation();
+               }
+       }
+};
+$.fn.suggestions = function () {
+
+       // Multi-context fields
+       var returnValue,
+               args = arguments;
+
+       $(this).each( function () {
+               var context, key;
+
+               /* Construction / Loading */
+
+               context = $(this).data( 'suggestions-context' );
+               if ( context === undefined || context === null ) {
+                       context = {
+                               config: {
+                                       fetch: function () {},
+                                       cancel: function () {},
+                                       special: {},
+                                       result: {},
+                                       $region: $(this),
+                                       suggestions: [],
+                                       maxRows: 7,
+                                       delay: 120,
+                                       submitOnClick: false,
+                                       maxExpandFactor: 3,
+                                       expandFrom: 'auto',
+                                       highlightInput: false
+                               }
+                       };
+               }
+
+               /* API */
+
+               // Handle various calling styles
+               if ( args.length > 0 ) {
+                       if ( typeof args[0] === 'object' ) {
+                               // Apply set of properties
+                               for ( key in args[0] ) {
+                                       $.suggestions.configure( context, key, args[0][key] );
+                               }
+                       } else if ( typeof args[0] === 'string' ) {
+                               if ( args.length > 1 ) {
+                                       // Set property values
+                                       $.suggestions.configure( context, args[0], args[1] );
+                               } else if ( returnValue === null || returnValue === undefined ) {
+                                       // Get property values, but don't give access to internal data - returns only the first
+                                       returnValue = ( args[0] in context.config ? undefined : context.config[args[0]] );
+                               }
+                       }
+               }
+
+               /* Initialization */
+
+               if ( context.data === undefined ) {
+                       context.data = {
+                               // ID of running timer
+                               timerID: null,
+
+                               // Text in textbox when suggestions were last fetched
+                               prevText: null,
+
+                               // Number of results visible without scrolling
+                               visibleResults: 0,
+
+                               // Suggestion the last mousedown event occured on
+                               mouseDownOn: $( [] ),
+                               $textbox: $(this),
+                               selectedWithMouse: false
+                       };
+
+                       context.data.$container = $( '<div>' )
+                               .css( 'display', 'none' )
+                               .addClass( 'suggestions' )
+                               .append(
+                                       $( '<div>' ).addClass( 'suggestions-results' )
+                                               // Can't use click() because the container div is hidden when the
+                                               // textbox loses focus. Instead, listen for a mousedown followed
+                                               // by a mouseup on the same div.
+                                               .mousedown( function ( e ) {
+                                                       context.data.mouseDownOn = $( e.target ).closest( '.suggestions-results .suggestions-result' );
+                                               } )
+                                               .mouseup( function ( e ) {
+                                                       var $result = $( e.target ).closest( '.suggestions-results .suggestions-result' ),
+                                                               $other = context.data.mouseDownOn;
+
+                                                       context.data.mouseDownOn = $( [] );
+                                                       if ( $result.get( 0 ) !== $other.get( 0 ) ) {
+                                                               return;
+                                                       }
+                                                       // do not interfere with non-left clicks or if modifier keys are pressed (e.g. ctrl-click)
+                                                       if ( !( e.which !== 1 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey ) ) {
+                                                               $.suggestions.highlight( context, $result, true );
+                                                               $.suggestions.hide( context );
+                                                               if ( typeof context.config.result.select === 'function' ) {
+                                                                       context.config.result.select.call( $result, context.data.$textbox );
+                                                               }
+                                                       }
+                                                       // but still restore focus to the textbox, so that the suggestions will be hidden properly
+                                                       context.data.$textbox.focus();
+                                               } )
+                               )
+                               .append(
+                                       $( '<div>' ).addClass( 'suggestions-special' )
+                                               // Can't use click() because the container div is hidden when the
+                                               // textbox loses focus. Instead, listen for a mousedown followed
+                                               // by a mouseup on the same div.
+                                               .mousedown( function ( e ) {
+                                                       context.data.mouseDownOn = $( e.target ).closest( '.suggestions-special' );
+                                               } )
+                                               .mouseup( function ( e ) {
+                                                       var $special = $( e.target ).closest( '.suggestions-special' ),
+                                                               $other = context.data.mouseDownOn;
+
+                                                       context.data.mouseDownOn = $( [] );
+                                                       if ( $special.get( 0 ) !== $other.get( 0 ) ) {
+                                                               return;
+                                                       }
+                                                       // do not interfere with non-left clicks or if modifier keys are pressed (e.g. ctrl-click)
+                                                       if ( !( e.which !== 1 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey ) ) {
+                                                               $.suggestions.hide( context );
+                                                               if ( typeof context.config.special.select === 'function' ) {
+                                                                       context.config.special.select.call( $special, context.data.$textbox );
+                                                               }
+                                                       }
+                                                       // but still restore focus to the textbox, so that the suggestions will be hidden properly
+                                                       context.data.$textbox.focus();
+                                               } )
+                                               .mousemove( function ( e ) {
+                                                       context.data.selectedWithMouse = true;
+                                                       $.suggestions.highlight(
+                                                               context, $( e.target ).closest( '.suggestions-special' ), false
+                                                       );
+                                               } )
+                               )
+                               .appendTo( $( 'body' ) );
+
+                       $(this)
+                               // Stop browser autocomplete from interfering
+                               .attr( 'autocomplete', 'off')
+                               .keydown( function ( e ) {
+                                       // Store key pressed to handle later
+                                       context.data.keypressed = e.which;
+                                       context.data.keypressedCount = 0;
+                               } )
+                               .keypress( function ( e ) {
+                                       context.data.keypressedCount++;
+                                       $.suggestions.keypress( e, context, context.data.keypressed );
+                               } )
+                               .keyup( function ( e ) {
+                                       // Some browsers won't throw keypress() for arrow keys. If we got a keydown and a keyup without a
+                                       // keypress in between, solve it
+                                       if ( context.data.keypressedCount === 0 ) {
+                                               $.suggestions.keypress( e, context, context.data.keypressed );
+                                       }
+                               } )
+                               .blur( function () {
+                                       // When losing focus because of a mousedown
+                                       // on a suggestion, don't hide the suggestions
+                                       if ( context.data.mouseDownOn.length > 0 ) {
+                                               return;
+                                       }
+                                       $.suggestions.hide( context );
+                                       $.suggestions.cancel( context );
+                               } );
+               }
+
+               // Store the context for next time
+               $(this).data( 'suggestions-context', context );
+       } );
+       return returnValue !== undefined ? returnValue : $(this);
+};
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.tabIndex.js b/resources/src/jquery/jquery.tabIndex.js
new file mode 100644 (file)
index 0000000..cdae0ba
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * jQuery tabIndex
+ */
+( function ( $ ) {
+
+       /**
+        * Finds the lowerst tabindex in use within a selection
+        *
+        * @return number Lowest tabindex on the page
+        */
+       $.fn.firstTabIndex = function () {
+               var minTabIndex = null;
+               $(this).find( '[tabindex]' ).each( function () {
+                       var tabIndex = parseInt( $(this).prop( 'tabindex' ), 10 );
+                       // In IE6/IE7 the above jQuery selector returns all elements,
+                       // becuase it has a default value for tabIndex in IE6/IE7 of 0
+                       // (rather than null/undefined). Therefore check "> 0" as well.
+                       // Under IE7 under Windows NT 5.2 is also capable of returning NaN.
+                       if ( tabIndex > 0 && !isNaN( tabIndex ) ) {
+                               // Initial value
+                               if ( minTabIndex === null ) {
+                                       minTabIndex = tabIndex;
+                               } else if ( tabIndex < minTabIndex ) {
+                                       minTabIndex = tabIndex;
+                               }
+                       }
+               } );
+               return minTabIndex;
+       };
+
+       /**
+        * Finds the highest tabindex in use within a selection
+        *
+        * @return number Highest tabindex on the page
+        */
+       $.fn.lastTabIndex = function () {
+               var maxTabIndex = null;
+               $(this).find( '[tabindex]' ).each( function () {
+                       var tabIndex = parseInt( $(this).prop( 'tabindex' ), 10 );
+                       if ( tabIndex > 0 && !isNaN( tabIndex ) ) {
+                               // Initial value
+                               if ( maxTabIndex === null ) {
+                                       maxTabIndex = tabIndex;
+                               } else if ( tabIndex > maxTabIndex ) {
+                                       maxTabIndex = tabIndex;
+                               }
+                       }
+               } );
+               return maxTabIndex;
+       };
+
+}( jQuery ) );
diff --git a/resources/src/jquery/jquery.tablesorter.css b/resources/src/jquery/jquery.tablesorter.css
new file mode 100644 (file)
index 0000000..a88acc0
--- /dev/null
@@ -0,0 +1,17 @@
+/* Table Sorting */
+table.jquery-tablesorter th.headerSort {
+       /* @embed */
+       background-image: url(images/sort_both.gif);
+       cursor: pointer;
+       background-repeat: no-repeat;
+       background-position: center right;
+       padding-right: 21px;
+}
+table.jquery-tablesorter th.headerSortUp {
+       /* @embed */
+       background-image: url(images/sort_up.gif);
+}
+table.jquery-tablesorter th.headerSortDown {
+       /* @embed */
+       background-image: url(images/sort_down.gif);
+}
diff --git a/resources/src/jquery/jquery.tablesorter.js b/resources/src/jquery/jquery.tablesorter.js
new file mode 100644 (file)
index 0000000..af0d897
--- /dev/null
@@ -0,0 +1,1154 @@
+/**
+ * TableSorter for MediaWiki
+ *
+ * Written 2011 Leo Koppelkamm
+ * Based on tablesorter.com plugin, written (c) 2007 Christian Bach.
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Depends on mw.config (wgDigitTransformTable, wgDefaultDateFormat, wgContentLanguage)
+ * and mw.language.months.
+ *
+ * Uses 'tableSorterCollation' in mw.config (if available)
+ */
+/**
+ *
+ * @description Create a sortable table with multi-column sorting capabilitys
+ *
+ * @example $( 'table' ).tablesorter();
+ * @desc Create a simple tablesorter interface.
+ *
+ * @example $( 'table' ).tablesorter( { sortList: [ { 0: 'desc' }, { 1: 'asc' } ] } );
+ * @desc Create a tablesorter interface initially sorting on the first and second column.
+ *
+ * @option String cssHeader ( optional ) A string of the class name to be appended
+ *         to sortable tr elements in the thead of the table. Default value:
+ *         "header"
+ *
+ * @option String cssAsc ( optional ) A string of the class name to be appended to
+ *         sortable tr elements in the thead on a ascending sort. Default value:
+ *         "headerSortUp"
+ *
+ * @option String cssDesc ( optional ) A string of the class name to be appended
+ *         to sortable tr elements in the thead on a descending sort. Default
+ *         value: "headerSortDown"
+ *
+ * @option String sortInitialOrder ( optional ) A string of the inital sorting
+ *         order can be asc or desc. Default value: "asc"
+ *
+ * @option String sortMultisortKey ( optional ) A string of the multi-column sort
+ *         key. Default value: "shiftKey"
+ *
+ * @option Boolean sortLocaleCompare ( optional ) Boolean flag indicating whatever
+ *         to use String.localeCampare method or not. Set to false.
+ *
+ * @option Boolean cancelSelection ( optional ) Boolean flag indicating if
+ *         tablesorter should cancel selection of the table headers text.
+ *         Default value: true
+ *
+ * @option Array sortList ( optional ) An array containing objects specifying sorting.
+ *         By passing more than one object, multi-sorting will be applied. Object structure:
+ *         { <Integer column index>: <String 'asc' or 'desc'> }
+ *         Default value: []
+ *
+ * @option Boolean debug ( optional ) Boolean flag indicating if tablesorter
+ *         should display debuging information usefull for development.
+ *
+ * @event sortEnd.tablesorter: Triggered as soon as any sorting has been applied.
+ *
+ * @type jQuery
+ *
+ * @name tablesorter
+ *
+ * @cat Plugins/Tablesorter
+ *
+ * @author Christian Bach/christian.bach@polyester.se
+ */
+
+( function ( $, mw ) {
+       /* Local scope */
+
+       var ts,
+               parsers = [];
+
+       /* Parser utility functions */
+
+       function getParserById( name ) {
+               var i,
+                       len = parsers.length;
+               for ( i = 0; i < len; i++ ) {
+                       if ( parsers[i].id.toLowerCase() === name.toLowerCase() ) {
+                               return parsers[i];
+                       }
+               }
+               return false;
+       }
+
+       function getElementSortKey( node ) {
+               var $node = $( node ),
+                       // Use data-sort-value attribute.
+                       // Use data() instead of attr() so that live value changes
+                       // are processed as well (bug 38152).
+                       data = $node.data( 'sortValue' );
+
+               if ( data !== null && data !== undefined ) {
+                       // Cast any numbers or other stuff to a string, methods
+                       // like charAt, toLowerCase and split are expected.
+                       return String( data );
+               } else {
+                       if ( !node ) {
+                               return $node.text();
+                       } else if ( node.tagName.toLowerCase() === 'img' ) {
+                               return $node.attr( 'alt' ) || ''; // handle undefined alt
+                       } else {
+                               return $.map( $.makeArray( node.childNodes ), function( elem ) {
+                                       // 1 is for document.ELEMENT_NODE (the constant is undefined on old browsers)
+                                       if ( elem.nodeType === 1 ) {
+                                               return getElementSortKey( elem );
+                                       } else {
+                                               return $.text( elem );
+                                       }
+                               } ).join( '' );
+                       }
+               }
+       }
+
+       function detectParserForColumn( table, rows, cellIndex ) {
+               var l = parsers.length,
+                       nodeValue,
+                       // Start with 1 because 0 is the fallback parser
+                       i = 1,
+                       rowIndex = 0,
+                       concurrent = 0,
+                       needed = ( rows.length > 4 ) ? 5 : rows.length;
+
+               while ( i < l ) {
+                       if ( rows[rowIndex] && rows[rowIndex].cells[cellIndex] ) {
+                               nodeValue = $.trim( getElementSortKey( rows[rowIndex].cells[cellIndex] ) );
+                       } else {
+                               nodeValue = '';
+                       }
+
+                       if ( nodeValue !== '') {
+                               if ( parsers[i].is( nodeValue, table ) ) {
+                                       concurrent++;
+                                       rowIndex++;
+                                       if ( concurrent >= needed ) {
+                                               // Confirmed the parser for multiple cells, let's return it
+                                               return parsers[i];
+                                       }
+                               } else {
+                                       // Check next parser, reset rows
+                                       i++;
+                                       rowIndex = 0;
+                                       concurrent = 0;
+                               }
+                       } else {
+                               // Empty cell
+                               rowIndex++;
+                               if ( rowIndex > rows.length ) {
+                                       rowIndex = 0;
+                                       i++;
+                               }
+                       }
+               }
+
+               // 0 is always the generic parser (text)
+               return parsers[0];
+       }
+
+       function buildParserCache( table, $headers ) {
+               var rows = table.tBodies[0].rows,
+                       sortType,
+                       parsers = [];
+
+               if ( rows[0] ) {
+
+                       var cells = rows[0].cells,
+                               len = cells.length,
+                               i, parser;
+
+                       for ( i = 0; i < len; i++ ) {
+                               parser = false;
+                               sortType = $headers.eq( i ).data( 'sortType' );
+                               if ( sortType !== undefined ) {
+                                       parser = getParserById( sortType );
+                               }
+
+                               if ( parser === false ) {
+                                       parser = detectParserForColumn( table, rows, i );
+                               }
+
+                               parsers.push( parser );
+                       }
+               }
+               return parsers;
+       }
+
+       /* Other utility functions */
+
+       function buildCache( table ) {
+               var totalRows = ( table.tBodies[0] && table.tBodies[0].rows.length ) || 0,
+                       totalCells = ( table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length ) || 0,
+                       parsers = table.config.parsers,
+                       cache = {
+                               row: [],
+                               normalized: []
+                       };
+
+               for ( var i = 0; i < totalRows; ++i ) {
+
+                       // Add the table data to main data array
+                       var $row = $( table.tBodies[0].rows[i] ),
+                               cols = [];
+
+                       // if this is a child row, add it to the last row's children and
+                       // continue to the next row
+                       if ( $row.hasClass( table.config.cssChildRow ) ) {
+                               cache.row[cache.row.length - 1] = cache.row[cache.row.length - 1].add( $row );
+                               // go to the next for loop
+                               continue;
+                       }
+
+                       cache.row.push( $row );
+
+                       for ( var j = 0; j < totalCells; ++j ) {
+                               cols.push( parsers[j].format( getElementSortKey( $row[0].cells[j] ), table, $row[0].cells[j] ) );
+                       }
+
+                       cols.push( cache.normalized.length ); // add position for rowCache
+                       cache.normalized.push( cols );
+                       cols = null;
+               }
+
+               return cache;
+       }
+
+       function appendToTable( table, cache ) {
+               var i, pos, l, j,
+                       row = cache.row,
+                       normalized = cache.normalized,
+                       totalRows = normalized.length,
+                       checkCell = ( normalized[0].length - 1 ),
+                       fragment = document.createDocumentFragment();
+
+               for ( i = 0; i < totalRows; i++ ) {
+                       pos = normalized[i][checkCell];
+
+                       l = row[pos].length;
+
+                       for ( j = 0; j < l; j++ ) {
+                               fragment.appendChild( row[pos][j] );
+                       }
+
+               }
+               table.tBodies[0].appendChild( fragment );
+
+               $( table ).trigger( 'sortEnd.tablesorter' );
+       }
+
+       /**
+        * Find all header rows in a thead-less table and put them in a <thead> tag.
+        * This only treats a row as a header row if it contains only <th>s (no <td>s)
+        * and if it is preceded entirely by header rows. The algorithm stops when
+        * it encounters the first non-header row.
+        *
+        * After this, it will look at all rows at the bottom for footer rows
+        * And place these in a tfoot using similar rules.
+        * @param $table jQuery object for a <table>
+        */
+       function emulateTHeadAndFoot( $table ) {
+               var $thead, $tfoot, i, len,
+                       $rows = $table.find( '> tbody > tr' );
+               if ( !$table.get(0).tHead ) {
+                       $thead = $( '<thead>' );
+                       $rows.each( function () {
+                               if ( $(this).children( 'td' ).length ) {
+                                       // This row contains a <td>, so it's not a header row
+                                       // Stop here
+                                       return false;
+                               }
+                               $thead.append( this );
+                       } );
+                       $table.find(' > tbody:first').before( $thead );
+               }
+               if ( !$table.get(0).tFoot ) {
+                       $tfoot = $( '<tfoot>' );
+                       len = $rows.length;
+                       for ( i = len - 1; i >= 0; i-- ) {
+                               if ( $( $rows[i] ).children( 'td' ).length ){
+                                       break;
+                               }
+                               $tfoot.prepend( $( $rows[i] ));
+                       }
+                       $table.append( $tfoot );
+               }
+       }
+
+       function buildHeaders( table, msg ) {
+               var maxSeen = 0,
+                       colspanOffset = 0,
+                       columns,
+                       i,
+                       $tableHeaders = $( [] ),
+                       $tableRows = $( 'thead:eq(0) > tr', table );
+               if ( $tableRows.length <= 1 ) {
+                       $tableHeaders = $tableRows.children( 'th' );
+               } else {
+                       var rowspan,
+                               colspan,
+                               headerCount,
+                               longestTR,
+                               matrixRowIndex,
+                               matrixColumnIndex,
+                               exploded = [];
+
+                       // Loop through all the dom cells of the thead
+                       $tableRows.each( function ( rowIndex, row ) {
+                               $.each( row.cells, function( columnIndex, cell ) {
+                                       rowspan = Number( cell.rowSpan );
+                                       colspan = Number( cell.colSpan );
+
+                                       // Skip the spots in the exploded matrix that are already filled
+                                       while ( exploded[rowIndex] && exploded[rowIndex][columnIndex] !== undefined ) {
+                                               ++columnIndex;
+                                       }
+
+                                       // Find the actual dimensions of the thead, by placing each cell
+                                       // in the exploded matrix rowspan times colspan times, with the proper offsets
+                                       for ( matrixColumnIndex = columnIndex; matrixColumnIndex < columnIndex + colspan; ++matrixColumnIndex ) {
+                                               for ( matrixRowIndex = rowIndex; matrixRowIndex < rowIndex + rowspan; ++matrixRowIndex ) {
+                                                       if ( !exploded[matrixRowIndex] ) {
+                                                               exploded[matrixRowIndex] = [];
+                                                       }
+                                                       exploded[matrixRowIndex][matrixColumnIndex] = cell;
+                                               }
+                                       }
+                               } );
+                       } );
+                       // We want to find the row that has the most columns (ignoring colspan)
+                       $.each( exploded, function ( index, cellArray ) {
+                               headerCount = $.unique( $(cellArray) ).length;
+                               if ( headerCount >= maxSeen ) {
+                                       maxSeen = headerCount;
+                                       longestTR = index;
+                               }
+                       } );
+                       // We cannot use $.unique() here because it sorts into dom order, which is undesirable
+                       $tableHeaders = $( uniqueElements( exploded[longestTR] ) );
+               }
+
+               // as each header can span over multiple columns (using colspan=N),
+               // we have to bidirectionally map headers to their columns and columns to their headers
+               table.headerToColumns = [];
+               table.columnToHeader = [];
+
+               $tableHeaders.each( function ( headerIndex ) {
+                       columns = [];
+                       for ( i = 0; i < this.colSpan; i++ ) {
+                               table.columnToHeader[ colspanOffset + i ] = headerIndex;
+                               columns.push( colspanOffset + i );
+                       }
+
+                       table.headerToColumns[ headerIndex ] = columns;
+                       colspanOffset += this.colSpan;
+
+                       this.headerIndex = headerIndex;
+                       this.order = 0;
+                       this.count = 0;
+
+                       if ( $( this ).hasClass( table.config.unsortableClass ) ) {
+                               this.sortDisabled = true;
+                       }
+
+                       if ( !this.sortDisabled ) {
+                               $( this )
+                                       .addClass( table.config.cssHeader )
+                                       .prop( 'tabIndex', 0 )
+                                       .attr( {
+                                               role: 'columnheader button',
+                                               title: msg[1]
+                                       } );
+                       }
+
+                       // add cell to headerList
+                       table.config.headerList[headerIndex] = this;
+               } );
+
+               return $tableHeaders;
+
+       }
+
+       /**
+        * Sets the sort count of the columns that are not affected by the sorting to have them sorted
+        * in default (ascending) order when their header cell is clicked the next time.
+        *
+        * @param {jQuery} $headers
+        * @param {Number[][]} sortList
+        * @param {Number[][]} headerToColumns
+        */
+       function setHeadersOrder( $headers, sortList, headerToColumns ) {
+               // Loop through all headers to retrieve the indices of the columns the header spans across:
+               $.each( headerToColumns, function( headerIndex, columns ) {
+
+                       $.each( columns, function( i, columnIndex ) {
+                               var header = $headers[headerIndex];
+
+                               if ( !isValueInArray( columnIndex, sortList ) ) {
+                                       // Column shall not be sorted: Reset header count and order.
+                                       header.order = 0;
+                                       header.count = 0;
+                               } else {
+                                       // Column shall be sorted: Apply designated count and order.
+                                       $.each( sortList, function( j, sortColumn ) {
+                                               if ( sortColumn[0] === i ) {
+                                                       header.order = sortColumn[1];
+                                                       header.count = sortColumn[1] + 1;
+                                                       return false;
+                                               }
+                                       } );
+                               }
+                       } );
+
+               } );
+       }
+
+       function isValueInArray( v, a ) {
+               var l = a.length;
+               for ( var i = 0; i < l; i++ ) {
+                       if ( a[i][0] === v ) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       function uniqueElements( array ) {
+               var uniques = [];
+               $.each( array, function( index, elem ) {
+                       if ( elem !== undefined && $.inArray( elem, uniques ) === -1 ) {
+                               uniques.push( elem );
+                       }
+               } );
+               return uniques;
+       }
+
+       function setHeadersCss( table, $headers, list, css, msg, columnToHeader ) {
+               // Remove all header information and reset titles to default message
+               $headers.removeClass( css[0] ).removeClass( css[1] ).attr( 'title', msg[1] );
+
+               for ( var i = 0; i < list.length; i++ ) {
+                       $headers.eq( columnToHeader[ list[i][0] ] )
+                               .addClass( css[ list[i][1] ] )
+                               .attr( 'title', msg[ list[i][1] ] );
+               }
+       }
+
+       function sortText( a, b ) {
+               return ( (a < b) ? -1 : ((a > b) ? 1 : 0) );
+       }
+
+       function sortTextDesc( a, b ) {
+               return ( (b < a) ? -1 : ((b > a) ? 1 : 0) );
+       }
+
+       function multisort( table, sortList, cache ) {
+               var i,
+                       sortFn = [],
+                       len = sortList.length;
+               for ( i = 0; i < len; i++ ) {
+                       sortFn[i] = ( sortList[i][1] ) ? sortTextDesc : sortText;
+               }
+               cache.normalized.sort( function ( array1, array2 ) {
+                       var i, col, ret;
+                       for ( i = 0; i < len; i++ ) {
+                               col = sortList[i][0];
+                               ret = sortFn[i].call( this, array1[col], array2[col] );
+                               if ( ret !== 0 ) {
+                                       return ret;
+                               }
+                       }
+                       // Fall back to index number column to ensure stable sort
+                       return sortText.call( this, array1[array1.length - 1], array2[array2.length - 1] );
+               } );
+               return cache;
+       }
+
+       function buildTransformTable() {
+               var ascii, localised, i, digitClass,
+                       digits = '0123456789,.'.split( '' ),
+                       separatorTransformTable = mw.config.get( 'wgSeparatorTransformTable' ),
+                       digitTransformTable = mw.config.get( 'wgDigitTransformTable' );
+
+               if ( separatorTransformTable === null || ( separatorTransformTable[0] === '' && digitTransformTable[2] === '' ) ) {
+                       ts.transformTable = false;
+               } else {
+                       ts.transformTable = {};
+
+                       // Unpack the transform table
+                       ascii = separatorTransformTable[0].split( '\t' ).concat( digitTransformTable[0].split( '\t' ) );
+                       localised = separatorTransformTable[1].split( '\t' ).concat( digitTransformTable[1].split( '\t' ) );
+
+                       // Construct regex for number identification
+                       for ( i = 0; i < ascii.length; i++ ) {
+                               ts.transformTable[localised[i]] = ascii[i];
+                               digits.push( $.escapeRE( localised[i] ) );
+                       }
+               }
+               digitClass = '[' + digits.join( '', digits ) + ']';
+
+               // We allow a trailing percent sign, which we just strip. This works fine
+               // if percents and regular numbers aren't being mixed.
+               ts.numberRegex = new RegExp('^(' + '[-+\u2212]?[0-9][0-9,]*(\\.[0-9,]*)?(E[-+\u2212]?[0-9][0-9,]*)?' + // Fortran-style scientific
+               '|' + '[-+\u2212]?' + digitClass + '+[\\s\\xa0]*%?' + // Generic localised
+               ')$', 'i');
+       }
+
+       function buildDateTable() {
+               var i, name,
+                       regex = [];
+
+               ts.monthNames = {};
+
+               for ( i = 0; i < 12; i++ ) {
+                       name = mw.language.months.names[i].toLowerCase();
+                       ts.monthNames[name] = i + 1;
+                       regex.push( $.escapeRE( name ) );
+                       name = mw.language.months.genitive[i].toLowerCase();
+                       ts.monthNames[name] = i + 1;
+                       regex.push( $.escapeRE( name ) );
+                       name = mw.language.months.abbrev[i].toLowerCase().replace( '.', '' );
+                       ts.monthNames[name] = i + 1;
+                       regex.push( $.escapeRE( name ) );
+               }
+
+               // Build piped string
+               regex = regex.join( '|' );
+
+               // Build RegEx
+               // Any date formated with . , ' - or /
+               ts.dateRegex[0] = new RegExp( /^\s*(\d{1,2})[\,\.\-\/'\s]{1,2}(\d{1,2})[\,\.\-\/'\s]{1,2}(\d{2,4})\s*?/i);
+
+               // Written Month name, dmy
+               ts.dateRegex[1] = new RegExp( '^\\s*(\\d{1,2})[\\,\\.\\-\\/\'\\s]+(' + regex + ')' + '[\\,\\.\\-\\/\'\\s]+(\\d{2,4})\\s*$', 'i' );
+
+               // Written Month name, mdy
+               ts.dateRegex[2] = new RegExp( '^\\s*(' + regex + ')' + '[\\,\\.\\-\\/\'\\s]+(\\d{1,2})[\\,\\.\\-\\/\'\\s]+(\\d{2,4})\\s*$', 'i' );
+
+       }
+
+       /**
+        * Replace all rowspanned cells in the body with clones in each row, so sorting
+        * need not worry about them.
+        *
+        * @param $table jQuery object for a <table>
+        */
+       function explodeRowspans( $table ) {
+               var spanningRealCellIndex, rowSpan, colSpan,
+                       cell, i, $tds, $clone, $nextRows,
+                       rowspanCells = $table.find( '> tbody > tr > [rowspan]' ).get();
+
+               // Short circuit
+               if ( !rowspanCells.length ) {
+                       return;
+               }
+
+               // First, we need to make a property like cellIndex but taking into
+               // account colspans. We also cache the rowIndex to avoid having to take
+               // cell.parentNode.rowIndex in the sorting function below.
+               $table.find( '> tbody > tr' ).each( function () {
+                       var i,
+                               col = 0,
+                               l = this.cells.length;
+                       for ( i = 0; i < l; i++ ) {
+                               this.cells[i].realCellIndex = col;
+                               this.cells[i].realRowIndex = this.rowIndex;
+                               col += this.cells[i].colSpan;
+                       }
+               } );
+
+               // Split multi row cells into multiple cells with the same content.
+               // Sort by column then row index to avoid problems with odd table structures.
+               // Re-sort whenever a rowspanned cell's realCellIndex is changed, because it
+               // might change the sort order.
+               function resortCells() {
+                       rowspanCells = rowspanCells.sort( function ( a, b ) {
+                               var ret = a.realCellIndex - b.realCellIndex;
+                               if ( !ret ) {
+                                       ret = a.realRowIndex - b.realRowIndex;
+                               }
+                               return ret;
+                       } );
+                       $.each( rowspanCells, function () {
+                               this.needResort = false;
+                       } );
+               }
+               resortCells();
+
+               function filterfunc() {
+                       return this.realCellIndex >= spanningRealCellIndex;
+               }
+
+               function fixTdCellIndex() {
+                       this.realCellIndex += colSpan;
+                       if ( this.rowSpan > 1 ) {
+                               this.needResort = true;
+                       }
+               }
+
+               while ( rowspanCells.length ) {
+                       if ( rowspanCells[0].needResort ) {
+                               resortCells();
+                       }
+
+                       cell = rowspanCells.shift();
+                       rowSpan = cell.rowSpan;
+                       colSpan = cell.colSpan;
+                       spanningRealCellIndex = cell.realCellIndex;
+                       cell.rowSpan = 1;
+                       $nextRows = $( cell ).parent().nextAll();
+                       for ( i = 0; i < rowSpan - 1; i++ ) {
+                               $tds = $( $nextRows[i].cells ).filter( filterfunc );
+                               $clone = $( cell ).clone();
+                               $clone[0].realCellIndex = spanningRealCellIndex;
+                               if ( $tds.length ) {
+                                       $tds.each( fixTdCellIndex );
+                                       $tds.first().before( $clone );
+                               } else {
+                                       $nextRows.eq( i ).append( $clone );
+                               }
+                       }
+               }
+       }
+
+       function buildCollationTable() {
+               ts.collationTable = mw.config.get( 'tableSorterCollation' );
+               ts.collationRegex = null;
+               if ( ts.collationTable ) {
+                       var key,
+                               keys = [];
+
+                       // Build array of key names
+                       for ( key in ts.collationTable ) {
+                               // Check hasOwn to be safe
+                               if ( ts.collationTable.hasOwnProperty(key) ) {
+                                       keys.push(key);
+                               }
+                       }
+                       if ( keys.length ) {
+                               ts.collationRegex = new RegExp( '[' + keys.join( '' ) + ']', 'ig' );
+                       }
+               }
+       }
+
+       function cacheRegexs() {
+               if ( ts.rgx ) {
+                       return;
+               }
+               ts.rgx = {
+                       IPAddress: [
+                               new RegExp( /^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/)
+                       ],
+                       currency: [
+                               new RegExp( /(^[£$€¥]|[£$€¥]$)/),
+                               new RegExp( /[£$€¥]/g)
+                       ],
+                       url: [
+                               new RegExp( /^(https?|ftp|file):\/\/$/),
+                               new RegExp( /(https?|ftp|file):\/\//)
+                       ],
+                       isoDate: [
+                               new RegExp( /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/)
+                       ],
+                       usLongDate: [
+                               new RegExp( /^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/)
+                       ],
+                       time: [
+                               new RegExp( /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/)
+                       ]
+               };
+       }
+
+       /**
+        * Converts sort objects [ { Integer: String }, ... ] to the internally used nested array
+        * structure [ [ Integer , Integer ], ... ]
+        *
+        * @param sortObjects {Array} List of sort objects.
+        * @return {Array} List of internal sort definitions.
+        */
+
+       function convertSortList( sortObjects ) {
+               var sortList = [];
+               $.each( sortObjects, function( i, sortObject ) {
+                       $.each ( sortObject, function( columnIndex, order ) {
+                               var orderIndex = ( order === 'desc' ) ? 1 : 0;
+                               sortList.push( [parseInt( columnIndex, 10 ), orderIndex] );
+                       } );
+               } );
+               return sortList;
+       }
+
+       /* Public scope */
+
+       $.tablesorter = {
+
+                       defaultOptions: {
+                               cssHeader: 'headerSort',
+                               cssAsc: 'headerSortUp',
+                               cssDesc: 'headerSortDown',
+                               cssChildRow: 'expand-child',
+                               sortInitialOrder: 'asc',
+                               sortMultiSortKey: 'shiftKey',
+                               sortLocaleCompare: false,
+                               unsortableClass: 'unsortable',
+                               parsers: {},
+                               widgets: [],
+                               headers: {},
+                               cancelSelection: true,
+                               sortList: [],
+                               headerList: [],
+                               selectorHeaders: 'thead tr:eq(0) th',
+                               debug: false
+                       },
+
+                       dateRegex: [],
+                       monthNames: {},
+
+                       /**
+                        * @param $tables {jQuery}
+                        * @param settings {Object} (optional)
+                        */
+                       construct: function ( $tables, settings ) {
+                               return $tables.each( function ( i, table ) {
+                                       // Declare and cache.
+                                       var $headers, cache, config, sortCSS, sortMsg,
+                                               $table = $( table ),
+                                               firstTime = true;
+
+                                       // Quit if no tbody
+                                       if ( !table.tBodies ) {
+                                               return;
+                                       }
+                                       if ( !table.tHead ) {
+                                               // No thead found. Look for rows with <th>s and
+                                               // move them into a <thead> tag or a <tfoot> tag
+                                               emulateTHeadAndFoot( $table );
+
+                                               // Still no thead? Then quit
+                                               if ( !table.tHead ) {
+                                                       return;
+                                               }
+                                       }
+                                       $table.addClass( 'jquery-tablesorter' );
+
+                                       // FIXME config should probably not be stored in the plain table node
+                                       // New config object.
+                                       table.config = {};
+
+                                       // Merge and extend.
+                                       config = $.extend( table.config, $.tablesorter.defaultOptions, settings );
+
+                                       // Save the settings where they read
+                                       $.data( table, 'tablesorter', { config: config } );
+
+                                       // Get the CSS class names, could be done else where.
+                                       sortCSS = [ config.cssDesc, config.cssAsc ];
+                                       sortMsg = [ mw.msg( 'sort-descending' ), mw.msg( 'sort-ascending' ) ];
+
+                                       // Build headers
+                                       $headers = buildHeaders( table, sortMsg );
+
+                                       // Grab and process locale settings.
+                                       buildTransformTable();
+                                       buildDateTable();
+
+                                       // Precaching regexps can bring 10 fold
+                                       // performance improvements in some browsers.
+                                       cacheRegexs();
+
+                                       function setupForFirstSort() {
+                                               firstTime = false;
+
+                                               // Defer buildCollationTable to first sort. As user and site scripts
+                                               // may customize tableSorterCollation but load after $.ready(), other
+                                               // scripts may call .tablesorter() before they have done the
+                                               // tableSorterCollation customizations.
+                                               buildCollationTable();
+
+                                               // Legacy fix of .sortbottoms
+                                               // Wrap them inside inside a tfoot (because that's what they actually want to be) &
+                                               // and put the <tfoot> at the end of the <table>
+                                               var $sortbottoms = $table.find( '> tbody > tr.sortbottom' );
+                                               if ( $sortbottoms.length ) {
+                                                       var $tfoot = $table.children( 'tfoot' );
+                                                       if ( $tfoot.length ) {
+                                                               $tfoot.eq(0).prepend( $sortbottoms );
+                                                       } else {
+                                                               $table.append( $( '<tfoot>' ).append( $sortbottoms ) );
+                                                       }
+                                               }
+
+                                               explodeRowspans( $table );
+
+                                               // try to auto detect column type, and store in tables config
+                                               table.config.parsers = buildParserCache( table, $headers );
+                                       }
+
+                                       // Apply event handling to headers
+                                       // this is too big, perhaps break it out?
+                                       $headers.not( '.' + table.config.unsortableClass ).on( 'keypress click', function ( e ) {
+                                               if ( e.type === 'click' && e.target.nodeName.toLowerCase() === 'a' ) {
+                                                       // The user clicked on a link inside a table header.
+                                                       // Do nothing and let the default link click action continue.
+                                                       return true;
+                                               }
+
+                                               if ( e.type === 'keypress' && e.which !== 13 ) {
+                                                       // Only handle keypresses on the "Enter" key.
+                                                       return true;
+                                               }
+
+                                               if ( firstTime ) {
+                                                       setupForFirstSort();
+                                               }
+
+                                               // Build the cache for the tbody cells
+                                               // to share between calculations for this sort action.
+                                               // Re-calculated each time a sort action is performed due to possiblity
+                                               // that sort values change. Shouldn't be too expensive, but if it becomes
+                                               // too slow an event based system should be implemented somehow where
+                                               // cells get event .change() and bubbles up to the <table> here
+                                               cache = buildCache( table );
+
+                                               var totalRows = ( $table[0].tBodies[0] && $table[0].tBodies[0].rows.length ) || 0;
+                                               if ( !table.sortDisabled && totalRows > 0 ) {
+                                                       // Get current column sort order
+                                                       this.order = this.count % 2;
+                                                       this.count++;
+
+                                                       var cell, columns, newSortList, i;
+
+                                                       cell = this;
+                                                       // Get current column index
+                                                       columns = table.headerToColumns[ this.headerIndex ];
+                                                       newSortList = $.map( columns, function ( c ) {
+                                                               // jQuery "helpfully" flattens the arrays...
+                                                               return [[c, cell.order]];
+                                                       });
+                                                       // Index of first column belonging to this header
+                                                       i = columns[0];
+
+                                                       if ( !e[config.sortMultiSortKey] ) {
+                                                               // User only wants to sort on one column set
+                                                               // Flush the sort list and add new columns
+                                                               config.sortList = newSortList;
+                                                       } else {
+                                                               // Multi column sorting
+                                                               // It is not possible for one column to belong to multiple headers,
+                                                               // so this is okay - we don't need to check for every value in the columns array
+                                                               if ( isValueInArray( i, config.sortList ) ) {
+                                                                       // The user has clicked on an already sorted column.
+                                                                       // Reverse the sorting direction for all tables.
+                                                                       for ( var j = 0; j < config.sortList.length; j++ ) {
+                                                                               var s = config.sortList[j],
+                                                                                       o = config.headerList[s[0]];
+                                                                               if ( isValueInArray( s[0], newSortList ) ) {
+                                                                                       o.count = s[1];
+                                                                                       o.count++;
+                                                                                       s[1] = o.count % 2;
+                                                                               }
+                                                                       }
+                                                               } else {
+                                                                       // Add columns to sort list array
+                                                                       config.sortList = config.sortList.concat( newSortList );
+                                                               }
+                                                       }
+
+                                                       // Reset order/counts of cells not affected by sorting
+                                                       setHeadersOrder( $headers, config.sortList, table.headerToColumns );
+
+                                                       // Set CSS for headers
+                                                       setHeadersCss( $table[0], $headers, config.sortList, sortCSS, sortMsg, table.columnToHeader );
+                                                       appendToTable(
+                                                               $table[0], multisort( $table[0], config.sortList, cache )
+                                                       );
+
+                                                       // Stop normal event by returning false
+                                                       return false;
+                                               }
+
+                                       // Cancel selection
+                                       } ).mousedown( function () {
+                                               if ( config.cancelSelection ) {
+                                                       this.onselectstart = function () {
+                                                               return false;
+                                                       };
+                                                       return false;
+                                               }
+                                       } );
+
+                                       /**
+                                        * Sorts the table. If no sorting is specified by passing a list of sort
+                                        * objects, the table is sorted according to the initial sorting order.
+                                        * Passing an empty array will reset sorting (basically just reset the headers
+                                        * making the table appear unsorted).
+                                        *
+                                        * @param sortList {Array} (optional) List of sort objects.
+                                        */
+                                       $table.data( 'tablesorter' ).sort = function ( sortList ) {
+
+                                               if ( firstTime ) {
+                                                       setupForFirstSort();
+                                               }
+
+                                               if ( sortList === undefined ) {
+                                                       sortList = config.sortList;
+                                               } else if ( sortList.length > 0 ) {
+                                                       sortList = convertSortList( sortList );
+                                               }
+
+                                               // Set each column's sort count to be able to determine the correct sort
+                                               // order when clicking on a header cell the next time
+                                               setHeadersOrder( $headers, sortList, table.headerToColumns );
+
+                                               // re-build the cache for the tbody cells
+                                               cache = buildCache( table );
+
+                                               // set css for headers
+                                               setHeadersCss( table, $headers, sortList, sortCSS, sortMsg, table.columnToHeader );
+
+                                               // sort the table and append it to the dom
+                                               appendToTable( table, multisort( table, sortList, cache ) );
+                                       };
+
+                                       // sort initially
+                                       if ( config.sortList.length > 0 ) {
+                                               setupForFirstSort();
+                                               config.sortList = convertSortList( config.sortList );
+                                               $table.data( 'tablesorter' ).sort();
+                                       }
+
+                               } );
+                       },
+
+                       addParser: function ( parser ) {
+                               var l = parsers.length,
+                                       a = true;
+                               for ( var i = 0; i < l; i++ ) {
+                                       if ( parsers[i].id.toLowerCase() === parser.id.toLowerCase() ) {
+                                               a = false;
+                                       }
+                               }
+                               if ( a ) {
+                                       parsers.push( parser );
+                               }
+                       },
+
+                       formatDigit: function ( s ) {
+                               var out, c, p, i;
+                               if ( ts.transformTable !== false ) {
+                                       out = '';
+                                       for ( p = 0; p < s.length; p++ ) {
+                                               c = s.charAt(p);
+                                               if ( c in ts.transformTable ) {
+                                                       out += ts.transformTable[c];
+                                               } else {
+                                                       out += c;
+                                               }
+                                       }
+                                       s = out;
+                               }
+                               i = parseFloat( s.replace( /[, ]/g, '' ).replace( '\u2212', '-' ) );
+                               return isNaN( i ) ? 0 : i;
+                       },
+
+                       formatFloat: function ( s ) {
+                               var i = parseFloat(s);
+                               return isNaN( i ) ? 0 : i;
+                       },
+
+                       formatInt: function ( s ) {
+                               var i = parseInt( s, 10 );
+                               return isNaN( i ) ? 0 : i;
+                       },
+
+                       clearTableBody: function ( table ) {
+                               $( table.tBodies[0] ).empty();
+                       }
+               };
+
+       // Shortcut
+       ts = $.tablesorter;
+
+       // Register as jQuery prototype method
+       $.fn.tablesorter = function ( settings ) {
+               return ts.construct( this, settings );
+       };
+
+       // Add default parsers
+       ts.addParser( {
+               id: 'text',
+               is: function () {
+                       return true;
+               },
+               format: function ( s ) {
+                       s = $.trim( s.toLowerCase() );
+                       if ( ts.collationRegex ) {
+                               var tsc = ts.collationTable;
+                               s = s.replace( ts.collationRegex, function ( match ) {
+                                       var r = tsc[match] ? tsc[match] : tsc[match.toUpperCase()];
+                                       return r.toLowerCase();
+                               } );
+                       }
+                       return s;
+               },
+               type: 'text'
+       } );
+
+       ts.addParser( {
+               id: 'IPAddress',
+               is: function ( s ) {
+                       return ts.rgx.IPAddress[0].test(s);
+               },
+               format: function ( s ) {
+                       var a = s.split( '.' ),
+                               r = '',
+                               l = a.length;
+                       for ( var i = 0; i < l; i++ ) {
+                               var item = a[i];
+                               if ( item.length === 1 ) {
+                                       r += '00' + item;
+                               } else if ( item.length === 2 ) {
+                                       r += '0' + item;
+                               } else {
+                                       r += item;
+                               }
+                       }
+                       return $.tablesorter.formatFloat(r);
+               },
+               type: 'numeric'
+       } );
+
+       ts.addParser( {
+               id: 'currency',
+               is: function ( s ) {
+                       return ts.rgx.currency[0].test(s);
+               },
+               format: function ( s ) {
+                       return $.tablesorter.formatDigit( s.replace( ts.rgx.currency[1], '' ) );
+               },
+               type: 'numeric'
+       } );
+
+       ts.addParser( {
+               id: 'url',
+               is: function ( s ) {
+                       return ts.rgx.url[0].test(s);
+               },
+               format: function ( s ) {
+                       return $.trim( s.replace( ts.rgx.url[1], '' ) );
+               },
+               type: 'text'
+       } );
+
+       ts.addParser( {
+               id: 'isoDate',
+               is: function ( s ) {
+                       return ts.rgx.isoDate[0].test(s);
+               },
+               format: function ( s ) {
+                       return $.tablesorter.formatFloat((s !== '') ? new Date(s.replace(
+                       new RegExp( /-/g), '/')).getTime() : '0' );
+               },
+               type: 'numeric'
+       } );
+
+       ts.addParser( {
+               id: 'usLongDate',
+               is: function ( s ) {
+                       return ts.rgx.usLongDate[0].test(s);
+               },
+               format: function ( s ) {
+                       return $.tablesorter.formatFloat( new Date(s).getTime() );
+               },
+               type: 'numeric'
+       } );
+
+       ts.addParser( {
+               id: 'date',
+               is: function ( s ) {
+                       return ( ts.dateRegex[0].test(s) || ts.dateRegex[1].test(s) || ts.dateRegex[2].test(s ));
+               },
+               format: function ( s ) {
+                       var match;
+                       s = $.trim( s.toLowerCase() );
+
+                       if ( ( match = s.match( ts.dateRegex[0] ) ) !== null ) {
+                               if ( mw.config.get( 'wgDefaultDateFormat' ) === 'mdy' || mw.config.get( 'wgContentLanguage' ) === 'en' ) {
+                                       s = [ match[3], match[1], match[2] ];
+                               } else if ( mw.config.get( 'wgDefaultDateFormat' ) === 'dmy' ) {
+                                       s = [ match[3], match[2], match[1] ];
+                               } else {
+                                       // If we get here, we don't know which order the dd-dd-dddd
+                                       // date is in. So return something not entirely invalid.
+                                       return '99999999';
+                               }
+                       } else if ( ( match = s.match( ts.dateRegex[1] ) ) !== null ) {
+                               s = [ match[3], '' + ts.monthNames[match[2]], match[1] ];
+                       } else if ( ( match = s.match( ts.dateRegex[2] ) ) !== null ) {
+                               s = [ match[3], '' + ts.monthNames[match[1]], match[2] ];
+                       } else {
+                               // Should never get here
+                               return '99999999';
+                       }
+
+                       // Pad Month and Day
+                       if ( s[1].length === 1 ) {
+                               s[1] = '0' + s[1];
+                       }
+                       if ( s[2].length === 1 ) {
+                               s[2] = '0' + s[2];
+                       }
+
+                       var y;
+                       if ( ( y = parseInt( s[0], 10) ) < 100 ) {
+                               // Guestimate years without centuries
+                               if ( y < 30 ) {
+                                       s[0] = 2000 + y;
+                               } else {
+                                       s[0] = 1900 + y;
+                               }
+                       }
+                       while ( s[0].length < 4 ) {
+                               s[0] = '0' + s[0];
+                       }
+                       return parseInt( s.join( '' ), 10 );
+               },
+               type: 'numeric'
+       } );
+
+       ts.addParser( {
+               id: 'time',
+               is: function ( s ) {
+                       return ts.rgx.time[0].test(s);
+               },
+               format: function ( s ) {
+                       return $.tablesorter.formatFloat( new Date( '2000/01/01 ' + s ).getTime() );
+               },
+               type: 'numeric'
+       } );
+
+       ts.addParser( {
+               id: 'number',
+               is: function ( s ) {
+                       return $.tablesorter.numberRegex.test( $.trim( s ));
+               },
+               format: function ( s ) {
+                       return $.tablesorter.formatDigit(s);
+               },
+               type: 'numeric'
+       } );
+
+}( jQuery, mediaWiki ) );
diff --git a/resources/src/jquery/jquery.textSelection.js b/resources/src/jquery/jquery.textSelection.js
new file mode 100644 (file)
index 0000000..7262fe6
--- /dev/null
@@ -0,0 +1,573 @@
+/**
+ * These plugins provide extra functionality for interaction with textareas.
+ */
+( function ( $ ) {
+       if ( document.selection && document.selection.createRange ) {
+               // On IE, patch the focus() method to restore the windows' scroll position
+               // (bug 32241)
+               $.fn.extend({
+                       focus: ( function ( jqFocus ) {
+                               return function () {
+                                       var $w, state, result;
+                                       if ( arguments.length === 0 ) {
+                                               $w = $( window );
+                                               state = { top: $w.scrollTop(), left: $w.scrollLeft() };
+                                               result = jqFocus.apply( this, arguments );
+                                               window.scrollTo( state.top, state.left );
+                                               return result;
+                                       }
+                                       return jqFocus.apply( this, arguments );
+                               };
+                       }( $.fn.focus ) )
+               });
+       }
+
+       $.fn.textSelection = function ( command, options ) {
+               var fn,
+                       context,
+                       hasIframe,
+                       needSave,
+                       retval;
+
+               /**
+                * Helper function to get an IE TextRange object for an element
+                */
+               function rangeForElementIE( e ) {
+                       if ( e.nodeName.toLowerCase() === 'input' ) {
+                               return e.createTextRange();
+                       } else {
+                               var sel = document.body.createTextRange();
+                               sel.moveToElementText( e );
+                               return sel;
+                       }
+               }
+
+               /**
+                * Helper function for IE for activating the textarea. Called only in the
+                * IE-specific code paths below; makes use of IE-specific non-standard
+                * function setActive() if possible to avoid screen flicker.
+                */
+               function activateElementOnIE( element ) {
+                       if ( element.setActive ) {
+                               element.setActive(); // bug 32241: doesn't scroll
+                       } else {
+                               $( element ).focus(); // may scroll (but we patched it above)
+                       }
+               }
+
+               fn = {
+                       /**
+                        * Get the contents of the textarea
+                        */
+                       getContents: function () {
+                               return this.val();
+                       },
+                       /**
+                        * Get the currently selected text in this textarea. Will focus the textarea
+                        * in some browsers (IE/Opera)
+                        */
+                       getSelection: function () {
+                               var retval, range,
+                                       el = this.get( 0 );
+
+                               if ( $(el).is( ':hidden' ) ) {
+                                       retval = '';
+                               } else if ( document.selection && document.selection.createRange ) {
+                                       activateElementOnIE( el );
+                                       range = document.selection.createRange();
+                                       retval = range.text;
+                               } else if ( el.selectionStart || el.selectionStart === 0 ) {
+                                       retval = el.value.substring( el.selectionStart, el.selectionEnd );
+                               }
+
+                               return retval;
+                       },
+                       /**
+                        * Ported from skins/common/edit.js by Trevor Parscal
+                        * (c) 2009 Wikimedia Foundation (GPLv2) - http://www.wikimedia.org
+                        *
+                        * Inserts text at the beginning and end of a text selection, optionally
+                        * inserting text at the caret when selection is empty.
+                        *
+                        * @fixme document the options parameters
+                        */
+                       encapsulateSelection: function ( options ) {
+                               return this.each( function () {
+                                       var selText, scrollTop, insertText,
+                                               isSample, range, range2, range3, startPos, endPos,
+                                               pre = options.pre,
+                                               post = options.post;
+
+                                       /**
+                                        * Check if the selected text is the same as the insert text
+                                        */
+                                       function checkSelectedText() {
+                                               if ( !selText ) {
+                                                       selText = options.peri;
+                                                       isSample = true;
+                                               } else if ( options.replace ) {
+                                                       selText = options.peri;
+                                               } else {
+                                                       while ( selText.charAt( selText.length - 1 ) === ' ' ) {
+                                                               // Exclude ending space char
+                                                               selText = selText.substring( 0, selText.length - 1 );
+                                                               post += ' ';
+                                                       }
+                                                       while ( selText.charAt( 0 ) === ' ' ) {
+                                                               // Exclude prepending space char
+                                                               selText = selText.substring( 1, selText.length );
+                                                               pre = ' ' + pre;
+                                                       }
+                                               }
+                                       }
+
+                                       /**
+                                        * Do the splitlines stuff.
+                                        *
+                                        * Wrap each line of the selected text with pre and post
+                                        */
+                                       function doSplitLines( selText, pre, post ) {
+                                               var i,
+                                                       insertText = '',
+                                                       selTextArr = selText.split( '\n' );
+                                               for ( i = 0; i < selTextArr.length; i++ ) {
+                                                       insertText += pre + selTextArr[i] + post;
+                                                       if ( i !== selTextArr.length - 1 ) {
+                                                               insertText += '\n';
+                                                       }
+                                               }
+                                               return insertText;
+                                       }
+
+                                       isSample = false;
+                                       // Do nothing if display none
+                                       if ( this.style.display !== 'none' ) {
+                                               if ( document.selection && document.selection.createRange ) {
+                                                       // IE
+
+                                                       // Note that IE9 will trigger the next section unless we check this first.
+                                                       // See bug 35201.
+
+                                                       activateElementOnIE( this );
+                                                       if ( context ) {
+                                                               context.fn.restoreCursorAndScrollTop();
+                                                       }
+                                                       if ( options.selectionStart !== undefined ) {
+                                                               $(this).textSelection( 'setSelection', { 'start': options.selectionStart, 'end': options.selectionEnd } );
+                                                       }
+
+                                                       selText = $(this).textSelection( 'getSelection' );
+                                                       scrollTop = this.scrollTop;
+                                                       range = document.selection.createRange();
+
+                                                       checkSelectedText();
+                                                       insertText = pre + selText + post;
+                                                       if ( options.splitlines ) {
+                                                               insertText = doSplitLines( selText, pre, post );
+                                                       }
+                                                       if ( options.ownline && range.moveStart ) {
+                                                               range2 = document.selection.createRange();
+                                                               range2.collapse();
+                                                               range2.moveStart( 'character', -1 );
+                                                               // FIXME: Which check is correct?
+                                                               if ( range2.text !== '\r' && range2.text !== '\n' && range2.text !== '' ) {
+                                                                       insertText = '\n' + insertText;
+                                                                       pre += '\n';
+                                                               }
+                                                               range3 = document.selection.createRange();
+                                                               range3.collapse( false );
+                                                               range3.moveEnd( 'character', 1 );
+                                                               if ( range3.text !== '\r' && range3.text !== '\n' && range3.text !== '' ) {
+                                                                       insertText += '\n';
+                                                                       post += '\n';
+                                                               }
+                                                       }
+
+                                                       range.text = insertText;
+                                                       if ( isSample && options.selectPeri && range.moveStart ) {
+                                                               range.moveStart( 'character', -post.length - selText.length );
+                                                               range.moveEnd( 'character', -post.length );
+                                                       }
+                                                       range.select();
+                                                       // Restore the scroll position
+                                                       this.scrollTop = scrollTop;
+                                               } else if ( this.selectionStart || this.selectionStart === 0 ) {
+                                                       // Mozilla/Opera
+
+                                                       $(this).focus();
+                                                       if ( options.selectionStart !== undefined ) {
+                                                               $(this).textSelection( 'setSelection', { 'start': options.selectionStart, 'end': options.selectionEnd } );
+                                                       }
+
+                                                       selText = $(this).textSelection( 'getSelection' );
+                                                       startPos = this.selectionStart;
+                                                       endPos = this.selectionEnd;
+                                                       scrollTop = this.scrollTop;
+                                                       checkSelectedText();
+                                                       if ( options.selectionStart !== undefined
+                                                                       && endPos - startPos !== options.selectionEnd - options.selectionStart )
+                                                       {
+                                                               // This means there is a difference in the selection range returned by browser and what we passed.
+                                                               // This happens for Chrome in the case of composite characters. Ref bug #30130
+                                                               // Set the startPos to the correct position.
+                                                               startPos = options.selectionStart;
+                                                       }
+
+                                                       insertText = pre + selText + post;
+                                                       if ( options.splitlines ) {
+                                                               insertText = doSplitLines( selText, pre, post );
+                                                       }
+                                                       if ( options.ownline ) {
+                                                               if ( startPos !== 0 && this.value.charAt( startPos - 1 ) !== '\n' && this.value.charAt( startPos - 1 ) !== '\r' ) {
+                                                                       insertText = '\n' + insertText;
+                                                                       pre += '\n';
+                                                               }
+                                                               if ( this.value.charAt( endPos ) !== '\n' && this.value.charAt( endPos ) !== '\r' ) {
+                                                                       insertText += '\n';
+                                                                       post += '\n';
+                                                               }
+                                                       }
+                                                       this.value = this.value.substring( 0, startPos ) + insertText +
+                                                               this.value.substring( endPos, this.value.length );
+                                                       // Setting this.value scrolls the textarea to the top, restore the scroll position
+                                                       this.scrollTop = scrollTop;
+                                                       if ( window.opera ) {
+                                                               pre = pre.replace( /\r?\n/g, '\r\n' );
+                                                               selText = selText.replace( /\r?\n/g, '\r\n' );
+                                                               post = post.replace( /\r?\n/g, '\r\n' );
+                                                       }
+                                                       if ( isSample && options.selectPeri && !options.splitlines ) {
+                                                               this.selectionStart = startPos + pre.length;
+                                                               this.selectionEnd = startPos + pre.length + selText.length;
+                                                       } else {
+                                                               this.selectionStart = startPos + insertText.length;
+                                                               this.selectionEnd = this.selectionStart;
+                                                       }
+                                               }
+                                       }
+                                       $(this).trigger( 'encapsulateSelection', [ options.pre, options.peri, options.post, options.ownline,
+                                               options.replace, options.spitlines ] );
+                               });
+                       },
+                       /**
+                        * Ported from Wikia's LinkSuggest extension
+                        * https://svn.wikia-code.com/wikia/trunk/extensions/wikia/LinkSuggest
+                        * Some code copied from
+                        * http://www.dedestruct.com/2008/03/22/howto-cross-browser-cursor-position-in-textareas/
+                        *
+                        * Get the position (in resolution of bytes not necessarily characters)
+                        * in a textarea
+                        *
+                        * Will focus the textarea in some browsers (IE/Opera)
+                        *
+                        * @fixme document the options parameters
+                        */
+                        getCaretPosition: function ( options ) {
+                               function getCaret( e ) {
+                                       var caretPos = 0,
+                                               endPos = 0,
+                                               preText, rawPreText, periText,
+                                               rawPeriText, postText, rawPostText,
+                                               // IE Support
+                                               preFinished,
+                                               periFinished,
+                                               postFinished,
+                                               // Range containing text in the selection
+                                               periRange,
+                                               // Range containing text before the selection
+                                               preRange,
+                                               // Range containing text after the selection
+                                               postRange;
+
+                                       if ( document.selection && document.selection.createRange ) {
+                                               // IE doesn't properly report non-selected caret position through
+                                               // the selection ranges when textarea isn't focused. This can
+                                               // lead to saving a bogus empty selection, which then screws up
+                                               // whatever we do later (bug 31847).
+                                               activateElementOnIE( e );
+
+                                               preFinished = false;
+                                               periFinished = false;
+                                               postFinished = false;
+                                               periRange = document.selection.createRange().duplicate();
+
+                                               preRange = rangeForElementIE( e );
+                                               // Move the end where we need it
+                                               preRange.setEndPoint( 'EndToStart', periRange );
+
+                                               postRange = rangeForElementIE( e );
+                                               // Move the start where we need it
+                                               postRange.setEndPoint( 'StartToEnd', periRange );
+
+                                               // Load the text values we need to compare
+                                               preText = rawPreText = preRange.text;
+                                               periText = rawPeriText = periRange.text;
+                                               postText = rawPostText = postRange.text;
+
+                                               /*
+                                                * Check each range for trimmed newlines by shrinking the range by 1
+                                                * character and seeing if the text property has changed. If it has
+                                                * not changed then we know that IE has trimmed a \r\n from the end.
+                                                */
+                                               do {
+                                                       if ( !preFinished ) {
+                                                               if ( preRange.compareEndPoints( 'StartToEnd', preRange ) === 0 ) {
+                                                                       preFinished = true;
+                                                               } else {
+                                                                       preRange.moveEnd( 'character', -1 );
+                                                                       if ( preRange.text === preText ) {
+                                                                               rawPreText += '\r\n';
+                                                                       } else {
+                                                                               preFinished = true;
+                                                                       }
+                                                               }
+                                                       }
+                                                       if ( !periFinished ) {
+                                                               if ( periRange.compareEndPoints( 'StartToEnd', periRange ) === 0 ) {
+                                                                       periFinished = true;
+                                                               } else {
+                                                                       periRange.moveEnd( 'character', -1 );
+                                                                       if ( periRange.text === periText ) {
+                                                                               rawPeriText += '\r\n';
+                                                                       } else {
+                                                                               periFinished = true;
+                                                                       }
+                                                               }
+                                                       }
+                                                       if ( !postFinished ) {
+                                                               if ( postRange.compareEndPoints( 'StartToEnd', postRange ) === 0 ) {
+                                                                       postFinished = true;
+                                                               } else {
+                                                                       postRange.moveEnd( 'character', -1 );
+                                                                       if ( postRange.text === postText ) {
+                                                                               rawPostText += '\r\n';
+                                                                       } else {
+                                                                               postFinished = true;
+                                                                       }
+                                                               }
+                                                       }
+                                               } while ( ( !preFinished || !periFinished || !postFinished ) );
+                                               caretPos = rawPreText.replace( /\r\n/g, '\n' ).length;
+                                               endPos = caretPos + rawPeriText.replace( /\r\n/g, '\n' ).length;
+                                       } else if ( e.selectionStart || e.selectionStart === 0 ) {
+                                               // Firefox support
+                                               caretPos = e.selectionStart;
+                                               endPos = e.selectionEnd;
+                                       }
+                                       return options.startAndEnd ? [ caretPos, endPos ] : caretPos;
+                               }
+                               return getCaret( this.get( 0 ) );
+                       },
+                       /**
+                        * @fixme document the options parameters
+                        */
+                       setSelection: function ( options ) {
+                               return this.each( function () {
+                                       var selection, length, newLines;
+                                       // Do nothing if hidden
+                                       if ( !$(this).is( ':hidden' ) ) {
+                                               if ( this.selectionStart || this.selectionStart === 0 ) {
+                                                       // Opera 9.0 doesn't allow setting selectionStart past
+                                                       // selectionEnd; any attempts to do that will be ignored
+                                                       // Make sure to set them in the right order
+                                                       if ( options.start > this.selectionEnd ) {
+                                                               this.selectionEnd = options.end;
+                                                               this.selectionStart = options.start;
+                                                       } else {
+                                                               this.selectionStart = options.start;
+                                                               this.selectionEnd = options.end;
+                                                       }
+                                               } else if ( document.body.createTextRange ) {
+                                                       selection = rangeForElementIE( this );
+                                                       length = this.value.length;
+                                                       // IE doesn't count \n when computing the offset, so we won't either
+                                                       newLines = this.value.match( /\n/g );
+                                                       if ( newLines ) {
+                                                               length = length - newLines.length;
+                                                       }
+                                                       selection.moveStart( 'character', options.start );
+                                                       selection.moveEnd( 'character', -length + options.end );
+
+                                                       // This line can cause an error under certain circumstances (textarea empty, no selection)
+                                                       // Silence that error
+                                                       try {
+                                                               selection.select();
+                                                       } catch ( e ) { }
+                                               }
+                                       }
+                               });
+                       },
+                       /**
+                        * Ported from Wikia's LinkSuggest extension
+                        * https://svn.wikia-code.com/wikia/trunk/extensions/wikia/LinkSuggest
+                        *
+                        * Scroll a textarea to the current cursor position. You can set the cursor
+                        * position with setSelection()
+                        * @param options boolean Whether to force a scroll even if the caret position
+                        *  is already visible. Defaults to false
+                        *
+                        * @fixme document the options parameters (function body suggests options.force is a boolean, not options itself)
+                        */
+                       scrollToCaretPosition: function ( options ) {
+                               function getLineLength( e ) {
+                                       return Math.floor( e.scrollWidth / ( $.client.profile().platform === 'linux' ? 7 : 8 ) );
+                               }
+                               function getCaretScrollPosition( e ) {
+                                       // FIXME: This functions sucks and is off by a few lines most
+                                       // of the time. It should be replaced by something decent.
+                                       var i, j,
+                                               nextSpace,
+                                               text = e.value.replace( /\r/g, '' ),
+                                               caret = $( e ).textSelection( 'getCaretPosition' ),
+                                               lineLength = getLineLength( e ),
+                                               row = 0,
+                                               charInLine = 0,
+                                               lastSpaceInLine = 0;
+
+                                       for ( i = 0; i < caret; i++ ) {
+                                               charInLine++;
+                                               if ( text.charAt( i ) === ' ' ) {
+                                                       lastSpaceInLine = charInLine;
+                                               } else if ( text.charAt( i ) === '\n' ) {
+                                                       lastSpaceInLine = 0;
+                                                       charInLine = 0;
+                                                       row++;
+                                               }
+                                               if ( charInLine > lineLength ) {
+                                                       if ( lastSpaceInLine > 0 ) {
+                                                               charInLine = charInLine - lastSpaceInLine;
+                                                               lastSpaceInLine = 0;
+                                                               row++;
+                                                       }
+                                               }
+                                       }
+                                       nextSpace = 0;
+                                       for ( j = caret; j < caret + lineLength; j++ ) {
+                                               if (
+                                                       text.charAt( j ) === ' ' ||
+                                                       text.charAt( j ) === '\n' ||
+                                                       caret === text.length
+                                               ) {
+                                                       nextSpace = j;
+                                                       break;
+                                               }
+                                       }
+                                       if ( nextSpace > lineLength && caret <= lineLength ) {
+                                               charInLine = caret - lastSpaceInLine;
+                                               row++;
+                                       }
+                                       return ( $.client.profile().platform === 'mac' ? 13 : ( $.client.profile().platform === 'linux' ? 15 : 16 ) ) * row;
+                               }
+                               return this.each(function () {
+                                       var scroll, range, savedRange, pos, oldScrollTop;
+                                       // Do nothing if hidden
+                                       if ( !$(this).is( ':hidden' ) ) {
+                                               if ( this.selectionStart || this.selectionStart === 0 ) {
+                                                       // Mozilla
+                                                       scroll = getCaretScrollPosition( this );
+                                                       if ( options.force || scroll < $(this).scrollTop() ||
+                                                                       scroll > $(this).scrollTop() + $(this).height() ) {
+                                                               $(this).scrollTop( scroll );
+                                                       }
+                                               } else if ( document.selection && document.selection.createRange ) {
+                                                       // IE / Opera
+                                                       /*
+                                                        * IE automatically scrolls the selected text to the
+                                                        * bottom of the textarea at range.select() time, except
+                                                        * if it was already in view and the cursor position
+                                                        * wasn't changed, in which case it does nothing. To
+                                                        * cover that case, we'll force it to act by moving one
+                                                        * character back and forth.
+                                                        */
+                                                       range = document.body.createTextRange();
+                                                       savedRange = document.selection.createRange();
+                                                       pos = $(this).textSelection( 'getCaretPosition' );
+                                                       oldScrollTop = this.scrollTop;
+                                                       range.moveToElementText( this );
+                                                       range.collapse();
+                                                       range.move( 'character', pos + 1);
+                                                       range.select();
+                                                       if ( this.scrollTop !== oldScrollTop ) {
+                                                               this.scrollTop += range.offsetTop;
+                                                       } else if ( options.force ) {
+                                                               range.move( 'character', -1 );
+                                                               range.select();
+                                                       }
+                                                       savedRange.select();
+                                               }
+                                       }
+                                       $(this).trigger( 'scrollToPosition' );
+                               } );
+                       }
+               };
+
+               // Apply defaults
+               switch ( command ) {
+                       //case 'getContents': // no params
+                       //case 'setContents': // no params with defaults
+                       //case 'getSelection': // no params
+                       case 'encapsulateSelection':
+                               options = $.extend( {
+                                       pre: '', // Text to insert before the cursor/selection
+                                       peri: '', // Text to insert between pre and post and select afterwards
+                                       post: '', // Text to insert after the cursor/selection
+                                       ownline: false, // Put the inserted text on a line of its own
+                                       replace: false, // If there is a selection, replace it with peri instead of leaving it alone
+                                       selectPeri: true, // Select the peri text if it was inserted (but not if there was a selection and replace==false, or if splitlines==true)
+                                       splitlines: false, // If multiple lines are selected, encapsulate each line individually
+                                       selectionStart: undefined, // Position to start selection at
+                                       selectionEnd: undefined // Position to end selection at. Defaults to start
+                               }, options );
+                               break;
+                       case 'getCaretPosition':
+                               options = $.extend( {
+                                       // Return [start, end] instead of just start
+                                       startAndEnd: false
+                               }, options );
+                               // FIXME: We may not need character position-based functions if we insert markers in the right places
+                               break;
+                       case 'setSelection':
+                               options = $.extend( {
+                                       // Position to start selection at
+                                       start: undefined,
+                                       // Position to end selection at. Defaults to start
+                                       end: undefined,
+                                       // Element to start selection in (iframe only)
+                                       startContainer: undefined,
+                                       // Element to end selection in (iframe only). Defaults to startContainer
+                                       endContainer: undefined
+                               }, options );
+
+                               if ( options.end === undefined ) {
+                                       options.end = options.start;
+                               }
+                               if ( options.endContainer === undefined ) {
+                                       options.endContainer = options.startContainer;
+                               }
+                               // FIXME: We may not need character position-based functions if we insert markers in the right places
+                               break;
+                       case 'scrollToCaretPosition':
+                               options = $.extend( {
+                                       force: false // Force a scroll even if the caret position is already visible
+                               }, options );
+                               break;
+               }
+
+               context = $(this).data( 'wikiEditor-context' );
+               hasIframe = context !== undefined && context && context.$iframe !== undefined;
+
+               // IE selection restore voodoo
+               needSave = false;
+               if ( hasIframe && context.savedSelection !== null ) {
+                       context.fn.restoreSelection();
+                       needSave = true;
+               }
+               retval = ( hasIframe ? context.fn : fn )[command].call( this, options );
+               if ( hasIframe && needSave ) {
+                       context.fn.saveSelection();
+               }
+
+               return retval;
+       };
+
+}( jQuery ) );
diff --git a/resources/src/mediawiki.action/images/green-checkmark.png b/resources/src/mediawiki.action/images/green-checkmark.png
new file mode 100644 (file)
index 0000000..8ec604e
Binary files /dev/null and b/resources/src/mediawiki.action/images/green-checkmark.png differ
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css b/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css
new file mode 100644 (file)
index 0000000..1af4a7a
--- /dev/null
@@ -0,0 +1,17 @@
+/* Styles for collapsible lists of templates used and hidden categories */
+.mw-editfooter-toggler {
+       cursor: pointer;
+       background-position: left center;
+       padding-left: 16px;
+}
+
+.mw-editfooter-list {
+       margin-bottom: 1em;
+       margin-left: 2.5em;
+}
+
+/* Show/hide animation is incorrect if the table has a margin set. Extra
+ * "table.wikitable" is needed in the selector for CSS specificity. */
+table.wikitable.preview-limit-report {
+       margin: 0;
+}
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js b/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js
new file mode 100644 (file)
index 0000000..7ae51ab
--- /dev/null
@@ -0,0 +1,54 @@
+jQuery( document ).ready( function ( $ ) {
+       var collapsibleLists, i, handleOne;
+
+       // Collapsible lists of categories and templates
+       collapsibleLists = [
+               {
+                       $list: $( '.templatesUsed ul' ),
+                       $toggler: $( '.mw-templatesUsedExplanation' ),
+                       cookieName: 'templates-used-list'
+               },
+               {
+                       $list: $( '.hiddencats ul' ),
+                       $toggler: $( '.mw-hiddenCategoriesExplanation' ),
+                       cookieName: 'hidden-categories-list'
+               },
+               {
+                       $list: $( '.preview-limit-report-wrapper' ),
+                       $toggler: $( '.mw-limitReportExplanation' ),
+                       cookieName: 'preview-limit-report'
+               }
+       ];
+
+       handleOne = function ( $list, $toggler, cookieName ) {
+               var isCollapsed = $.cookie( cookieName ) !== 'expanded';
+
+               // Style the toggler with an arrow icon and add a tabIndex and a role for accessibility
+               $toggler.addClass( 'mw-editfooter-toggler' ).prop( 'tabIndex', 0 ).attr( 'role', 'button' );
+               $list.addClass( 'mw-editfooter-list' );
+
+               $list.makeCollapsible( {
+                       $customTogglers: $toggler,
+                       linksPassthru: true,
+                       plainMode: true,
+                       collapsed: isCollapsed
+               } );
+
+               $toggler.addClass( isCollapsed ? 'mw-icon-arrow-collapsed' : 'mw-icon-arrow-expanded' );
+
+               $list.on( 'beforeExpand.mw-collapsible', function () {
+                       $toggler.removeClass( 'mw-icon-arrow-collapsed' ).addClass( 'mw-icon-arrow-expanded' );
+                       $.cookie( cookieName, 'expanded' );
+               } );
+
+               $list.on( 'beforeCollapse.mw-collapsible', function () {
+                       $toggler.removeClass( 'mw-icon-arrow-expanded' ).addClass( 'mw-icon-arrow-collapsed' );
+                       $.cookie( cookieName, 'collapsed' );
+               } );
+       };
+
+       for ( i = 0; i < collapsibleLists.length; i++ ) {
+               // Pass to a function for iteration-local variables
+               handleOne( collapsibleLists[i].$list, collapsibleLists[i].$toggler, collapsibleLists[i].cookieName );
+       }
+} );
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js b/resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js
new file mode 100644 (file)
index 0000000..f8448e6
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Javascript for module editWarning
+ */
+( function ( mw, $ ) {
+       $( function () {
+               // Check if EditWarning is enabled and if we need it
+               if ( $( '#wpTextbox1' ).length === 0 ) {
+                       return true;
+               }
+               // Get the original values of some form elements
+               $( '#wpTextbox1, #wpSummary' ).each( function () {
+                       $( this ).data( 'origtext', $( this ).val() );
+               } );
+               var savedWindowOnBeforeUnload;
+               $( window )
+                       .on( 'beforeunload.editwarning', function () {
+                               var retval;
+
+                               // Check if the current values of some form elements are the same as
+                               // the original values
+                               if (
+                                       mw.config.get( 'wgAction' ) === 'submit' ||
+                                               $( '#wpTextbox1' ).data( 'origtext' ) !== $( '#wpTextbox1' ).val() ||
+                                               $( '#wpSummary' ).data( 'origtext' ) !== $( '#wpSummary' ).val()
+                               ) {
+                                       // Return our message
+                                       retval = mw.msg( 'editwarning-warning' );
+                               }
+
+                               // Unset the onbeforeunload handler so we don't break page caching in Firefox
+                               savedWindowOnBeforeUnload = window.onbeforeunload;
+                               window.onbeforeunload = null;
+                               if ( retval !== undefined ) {
+                                       // ...but if the user chooses not to leave the page, we need to rebind it
+                                       setTimeout( function () {
+                                               window.onbeforeunload = savedWindowOnBeforeUnload;
+                                       }, 1 );
+                                       return retval;
+                               }
+                       } )
+                       .on( 'pageshow.editwarning', function () {
+                               // Re-add onbeforeunload handler
+                               if ( !window.onbeforeunload ) {
+                                       window.onbeforeunload = savedWindowOnBeforeUnload;
+                               }
+                       } );
+
+               // Add form submission handler
+               $( '#editform' ).submit( function () {
+                       // Unbind our handlers
+                       $( window ).off( '.editwarning' );
+               } );
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.js b/resources/src/mediawiki.action/mediawiki.action.edit.js
new file mode 100644 (file)
index 0000000..62f8e06
--- /dev/null
@@ -0,0 +1,191 @@
+/**
+ * Interface for the classic edit toolbar.
+ *
+ * @class mw.toolbar
+ * @singleton
+ */
+( function ( mw, $ ) {
+       var toolbar, isReady, $toolbar, queue, slice, $currentFocused;
+
+       /**
+        * Internal helper that does the actual insertion of the button into the toolbar.
+        *
+        * See #addButton for parameter documentation.
+        *
+        * @private
+        */
+       function insertButton( b, speedTip, tagOpen, tagClose, sampleText, imageId ) {
+               // Backwards compatibility
+               if ( typeof b !== 'object' ) {
+                       b = {
+                               imageFile: b,
+                               speedTip: speedTip,
+                               tagOpen: tagOpen,
+                               tagClose: tagClose,
+                               sampleText: sampleText,
+                               imageId: imageId
+                       };
+               }
+               var $image = $( '<img>' ).attr( {
+                       width: 23,
+                       height: 22,
+                       src: b.imageFile,
+                       alt: b.speedTip,
+                       title: b.speedTip,
+                       id: b.imageId || undefined,
+                       'class': 'mw-toolbar-editbutton'
+               } ).click( function () {
+                       toolbar.insertTags( b.tagOpen, b.tagClose, b.sampleText );
+                       return false;
+               } );
+
+               $toolbar.append( $image );
+       }
+
+       isReady = false;
+       $toolbar = false;
+       /**
+        * @private
+        * @property {Array}
+        * Contains button objects (and for backwards compatibilty, it can
+        * also contains an arguments array for insertButton).
+        */
+       queue = [];
+       slice = queue.slice;
+
+       toolbar = {
+
+               /**
+                * Add buttons to the toolbar.
+                *
+                * Takes care of race conditions and time-based dependencies
+                * by placing buttons in a queue if this method is called before
+                * the toolbar is created.
+                *
+                * For compatiblity, passing the properties listed below as separate arguments
+                * (in the listed order) is also supported.
+                *
+                * @param {Object} button Object with the following properties:
+                * @param {string} button.imageFile
+                * @param {string} button.speedTip
+                * @param {string} button.tagOpen
+                * @param {string} button.tagClose
+                * @param {string} button.sampleText
+                * @param {string} [button.imageId]
+                */
+               addButton: function () {
+                       if ( isReady ) {
+                               insertButton.apply( toolbar, arguments );
+                       } else {
+                               // Convert arguments list to array
+                               queue.push( slice.call( arguments ) );
+                       }
+               },
+               /**
+                * Example usage:
+                *     addButtons( [ { .. }, { .. }, { .. } ] );
+                *     addButtons( { .. }, { .. } );
+                *
+                * @param {Object|Array} [buttons...] An array of button objects or the first
+                *  button object in a list of variadic arguments.
+                */
+               addButtons: function ( buttons ) {
+                       if ( !$.isArray( buttons ) ) {
+                               buttons = slice.call( arguments );
+                       }
+                       if ( isReady ) {
+                               $.each( buttons, function () {
+                                       insertButton( this );
+                               } );
+                       } else {
+                               // Push each button into the queue
+                               queue.push.apply( queue, buttons );
+                       }
+               },
+
+               /**
+                * Apply tagOpen/tagClose to selection in currently focused textarea.
+                *
+                * Uses `sampleText` if selection is empty.
+                *
+                * @param {string} tagOpen
+                * @param {string} tagClose
+                * @param {string} sampleText
+                */
+               insertTags: function ( tagOpen, tagClose, sampleText ) {
+                       if ( $currentFocused && $currentFocused.length ) {
+                               $currentFocused.textSelection(
+                                       'encapsulateSelection', {
+                                               pre: tagOpen,
+                                               peri: sampleText,
+                                               post: tagClose
+                                       }
+                               );
+                       }
+               },
+
+               // For backwards compatibility,
+               // Called from EditPage.php, maybe in other places as well.
+               init: function () {}
+       };
+
+       // Legacy (for compatibility with the code previously in skins/common.edit.js)
+       mw.log.deprecate( window, 'addButton', toolbar.addButton, 'Use mw.toolbar.addButton instead.' );
+       mw.log.deprecate( window, 'insertTags', toolbar.insertTags, 'Use mw.toolbar.insertTags instead.' );
+
+       // Expose API publicly
+       mw.toolbar = toolbar;
+
+       $( function () {
+               var i, b, editBox, scrollTop, $editForm;
+
+               // Used to determine where to insert tags
+               $currentFocused = $( '#wpTextbox1' );
+
+               // Populate the selector cache for $toolbar
+               $toolbar = $( '#toolbar' );
+
+               for ( i = 0; i < queue.length; i++ ) {
+                       b = queue[i];
+                       if ( $.isArray( b ) ) {
+                               // Forwarded arguments array from mw.toolbar.addButton
+                               insertButton.apply( toolbar, b );
+                       } else {
+                               // Raw object from mw.toolbar.addButtons
+                               insertButton( b );
+                       }
+               }
+
+               // Clear queue
+               queue.length = 0;
+
+               // This causes further calls to addButton to go to insertion directly
+               // instead of to the queue.
+               // It is important that this is after the one and only loop through
+               // the the queue
+               isReady = true;
+
+               // Make sure edit summary does not exceed byte limit
+               $( '#wpSummary' ).byteLimit( 255 );
+
+               // Restore the edit box scroll state following a preview operation,
+               // and set up a form submission handler to remember this state.
+               editBox = document.getElementById( 'wpTextbox1' );
+               scrollTop = document.getElementById( 'wpScrolltop' );
+               $editForm = $( '#editform' );
+               if ( $editForm.length && editBox && scrollTop ) {
+                       if ( scrollTop.value ) {
+                               editBox.scrollTop = scrollTop.value;
+                       }
+                       $editForm.submit( function () {
+                               scrollTop.value = editBox.scrollTop;
+                       });
+               }
+
+               // Apply to dynamically created textboxes as well as normal ones
+               $( document ).on( 'focus', 'textarea, input:text', function () {
+                       $currentFocused = $( this );
+               } );
+       });
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.preview.js b/resources/src/mediawiki.action/mediawiki.action.edit.preview.js
new file mode 100644 (file)
index 0000000..4c2fc3a
--- /dev/null
@@ -0,0 +1,164 @@
+/**
+ * Live edit preview.
+ */
+( function ( mw, $ ) {
+
+       /**
+        * @param {jQuery.Event} e
+        */
+       function doLivePreview( e ) {
+               var $wikiPreview, $editform, copySelectors, $copyElements, $spinner,
+                       targetUrl, postData, $previewDataHolder;
+
+               e.preventDefault();
+
+               // Deprecated: Use mw.hook instead
+               $( mw ).trigger( 'LivePreviewPrepare' );
+
+               $wikiPreview = $( '#wikiPreview' );
+               $editform = $( '#editform' );
+
+               // Show #wikiPreview if it's hidden to be able to scroll to it
+               // (if it is hidden, it's also empty, so nothing changes in the rendering)
+               $wikiPreview.show();
+
+               // Jump to where the preview will appear
+               $wikiPreview[0].scrollIntoView();
+
+               // List of selectors matching elements that we will
+               // update from from the ajax-loaded preview page.
+               copySelectors = [
+                       // Main
+                       '#firstHeading',
+                       '#wikiPreview',
+                       '#wikiDiff',
+                       '#catlinks',
+                       '.hiddencats',
+                       '#p-lang',
+                       // Editing-related
+                       '.templatesUsed',
+                       '.limitreport',
+                       '.mw-summary-preview'
+               ];
+               $copyElements = $( copySelectors.join( ',' ) );
+
+               // Not shown during normal preview, to be removed if present
+               $( '.mw-newarticletext' ).remove();
+
+               $spinner = $.createSpinner( {
+                       size: 'large',
+                       type: 'block'
+               } );
+               $wikiPreview.before( $spinner );
+               $spinner.css( {
+                       marginTop: $spinner.height()
+               } );
+
+               // Can't use fadeTo because it calls show(), and we might want to keep some elements hidden
+               // (e.g. empty #catlinks)
+               $copyElements.animate( { opacity: 0.4 }, 'fast' );
+
+               $previewDataHolder = $( '<div>' );
+               targetUrl = $editform.attr( 'action' );
+               targetUrl += targetUrl.indexOf( '?' ) !== -1 ? '&' : '?';
+               targetUrl += $.param( {
+                       debug: mw.config.get( 'debug' ),
+                       uselang: mw.config.get( 'wgUserLanguage' ),
+                       useskin: mw.config.get( 'skin' )
+               } );
+
+               // Gather all the data from the form
+               postData = $editform.formToArray();
+               postData.push( {
+                       name: e.target.name,
+                       value: ''
+               } );
+
+               // Load new preview data.
+               // TODO: This should use the action=parse API instead of loading the entire page,
+               // although that requires figuring out how to convert that raw data into proper HTML.
+               $previewDataHolder.load( targetUrl + ' ' + copySelectors.join( ',' ), postData, function () {
+                       var i, $from, $next, $parent;
+
+                       // Copy the contents of the specified elements from the loaded page to the real page.
+                       // Also copy their class attributes.
+                       for ( i = 0; i < copySelectors.length; i++ ) {
+                               $from = $previewDataHolder.find( copySelectors[i] );
+
+                               if ( copySelectors[i] === '#wikiPreview' ) {
+                                       $next = $wikiPreview.next();
+                                       // If there is no next node, use parent instead.
+                                       // Only query parent if needed, false otherwise.
+                                       $parent = !$next.length && $wikiPreview.parent();
+
+                                       $wikiPreview
+                                               .detach()
+                                               .empty()
+                                               .append( $from.contents() )
+                                               .attr( 'class', $from.attr( 'class' ) );
+
+                                       mw.hook( 'wikipage.content' ).fire( $wikiPreview );
+
+                                       // Reattach
+                                       if ( $parent ) {
+                                               $parent.append( $wikiPreview );
+                                       } else {
+                                               $next.before( $wikiPreview );
+                                       }
+
+                               } else {
+                                       $( copySelectors[i] )
+                                               .empty()
+                                               .append( $from.contents() )
+                                               .attr( 'class', $from.attr( 'class' ) );
+                               }
+                       }
+
+                       // Deprecated: Use mw.hook instead
+                       $( mw ).trigger( 'LivePreviewDone', [copySelectors] );
+
+                       $spinner.remove();
+                       $copyElements.animate( {
+                               opacity: 1
+                       }, 'fast' );
+               } );
+       }
+
+       $( function () {
+               // Do not enable on user .js/.css pages, as there's no sane way of "previewing"
+               // the scripts or styles without reloading the page.
+               if ( $( '#mw-userjsyoucanpreview' ).length || $( '#mw-usercssyoucanpreview' ).length ) {
+                       return;
+               }
+
+               // The following elements can change in a preview but are not output
+               // by the server when they're empty until the preview response.
+               // TODO: Make the server output these always (in a hidden state), so we don't
+               // have to fish and (hopefully) put them in the right place (since skins
+               // can change where they are output).
+
+               if ( !document.getElementById( 'p-lang' ) && document.getElementById( 'p-tb' ) ) {
+                       $( '#p-tb' ).after(
+                               $( '<div>' ).attr( 'id', 'p-lang' )
+                       );
+               }
+
+               if ( !$( '.mw-summary-preview' ).length ) {
+                       $( '.editCheckboxes' ).before(
+                               $( '<div>' ).addClass( 'mw-summary-preview' )
+                       );
+               }
+
+               if ( !document.getElementById( 'wikiDiff' ) && document.getElementById( 'wikiPreview' ) ) {
+                       $( '#wikiPreview' ).after(
+                               $( '<div>' ).attr( 'id', 'wikiDiff' )
+                       );
+               }
+
+               // This should be moved down to '#editform', but is kept on the body for now
+               // because the LiquidThreads extension is re-using this module with only half
+               // the EditPage (doesn't include #editform presumably, bug 55463).
+               $( document.body ).on( 'click', '#wpPreview, #wpDiff', doLivePreview );
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.styles.css b/resources/src/mediawiki.action/mediawiki.action.edit.styles.css
new file mode 100644 (file)
index 0000000..4a2bab3
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * Styles for elements of the editing form.
+ */
+
+/* General layout */
+#wpTextbox1 {
+       margin: 0;
+       display: block;
+}
+
+.editOptions {
+       background-color: #F0F0F0;
+       border: 1px solid silver;
+       border-top: none;
+       padding: 1em 1em 1.5em 1em;
+       margin-bottom: 2em;
+}
+
+/* Adjustments to edit form elements */
+.editCheckboxes {
+       margin-bottom: 1em;
+}
+
+.editCheckboxes input:first-child {
+       margin-left: 0;
+}
+
+.cancelLink {
+       margin-left: 0.5em;
+}
+
+#editpage-copywarn {
+       font-size: 0.9em;
+}
+
+#wpSummary {
+       display: block;
+       margin-top: 0;
+       margin-bottom: 0.5em;
+}
+
+.editButtons input:first-child {
+       margin-left: .1em;
+}
diff --git a/resources/src/mediawiki.action/mediawiki.action.history.diff.css b/resources/src/mediawiki.action/mediawiki.action.history.diff.css
new file mode 100644 (file)
index 0000000..31ca107
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+** Diff rendering
+*/
+table.diff {
+       background-color: white;
+       border: none;
+       border-spacing: 4px;
+       margin: 0;
+       width: 100%;
+       /* Ensure that colums are of equal width */
+       table-layout: fixed;
+}
+
+table.diff td {
+       padding: 0.33em 0.5em;
+}
+
+table.diff td.diff-marker {
+       /* Compensate padding for increased font-size */
+       padding: 0.25em;
+}
+
+table.diff col.diff-marker {
+       width: 2%;
+}
+
+table.diff col.diff-content {
+       width: 48%;
+}
+
+table.diff td div {
+       /* Force-wrap very long lines such as URLs or page-widening char strings */
+       word-wrap: break-word;
+}
+
+td.diff-otitle,
+td.diff-ntitle {
+       text-align: center;
+}
+
+td.diff-lineno {
+       font-weight: bold;
+}
+
+td.diff-marker {
+       text-align: right;
+       font-weight: bold;
+       font-size: 1.25em;
+}
+
+td.diff-addedline,
+td.diff-deletedline,
+td.diff-context {
+       font-size: 88%;
+       vertical-align: top;
+       white-space: -moz-pre-wrap;
+       white-space: pre-wrap;
+       border-style: solid;
+       border-width: 1px 1px 1px 4px;
+       border-radius: 0.33em;
+}
+
+td.diff-addedline {
+       border-color: #a3d3ff;
+}
+
+td.diff-deletedline {
+       border-color: #ffe49c;
+}
+
+td.diff-context {
+       background: #f9f9f9;
+       border-color: #e6e6e6;
+       color: #333333;
+}
+
+.diffchange {
+       font-weight: bold;
+       text-decoration: none;
+}
+
+td.diff-addedline .diffchange,
+td.diff-deletedline .diffchange {
+       border-radius: 0.33em;
+       padding: 0.25em 0;
+}
+
+td.diff-addedline .diffchange {
+       background: #d8ecff;
+}
+
+td.diff-deletedline .diffchange {
+       background: #feeec8;
+}
diff --git a/resources/src/mediawiki.action/mediawiki.action.history.js b/resources/src/mediawiki.action/mediawiki.action.history.js
new file mode 100644 (file)
index 0000000..2a02d87
--- /dev/null
@@ -0,0 +1,125 @@
+/**
+ * JavaScript for History action
+ */
+jQuery( function ( $ ) {
+       var     $historyCompareForm = $( '#mw-history-compare' ),
+               $historySubmitter,
+               $lis = $( '#pagehistory > li' );
+
+       /**
+        * @context {Element} input
+        * @param e {jQuery.Event}
+        */
+       function updateDiffRadios() {
+               var diffLi = false, // the li where the diff radio is checked
+                       oldLi = false; // the li where the oldid radio is checked
+
+               if ( !$lis.length ) {
+                       return true;
+               }
+
+               $lis
+               .removeClass( 'selected' )
+               .each( function () {
+                       var     $li = $( this ),
+                               $inputs = $li.find( 'input[type="radio"]' ),
+                               $oldidRadio = $inputs.filter( '[name="oldid"]' ).eq( 0 ),
+                               $diffRadio = $inputs.filter( '[name="diff"]' ).eq( 0 );
+
+                       if ( !$oldidRadio.length || !$diffRadio.length ) {
+                               return true;
+                       }
+
+                       if ( $oldidRadio.prop( 'checked' ) ) {
+                               oldLi = true;
+                               $li.addClass( 'selected' );
+                               $oldidRadio.css( 'visibility', 'visible' );
+                               $diffRadio.css( 'visibility', 'hidden' );
+
+                       } else if ( $diffRadio.prop( 'checked' ) ) {
+                               diffLi = true;
+                               $li.addClass( 'selected' );
+                               $oldidRadio.css( 'visibility', 'hidden' );
+                               $diffRadio.css( 'visibility', 'visible' );
+
+                       // This list item has neither checked
+                       } else {
+                               // We're below the selected radios
+                               if ( diffLi && oldLi ) {
+                                       $oldidRadio.css( 'visibility', 'visible' );
+                                       $diffRadio.css( 'visibility', 'hidden' );
+
+                               // We're between the selected radios
+                               } else if ( diffLi ) {
+                                       $diffRadio.css( 'visibility', 'visible' );
+                                       $oldidRadio.css( 'visibility', 'visible' );
+
+                               // We're above the selected radios
+                               } else {
+                                       $diffRadio.css( 'visibility', 'visible' );
+                                       $oldidRadio.css( 'visibility', 'hidden' );
+                               }
+                       }
+               } );
+
+               return true;
+       }
+
+       $lis.find( 'input[name="diff"], input[name="oldid"]' ).click( updateDiffRadios );
+
+       // Set initial state
+       updateDiffRadios();
+
+       // Prettify url output for HistoryAction submissions,
+       // to cover up action=historysubmit construction.
+
+       // Ideally we'd use e.target instead of $historySubmitter, but e.target points
+       // to the form element for submit actions, so.
+       $historyCompareForm.find( '.historysubmit' ).click( function () {
+               $historySubmitter = $( this );
+       } );
+
+       // On submit we clone the form element, remove unneeded fields in the clone
+       // that pollute the query parameter with stuff from the other "use case",
+       // and then submit the clone.
+       // Without the cloning we'd be changing the real form, which is slower, could make
+       // the page look broken for a second in slow browsers and might show the form broken
+       // again when coming back from a "next" page.
+       $historyCompareForm.submit( function ( e ) {
+               var     $copyForm, $copyRadios, $copyAction;
+
+               if ( $historySubmitter ) {
+                       $copyForm = $historyCompareForm.clone();
+                       $copyRadios = $copyForm.find( '#pagehistory > li' ).find( 'input[name="diff"], input[name="oldid"]' );
+                       $copyAction = $copyForm.find( '> [name="action"]' );
+
+                       // Remove action=historysubmit and ids[..]=..
+                       if ( $historySubmitter.hasClass( 'mw-history-compareselectedversions-button' ) ) {
+                               $copyAction.remove();
+                               $copyForm.find( 'input[name^="ids["]:checked' ).prop( 'checked', false );
+
+                       // Remove diff=&oldid=, change action=historysubmit to revisiondelete, remove revisiondelete
+                       } else if ( $historySubmitter.hasClass( 'mw-history-revisiondelete-button' ) ) {
+                               $copyRadios.remove();
+                               $copyAction.val( $historySubmitter.attr( 'name' ) );
+                               $copyForm.find( ':submit' ).remove();
+                       }
+
+                       // IE7 doesn't do submission from an off-DOM clone, so insert hidden into document first
+                       // Also remove potentially conflicting id attributes that we don't need anyway
+                       $copyForm
+                               .css( 'display', 'none' )
+                               .find( '[id]' )
+                                       .removeAttr( 'id' )
+                               .end()
+                               .insertAfter( $historyCompareForm )
+                               .submit();
+
+                       e.preventDefault();
+                       return false; // Because the submit is special, return false as well.
+               }
+
+               // Continue natural browser handling other wise
+               return true;
+       } );
+} );
diff --git a/resources/src/mediawiki.action/mediawiki.action.view.dblClickEdit.js b/resources/src/mediawiki.action/mediawiki.action.view.dblClickEdit.js
new file mode 100644 (file)
index 0000000..727a525
--- /dev/null
@@ -0,0 +1,12 @@
+/**
+ * This module enables double-click-to-edit functionality.
+ */
+( function ( mw, $ ) {
+       $( function () {
+               mw.util.$content.dblclick( function ( e ) {
+                       e.preventDefault();
+                       // Trigger native HTMLElement click instead of opening URL (bug 43052)
+                       $( '#ca-edit a' ).get( 0 ).click();
+               } );
+       } );
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.action/mediawiki.action.view.metadata.js b/resources/src/mediawiki.action/mediawiki.action.view.metadata.js
new file mode 100644 (file)
index 0000000..21f40c5
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * Exif metadata display for MediaWiki file uploads
+ *
+ * Add an expand/collapse link and collapse by default if set to
+ * (with JS disabled, user will see all items)
+ *
+ * See also:
+ * - ImagePage.php#makeMetadataTable (creates the HTML)
+ * - skins/common/shared.css (hides tr.collapsable inside table.collapsed)
+ */
+( function ( mw, $ ) {
+       $( function () {
+               var $row, $col, $link,
+                       showText = mw.msg( 'metadata-expand' ),
+                       hideText = mw.msg( 'metadata-collapse' ),
+                       $table = $( '#mw_metadata' ),
+                       $tbody = $table.find( 'tbody' );
+
+               if ( !$tbody.length || !$tbody.find( '.collapsable' ).length ) {
+                       return;
+               }
+
+               $row = $( '<tr class="mw-metadata-show-hide-extended"></tr>' );
+               $col = $( '<td colspan="2"></td>' );
+
+               $link = $( '<a>', {
+                       text: showText,
+                       href: '#'
+               } ).click( function () {
+                       if ( $table.hasClass( 'collapsed' ) ) {
+                               $( this ).text( hideText );
+                       } else {
+                               $( this ).text( showText );
+                       }
+                       $table.toggleClass( 'expanded collapsed' );
+                       return false;
+               } );
+
+               $col.append( $link );
+               $row.append( $col );
+               $tbody.append( $row );
+
+               // And collapse!
+               $table.addClass( 'collapsed' );
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.action/mediawiki.action.view.postEdit.css b/resources/src/mediawiki.action/mediawiki.action.view.postEdit.css
new file mode 100644 (file)
index 0000000..be88337
--- /dev/null
@@ -0,0 +1,77 @@
+.postedit-container {
+       margin: 0 auto;
+       position: fixed;
+       top: 0;
+       height: 0;
+       left: 50%;
+       z-index: 1000;
+       font-size: 13px;
+}
+
+.postedit-container:hover {
+       cursor: pointer;
+}
+
+.postedit {
+       position: relative;
+       top: 0.6em;
+       left: -50%;
+       padding: .6em 3.6em .6em 1.1em;
+       line-height: 1.5625em;
+       color: #626465;
+       background-color: #f4f4f4;
+       border: 1px solid #dcd9d9;
+       text-shadow: 0 0.0625em 0 rgba(255, 255, 255, 0.5);
+       border-radius: 5px;
+       -webkit-box-shadow: 0 2px 5px 0 #ccc;
+       box-shadow: 0 2px 5px 0 #ccc;
+       -webkit-transition: all 0.25s ease-in-out;
+       -moz-transition: all 0.25s ease-in-out;
+       -ms-transition: all 0.25s ease-in-out;
+       -o-transition: all 0.25s ease-in-out;
+       transition: all 0.25s ease-in-out;
+}
+
+.skin-monobook .postedit {
+       top: 6em !important;
+}
+
+.postedit-faded {
+       opacity: 0;
+}
+
+.postedit-icon {
+       padding-left: 41px; /* 25 + 8 + 8 */
+       /* like min-height, but old IE compatible and keeps text vertically aligned, too */
+       line-height: 25px;
+       background-repeat: no-repeat;
+       background-position: 8px 50%;
+}
+
+.postedit-icon-checkmark {
+       /* @embed */
+       background-image: url(images/green-checkmark.png);
+       background-position: left;
+}
+
+.postedit-close {
+       position: absolute;
+       padding: 0 .8em;
+       right: 0;
+       top: 0;
+       font-size: 1.25em;
+       font-weight: bold;
+       line-height: 2.3em;
+       color: black;
+       text-shadow: 0 0.0625em 0 white;
+       text-decoration: none;
+       opacity: 0.2;
+       filter: alpha(opacity=20);
+}
+
+.postedit-close:hover {
+       color: black;
+       text-decoration: none;
+       opacity: 0.4;
+       filter: alpha(opacity=40);
+}
diff --git a/resources/src/mediawiki.action/mediawiki.action.view.postEdit.js b/resources/src/mediawiki.action/mediawiki.action.view.postEdit.js
new file mode 100644 (file)
index 0000000..6e4df9f
--- /dev/null
@@ -0,0 +1,76 @@
+( function ( mw, $ ) {
+       'use strict';
+
+       /**
+        * @event postEdit
+        * @member mw.hook
+        * @param {Object} [data] Optional data
+        * @param {string|jQuery|Array} [data.message] Message that listeners
+        *  should use when displaying notifications. String for plain text,
+        *  use array or jQuery object to pass actual nodes.
+        * @param {string|mw.user} [data.user=mw.user] User that made the edit.
+        */
+
+       /**
+        * After the listener for #postEdit removes the notification.
+        *
+        * @event postEdit_afterRemoval
+        * @member mw.hook
+        */
+
+       var config = mw.config.get( [ 'wgAction', 'wgCookiePrefix', 'wgCurRevisionId' ] ),
+               // This should match EditPage::POST_EDIT_COOKIE_KEY_PREFIX:
+               cookieKey = config.wgCookiePrefix + 'PostEditRevision' + config.wgCurRevisionId,
+               $div, id;
+
+       function showConfirmation( data ) {
+               data = data || {};
+               if ( data.message === undefined ) {
+                       data.message = $.parseHTML( mw.message( 'postedit-confirmation', data.user || mw.user ).escaped() );
+               }
+
+               $div = $(
+                       '<div class="postedit-container">' +
+                               '<div class="postedit">' +
+                                       '<div class="postedit-icon postedit-icon-checkmark postedit-content"></div>' +
+                                       '<a href="#" class="postedit-close">&times;</a>' +
+                               '</div>' +
+                       '</div>'
+               );
+
+               if ( typeof data.message === 'string' ) {
+                       $div.find( '.postedit-content' ).text( data.message );
+               } else if ( typeof data.message === 'object' ) {
+                       $div.find( '.postedit-content' ).append( data.message );
+               }
+
+               $div
+                       .click( fadeOutConfirmation )
+                       .prependTo( 'body' );
+
+               id = setTimeout( fadeOutConfirmation, 3000 );
+       }
+
+       function fadeOutConfirmation() {
+               clearTimeout( id );
+               $div.find( '.postedit' ).addClass( 'postedit postedit-faded' );
+               setTimeout( removeConfirmation, 500 );
+
+               return false;
+       }
+
+       function removeConfirmation() {
+               $div.remove();
+               mw.hook( 'postEdit.afterRemoval' ).fire();
+       }
+
+       mw.hook( 'postEdit' ).add( showConfirmation );
+
+       if ( config.wgAction === 'view' && $.cookie( cookieKey ) === '1' ) {
+               $.cookie( cookieKey, null, { path: '/' } );
+               mw.config.set( 'wgPostEdit', true );
+
+               mw.hook( 'postEdit' ).fire();
+       }
+
+} ( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.action/mediawiki.action.view.redirectToFragment.js b/resources/src/mediawiki.action/mediawiki.action.view.redirectToFragment.js
new file mode 100644 (file)
index 0000000..1e2d624
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * JavaScript to scroll the page to an id, when a redirect with fragment is viewed.
+ */
+( function ( mw, $ ) {
+       var profile = $.client.profile(),
+               fragment = mw.config.get( 'wgRedirectToFragment' );
+
+       if ( fragment === null ) {
+               // nothing to do
+               return;
+       }
+
+       if ( profile.layout === 'webkit' && profile.layoutVersion < 420 ) {
+               // Released Safari w/ WebKit 418.9.1 messes up horribly
+               // Nightlies of 420+ are ok
+               return;
+       }
+       if ( !window.location.hash ) {
+               window.location.hash = fragment;
+
+               // Mozilla needs to wait until after load, otherwise the window doesn't
+               // scroll.  See <https://bugzilla.mozilla.org/show_bug.cgi?id=516293>.
+               // There's no obvious way to detect this programmatically, so we use
+               // version-testing.  If Firefox fixes the bug, they'll jump twice, but
+               // better twice than not at all, so make the fix hit future versions as
+               // well.
+               if ( profile.layout === 'gecko' ) {
+                       $( function () {
+                               if ( window.location.hash === fragment ) {
+                                       window.location.hash = fragment;
+                               }
+                       } );
+               }
+       }
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.action/mediawiki.action.view.rightClickEdit.js b/resources/src/mediawiki.action/mediawiki.action.view.rightClickEdit.js
new file mode 100644 (file)
index 0000000..93befe3
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * JavaScript to enable right click edit functionality.
+ * When the user right-clicks in a heading, it will open the
+ * edit screen.
+ */
+jQuery( function ( $ ) {
+       // Select all h1-h6 elements that contain editsection links
+       // Don't use the ":has:(.mw-editsection a)" selector because it performs very bad.
+       // http://jsperf.com/jq-1-7-2-vs-jq-1-8-1-performance-of-mw-has/2
+       $( document ).on( 'contextmenu', 'h1, h2, h3, h4, h5, h6', function ( e ) {
+               var $edit = $( this ).find( '.mw-editsection a' );
+               if ( !$edit.length ) {
+                       return;
+               }
+
+               // Headings can contain rich text.
+               // Make sure to not block contextmenu events on (other) anchor tags
+               // inside the heading (e.g. to do things like copy URL, open in new tab, ..).
+               // e.target can be the heading, but it can also be anything inside the heading.
+               if ( e.target.nodeName.toLowerCase() !== 'a' ) {
+                       // Trigger native HTMLElement click instead of opening URL (bug 43052)
+                       e.preventDefault();
+                       $edit.get( 0 ).click();
+               }
+       } );
+} );
diff --git a/resources/src/mediawiki.api/mediawiki.api.category.js b/resources/src/mediawiki.api/mediawiki.api.category.js
new file mode 100644 (file)
index 0000000..a90617d
--- /dev/null
@@ -0,0 +1,146 @@
+/**
+ * @class mw.Api.plugin.category
+ */
+( function ( mw, $ ) {
+
+       var msg = 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.';
+       $.extend( mw.Api.prototype, {
+               /**
+                * Determine if a category exists.
+                *
+                * @param {mw.Title|string} title
+                * @param {Function} [ok] Success callback (deprecated)
+                * @param {Function} [err] Error callback (deprecated)
+                * @return {jQuery.Promise}
+                * @return {Function} return.done
+                * @return {boolean} return.done.isCategory Whether the category exists.
+                */
+               isCategory: function ( title, ok, err ) {
+                       var apiPromise = this.get( {
+                               prop: 'categoryinfo',
+                               titles: String( title )
+                       } );
+
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                       }
+
+                       return apiPromise
+                               .then( function ( data ) {
+                                       var exists = false;
+                                       if ( data.query && data.query.pages ) {
+                                               $.each( data.query.pages, function ( id, page ) {
+                                                       if ( page.categoryinfo ) {
+                                                               exists = true;
+                                                       }
+                                               } );
+                                       }
+                                       return exists;
+                               } )
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
+               },
+
+               /**
+                * Get a list of categories that match a certain prefix.
+                *
+                * E.g. given "Foo", return "Food", "Foolish people", "Foosball tables"...
+                *
+                * @param {string} prefix Prefix to match.
+                * @param {Function} [ok] Success callback (deprecated)
+                * @param {Function} [err] Error callback (deprecated)
+                * @return {jQuery.Promise}
+                * @return {Function} return.done
+                * @return {string[]} return.done.categories Matched categories
+                */
+               getCategoriesByPrefix: function ( prefix, ok, err ) {
+                       // Fetch with allpages to only get categories that have a corresponding description page.
+                       var apiPromise = this.get( {
+                               list: 'allpages',
+                               apprefix: prefix,
+                               apnamespace: mw.config.get( 'wgNamespaceIds' ).category
+                       } );
+
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                       }
+
+                       return apiPromise
+                               .then( function ( data ) {
+                                       var texts = [];
+                                       if ( data.query && data.query.allpages ) {
+                                               $.each( data.query.allpages, function ( i, category ) {
+                                                       texts.push( new mw.Title( category.title ).getNameText() );
+                                               } );
+                                       }
+                                       return texts;
+                               } )
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
+               },
+
+               /**
+                * Get the categories that a particular page on the wiki belongs to.
+                *
+                * @param {mw.Title|string} title
+                * @param {Function} [ok] Success callback (deprecated)
+                * @param {Function} [err] Error callback (deprecated)
+                * @param {boolean} [async=true] Asynchronousness (deprecated)
+                * @return {jQuery.Promise}
+                * @return {Function} return.done
+                * @return {boolean|mw.Title[]} return.done.categories List of category titles or false
+                *  if title was not found.
+                */
+               getCategories: function ( title, ok, err, async ) {
+                       var apiPromise = this.get( {
+                               prop: 'categories',
+                               titles: String( title )
+                       }, {
+                               async: async === undefined ? true : async
+                       } );
+
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                       }
+                       if ( async !== undefined ) {
+                               mw.track( 'mw.deprecate', 'api.async' );
+                               mw.log.warn(
+                                       'Use of mediawiki.api async=false param is deprecated. ' +
+                                       'The sychronous mode will be removed in the future.'
+                               );
+                       }
+
+                       return apiPromise
+                               .then( function ( data ) {
+                                       var titles = false;
+                                       if ( data.query && data.query.pages ) {
+                                               $.each( data.query.pages, function ( id, page ) {
+                                                       if ( page.categories ) {
+                                                               if ( titles === false ) {
+                                                                       titles = [];
+                                                               }
+                                                               $.each( page.categories, function ( i, cat ) {
+                                                                       titles.push( new mw.Title( cat.title ) );
+                                                               } );
+                                                       }
+                                               } );
+                                       }
+                                       return titles;
+                               } )
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
+               }
+       } );
+
+       /**
+        * @class mw.Api
+        * @mixins mw.Api.plugin.category
+        */
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.api/mediawiki.api.edit.js b/resources/src/mediawiki.api/mediawiki.api.edit.js
new file mode 100644 (file)
index 0000000..edfb34a
--- /dev/null
@@ -0,0 +1,75 @@
+/**
+ * @class mw.Api.plugin.edit
+ */
+( function ( mw, $ ) {
+
+       var msg = 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.';
+       $.extend( mw.Api.prototype, {
+
+               /**
+                * Post to API with edit token. If we have no token, get one and try to post.
+                * If we have a cached token try using that, and if it fails, blank out the
+                * cached token and start over.
+                *
+                * @param {Object} params API parameters
+                * @param {Function} [ok] Success callback (deprecated)
+                * @param {Function} [err] Error callback (deprecated)
+                * @return {jQuery.Promise} See #post
+                */
+               postWithEditToken: function ( params, ok, err ) {
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                       }
+                       return this.postWithToken( 'edit', params ).done( ok ).fail( err );
+               },
+
+               /**
+                * Api helper to grab an edit token.
+                *
+                * @param {Function} [ok] Success callback (deprecated)
+                * @param {Function} [err] Error callback (deprecated)
+                * @return {jQuery.Promise}
+                * @return {Function} return.done
+                * @return {string} return.done.token Received token.
+                */
+               getEditToken: function ( ok, err ) {
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                       }
+                       return this.getToken( 'edit' ).done( ok ).fail( err );
+               },
+
+               /**
+                * Create a new section of the page.
+                * @see #postWithEditToken
+                * @param {mw.Title|String} title Target page
+                * @param {string} header
+                * @param {string} message wikitext message
+                * @param {Function} [ok] Success handler (deprecated)
+                * @param {Function} [err] Error handler (deprecated)
+                * @return {jQuery.Promise}
+                */
+               newSection: function ( title, header, message, ok, err ) {
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                       }
+                       return this.postWithEditToken( {
+                               action: 'edit',
+                               section: 'new',
+                               format: 'json',
+                               title: String( title ),
+                               summary: header,
+                               text: message
+                       } ).done( ok ).fail( err );
+               }
+       } );
+
+       /**
+        * @class mw.Api
+        * @mixins mw.Api.plugin.edit
+        */
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.api/mediawiki.api.js b/resources/src/mediawiki.api/mediawiki.api.js
new file mode 100644 (file)
index 0000000..f300672
--- /dev/null
@@ -0,0 +1,352 @@
+( function ( mw, $ ) {
+
+       // We allow people to omit these default parameters from API requests
+       // there is very customizable error handling here, on a per-call basis
+       // wondering, would it be simpler to make it easy to clone the api object,
+       // change error handling, and use that instead?
+       var defaultOptions = {
+
+                       // Query parameters for API requests
+                       parameters: {
+                               action: 'query',
+                               format: 'json'
+                       },
+
+                       // Ajax options for jQuery.ajax()
+                       ajax: {
+                               url: mw.util.wikiScript( 'api' ),
+
+                               timeout: 30 * 1000, // 30 seconds
+
+                               dataType: 'json'
+                       }
+               },
+               // Keyed by ajax url and symbolic name for the individual request
+               deferreds = {};
+
+       // Pre-populate with fake ajax deferreds to save http requests for tokens
+       // we already have on the page via the user.tokens module (bug 34733).
+       deferreds[ defaultOptions.ajax.url ] = {};
+       $.each( mw.user.tokens.get(), function ( key, value ) {
+               // This requires #getToken to use the same key as user.tokens.
+               // Format: token-type + "Token" (eg. editToken, patrolToken, watchToken).
+               deferreds[ defaultOptions.ajax.url ][ key ] = $.Deferred()
+                       .resolve( value )
+                       .promise( { abort: function () {} } );
+       } );
+
+       /**
+        * Constructor to create an object to interact with the API of a particular MediaWiki server.
+        * mw.Api objects represent the API of a particular MediaWiki server.
+        *
+        * TODO: Share API objects with exact same config.
+        *
+        *     var api = new mw.Api();
+        *     api.get( {
+        *         action: 'query',
+        *         meta: 'userinfo'
+        *     } ).done ( function ( data ) {
+        *         console.log( data );
+        *     } );
+        *
+        * @class
+        *
+        * @constructor
+        * @param {Object} options See defaultOptions documentation above. Ajax options can also be
+        *  overridden for each individual request to {@link jQuery#ajax} later on.
+        */
+       mw.Api = function ( options ) {
+
+               if ( options === undefined ) {
+                       options = {};
+               }
+
+               // Force a string if we got a mw.Uri object
+               if ( options.ajax && options.ajax.url !== undefined ) {
+                       options.ajax.url = String( options.ajax.url );
+               }
+
+               options.parameters = $.extend( {}, defaultOptions.parameters, options.parameters );
+               options.ajax = $.extend( {}, defaultOptions.ajax, options.ajax );
+
+               this.defaults = options;
+       };
+
+       mw.Api.prototype = {
+
+               /**
+                * Normalize the ajax options for compatibility and/or convenience methods.
+                *
+                * @param {Object} [arg] An object contaning one or more of options.ajax.
+                * @return {Object} Normalized ajax options.
+                */
+               normalizeAjaxOptions: function ( arg ) {
+                       // Arg argument is usually empty
+                       // (before MW 1.20 it was used to pass ok callbacks)
+                       var opts = arg || {};
+                       // Options can also be a success callback handler
+                       if ( typeof arg === 'function' ) {
+                               opts = { ok: arg };
+                       }
+                       return opts;
+               },
+
+               /**
+                * Perform API get request
+                *
+                * @param {Object} parameters
+                * @param {Object|Function} [ajaxOptions]
+                * @return {jQuery.Promise}
+                */
+               get: function ( parameters, ajaxOptions ) {
+                       ajaxOptions = this.normalizeAjaxOptions( ajaxOptions );
+                       ajaxOptions.type = 'GET';
+                       return this.ajax( parameters, ajaxOptions );
+               },
+
+               /**
+                * Perform API post request
+                *
+                * TODO: Post actions for non-local hostnames will need proxy.
+                *
+                * @param {Object} parameters
+                * @param {Object|Function} [ajaxOptions]
+                * @return {jQuery.Promise}
+                */
+               post: function ( parameters, ajaxOptions ) {
+                       ajaxOptions = this.normalizeAjaxOptions( ajaxOptions );
+                       ajaxOptions.type = 'POST';
+                       return this.ajax( parameters, ajaxOptions );
+               },
+
+               /**
+                * Perform the API call.
+                *
+                * @param {Object} parameters
+                * @param {Object} [ajaxOptions]
+                * @return {jQuery.Promise} Done: API response data and the jqXHR object.
+                *  Fail: Error code
+                */
+               ajax: function ( parameters, ajaxOptions ) {
+                       var token,
+                               apiDeferred = $.Deferred(),
+                               msg = 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.',
+                               xhr;
+
+                       parameters = $.extend( {}, this.defaults.parameters, parameters );
+                       ajaxOptions = $.extend( {}, this.defaults.ajax, ajaxOptions );
+
+                       // Ensure that token parameter is last (per [[mw:API:Edit#Token]]).
+                       if ( parameters.token ) {
+                               token = parameters.token;
+                               delete parameters.token;
+                       }
+                       // Some deployed MediaWiki >= 1.17 forbid periods in URLs, due to an IE XSS bug
+                       // So let's escape them here. See bug #28235
+                       // This works because jQuery accepts data as a query string or as an Object
+                       ajaxOptions.data = $.param( parameters ).replace( /\./g, '%2E' );
+
+                       // If we extracted a token parameter, add it back in.
+                       if ( token ) {
+                               ajaxOptions.data += '&token=' + encodeURIComponent( token );
+                       }
+
+                       // Backwards compatibility: Before MediaWiki 1.20,
+                       // callbacks were done with the 'ok' and 'err' property in ajaxOptions.
+                       if ( ajaxOptions.ok ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                               apiDeferred.done( ajaxOptions.ok );
+                               delete ajaxOptions.ok;
+                       }
+                       if ( ajaxOptions.err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                               apiDeferred.fail( ajaxOptions.err );
+                               delete ajaxOptions.err;
+                       }
+
+                       // Make the AJAX request
+                       xhr = $.ajax( ajaxOptions )
+                               // If AJAX fails, reject API call with error code 'http'
+                               // and details in second argument.
+                               .fail( function ( xhr, textStatus, exception ) {
+                                       apiDeferred.reject( 'http', {
+                                               xhr: xhr,
+                                               textStatus: textStatus,
+                                               exception: exception
+                                       } );
+                               } )
+                               // AJAX success just means "200 OK" response, also check API error codes
+                               .done( function ( result, textStatus, jqXHR ) {
+                                       if ( result === undefined || result === null || result === '' ) {
+                                               apiDeferred.reject( 'ok-but-empty',
+                                                       'OK response but empty result (check HTTP headers?)'
+                                               );
+                                       } else if ( result.error ) {
+                                               var code = result.error.code === undefined ? 'unknown' : result.error.code;
+                                               apiDeferred.reject( code, result );
+                                       } else {
+                                               apiDeferred.resolve( result, jqXHR );
+                                       }
+                               } );
+
+                       // Return the Promise
+                       return apiDeferred.promise( { abort: xhr.abort } ).fail( function ( code, details ) {
+                               mw.log( 'mw.Api error: ', code, details );
+                       } );
+               },
+
+               /**
+                * Post to API with specified type of token. If we have no token, get one and try to post.
+                * If we have a cached token try using that, and if it fails, blank out the
+                * cached token and start over. For example to change an user option you could do:
+                *
+                *     new mw.Api().postWithToken( 'options', {
+                *         action: 'options',
+                *         optionname: 'gender',
+                *         optionvalue: 'female'
+                *     } );
+                *
+                * @param {string} tokenType The name of the token, like options or edit.
+                * @param {Object} params API parameters
+                * @return {jQuery.Promise} See #post
+                * @since 1.22
+                */
+               postWithToken: function ( tokenType, params ) {
+                       var api = this;
+
+                       return api.getToken( tokenType ).then( function ( token ) {
+                               params.token = token;
+                               return api.post( params ).then(
+                                       // If no error, return to caller as-is
+                                       null,
+                                       // Error handler
+                                       function ( code ) {
+                                               if ( code === 'badtoken' ) {
+                                                       // Clear from cache
+                                                       deferreds[ this.defaults.ajax.url ][ tokenType + 'Token' ] =
+                                                               params.token = undefined;
+
+                                                       // Try again, once
+                                                       return api.getToken( tokenType ).then( function ( token ) {
+                                                               params.token = token;
+                                                               return api.post( params );
+                                                       } );
+                                               }
+
+                                               // Different error, pass on to let caller handle the error code
+                                               return this;
+                                       }
+                               );
+                       } );
+               },
+
+               /**
+                * Get a token for a certain action from the API.
+                *
+                * @param {string} type Token type
+                * @return {jQuery.Promise}
+                * @return {Function} return.done
+                * @return {string} return.done.token Received token.
+                * @since 1.22
+                */
+               getToken: function ( type ) {
+                       var apiPromise,
+                               deferredGroup = deferreds[ this.defaults.ajax.url ],
+                               d = deferredGroup && deferredGroup[ type + 'Token' ];
+
+                       if ( !d ) {
+                               d = $.Deferred();
+
+                               apiPromise = this.get( { action: 'tokens', type: type } )
+                                       .done( function ( data ) {
+                                               // If token type is not available for this user,
+                                               // key '...token' is missing or can contain Boolean false
+                                               if ( data.tokens && data.tokens[type + 'token'] ) {
+                                                       d.resolve( data.tokens[type + 'token'] );
+                                               } else {
+                                                       d.reject( 'token-missing', data );
+                                               }
+                                       } )
+                                       .fail( d.reject );
+
+                               // Attach abort handler
+                               d.abort = apiPromise.abort;
+
+                               // Store deferred now so that we can use this again even if it isn't ready yet
+                               if ( !deferredGroup ) {
+                                       deferredGroup = deferreds[ this.defaults.ajax.url ] = {};
+                               }
+                               deferredGroup[ type + 'Token' ] = d;
+                       }
+
+                       return d.promise( { abort: d.abort } );
+               }
+       };
+
+       /**
+        * @static
+        * @property {Array}
+        * List of errors we might receive from the API.
+        * For now, this just documents our expectation that there should be similar messages
+        * available.
+        */
+       mw.Api.errors = [
+               // occurs when POST aborted
+               // jQuery 1.4 can't distinguish abort or lost connection from 200 OK + empty result
+               'ok-but-empty',
+
+               // timeout
+               'timeout',
+
+               // really a warning, but we treat it like an error
+               'duplicate',
+               'duplicate-archive',
+
+               // upload succeeded, but no image info.
+               // this is probably impossible, but might as well check for it
+               'noimageinfo',
+               // remote errors, defined in API
+               'uploaddisabled',
+               'nomodule',
+               'mustbeposted',
+               'badaccess-groups',
+               'stashfailed',
+               'missingresult',
+               'missingparam',
+               'invalid-file-key',
+               'copyuploaddisabled',
+               'mustbeloggedin',
+               'empty-file',
+               'file-too-large',
+               'filetype-missing',
+               'filetype-banned',
+               'filetype-banned-type',
+               'filename-tooshort',
+               'illegal-filename',
+               'verification-error',
+               'hookaborted',
+               'unknown-error',
+               'internal-error',
+               'overwrite',
+               'badtoken',
+               'fetchfileerror',
+               'fileexists-shared-forbidden',
+               'invalidtitle',
+               'notloggedin'
+       ];
+
+       /**
+        * @static
+        * @property {Array}
+        * List of warnings we might receive from the API.
+        * For now, this just documents our expectation that there should be similar messages
+        * available.
+        */
+       mw.Api.warnings = [
+               'duplicate',
+               'exists'
+       ];
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.api/mediawiki.api.login.js b/resources/src/mediawiki.api/mediawiki.api.login.js
new file mode 100644 (file)
index 0000000..ccbae06
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * Make the two-step login easier.
+ * @author Niklas Laxström
+ * @class mw.Api.plugin.login
+ * @since 1.22
+ */
+( function ( mw, $ ) {
+       'use strict';
+
+       $.extend( mw.Api.prototype, {
+               /**
+                * @param {string} username
+                * @param {string} password
+                * @return {jQuery.Promise} See mw.Api#post
+                */
+               login: function ( username, password ) {
+                       var params, request,
+                               deferred = $.Deferred(),
+                               api = this;
+
+                       params = {
+                               action: 'login',
+                               lgname: username,
+                               lgpassword: password
+                       };
+
+                       request = api.post( params );
+                       request.fail( deferred.reject );
+                       request.done( function ( data ) {
+                               params.lgtoken = data.login.token;
+                               api.post( params )
+                                       .fail( deferred.reject )
+                                       .done( function ( data ) {
+                                               var code;
+                                               if ( data.login && data.login.result === 'Success' ) {
+                                                       deferred.resolve( data );
+                                               } else {
+                                                       // Set proper error code whenever possible
+                                                       code = data.error && data.error.code || 'unknown';
+                                                       deferred.reject( code, data );
+                                               }
+                                       } );
+                       } );
+
+                       return deferred.promise( { abort: request.abort } );
+               }
+       } );
+
+       /**
+        * @class mw.Api
+        * @mixins mw.Api.plugin.login
+        */
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.api/mediawiki.api.parse.js b/resources/src/mediawiki.api/mediawiki.api.parse.js
new file mode 100644 (file)
index 0000000..b1f1d2b
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * @class mw.Api.plugin.parse
+ */
+( function ( mw, $ ) {
+
+       $.extend( mw.Api.prototype, {
+               /**
+                * Convenience method for 'action=parse'.
+                *
+                * @param {string} wikitext
+                * @param {Function} [ok] Success callback (deprecated)
+                * @param {Function} [err] Error callback (deprecated)
+                * @return {jQuery.Promise}
+                * @return {Function} return.done
+                * @return {string} return.done.data Parsed HTML of `wikitext`.
+                */
+               parse: function ( wikitext, ok, err ) {
+                       var apiPromise = this.get( {
+                               action: 'parse',
+                               contentmodel: 'wikitext',
+                               text: wikitext
+                       } );
+
+                       // Backwards compatibility (< MW 1.20)
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.' );
+                       }
+
+                       return apiPromise
+                               .then( function ( data ) {
+                                       return data.parse.text['*'];
+                               } )
+                               .done( ok )
+                               .fail( err )
+                               .promise( { abort: apiPromise.abort } );
+               }
+       } );
+
+       /**
+        * @class mw.Api
+        * @mixins mw.Api.plugin.parse
+        */
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.api/mediawiki.api.watch.js b/resources/src/mediawiki.api/mediawiki.api.watch.js
new file mode 100644 (file)
index 0000000..aa33d86
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ * @class mw.Api.plugin.watch
+ * @since 1.19
+ */
+( function ( mw, $ ) {
+
+       /**
+        * @private
+        * @static
+        * @context mw.Api
+        *
+        * @param {string|mw.Title|string[]|mw.Title[]} pages Full page name or instance of mw.Title, or an
+        *  array thereof. If an array is passed, the return value passed to the promise will also be an
+        *  array of appropriate objects.
+        * @param {Function} [ok] Success callback (deprecated)
+        * @param {Function} [err] Error callback (deprecated)
+        * @return {jQuery.Promise}
+        * @return {Function} return.done
+        * @return {Object|Object[]} return.done.watch Object or list of objects (depends on the `pages`
+        *  parameter)
+        * @return {string} return.done.watch.title Full pagename
+        * @return {boolean} return.done.watch.watched Whether the page is now watched or unwatched
+        * @return {string} return.done.watch.message Parsed HTML of the confirmational interface message
+        */
+       function doWatchInternal( pages, ok, err, addParams ) {
+               // XXX: Parameter addParams is undocumented because we inherit this
+               // documentation in the public method...
+               var apiPromise = this.post(
+                       $.extend(
+                               {
+                                       action: 'watch',
+                                       titles: $.isArray( pages ) ? pages.join( '|' ) : String( pages ),
+                                       token: mw.user.tokens.get( 'watchToken' ),
+                                       uselang: mw.config.get( 'wgUserLanguage' )
+                               },
+                               addParams
+                       )
+               );
+
+               // Backwards compatibility (< MW 1.20)
+               if ( ok || err ) {
+                       mw.track( 'mw.deprecate', 'api.cbParam' );
+                       mw.log.warn( 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.' );
+               }
+
+               return apiPromise
+                       .then( function ( data ) {
+                               // If a single page was given (not an array) respond with a single item as well.
+                               return $.isArray( pages ) ? data.watch : data.watch[0];
+                       } )
+                       .done( ok )
+                       .fail( err )
+                       .promise( { abort: apiPromise.abort } );
+       }
+
+       $.extend( mw.Api.prototype, {
+               /**
+                * Convenience method for `action=watch`.
+                *
+                * @inheritdoc #doWatchInternal
+                */
+               watch: function ( pages, ok, err ) {
+                       return doWatchInternal.call( this, pages, ok, err );
+               },
+               /**
+                * Convenience method for `action=watch&unwatch=1`.
+                *
+                * @inheritdoc #doWatchInternal
+                */
+               unwatch: function ( pages, ok, err ) {
+                       return doWatchInternal.call( this, pages, ok, err, { unwatch: 1 } );
+               }
+       } );
+
+       /**
+        * @class mw.Api
+        * @mixins mw.Api.plugin.watch
+        */
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.language/languages/bs.js b/resources/src/mediawiki.language/languages/bs.js
new file mode 100644 (file)
index 0000000..b56e4b2
--- /dev/null
@@ -0,0 +1,19 @@
+/*!
+ * Bosnian (bosanski) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'bs', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+       switch ( form ) {
+               case 'instrumental': // instrumental
+                       word = 's ' + word;
+                       break;
+               case 'lokativ': // locative
+                       word = 'o ' + word;
+                       break;
+       }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/languages/dsb.js b/resources/src/mediawiki.language/languages/dsb.js
new file mode 100644 (file)
index 0000000..69c36cc
--- /dev/null
@@ -0,0 +1,19 @@
+/*!
+ * Lower Sorbian (Dolnoserbski) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'dsb', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+       switch ( form ) {
+               case 'instrumental': // instrumental
+                       word = 'z ' + word;
+                       break;
+               case 'lokatiw': // lokatiw
+                       word = 'wo ' + word;
+                       break;
+       }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/languages/fi.js b/resources/src/mediawiki.language/languages/fi.js
new file mode 100644 (file)
index 0000000..2382aae
--- /dev/null
@@ -0,0 +1,47 @@
+/*!
+ * Finnish (Suomi) language functions
+ * @author Santhosh Thottingal
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms, aou, origWord;
+
+       grammarForms = mediaWiki.language.getData( 'fi', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+
+       // vowel harmony flag
+       aou = word.match( /[aou][^äöy]*$/i );
+       origWord = word;
+       if ( word.match( /wiki$/i ) ) {
+               aou = false;
+       }
+       //append i after final consonant
+       if ( word.match( /[bcdfghjklmnpqrstvwxz]$/i ) ) {
+               word += 'i';
+       }
+
+       switch ( form ) {
+               case 'genitive':
+                       word += 'n';
+                       break;
+               case 'elative':
+                       word += ( aou ? 'sta' : 'stä' );
+                       break;
+               case 'partitive':
+                       word += ( aou ? 'a' : 'ä' );
+                       break;
+               case 'illative':
+                       // Double the last letter and add 'n'
+                       word += word.substr(  word.length - 1 ) + 'n';
+                       break;
+               case 'inessive':
+                       word += ( aou ? 'ssa' : 'ssä' );
+                       break;
+               default:
+                       word = origWord;
+                       break;
+       }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/languages/ga.js b/resources/src/mediawiki.language/languages/ga.js
new file mode 100644 (file)
index 0000000..fb4e939
--- /dev/null
@@ -0,0 +1,38 @@
+/*!
+ * Irish (Gaeilge) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       /*jshint onecase:true */
+       var grammarForms = mediaWiki.language.getData( 'ga', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+       switch ( form ) {
+               case 'ainmlae':
+                       switch ( word ) {
+                               case 'an Domhnach':
+                                       word = 'Dé Domhnaigh';
+                                       break;
+                               case 'an Luan':
+                                       word = 'Dé Luain';
+                                       break;
+                               case 'an Mháirt':
+                                       word = 'Dé Mháirt';
+                                       break;
+                               case 'an Chéadaoin':
+                                       word = 'Dé Chéadaoin';
+                                       break;
+                               case 'an Déardaoin':
+                                       word = 'Déardaoin';
+                                       break;
+                               case 'an Aoine':
+                                       word = 'Dé hAoine';
+                                       break;
+                               case 'an Satharn':
+                                       word = 'Dé Sathairn';
+                                       break;
+                       }
+       }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/languages/he.js b/resources/src/mediawiki.language/languages/he.js
new file mode 100644 (file)
index 0000000..486e993
--- /dev/null
@@ -0,0 +1,29 @@
+/*!
+ * Hebrew (עברית) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'he', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+       switch ( form ) {
+               case 'prefixed':
+               case 'תחילית': // the same word in Hebrew
+                       // Duplicate prefixed "Waw", but only if it's not already double
+                       if ( word.substr( 0, 1 ) === 'ו' && word.substr( 0, 2 ) !== 'וו' ) {
+                               word = 'ו' + word;
+                       }
+
+                       // Remove the "He" if prefixed
+                       if ( word.substr( 0, 1 ) === 'ה' ) {
+                               word = word.substr( 1, word.length );
+                       }
+
+                       // Add a hyphen (maqaf) before numbers and non-Hebrew letters
+                       if (  word.substr( 0, 1 ) < 'א' ||  word.substr( 0, 1 ) > 'ת' ) {
+                               word = '־' + word;
+                       }
+       }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/languages/hsb.js b/resources/src/mediawiki.language/languages/hsb.js
new file mode 100644 (file)
index 0000000..2d6b733
--- /dev/null
@@ -0,0 +1,19 @@
+/*!
+ * Upper Sorbian (Hornjoserbsce) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'hsb', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+       switch ( form ) {
+               case 'instrumental': // instrumental
+                       word = 'z ' + word;
+                       break;
+               case 'lokatiw': // lokatiw
+                       word = 'wo ' + word;
+                       break;
+               }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/languages/hu.js b/resources/src/mediawiki.language/languages/hu.js
new file mode 100644 (file)
index 0000000..d72a1c0
--- /dev/null
@@ -0,0 +1,23 @@
+/*!
+ * Hungarian language functions
+ * @author Santhosh Thottingal
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'hu', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+       switch ( form ) {
+               case 'rol':
+                       word += 'ról';
+                       break;
+               case 'ba':
+                       word += 'ba';
+                       break;
+               case 'k':
+                       word += 'k';
+                       break;
+       }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/languages/hy.js b/resources/src/mediawiki.language/languages/hy.js
new file mode 100644 (file)
index 0000000..ae16f24
--- /dev/null
@@ -0,0 +1,29 @@
+/*!
+ * Armenian (Հայերեն) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       /*jshint onecase:true */
+       var grammarForms = mediaWiki.language.getData( 'hy', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+
+       // These rules are not perfect, but they are currently only used for site names so it doesn't
+       // matter if they are wrong sometimes. Just add a special case for your site name if necessary.
+
+       switch ( form ) {
+               case 'genitive': // սեռական հոլով
+                       if ( word.substr( -1 ) === 'ա' ) {
+                               word = word.substr( 0, word.length - 1 ) + 'այի';
+                       } else if ( word.substr( -1 ) === 'ո' ) {
+                               word = word.substr( 0, word.length - 1 ) + 'ոյի';
+                       } else if ( word.substr( -4 ) === 'գիրք' ) {
+                               word = word.substr( 0, word.length - 4 ) + 'գրքի';
+                       } else {
+                               word = word + 'ի';
+                       }
+                       break;
+               }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/languages/la.js b/resources/src/mediawiki.language/languages/la.js
new file mode 100644 (file)
index 0000000..04b7d0a
--- /dev/null
@@ -0,0 +1,50 @@
+/*!
+ * Latin (lingua Latina) language functions
+ * @author Santhosh Thottingal
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'la', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+       switch ( form ) {
+               case 'genitive':
+                       // only a few declensions, and even for those mostly the singular only
+                       word = word.replace( /u[ms]$/i, 'i' ); // 2nd declension singular
+                       word = word.replace( /ommunia$/i, 'ommunium' ); // 3rd declension neuter plural (partly)
+                       word = word.replace( /a$/i, 'ae' ); // 1st declension singular
+                       word = word.replace( /libri$/i,'librorum' ); // 2nd declension plural (partly)
+                       word = word.replace( /nuntii$/i, 'nuntiorum' ); // 2nd declension plural (partly)
+                       word = word.replace( /tio$/i,'tionis' ); // 3rd declension singular (partly)
+                       word = word.replace( /ns$/i, 'ntis' );
+                       word = word.replace( /as$/i, 'atis' );
+                       word = word.replace( /es$/i, 'ei' ); // 5th declension singular
+                       break;
+               case 'accusative':
+                       // only a few declensions, and even for those mostly the singular only
+                       word = word.replace( /u[ms]$/i, 'um' ); // 2nd declension singular
+                       word = word.replace( /ommunia$/i, 'am' ); // 3rd declension neuter plural (partly)
+                       word = word.replace( /a$/i, 'ommunia' ); // 1st declension singular
+                       word = word.replace( /libri$/i,'libros' ); // 2nd declension plural (partly)
+                       word = word.replace( /nuntii$/i, 'nuntios' );// 2nd declension plural (partly)
+                       word = word.replace( /tio$/i,'tionem' ); // 3rd declension singular (partly)
+                       word = word.replace( /ns$/i, 'ntem' );
+                       word = word.replace( /as$/i, 'atem');
+                       word = word.replace( /es$/i, 'em' ); // 5th declension singular
+                       break;
+               case 'ablative':
+                       // only a few declensions, and even for those mostly the singular only
+                       word = word.replace( /u[ms]$/i, 'o' ); // 2nd declension singular
+                       word = word.replace( /ommunia$/i, 'ommunibus' ); // 3rd declension neuter plural (partly)
+                       word = word.replace( /a$/i, 'a' ); // 1st declension singular
+                       word = word.replace( /libri$/i,'libris' ); // 2nd declension plural (partly)
+                       word = word.replace( /nuntii$/i, 'nuntiis' ); // 2nd declension plural (partly)
+                       word = word.replace( /tio$/i,'tione' ); // 3rd declension singular (partly)
+                       word = word.replace( /ns$/i, 'nte' );
+                       word = word.replace( /as$/i, 'ate');
+                       word = word.replace( /es$/i, 'e' ); // 5th declension singular
+                       break;
+       }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/languages/os.js b/resources/src/mediawiki.language/languages/os.js
new file mode 100644 (file)
index 0000000..bdf59be
--- /dev/null
@@ -0,0 +1,69 @@
+/*!
+ * Ossetian (Ирон) language functions
+ * @author Santhosh Thottingal
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'os', 'grammarForms' ),
+               // Ending for allative case
+               endAllative = 'мæ',
+               // Variable for 'j' beetwen vowels
+               jot = '',
+               // Variable for "-" for not Ossetic words
+               hyphen = '',
+               // Variable for ending
+               ending = '';
+
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+       // Checking if the $word is in plural form
+       if ( word.match( /тæ$/i ) ) {
+               word = word.substring( 0, word.length - 1 );
+               endAllative = 'æм';
+       }
+       // Works if word is in singular form.
+       // Checking if word ends on one of the vowels: е, ё, и, о, ы, э, ю, я.
+       else if ( word.match( /[аæеёиоыэюя]$/i ) ) {
+               jot = 'й';
+       }
+       // Checking if word ends on 'у'. 'У' can be either consonant 'W' or vowel 'U' in cyrillic Ossetic.
+       // Examples: {{grammar:genitive|аунеу}} = аунеуы, {{grammar:genitive|лæппу}} = лæппуйы.
+       else if ( word.match( /у$/i ) ) {
+               if ( !word.substring( word.length - 2, word.length - 1 ).match( /[аæеёиоыэюя]$/i ) ) {
+                       jot = 'й';
+               }
+       } else if ( !word.match( /[бвгджзйклмнопрстфхцчшщьъ]$/i ) ) {
+               hyphen = '-';
+       }
+
+       switch ( form ) {
+               case 'genitive':
+                       ending = hyphen + jot + 'ы';
+                       break;
+               case 'dative':
+                       ending = hyphen + jot + 'æн';
+                       break;
+               case 'allative':
+                       ending = hyphen + endAllative;
+                       break;
+               case 'ablative':
+                       if ( jot === 'й' ) {
+                               ending = hyphen + jot + 'æ';
+                       }
+                       else {
+                               ending = hyphen + jot + 'æй';
+                       }
+                       break;
+               case 'superessive':
+                       ending = hyphen + jot + 'ыл';
+                       break;
+               case 'equative':
+                       ending = hyphen + jot + 'ау';
+                       break;
+               case 'comitative':
+                       ending = hyphen + 'имæ';
+                       break;
+       }
+       return word + ending;
+};
diff --git a/resources/src/mediawiki.language/languages/ru.js b/resources/src/mediawiki.language/languages/ru.js
new file mode 100644 (file)
index 0000000..e66b9cd
--- /dev/null
@@ -0,0 +1,53 @@
+/*!
+ * Russian (Русский) language functions
+ */
+
+// These tests were originally made for names of Wikimedia
+// websites, so they don't currently cover all the possible
+// cases.
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       'use strict';
+
+       var grammarForms = mediaWiki.language.getData( 'ru', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+       switch ( form ) {
+               case 'genitive': // родительный падеж
+                       if ( word.substr( word.length - 1 ) === 'ь' ) {
+                               word = word.substr(0, word.length - 1 ) + 'я';
+                       } else if ( word.substr( word.length - 2 ) === 'ия' ) {
+                               word = word.substr(0, word.length - 2 ) + 'ии';
+                       } else if ( word.substr( word.length - 2 ) === 'ка' ) {
+                               word = word.substr(0, word.length - 2 ) + 'ки';
+                       } else if ( word.substr( word.length - 2 )  === 'ти' ) {
+                               word = word.substr(0, word.length - 2 ) + 'тей';
+                       } else if ( word.substr( word.length - 2 ) === 'ды' ) {
+                               word = word.substr(0, word.length - 2 ) + 'дов';
+                       } else if ( word.substr( word.length - 3 ) === 'ные' ) {
+                               word = word.substr(0, word.length - 3 ) + 'ных';
+                       } else if ( word.substr( word.length - 3 ) === 'ник' ) {
+                               word = word.substr(0, word.length - 3 ) + 'ника';
+                       }
+                       break;
+               case 'prepositional': // предложный падеж
+                       if ( word.substr( word.length - 1 ) === 'ь' ) {
+                               word = word.substr(0, word.length - 1 ) + 'е';
+                       } else if ( word.substr( word.length - 2 ) === 'ия' ) {
+                               word = word.substr(0, word.length - 2 ) + 'ии';
+                       } else if ( word.substr( word.length - 2 ) === 'ка' ) {
+                               word = word.substr(0, word.length - 2 ) + 'ке';
+                       } else if ( word.substr( word.length - 2 )  === 'ти' ) {
+                               word = word.substr(0, word.length - 2 ) + 'тях';
+                       } else if ( word.substr( word.length - 2 ) === 'ды' ) {
+                               word = word.substr(0, word.length - 2 ) + 'дах';
+                       } else if ( word.substr( word.length - 3 ) === 'ные' ) {
+                               word = word.substr(0, word.length - 3 ) + 'ных';
+                       } else if ( word.substr( word.length - 3 ) === 'ник' ) {
+                               word = word.substr(0, word.length - 3 ) + 'нике';
+                       }
+                       break;
+       }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/languages/sl.js b/resources/src/mediawiki.language/languages/sl.js
new file mode 100644 (file)
index 0000000..d20d0b3
--- /dev/null
@@ -0,0 +1,19 @@
+/*!
+ * Slovenian (Slovenščina) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'sl', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+       switch ( form ) {
+               case 'mestnik': // locative
+                       word = 'o ' + word;
+                       break;
+               case 'orodnik': // instrumental
+                       word = 'z ' + word;
+                       break;
+       }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/languages/uk.js b/resources/src/mediawiki.language/languages/uk.js
new file mode 100644 (file)
index 0000000..69f7ec5
--- /dev/null
@@ -0,0 +1,37 @@
+/*!
+ * Ukrainian (Українська) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'uk', 'grammarForms' );
+       if ( grammarForms && grammarForms[form] ) {
+               return grammarForms[form][word];
+       }
+       switch ( form ) {
+               case 'genitive': // родовий відмінок
+                       if ( word.substr( word.length - 4 ) !== 'вікі' && word.substr( word.length - 4 ) !== 'Вікі' ) {
+                               if ( word.substr( word.length - 1 ) === 'ь' ) {
+                                       word = word.substr(0, word.length - 1 ) + 'я';
+                               } else if ( word.substr( word.length - 2 ) === 'ія' ) {
+                                       word = word.substr(0, word.length - 2 ) + 'ії';
+                               } else if ( word.substr( word.length - 2 ) === 'ка' ) {
+                                       word = word.substr(0, word.length - 2 ) + 'ки';
+                               } else if ( word.substr( word.length - 2 ) === 'ти' ) {
+                                       word = word.substr(0, word.length - 2 ) + 'тей';
+                               } else if ( word.substr( word.length - 2 ) === 'ды' ) {
+                                       word = word.substr(0, word.length - 2 ) + 'дов';
+                               } else if ( word.substr( word.length - 3 ) === 'ник' ) {
+                                       word = word.substr(0, word.length - 3 ) + 'ника';
+                               }
+                       }
+                       break;
+               case 'accusative': // знахідний відмінок
+                       if ( word.substr( word.length - 4 ) !== 'вікі' && word.substr( word.length - 4 ) !== 'Вікі' ) {
+                               if ( word.substr( word.length - 2 ) === 'ія' ) {
+                                       word = word.substr(0, word.length - 2 ) + 'ію';
+                               }
+                       }
+                       break;
+       }
+       return word;
+};
diff --git a/resources/src/mediawiki.language/mediawiki.cldr.js b/resources/src/mediawiki.language/mediawiki.cldr.js
new file mode 100644 (file)
index 0000000..f6fb8f1
--- /dev/null
@@ -0,0 +1,32 @@
+( function ( mw ) {
+       'use strict';
+
+       /**
+        * Namespace for CLDR-related utility methods.
+        *
+        * @class
+        * @singleton
+        */
+       mw.cldr = {
+               /**
+                * Get the plural form index for the number.
+                *
+                * In case none of the rules passed, we return `pluralRules.length` -
+                * that means it is the "other" form.
+                *
+                * @param {number} number
+                * @param {Array} pluralRules
+                * @return {number} plural form index
+                */
+               getPluralForm: function ( number, pluralRules ) {
+                       var i;
+                       for ( i = 0; i < pluralRules.length; i++ ) {
+                               if ( mw.libs.pluralRuleParser( pluralRules[i], number ) ) {
+                                       break;
+                               }
+                       }
+                       return i;
+               }
+       };
+
+}( mediaWiki ) );
diff --git a/resources/src/mediawiki.language/mediawiki.language.init.js b/resources/src/mediawiki.language/mediawiki.language.init.js
new file mode 100644 (file)
index 0000000..fd77025
--- /dev/null
@@ -0,0 +1,79 @@
+( function ( mw ) {
+       /**
+        * Base language object with methods related to language support, attempting to mirror some of the
+        * functionality of the Language class in MediaWiki:
+        *
+        *   - storing and retrieving language data
+        *   - transforming message syntax (`{{PLURAL:}}`, `{{GRAMMAR:}}`, `{{GENDER:}}`)
+        *   - formatting numbers
+        *
+        * @class
+        * @singleton
+        */
+       mw.language = {
+               /**
+                * Language-related data (keyed by language, contains instances of mw.Map). Loaded dynamically
+                * (see ResourceLoaderLanguageDataModule in PHP docs, aka mediawiki.language.data module).
+                *
+                * To set data:
+                *
+                *     // Override, extend or create the language data object of 'nl'
+                *     mw.language.setData( 'nl', 'myKey', 'My value' );
+                *
+                *     // Set multiple values at once
+                *     mw.language.setData( 'nl', { foo: 'X', bar: 'Y' } );
+                *
+                * To get GrammarForms data for language 'nl':
+                *
+                *     var grammarForms = mw.language.getData( 'nl', 'grammarForms' );
+                *
+                * Possible data keys:
+                *
+                *  - `digitTransformTable`
+                *  - `separatorTransformTable`
+                *  - `grammarForms`
+                *  - `pluralRules`
+                *  - `digitGroupingPattern`
+                *
+                * @property
+                */
+               data: {},
+
+               /**
+                * Convenience method for retrieving language data.
+                *
+                * Structured by language code and data key, covering for the potential inexistence of a
+                * data object for this language.
+                *
+                * @param {string} langCode
+                * @param {string} dataKey
+                * @return {Mixed} Value stored in the mw.Map (or `undefined` if there is no map for the specified
+                *  langCode).
+                */
+               getData: function ( langCode, dataKey ) {
+                       var langData = mw.language.data;
+                       if ( langData && langData[langCode] instanceof mw.Map ) {
+                               return langData[langCode].get( dataKey );
+                       }
+                       return undefined;
+               },
+
+               /**
+                * Convenience method for setting language data.
+                *
+                * Creates the data mw.Map if there isn't one for the specified language already.
+                *
+                * @param {string} langCode
+                * @param {string|Object} dataKey Key or object of key/values.
+                * @param {Mixed} value Value for dataKey, ignored if dataKey is an object.
+                */
+               setData: function ( langCode, dataKey, value ) {
+                       var langData = mw.language.data;
+                       if ( !( langData[langCode] instanceof mw.Map ) ) {
+                               langData[langCode] = new mw.Map();
+                       }
+                       langData[langCode].set( dataKey, value );
+               }
+       };
+
+}( mediaWiki ) );
diff --git a/resources/src/mediawiki.language/mediawiki.language.js b/resources/src/mediawiki.language/mediawiki.language.js
new file mode 100644 (file)
index 0000000..a0b5569
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Methods for transforming message syntax.
+ */
+( function ( mw, $ ) {
+
+/**
+ * @class mw.language
+ */
+$.extend( mw.language, {
+
+       /**
+        * Process the PLURAL template substitution
+        *
+        * @private
+        * @param {Object} template Template object
+        * @param {string} template.title
+        * @param {Array} template.parameters
+        * @return {string}
+        */
+       procPLURAL: function ( template ) {
+               if ( template.title && template.parameters && mw.language.convertPlural ) {
+                       // Check if we have forms to replace
+                       if ( template.parameters.length === 0 ) {
+                               return '';
+                       }
+                       // Restore the count into a Number ( if it got converted earlier )
+                       var count = mw.language.convertNumber( template.title, true );
+                       // Do convertPlural call
+                       return mw.language.convertPlural( parseInt( count, 10 ), template.parameters );
+               }
+               // Could not process plural return first form or nothing
+               if ( template.parameters[0] ) {
+                       return template.parameters[0];
+               }
+               return '';
+       },
+
+       /**
+        * Plural form transformations, needed for some languages.
+        *
+        * @param {number} count Non-localized quantifier
+        * @param {Array} forms List of plural forms
+        * @return {string} Correct form for quantifier in this language
+        */
+       convertPlural: function ( count, forms ) {
+               var pluralRules,
+                       formCount,
+                       form,
+                       index,
+                       equalsPosition,
+                       pluralFormIndex = 0;
+
+               if ( !forms || forms.length === 0 ) {
+                       return '';
+               }
+
+               // Handle for explicit n= forms
+               for ( index = 0; index < forms.length; index++ ) {
+                       form = forms[index];
+                       if ( /^\d+=/.test( form ) ) {
+                               equalsPosition = form.indexOf( '=' );
+                               formCount = parseInt( form.substring( 0, equalsPosition ), 10 );
+                               if ( formCount === count ) {
+                                       return form.substr( equalsPosition + 1 );
+                               }
+                               forms[index] = undefined;
+                       }
+               }
+
+               // Remove explicit plural forms from the forms.
+               forms = $.map( forms, function ( form ) {
+                       return form;
+               } );
+
+               if ( forms.length === 0 ) {
+                       return '';
+               }
+
+               pluralRules = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'pluralRules' );
+               if ( !pluralRules ) {
+                       // default fallback.
+                       return ( count === 1 ) ? forms[0] : forms[1];
+               }
+               pluralFormIndex = mw.cldr.getPluralForm( count, pluralRules );
+               pluralFormIndex = Math.min( pluralFormIndex, forms.length - 1 );
+               return forms[pluralFormIndex];
+       },
+
+       /**
+        * Pads an array to a specific length by copying the last one element.
+        *
+        * @private
+        * @param {Array} forms Number of forms given to convertPlural
+        * @param {number} count Number of forms required
+        * @return {Array} Padded array of forms
+        */
+       preConvertPlural: function ( forms, count ) {
+               while ( forms.length < count ) {
+                       forms.push( forms[ forms.length - 1 ] );
+               }
+               return forms;
+       },
+
+       /**
+        * Provides an alternative text depending on specified gender.
+        *
+        * Usage in message text: `{{gender:[gender|user object]|masculine|feminine|neutral}}`.
+        * If second or third parameter are not specified, masculine is used.
+        *
+        * These details may be overriden per language.
+        *
+        * @param {string} gender 'male', 'female', or anything else for neutral.
+        * @param {Array} forms List of gender forms
+        * @return string
+        */
+       gender: function ( gender, forms ) {
+               if ( !forms || forms.length === 0 ) {
+                       return '';
+               }
+               forms = mw.language.preConvertPlural( forms, 2 );
+               if ( gender === 'male' ) {
+                       return forms[0];
+               }
+               if ( gender === 'female' ) {
+                       return forms[1];
+               }
+               return ( forms.length === 3 ) ? forms[2] : forms[0];
+       },
+
+       /**
+        * Grammatical transformations, needed for inflected languages.
+        * Invoked by putting `{{grammar:form|word}}` in a message.
+        *
+        * The rules can be defined in $wgGrammarForms global or computed
+        * dynamically by overriding this method per language.
+        *
+        * @param {string} word
+        * @param {string} form
+        * @return {string}
+        */
+       convertGrammar: function ( word, form ) {
+               var grammarForms = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'grammarForms' );
+               if ( grammarForms && grammarForms[form] ) {
+                       return grammarForms[form][word] || word;
+               }
+               return word;
+       }
+
+} );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.language/mediawiki.language.months.js b/resources/src/mediawiki.language/mediawiki.language.months.js
new file mode 100644 (file)
index 0000000..5a1a5cb
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Transfer of month names from messages into mw.language.
+ *
+ * Loading this module also ensures the availability of appropriate messages via mw.msg.
+ */
+( function ( mw, $ ) {
+       var
+               monthMessages = [
+                       'january', 'february', 'march', 'april',
+                       'may_long', 'june', 'july', 'august',
+                       'september', 'october', 'november', 'december'
+               ],
+               monthGenMessages = [
+                       'january-gen', 'february-gen', 'march-gen', 'april-gen',
+                       'may-gen', 'june-gen', 'july-gen', 'august-gen',
+                       'september-gen', 'october-gen', 'november-gen', 'december-gen'
+               ],
+               monthAbbrevMessages = [
+                       'jan', 'feb', 'mar', 'apr',
+                       'may', 'jun', 'jul', 'aug',
+                       'sep', 'oct', 'nov', 'dec'
+               ];
+
+       // Function suitable for passing to jQuery.map
+       // Can't use mw.msg directly because jQuery.map passes element index as second argument
+       function mwMsgMapper( key ) {
+               return mw.msg( key );
+       }
+
+       /**
+        * Information about month names in current UI language.
+        *
+        * Object keys:
+        *
+        * - `names`: array of month names (in nominative case in languages which have the distinction),
+        *   zero-indexed
+        * - `genitive`: array of month names in genitive case, zero-indexed
+        * - `abbrev`: array of three-letter-long abbreviated month names, zero-indexed
+        * - `keys`: object with three keys like the above, containing zero-indexed arrays of message keys
+        *   for appropriate messages which can be passed to mw.msg.
+        *
+        * @property
+        * @member mw.language
+        */
+       mw.language.months = {
+               keys: {
+                       names: monthMessages,
+                       genitive: monthGenMessages,
+                       abbrev: monthAbbrevMessages
+               },
+               names: $.map( monthMessages, mwMsgMapper ),
+               genitive: $.map( monthGenMessages, mwMsgMapper ),
+               abbrev: $.map( monthAbbrevMessages, mwMsgMapper )
+       };
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.language/mediawiki.language.numbers.js b/resources/src/mediawiki.language/mediawiki.language.numbers.js
new file mode 100644 (file)
index 0000000..56fa0da
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Number-related utilities for mediawiki.language.
+ */
+( function ( mw, $ ) {
+       /**
+        * @class mw.language
+        */
+
+       /**
+        * Pad a string to guarantee that it is at least `size` length by
+        * filling with the character `ch` at either the start or end of the
+        * string. Pads at the start, by default.
+        *
+        * Example: Fill the string to length 10 with '+' characters on the right.
+        *
+        *     pad( 'blah', 10, '+', true ); // => 'blah++++++'
+        *
+        * @private
+        * @param {string} text The string to pad
+        * @param {number} size The length to pad to
+        * @param {string} [ch='0'] Character to pad with
+        * @param {boolean} [end=false] Adds padding at the end if true, otherwise pads at start
+        * @return {string}
+        */
+       function pad( text, size, ch, end ) {
+               if ( !ch ) {
+                       ch = '0';
+               }
+
+               var out = String( text ),
+                       padStr = replicate( ch, Math.ceil( ( size - out.length ) / ch.length ) );
+
+               return end ? out + padStr : padStr + out;
+       }
+
+       /**
+        * Efficiently replicate a string `n` times.
+        *
+        * @private
+        * @param {string} str The string to replicate
+        * @param {number} num Number of times to replicate the string
+        * @return {string}
+        */
+       function replicate( str, num ) {
+               if ( num <= 0 || !str ) {
+                       return '';
+               }
+
+               var buf = [];
+               while (num) {
+                       buf.push( str );
+                       str += str;
+               }
+               return buf.join( '' );
+       }
+
+       /**
+        * Apply numeric pattern to absolute value using options. Gives no
+        * consideration to local customs.
+        *
+        * Adapted from dojo/number library with thanks
+        * <http://dojotoolkit.org/reference-guide/1.8/dojo/number.html>
+        *
+        * @private
+        * @param {number} value the number to be formatted, ignores sign
+        * @param {string} pattern the number portion of a pattern (e.g. `#,##0.00`)
+        * @param {Object} [options] If provided, both option keys must be present:
+        * @param {string} options.decimal The decimal separator. Defaults to: `'.'`.
+        * @param {string} options.group The group separator. Defaults to: `','`.
+        * @return {string}
+        */
+       function commafyNumber( value, pattern, options ) {
+               options = options || {
+                       group: ',',
+                       decimal: '.'
+               };
+
+               if ( isNaN( value) ) {
+                       return value;
+               }
+
+               var padLength,
+                       patternDigits,
+                       index,
+                       whole,
+                       off,
+                       remainder,
+                       patternParts = pattern.split( '.' ),
+                       maxPlaces = ( patternParts[1] || [] ).length,
+                       valueParts = String( Math.abs( value ) ).split( '.' ),
+                       fractional = valueParts[1] || '',
+                       groupSize = 0,
+                       groupSize2 = 0,
+                       pieces = [];
+
+               if ( patternParts[1] ) {
+                       // Pad fractional with trailing zeros
+                       padLength = ( patternParts[1] && patternParts[1].lastIndexOf( '0' ) + 1 );
+
+                       if ( padLength > fractional.length ) {
+                               valueParts[1] = pad( fractional, padLength, '0', true );
+                       }
+
+                       // Truncate fractional
+                       if ( maxPlaces < fractional.length ) {
+                               valueParts[1] = fractional.substr( 0, maxPlaces );
+                       }
+               } else {
+                       if ( valueParts[1] ) {
+                               valueParts.pop();
+                       }
+               }
+
+               // Pad whole with leading zeros
+               patternDigits = patternParts[0].replace( ',', '' );
+
+               padLength = patternDigits.indexOf( '0' );
+
+               if ( padLength !== -1 ) {
+                       padLength = patternDigits.length - padLength;
+
+                       if ( padLength > valueParts[0].length ) {
+                               valueParts[0] = pad( valueParts[0], padLength );
+                       }
+
+                       // Truncate whole
+                       if ( patternDigits.indexOf( '#' ) === -1 ) {
+                               valueParts[0] = valueParts[0].substr( valueParts[0].length - padLength );
+                       }
+               }
+
+               // Add group separators
+               index = patternParts[0].lastIndexOf( ',' );
+
+               if ( index !== -1 ) {
+                       groupSize = patternParts[0].length - index - 1;
+                       remainder = patternParts[0].substr( 0, index );
+                       index = remainder.lastIndexOf( ',' );
+                       if ( index !== -1 ) {
+                               groupSize2 = remainder.length - index - 1;
+                       }
+               }
+
+               for ( whole = valueParts[0]; whole; ) {
+                       off = whole.length - groupSize;
+
+                       pieces.push( ( off > 0 ) ? whole.substr( off ) : whole );
+                       whole = ( off > 0 ) ? whole.slice( 0, off ) : '';
+
+                       if ( groupSize2 ) {
+                               groupSize = groupSize2;
+                       }
+               }
+               valueParts[0] = pieces.reverse().join( options.group );
+
+               return valueParts.join( options.decimal );
+       }
+
+       $.extend( mw.language, {
+
+               /**
+                * Converts a number using #getDigitTransformTable.
+                *
+                * @param {number} num Value to be converted
+                * @param {boolean} [integer=false] Whether to convert the return value to an integer
+                * @return {number|string} Formatted number
+                */
+               convertNumber: function ( num, integer ) {
+                       var i, tmp, transformTable, numberString, convertedNumber, pattern;
+
+                       pattern = mw.language.getData( mw.config.get( 'wgUserLanguage' ),
+                               'digitGroupingPattern' ) || '#,##0.###';
+
+                       // Set the target transform table:
+                       transformTable = mw.language.getDigitTransformTable();
+
+                       if ( !transformTable ) {
+                               return num;
+                       }
+
+                       // Check if the 'restore' to Latin number flag is set:
+                       if ( integer ) {
+                               if ( parseInt( num, 10 ) === num ) {
+                                       return num;
+                               }
+                               tmp = [];
+                               for ( i in transformTable ) {
+                                       tmp[ transformTable[ i ] ] = i;
+                               }
+                               transformTable = tmp;
+                               numberString = num + '';
+                       } else {
+                               numberString = mw.language.commafy( num, pattern );
+                       }
+
+                       convertedNumber = '';
+                       for ( i = 0; i < numberString.length; i++ ) {
+                               if ( transformTable[ numberString[i] ] ) {
+                                       convertedNumber += transformTable[numberString[i]];
+                               } else {
+                                       convertedNumber += numberString[i];
+                               }
+                       }
+                       return integer ? parseInt( convertedNumber, 10 ) : convertedNumber;
+               },
+
+               /**
+                * Get the  digit transform table for current UI language.
+                * @return {Object|Array}
+                */
+               getDigitTransformTable: function () {
+                       return mw.language.getData( mw.config.get( 'wgUserLanguage' ),
+                               'digitTransformTable' ) || [];
+               },
+
+               /**
+                * Get the  separator transform table for current UI language.
+                * @return {Object|Array}
+                */
+               getSeparatorTransformTable: function () {
+                       return mw.language.getData( mw.config.get( 'wgUserLanguage' ),
+                               'separatorTransformTable' ) || [];
+               },
+
+               /**
+                * Apply pattern to format value as a string.
+                *
+                * Using patterns from [Unicode TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns).
+                *
+                * @param {number} value
+                * @param {string} pattern Pattern string as described by Unicode TR35
+                * @throws {Error} If unable to find a number expression in `pattern`.
+                * @return {string}
+                */
+               commafy: function ( value, pattern ) {
+                       var numberPattern,
+                               transformTable = mw.language.getSeparatorTransformTable(),
+                               group = transformTable[','] || ',',
+                               numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/, // not precise, but good enough
+                               decimal = transformTable['.'] || '.',
+                               patternList = pattern.split( ';' ),
+                               positivePattern = patternList[0];
+
+                       pattern = patternList[ ( value < 0 ) ? 1 : 0] || ( '-' + positivePattern );
+                       numberPattern = positivePattern.match( numberPatternRE );
+
+                       if ( !numberPattern ) {
+                               throw new Error( 'unable to find a number expression in pattern: ' + pattern );
+                       }
+
+                       return pattern.replace( numberPatternRE, commafyNumber( value, numberPattern[0], {
+                               decimal: decimal,
+                               group: group
+                       } ) );
+               }
+
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.less/mediawiki.mixins.animation.less b/resources/src/mediawiki.less/mediawiki.mixins.animation.less
new file mode 100644 (file)
index 0000000..ec3cddc
--- /dev/null
@@ -0,0 +1,12 @@
+.animation (...) {
+       -webkit-animation: @arguments;
+       -moz-animation: @arguments;
+       -o-animation: @arguments;
+       animation: @arguments;
+}
+
+.transform-rotate (@deg) {
+       -webkit-transform: rotate(@deg);
+       -moz-transform: rotate(@deg);
+       transform: rotate(@deg);
+}
\ No newline at end of file
diff --git a/resources/src/mediawiki.less/mediawiki.mixins.less b/resources/src/mediawiki.less/mediawiki.mixins.less
new file mode 100644 (file)
index 0000000..80b68cc
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * Common LESS mixin library for MediaWiki
+ *
+ * By default the folder containing this file is included in $wgResourceLoaderLESSImportPaths,
+ * which makes this file importable by all less files via '@import "mediawiki.mixins";'.
+ *
+ * The mixins included below are considered a public interface for MediaWiki extensions.
+ * The signatures of parametrized mixins should be kept as stable as possible.
+ *
+ * See <http://lesscss.org/#-mixins> for more information about how to write mixins.
+ */
+
+.background-image(@url) when (embeddable(@url)) {
+       background-image: embed(@url);
+       background-image: url(@url)!ie;
+}
+
+.background-image(@url) when not (embeddable(@url)) {
+       background-image: url(@url);
+}
+
+.vertical-gradient ( @startColor: gray, @endColor: white, @startPos: 0, @endPos: 100% ) {
+       background-color: @endColor;
+       background-image: -moz-linear-gradient( top, @startColor @startPos, @endColor @endPos ); // Firefox 3.6+
+       background-image: -webkit-gradient( linear, left top, left bottom, color-stop( @startPos, @startColor ), color-stop( @endPos, @endColor ) ); // Safari 4+, Chrome 2+
+       background-image: -webkit-linear-gradient( top, @startColor @startPos, @endColor @endPos ); // Safari 5.1+, Chrome 10+
+       background-image: linear-gradient( @startColor @startPos, @endColor @endPos ); // Standard
+}
+
+/* Note gzip compression means that it is okay to embed twice */
+/* http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique */
+.background-image-svg(@svg, @fallback) {
+       background-image: url(@fallback);
+       /* SVG support using a transparent gradient to guarantee cross-browser
+        * compatibility (browsers able to understand gradient syntax support also SVG) */
+       /* @embed */ background-image: -webkit-linear-gradient(transparent, transparent), url(@svg);
+       /* @embed */ background-image: linear-gradient(transparent, transparent), url(@svg);
+}
+
+/* Caution: Does not support localisable images */
+.list-style-image(@url) when (embeddable(@url)) {
+       list-style-image: embed(@url);
+       list-style-image: url(@url)!ie;
+}
+
+.list-style-image(@url) when not (embeddable(@url)) {
+       list-style-image: url(@url);
+}
+
+.transition(@string) {
+       -webkit-transition: @string;
+       transition: @string;
+}
diff --git a/resources/src/mediawiki.less/mediawiki.mixins.rotation.less b/resources/src/mediawiki.less/mediawiki.mixins.rotation.less
new file mode 100644 (file)
index 0000000..e28b333
--- /dev/null
@@ -0,0 +1,33 @@
+// This is a separate file because importing the mixin causes
+// the keyframes blocks to be included in the output, regardless
+// of whether .rotation is used.
+@import "mediawiki.mixins.animation";
+
+.rotate-frames () {
+       from {
+               .transform-rotate(0deg);
+       }
+       to {
+               .transform-rotate(360deg);
+       }
+}
+
+@-webkit-keyframes rotate {
+       .rotate-frames;
+}
+
+@-moz-keyframes rotate {
+       .rotate-frames;
+}
+
+@-o-keyframes rotate {
+       .rotate-frames;
+}
+
+@keyframes rotate {
+       .rotate-frames;
+}
+
+.rotation( @time ) {
+       .animation(rotate, @time, infinite, linear);
+}
diff --git a/resources/src/mediawiki.libs/CLDRPluralRuleParser.js b/resources/src/mediawiki.libs/CLDRPluralRuleParser.js
new file mode 100644 (file)
index 0000000..83c2524
--- /dev/null
@@ -0,0 +1,475 @@
+/* This is CLDRPluralRuleParser v1.1, ported to MediaWiki ResourceLoader */
+
+/**
+* CLDRPluralRuleParser.js
+* A parser engine for CLDR plural rules.
+*
+* Copyright 2012 GPLV3+, Santhosh Thottingal
+*
+* @version 0.1.0-alpha
+* @source https://github.com/santhoshtr/CLDRPluralRuleParser
+* @author Santhosh Thottingal <santhosh.thottingal@gmail.com>
+* @author Timo Tijhof
+* @author Amir Aharoni
+*/
+
+( function ( mw ) {
+/**
+ * Evaluates a plural rule in CLDR syntax for a number
+ * @param {string} rule
+ * @param {integer} number
+ * @return {boolean} true if evaluation passed, false if evaluation failed.
+ */
+
+function pluralRuleParser(rule, number) {
+       /*
+       Syntax: see http://unicode.org/reports/tr35/#Language_Plural_Rules
+       -----------------------------------------------------------------
+       condition     = and_condition ('or' and_condition)*
+               ('@integer' samples)?
+               ('@decimal' samples)?
+       and_condition = relation ('and' relation)*
+       relation      = is_relation | in_relation | within_relation
+       is_relation   = expr 'is' ('not')? value
+       in_relation   = expr (('not')? 'in' | '=' | '!=') range_list
+       within_relation = expr ('not')? 'within' range_list
+       expr          = operand (('mod' | '%') value)?
+       operand       = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
+       range_list    = (range | value) (',' range_list)*
+       value         = digit+
+       digit         = 0|1|2|3|4|5|6|7|8|9
+       range         = value'..'value
+       samples       = sampleRange (',' sampleRange)* (',' ('…'|'...'))?
+       sampleRange   = decimalValue '~' decimalValue
+       decimalValue  = value ('.' value)?
+       */
+
+       // we don't evaluate the samples section of the rule. Ignore it.
+       rule = rule.split('@')[0].replace(/^\s*/, '').replace(/\s*$/, '');
+
+       if (!rule.length) {
+               // empty rule or 'other' rule.
+               return true;
+       }
+       // Indicates current position in the rule as we parse through it.
+       // Shared among all parsing functions below.
+       var pos = 0,
+               operand,
+               expression,
+               relation,
+               result,
+               whitespace = makeRegexParser(/^\s+/),
+               value = makeRegexParser(/^\d+/),
+               _n_ = makeStringParser('n'),
+               _i_ = makeStringParser('i'),
+               _f_ = makeStringParser('f'),
+               _t_ = makeStringParser('t'),
+               _v_ = makeStringParser('v'),
+               _w_ = makeStringParser('w'),
+               _is_ = makeStringParser('is'),
+               _isnot_ = makeStringParser('is not'),
+               _isnot_sign_ = makeStringParser('!='),
+               _equal_ = makeStringParser('='),
+               _mod_ = makeStringParser('mod'),
+               _percent_ = makeStringParser('%'),
+               _not_ = makeStringParser('not'),
+               _in_ = makeStringParser('in'),
+               _within_ = makeStringParser('within'),
+               _range_ = makeStringParser('..'),
+               _comma_ = makeStringParser(','),
+               _or_ = makeStringParser('or'),
+               _and_ = makeStringParser('and');
+
+       function debug() {
+               // console.log.apply(console, arguments);
+       }
+
+       debug('pluralRuleParser', rule, number);
+
+       // Try parsers until one works, if none work return null
+
+       function choice(parserSyntax) {
+               return function() {
+                       for (var i = 0; i < parserSyntax.length; i++) {
+                               var result = parserSyntax[i]();
+                               if (result !== null) {
+                                       return result;
+                               }
+                       }
+                       return null;
+               };
+       }
+
+       // Try several parserSyntax-es in a row.
+       // All must succeed; otherwise, return null.
+       // This is the only eager one.
+
+       function sequence(parserSyntax) {
+               var originalPos = pos;
+               var result = [];
+               for (var i = 0; i < parserSyntax.length; i++) {
+                       var res = parserSyntax[i]();
+                       if (res === null) {
+                               pos = originalPos;
+                               return null;
+                       }
+                       result.push(res);
+               }
+               return result;
+       }
+
+       // Run the same parser over and over until it fails.
+       // Must succeed a minimum of n times; otherwise, return null.
+
+       function nOrMore(n, p) {
+               return function() {
+                       var originalPos = pos;
+                       var result = [];
+                       var parsed = p();
+                       while (parsed !== null) {
+                               result.push(parsed);
+                               parsed = p();
+                       }
+                       if (result.length < n) {
+                               pos = originalPos;
+                               return null;
+                       }
+                       return result;
+               };
+       }
+
+       // Helpers -- just make parserSyntax out of simpler JS builtin types
+       function makeStringParser(s) {
+               var len = s.length;
+               return function() {
+                       var result = null;
+                       if (rule.substr(pos, len) === s) {
+                               result = s;
+                               pos += len;
+                       }
+
+                       return result;
+               };
+       }
+
+       function makeRegexParser(regex) {
+               return function() {
+                       var matches = rule.substr(pos).match(regex);
+                       if (matches === null) {
+                               return null;
+                       }
+                       pos += matches[0].length;
+                       return matches[0];
+               };
+       }
+
+       /*
+        * integer digits of n.
+        */
+       function i() {
+               var result = _i_();
+               if (result === null) {
+                       debug(' -- failed i', parseInt(number, 10));
+                       return result;
+               }
+               result = parseInt(number, 10);
+               debug(' -- passed i ', result);
+               return result;
+       }
+
+       /*
+        * absolute value of the source number (integer and decimals).
+        */
+       function n() {
+               var result = _n_();
+               if (result === null) {
+                       debug(' -- failed n ', number);
+                       return result;
+               }
+               result = parseFloat(number, 10);
+               debug(' -- passed n ', result);
+               return result;
+       }
+
+       /*
+        * visible fractional digits in n, with trailing zeros.
+        */
+       function f() {
+               var result = _f_();
+               if (result === null) {
+                       debug(' -- failed f ', number);
+                       return result;
+               }
+               result = (number + '.').split('.')[1] || 0;
+               debug(' -- passed f ', result);
+               return result;
+       }
+
+       /*
+        * visible fractional digits in n, without trailing zeros.
+        */
+       function t() {
+               var result = _t_();
+               if (result === null) {
+                       debug(' -- failed t ', number);
+                       return result;
+               }
+               result = (number + '.').split('.')[1].replace(/0$/, '') || 0;
+               debug(' -- passed t ', result);
+               return result;
+       }
+
+       /*
+        * number of visible fraction digits in n, with trailing zeros.
+        */
+       function v() {
+               var result = _v_();
+               if (result === null) {
+                       debug(' -- failed v ', number);
+                       return result;
+               }
+               result = (number + '.').split('.')[1].length || 0;
+               debug(' -- passed v ', result);
+               return result;
+       }
+
+       /*
+        * number of visible fraction digits in n, without trailing zeros.
+        */
+       function w() {
+               var result = _w_();
+               if (result === null) {
+                       debug(' -- failed w ', number);
+                       return result;
+               }
+               result = (number + '.').split('.')[1].replace(/0$/, '').length || 0;
+               debug(' -- passed w ', result);
+               return result;
+       }
+
+       // operand       = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
+       operand = choice([n, i, f, t, v, w]);
+
+       // expr          = operand (('mod' | '%') value)?
+       expression = choice([mod, operand]);
+
+       function mod() {
+               var result = sequence([operand, whitespace, choice([_mod_, _percent_]), whitespace, value]);
+               if (result === null) {
+                       debug(' -- failed mod');
+                       return null;
+               }
+               debug(' -- passed ' + parseInt(result[0], 10) + ' ' + result[2] + ' ' + parseInt(result[4], 10));
+               return parseInt(result[0], 10) % parseInt(result[4], 10);
+       }
+
+       function not() {
+               var result = sequence([whitespace, _not_]);
+               if (result === null) {
+                       debug(' -- failed not');
+                       return null;
+               }
+
+               return result[1];
+       }
+
+       // is_relation   = expr 'is' ('not')? value
+       function is() {
+               var result = sequence([expression, whitespace, choice([_is_]), whitespace, value]);
+               if (result !== null) {
+                       debug(' -- passed is : ' + result[0] + ' == ' + parseInt(result[4], 10));
+                       return result[0] === parseInt(result[4], 10);
+               }
+               debug(' -- failed is');
+               return null;
+       }
+
+       // is_relation   = expr 'is' ('not')? value
+       function isnot() {
+               var result = sequence([expression, whitespace, choice([_isnot_, _isnot_sign_]), whitespace, value]);
+               if (result !== null) {
+                       debug(' -- passed isnot: ' + result[0] + ' != ' + parseInt(result[4], 10));
+                       return result[0] !== parseInt(result[4], 10);
+               }
+               debug(' -- failed isnot');
+               return null;
+       }
+
+       function not_in() {
+               var result = sequence([expression, whitespace, _isnot_sign_, whitespace, rangeList]);
+               if (result !== null) {
+                       debug(' -- passed not_in: ' + result[0] + ' != ' + result[4]);
+                       var range_list = result[4];
+                       for (var i = 0; i < range_list.length; i++) {
+                               if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) {
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+               debug(' -- failed not_in');
+               return null;
+       }
+
+       // range_list    = (range | value) (',' range_list)*
+       function rangeList() {
+               var result = sequence([choice([range, value]), nOrMore(0, rangeTail)]);
+               var resultList = [];
+               if (result !== null) {
+                       resultList = resultList.concat(result[0]);
+                       if (result[1][0]) {
+                               resultList = resultList.concat(result[1][0]);
+                       }
+                       return resultList;
+               }
+               debug(' -- failed rangeList');
+               return null;
+       }
+
+       function rangeTail() {
+               // ',' range_list
+               var result = sequence([_comma_, rangeList]);
+               if (result !== null) {
+                       return result[1];
+               }
+               debug(' -- failed rangeTail');
+               return null;
+       }
+
+       // range         = value'..'value
+
+       function range() {
+               var i;
+               var result = sequence([value, _range_, value]);
+               if (result !== null) {
+                       debug(' -- passed range');
+                       var array = [];
+                       var left = parseInt(result[0], 10);
+                       var right = parseInt(result[2], 10);
+                       for (i = left; i <= right; i++) {
+                               array.push(i);
+                       }
+                       return array;
+               }
+               debug(' -- failed range');
+               return null;
+       }
+
+       function _in() {
+               // in_relation   = expr ('not')? 'in' range_list
+               var result = sequence([expression, nOrMore(0, not), whitespace, choice([_in_, _equal_]), whitespace, rangeList]);
+               if (result !== null) {
+                       debug(' -- passed _in:' + result);
+                       var range_list = result[5];
+                       for (var i = 0; i < range_list.length; i++) {
+                               if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) {
+                                       return (result[1][0] !== 'not');
+                               }
+                       }
+                       return (result[1][0] === 'not');
+               }
+               debug(' -- failed _in ');
+               return null;
+       }
+
+       /*
+        * The difference between in and within is that in only includes integers in the specified range,
+        * while within includes all values.
+        */
+
+       function within() {
+               // within_relation = expr ('not')? 'within' range_list
+               var result = sequence([expression, nOrMore(0, not), whitespace, _within_, whitespace, rangeList]);
+               if (result !== null) {
+                       debug(' -- passed within');
+                       var range_list = result[5];
+                       if ((result[0] >= parseInt(range_list[0], 10)) &&
+                               (result[0] < parseInt(range_list[range_list.length - 1], 10))) {
+                               return (result[1][0] !== 'not');
+                       }
+                       return (result[1][0] === 'not');
+               }
+               debug(' -- failed within ');
+               return null;
+       }
+
+       // relation      = is_relation | in_relation | within_relation
+       relation = choice([is, not_in, isnot, _in, within]);
+
+       // and_condition = relation ('and' relation)*
+       function and() {
+               var result = sequence([relation, nOrMore(0, andTail)]);
+               if (result) {
+                       if (!result[0]) {
+                               return false;
+                       }
+                       for (var i = 0; i < result[1].length; i++) {
+                               if (!result[1][i]) {
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+               debug(' -- failed and');
+               return null;
+       }
+
+       // ('and' relation)*
+       function andTail() {
+               var result = sequence([whitespace, _and_, whitespace, relation]);
+               if (result !== null) {
+                       debug(' -- passed andTail' + result);
+                       return result[3];
+               }
+               debug(' -- failed andTail');
+               return null;
+
+       }
+       //  ('or' and_condition)*
+       function orTail() {
+               var result = sequence([whitespace, _or_, whitespace, and]);
+               if (result !== null) {
+                       debug(' -- passed orTail: ' + result[3]);
+                       return result[3];
+               }
+               debug(' -- failed orTail');
+               return null;
+
+       }
+
+       // condition     = and_condition ('or' and_condition)*
+       function condition() {
+               var result = sequence([and, nOrMore(0, orTail)]);
+               if (result) {
+                       for (var i = 0; i < result[1].length; i++) {
+                               if (result[1][i]) {
+                                       return true;
+                               }
+                       }
+                       return result[0];
+
+               }
+               return false;
+       }
+
+       result = condition();
+       /*
+        * For success, the pos must have gotten to the end of the rule
+        * and returned a non-null.
+        * n.b. This is part of language infrastructure, so we do not throw an internationalizable message.
+        */
+       if (result === null) {
+               throw new Error('Parse error at position ' + pos.toString() + ' for rule: ' + rule);
+       }
+
+       if (pos !== rule.length) {
+               debug('Warning: Rule not parsed completely. Parser stopped at ' + rule.substr(0, pos) + ' for rule: ' + rule);
+       }
+
+       return result;
+}
+
+/* pluralRuleParser ends here */
+mw.libs.pluralRuleParser = pluralRuleParser;
+
+} )( mediaWiki );
diff --git a/resources/src/mediawiki.libs/mediawiki.libs.jpegmeta.js b/resources/src/mediawiki.libs/mediawiki.libs.jpegmeta.js
new file mode 100644 (file)
index 0000000..b3ed88c
--- /dev/null
@@ -0,0 +1,737 @@
+/**
+ * This is JsJpegMeta v1.0
+ * From: https://code.google.com/p/jsjpegmeta/downloads/list
+ * From: https://github.com/bennoleslie/jsjpegmeta/blob/v1.0.0/jpegmeta.js
+ *
+ * Ported to MediaWiki ResourceLoader by Bryan Tong Minh
+ * Changes:
+ * - Add closure.
+ * - Add this.JpegMeta assignment to expose it as global.
+ * - Add mw.libs.jpegmeta wrapper.
+ */
+
+( function () {
+       /*
+       Copyright (c) 2009 Ben Leslie
+       
+       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.
+       */
+       
+       /*
+        This JavaScript library is used to parse meta-data from files 
+        with mime-type image/jpeg.
+       
+        Include it with something like:
+       
+          <script type="text/javascript" src="jpegmeta.js"></script>
+       
+        This adds a single 'module' object called 'JpegMeta' to the global
+        namespace.
+       
+        Public Functions
+        ----------------
+        JpegMeta.parseNum - parse unsigned integers from binary data
+        JpegMeta.parseSnum - parse signed integers from binary data
+       
+        Public Classes
+        --------------
+        JpegMeta.Rational - A rational number class
+        JpegMeta.JfifSegment
+        JpegMeta.ExifSegment
+        JpegMeta.JpegFile - Primary class for Javascript parsing
+       */
+
+       var JpegMeta = {};
+       // MediaWiki: Expose as global
+       this.JpegMeta = JpegMeta;
+       
+       /* 
+          parse an unsigned number of size bytes at offset in some binary string data.
+          If endian
+          is "<" parse the data as little endian, if endian
+          is ">" parse as big-endian.
+       */
+       JpegMeta.parseNum = function parseNum(endian, data, offset, size) {
+           var i;
+           var ret;
+           var big_endian = (endian === ">");
+           if (offset === undefined) offset = 0;
+           if (size === undefined) size = data.length - offset;
+           for (big_endian ? i = offset : i = offset + size - 1; 
+                big_endian ? i < offset + size : i >= offset; 
+                big_endian ? i++ : i--) {
+               ret <<= 8;
+               ret += data.charCodeAt(i);
+           }
+           return ret;
+       };
+       
+       /* 
+          parse an signed number of size bytes at offset in some binary string data.
+          If endian
+          is "<" parse the data as little endian, if endian
+          is ">" parse as big-endian.
+       */
+       JpegMeta.parseSnum = function parseSnum(endian, data, offset, size) {
+           var i;
+           var ret;
+           var neg;
+           var big_endian = (endian === ">");
+           if (offset === undefined) offset = 0;
+           if (size === undefined) size = data.length - offset;
+           for (big_endian ? i = offset : i = offset + size - 1; 
+                big_endian ? i < offset + size : i >= offset; 
+                big_endian ? i++ : i--) {
+               if (neg === undefined) {
+                   /* Negative if top bit is set */
+                   neg = (data.charCodeAt(i) & 0x80) === 0x80;
+               }
+               ret <<= 8;
+               /* If it is negative we invert the bits */
+               ret += neg ? ~data.charCodeAt(i) & 0xff: data.charCodeAt(i);
+           }
+           if (neg) {
+               /* If it is negative we do two's complement */
+               ret += 1;
+               ret *= -1;
+           }
+           return ret;
+       };
+       
+       /* Rational number class */
+       JpegMeta.Rational = function Rational(num, den)
+       {
+           this.num = num;
+           this.den = den || 1;
+           return this;
+       };
+       
+       /* Rational number methods */
+       JpegMeta.Rational.prototype.toString = function toString() {
+           if (this.num === 0) {
+               return "" + this.num;
+           }
+           if (this.den === 1) {
+               return "" + this.num;
+           }
+           if (this.num === 1) {
+               return this.num + " / " + this.den;
+           }
+           return this.num / this.den; // + "/" + this.den;
+       };
+       
+       JpegMeta.Rational.prototype.asFloat = function asFloat() {
+           return this.num / this.den;
+       };
+       
+       /* MetaGroup class */
+       JpegMeta.MetaGroup = function MetaGroup(fieldName, description) {
+           this.fieldName = fieldName;
+           this.description = description;
+           this.metaProps = {};
+           return this;
+       };
+       
+       JpegMeta.MetaGroup.prototype._addProperty = function _addProperty(fieldName, description, value) {
+           var property = new JpegMeta.MetaProp(fieldName, description, value);
+           this[property.fieldName] = property;
+           this.metaProps[property.fieldName] = property;
+       };
+       
+       JpegMeta.MetaGroup.prototype.toString = function toString() {
+           return "[MetaGroup " + this.description + "]";
+       };
+
+       /* MetaProp class */
+       JpegMeta.MetaProp = function MetaProp(fieldName, description, value) {
+           this.fieldName = fieldName;
+           this.description = description;
+           this.value = value;
+           return this;
+       };
+       
+       JpegMeta.MetaProp.prototype.toString = function toString() {
+           return "" + this.value;
+       };
+
+       /* JpegFile class */
+       JpegMeta.JpegFile = function JpegFile(binary_data, filename) {
+           /* Change this to EOI if we want to parse. */
+           var break_segment = this._SOS;
+           
+           this.metaGroups = {};
+           this._binary_data = binary_data;
+           this.filename = filename;
+           
+           /* Go through and parse. */
+           var pos = 0;
+           var pos_start_of_segment = 0;
+           var delim;
+           var mark;
+           var _mark;
+           var segsize;
+           var headersize;
+           var mark_code;
+           var mark_fn;
+       
+           /* Check to see if this looks like a JPEG file */
+           if (this._binary_data.slice(0, 2) !== this._SOI_MARKER) {
+               throw new Error("Doesn't look like a JPEG file. First two bytes are " + 
+                               this._binary_data.charCodeAt(0) + "," + 
+                               this._binary_data.charCodeAt(1) + ".");
+           }
+           
+           pos += 2;
+           
+           while (pos < this._binary_data.length) {
+               delim = this._binary_data.charCodeAt(pos++);
+               mark = this._binary_data.charCodeAt(pos++);
+               
+               pos_start_of_segment = pos;
+               
+               if (delim != this._DELIM) {
+                   break;
+               }
+               
+               if (mark === break_segment) {
+                   break;
+               }
+               
+               headersize = JpegMeta.parseNum(">", this._binary_data, pos, 2);
+               
+               /* Find the end */
+               pos += headersize;
+               while (pos < this._binary_data.length) {
+                   delim = this._binary_data.charCodeAt(pos++);
+                   if (delim == this._DELIM) {
+                       _mark = this._binary_data.charCodeAt(pos++);
+                       if (_mark != 0x0) {
+                           pos -= 2;
+                           break;
+                       }
+                   }
+               }
+               
+               segsize = pos - pos_start_of_segment;
+               
+               if (this._markers[mark]) {
+                   mark_code = this._markers[mark][0];
+                   mark_fn = this._markers[mark][1];
+               } else {
+                   mark_code = "UNKN";
+                   mark_fn = undefined;
+               }
+               
+               if (mark_fn) {
+                   this[mark_fn](mark, pos_start_of_segment + 2);
+               }
+               
+           }
+           
+           if (this.general === undefined) {
+               throw Error("Invalid JPEG file.");
+           }
+           
+           return this;
+       };
+       
+       this.JpegMeta.JpegFile.prototype.toString = function () {
+           return "[JpegFile " + this.filename + " " + 
+               this.general.type + " " + 
+               this.general.pixelWidth + "x" + 
+               this.general.pixelHeight +
+               " Depth: " + this.general.depth + "]";
+       };
+       
+       /* Some useful constants */
+       this.JpegMeta.JpegFile.prototype._SOI_MARKER = '\xff\xd8';
+       this.JpegMeta.JpegFile.prototype._DELIM = 0xff;
+       this.JpegMeta.JpegFile.prototype._EOI = 0xd9;
+       this.JpegMeta.JpegFile.prototype._SOS = 0xda;
+       
+       this.JpegMeta.JpegFile.prototype._sofHandler = function _sofHandler (mark, pos) {
+           if (this.general !== undefined) {
+               throw Error("Unexpected multiple-frame image");
+           }
+       
+           this._addMetaGroup("general", "General");
+           this.general._addProperty("depth", "Depth", JpegMeta.parseNum(">", this._binary_data, pos, 1));
+           this.general._addProperty("pixelHeight", "Pixel Height", JpegMeta.parseNum(">", this._binary_data, pos + 1, 2));
+           this.general._addProperty("pixelWidth", "Pixel Width",JpegMeta.parseNum(">", this._binary_data, pos + 3, 2));
+           this.general._addProperty("type", "Type", this._markers[mark][2]);
+       };
+       
+       /* JFIF idents */
+       this.JpegMeta.JpegFile.prototype._JFIF_IDENT = "JFIF\x00";
+       this.JpegMeta.JpegFile.prototype._JFXX_IDENT = "JFXX\x00";
+       
+       /* Exif idents */
+       this.JpegMeta.JpegFile.prototype._EXIF_IDENT = "Exif\x00";
+       
+       /* TIFF types */
+       this.JpegMeta.JpegFile.prototype._types = {
+           /* The format is identifier : ["type name", type_size_in_bytes ] */
+           1 : ["BYTE", 1],
+           2 : ["ASCII", 1],
+           3 : ["SHORT", 2],
+           4 : ["LONG", 4],
+           5 : ["RATIONAL", 8],
+           6 : ["SBYTE", 1],
+           7 : ["UNDEFINED", 1],
+           8 : ["SSHORT", 2],
+           9 : ["SLONG", 4],
+           10 : ["SRATIONAL", 8],
+           11 : ["FLOAT", 4],
+           12 : ["DOUBLE", 8]
+       };
+       
+       this.JpegMeta.JpegFile.prototype._tifftags = {
+           /* A. Tags relating to image data structure */
+           256 : ["Image width", "ImageWidth"],
+           257 : ["Image height", "ImageLength"],
+           258 : ["Number of bits per component", "BitsPerSample"],
+           259 : ["Compression scheme", "Compression", 
+                  {1 : "uncompressed", 6 : "JPEG compression" }],
+           262 : ["Pixel composition", "PhotmetricInerpretation",
+                  {2 : "RGB", 6 : "YCbCr"}],
+           274 : ["Orientation of image", "Orientation",
+                  /* FIXME: Check the mirror-image / reverse encoding and rotation */
+                  {1 : "Normal", 2 : "Reverse?", 
+                   3 : "Upside-down", 4 : "Upside-down Reverse",
+                   5 : "90 degree CW", 6 : "90 degree CW reverse",
+                   7 : "90 degree CCW", 8 : "90 degree CCW reverse"}],
+           277 : ["Number of components", "SamplesPerPixel"],
+           284 : ["Image data arrangement", "PlanarConfiguration",
+                  {1 : "chunky format", 2 : "planar format"}],
+           530 : ["Subsampling ratio of Y to C", "YCbCrSubSampling"],
+           531 : ["Y and C positioning", "YCbCrPositioning",
+                  {1 : "centered", 2 : "co-sited"}],
+           282 : ["X Resolution", "XResolution"],
+           283 : ["Y Resolution", "YResolution"],
+           296 : ["Resolution Unit", "ResolutionUnit",
+                  {2 : "inches", 3 : "centimeters"}],
+           /* B. Tags realting to recording offset */
+           273 : ["Image data location", "StripOffsets"],
+           278 : ["Number of rows per strip", "RowsPerStrip"],
+           279 : ["Bytes per compressed strip", "StripByteCounts"],
+           513 : ["Offset to JPEG SOI", "JPEGInterchangeFormat"],
+           514 : ["Bytes of JPEG Data", "JPEGInterchangeFormatLength"],
+           /* C. Tags relating to image data characteristics */
+           301 : ["Transfer function", "TransferFunction"],
+           318 : ["White point chromaticity", "WhitePoint"],
+           319 : ["Chromaticities of primaries", "PrimaryChromaticities"],
+           529 : ["Color space transformation matrix coefficients", "YCbCrCoefficients"],
+           532 : ["Pair of black and white reference values", "ReferenceBlackWhite"],
+           /* D. Other tags */
+           306 : ["Date and time", "DateTime"],
+           270 : ["Image title", "ImageDescription"],
+           271 : ["Make", "Make"],
+           272 : ["Model", "Model"],
+           305 : ["Software", "Software"],
+           315 : ["Person who created the image", "Artist"],
+           316 : ["Host Computer", "HostComputer"],
+           33432 : ["Copyright holder", "Copyright"],
+           
+           34665 : ["Exif tag", "ExifIfdPointer"],
+           34853 : ["GPS tag", "GPSInfoIfdPointer"]
+       };
+       
+       this.JpegMeta.JpegFile.prototype._exiftags = {
+           /* Tag Support Levels (2) - 0th IFX Exif Private Tags */
+           /* A. Tags Relating to Version */
+           36864 : ["Exif Version", "ExifVersion"],
+           40960 : ["FlashPix Version", "FlashpixVersion"],
+           
+           /* B. Tag Relating to Image Data Characteristics */
+           40961 : ["Color Space", "ColorSpace"],
+           
+           /* C. Tags Relating to Image Configuration */
+           37121 : ["Meaning of each component", "ComponentsConfiguration"],
+           37122 : ["Compressed Bits Per Pixel", "CompressedBitsPerPixel"],
+           40962 : ["Pixel X Dimension", "PixelXDimension"],
+           40963 : ["Pixel Y Dimension", "PixelYDimension"],
+           
+           /* D. Tags Relating to User Information */
+           37500 : ["Manufacturer notes", "MakerNote"],
+           37510 : ["User comments", "UserComment"],
+           
+           /* E. Tag Relating to Related File Information */
+           40964 : ["Related audio file", "RelatedSoundFile"],
+           
+           /* F. Tags Relating to Date and Time */
+           36867 : ["Date Time Original", "DateTimeOriginal"],
+           36868 : ["Date Time Digitized", "DateTimeDigitized"],
+           37520 : ["DateTime subseconds", "SubSecTime"],
+           37521 : ["DateTimeOriginal subseconds", "SubSecTimeOriginal"],
+           37522 : ["DateTimeDigitized subseconds", "SubSecTimeDigitized"],
+           
+           /* G. Tags Relating to Picture-Taking Conditions */
+           33434 : ["Exposure time", "ExposureTime"],
+           33437 : ["FNumber", "FNumber"],
+           34850 : ["Exposure program", "ExposureProgram"],
+           34852 : ["Spectral sensitivity", "SpectralSensitivity"],
+           34855 : ["ISO Speed Ratings", "ISOSpeedRatings"],
+           34856 : ["Optoelectric coefficient", "OECF"],
+           37377 : ["Shutter Speed",  "ShutterSpeedValue"],
+           37378 : ["Aperture Value", "ApertureValue"],
+           37379 : ["Brightness", "BrightnessValue"],
+           37380 : ["Exposure Bias Value", "ExposureBiasValue"],
+           37381 : ["Max Aperture Value", "MaxApertureValue"],
+           37382 : ["Subject Distance", "SubjectDistance"],
+           37383 : ["Metering Mode", "MeteringMode"],
+           37384 : ["Light Source", "LightSource"],
+           37385 : ["Flash", "Flash"],
+           37386 : ["Focal Length", "FocalLength"],
+           37396 : ["Subject Area", "SubjectArea"],
+           41483 : ["Flash Energy", "FlashEnergy"],
+           41484 : ["Spatial Frequency Response", "SpatialFrequencyResponse"],
+           41486 : ["Focal Plane X Resolution", "FocalPlaneXResolution"],
+           41487 : ["Focal Plane Y Resolution", "FocalPlaneYResolution"],
+           41488 : ["Focal Plane Resolution Unit", "FocalPlaneResolutionUnit"],
+           41492 : ["Subject Location", "SubjectLocation"],
+           41493 : ["Exposure Index", "ExposureIndex"],
+           41495 : ["Sensing Method", "SensingMethod"],
+           41728 : ["File Source", "FileSource"],
+           41729 : ["Scene Type", "SceneType"],
+           41730 : ["CFA Pattern", "CFAPattern"],
+           41985 : ["Custom Rendered", "CustomRendered"],
+           41986 : ["Exposure Mode", "Exposure Mode"],
+           41987 : ["White Balance", "WhiteBalance"],
+           41988 : ["Digital Zoom Ratio", "DigitalZoomRatio"],
+           41990 : ["Scene Capture Type", "SceneCaptureType"],
+           41991 : ["Gain Control", "GainControl"],
+           41992 : ["Contrast", "Contrast"],
+           41993 : ["Saturation", "Saturation"],
+           41994 : ["Sharpness", "Sharpness"],
+           41995 : ["Device settings description", "DeviceSettingDescription"],
+           41996 : ["Subject distance range", "SubjectDistanceRange"],
+           
+           /* H. Other Tags */
+           42016 : ["Unique image ID", "ImageUniqueID"],
+           
+           40965 : ["Interoperability tag", "InteroperabilityIFDPointer"]
+       };
+       
+       this.JpegMeta.JpegFile.prototype._gpstags = {
+           /* A. Tags Relating to GPS */
+           0 : ["GPS tag version", "GPSVersionID"],
+           1 : ["North or South Latitude", "GPSLatitudeRef"],
+           2 : ["Latitude", "GPSLatitude"],
+           3 : ["East or West Longitude", "GPSLongitudeRef"],
+           4 : ["Longitude", "GPSLongitude"],
+           5 : ["Altitude reference", "GPSAltitudeRef"],
+           6 : ["Altitude", "GPSAltitude"],
+           7 : ["GPS time (atomic clock)", "GPSTimeStamp"],
+           8 : ["GPS satellites usedd for measurement", "GPSSatellites"],
+           9 : ["GPS receiver status", "GPSStatus"],
+           10 : ["GPS mesaurement mode", "GPSMeasureMode"],
+           11 : ["Measurement precision", "GPSDOP"],
+           12 : ["Speed unit", "GPSSpeedRef"],
+           13 : ["Speed of GPS receiver", "GPSSpeed"],
+           14 : ["Reference for direction of movement", "GPSTrackRef"],
+           15 : ["Direction of movement", "GPSTrack"],
+           16 : ["Reference for direction of image", "GPSImgDirectionRef"],
+           17 : ["Direction of image", "GPSImgDirection"],
+           18 : ["Geodetic survey data used", "GPSMapDatum"],
+           19 : ["Reference for latitude of destination", "GPSDestLatitudeRef"],
+           20 : ["Latitude of destination", "GPSDestLatitude"],
+           21 : ["Reference for longitude of destination", "GPSDestLongitudeRef"],
+           22 : ["Longitude of destination", "GPSDestLongitude"],
+           23 : ["Reference for bearing of destination", "GPSDestBearingRef"],
+           24 : ["Bearing of destination", "GPSDestBearing"],
+           25 : ["Reference for distance to destination", "GPSDestDistanceRef"],
+           26 : ["Distance to destination", "GPSDestDistance"],
+           27 : ["Name of GPS processing method", "GPSProcessingMethod"],
+           28 : ["Name of GPS area", "GPSAreaInformation"],
+           29 : ["GPS Date", "GPSDateStamp"],
+           30 : ["GPS differential correction", "GPSDifferential"]
+       };
+
+       this.JpegMeta.JpegFile.prototype._markers = {
+           /* Start Of Frame markers, non-differential, Huffman coding */
+           0xc0: ["SOF0", "_sofHandler", "Baseline DCT"],
+           0xc1: ["SOF1", "_sofHandler", "Extended sequential DCT"],
+           0xc2: ["SOF2", "_sofHandler", "Progressive DCT"],
+           0xc3: ["SOF3", "_sofHandler", "Lossless (sequential)"],
+           
+           /* Start Of Frame markers, differential, Huffman coding */
+           0xc5: ["SOF5", "_sofHandler", "Differential sequential DCT"],
+           0xc6: ["SOF6", "_sofHandler", "Differential progressive DCT"],
+           0xc7: ["SOF7", "_sofHandler", "Differential lossless (sequential)"],
+           
+           /* Start Of Frame markers, non-differential, arithmetic coding */
+           0xc8: ["JPG", null, "Reserved for JPEG extensions"],
+           0xc9: ["SOF9", "_sofHandler", "Extended sequential DCT"],
+           0xca: ["SOF10", "_sofHandler", "Progressive DCT"],
+           0xcb: ["SOF11", "_sofHandler", "Lossless (sequential)"],
+           
+           /* Start Of Frame markers, differential, arithmetic coding */
+           0xcd: ["SOF13", "_sofHandler", "Differential sequential DCT"],
+           0xce: ["SOF14", "_sofHandler", "Differential progressive DCT"],
+           0xcf: ["SOF15", "_sofHandler", "Differential lossless (sequential)"],
+           
+           /* Huffman table specification */
+           0xc4: ["DHT", null, "Define Huffman table(s)"],
+           0xcc: ["DAC", null, "Define arithmetic coding conditioning(s)"],
+           
+           /* Restart interval termination" */
+           0xd0: ["RST0", null, "Restart with modulo 8 count “0”"],
+           0xd1: ["RST1", null, "Restart with modulo 8 count “1”"],
+           0xd2: ["RST2", null, "Restart with modulo 8 count “2”"],
+           0xd3: ["RST3", null, "Restart with modulo 8 count “3”"],
+           0xd4: ["RST4", null, "Restart with modulo 8 count “4”"],
+           0xd5: ["RST5", null, "Restart with modulo 8 count “5”"],
+           0xd6: ["RST6", null, "Restart with modulo 8 count “6”"],
+           0xd7: ["RST7", null, "Restart with modulo 8 count “7”"],
+           
+           /* Other markers */
+           0xd8: ["SOI", null, "Start of image"],
+           0xd9: ["EOI", null, "End of image"],
+           0xda: ["SOS", null, "Start of scan"],
+           0xdb: ["DQT", null, "Define quantization table(s)"],
+           0xdc: ["DNL", null, "Define number of lines"],
+           0xdd: ["DRI", null, "Define restart interval"],
+           0xde: ["DHP", null, "Define hierarchical progression"],
+           0xdf: ["EXP", null, "Expand reference component(s)"],
+           0xe0: ["APP0", "_app0Handler", "Reserved for application segments"],
+           0xe1: ["APP1", "_app1Handler"],
+           0xe2: ["APP2", null],
+           0xe3: ["APP3", null],
+           0xe4: ["APP4", null],
+           0xe5: ["APP5", null],
+           0xe6: ["APP6", null],
+           0xe7: ["APP7", null],
+           0xe8: ["APP8", null],
+           0xe9: ["APP9", null],
+           0xea: ["APP10", null],
+           0xeb: ["APP11", null],
+           0xec: ["APP12", null],
+           0xed: ["APP13", null],
+           0xee: ["APP14", null],
+           0xef: ["APP15", null],
+           0xf0: ["JPG0", null], /* Reserved for JPEG extensions */
+           0xf1: ["JPG1", null],
+           0xf2: ["JPG2", null],
+           0xf3: ["JPG3", null],
+           0xf4: ["JPG4", null],
+           0xf5: ["JPG5", null],
+           0xf6: ["JPG6", null],
+           0xf7: ["JPG7", null],
+           0xf8: ["JPG8", null],
+           0xf9: ["JPG9", null],
+           0xfa: ["JPG10", null],
+           0xfb: ["JPG11", null],
+           0xfc: ["JPG12", null],
+           0xfd: ["JPG13", null],
+           0xfe: ["COM", null], /* Comment */
+           
+           /* Reserved markers */
+           0x01: ["JPG13", null] /* For temporary private use in arithmetic coding */
+           /* 02 -> bf are reserverd */
+       };
+
+       /* Private methods */
+       this.JpegMeta.JpegFile.prototype._addMetaGroup = function _addMetaGroup(name, description) {
+           var group = new JpegMeta.MetaGroup(name, description);
+           this[group.fieldName] = group;
+           this.metaGroups[group.fieldName] = group;
+           return group;
+       };
+
+       this.JpegMeta.JpegFile.prototype._parseIfd = function _parseIfd(endian, _binary_data, base, ifd_offset, tags, name, description) {
+           var num_fields = JpegMeta.parseNum(endian, _binary_data, base + ifd_offset, 2);
+           /* Per tag variables */
+           var i, j;
+           var tag_base;
+           var tag_field;
+           var type, type_field, type_size;
+           var num_values;
+           var value_offset;
+           var value;
+           var _val;
+           var num;
+           var den;
+           
+           var group;
+           
+           group = this._addMetaGroup(name, description);
+       
+           for (var i = 0; i < num_fields; i++) {
+               /* parse the field */
+               tag_base = base + ifd_offset + 2 + (i * 12);
+               tag_field = JpegMeta.parseNum(endian, _binary_data, tag_base, 2);
+               type_field = JpegMeta.parseNum(endian, _binary_data, tag_base + 2, 2);
+               num_values = JpegMeta.parseNum(endian, _binary_data, tag_base + 4, 4);
+               value_offset = JpegMeta.parseNum(endian, _binary_data, tag_base + 8, 4);
+               if (this._types[type_field] === undefined) {
+                   continue;
+               }
+               type = this._types[type_field][0];
+               type_size = this._types[type_field][1];
+               
+               if (type_size * num_values <= 4) {
+                   /* Data is in-line */
+                   value_offset = tag_base + 8;
+               } else {
+                   value_offset = base + value_offset;
+               }
+               
+               /* Read the value */
+               if (type == "UNDEFINED") {
+                   value = _binary_data.slice(value_offset, value_offset + num_values);
+               } else if (type == "ASCII") {
+                   value = _binary_data.slice(value_offset, value_offset + num_values);
+                   value = value.split('\x00')[0];
+                   /* strip trail nul */
+               } else {
+                   value = new Array();
+                   for (j = 0; j < num_values; j++, value_offset += type_size) {
+                       if (type == "BYTE" || type == "SHORT" || type == "LONG") {
+                           value.push(JpegMeta.parseNum(endian, _binary_data, value_offset, type_size));
+                       }
+                       if (type == "SBYTE" || type == "SSHORT" || type == "SLONG") {
+                           value.push(JpegMeta.parseSnum(endian, _binary_data, value_offset, type_size));
+                       }
+                       if (type == "RATIONAL") {
+                           num = JpegMeta.parseNum(endian, _binary_data, value_offset, 4);
+                           den = JpegMeta.parseNum(endian, _binary_data, value_offset + 4, 4);
+                           value.push(new JpegMeta.Rational(num, den));
+                       }
+                       if (type == "SRATIONAL") {
+                           num = JpegMeta.parseSnum(endian, _binary_data, value_offset, 4);
+                           den = JpegMeta.parseSnum(endian, _binary_data, value_offset + 4, 4);
+                           value.push(new JpegMeta.Rational(num, den));
+                       }
+                       value.push();
+                   }
+                   if (num_values === 1) {
+                       value = value[0];
+                   }
+               }
+               if (tags[tag_field] !== undefined) {
+                       group._addProperty(tags[tag_field][1], tags[tag_field][0], value);
+               }
+           }
+       };
+
+       this.JpegMeta.JpegFile.prototype._jfifHandler = function _jfifHandler(mark, pos) {
+           if (this.jfif !== undefined) {
+               throw Error("Multiple JFIF segments found");
+           }
+           this._addMetaGroup("jfif", "JFIF");
+           this.jfif._addProperty("version_major", "Version Major", this._binary_data.charCodeAt(pos + 5));
+           this.jfif._addProperty("version_minor", "Version Minor", this._binary_data.charCodeAt(pos + 6));
+           this.jfif._addProperty("version", "JFIF Version", this.jfif.version_major.value + "." + this.jfif.version_minor.value);
+           this.jfif._addProperty("units", "Density Unit", this._binary_data.charCodeAt(pos + 7));
+           this.jfif._addProperty("Xdensity", "X density", JpegMeta.parseNum(">", this._binary_data, pos + 8, 2));
+           this.jfif._addProperty("Ydensity", "Y Density", JpegMeta.parseNum(">", this._binary_data, pos + 10, 2));
+           this.jfif._addProperty("Xthumbnail", "X Thumbnail", JpegMeta.parseNum(">", this._binary_data, pos + 12, 1));
+           this.jfif._addProperty("Ythumbnail", "Y Thumbnail", JpegMeta.parseNum(">", this._binary_data, pos + 13, 1));
+       };
+
+       /* Handle app0 segments */
+       this.JpegMeta.JpegFile.prototype._app0Handler = function app0Handler(mark, pos) {
+           var ident = this._binary_data.slice(pos, pos + 5);
+           if (ident == this._JFIF_IDENT) {
+               this._jfifHandler(mark, pos);
+           } else if (ident == this._JFXX_IDENT) {
+               /* Don't handle JFXX Ident yet */
+           } else {
+               /* Don't know about other idents */
+           }
+       };
+
+       /* Handle app1 segments */
+       this.JpegMeta.JpegFile.prototype._app1Handler = function _app1Handler(mark, pos) {
+           var ident = this._binary_data.slice(pos, pos + 5);
+           if (ident == this._EXIF_IDENT) {
+               this._exifHandler(mark, pos + 6);
+           } else {
+               /* Don't know about other idents */
+           }
+       };
+
+       /* Handle exif segments */
+       JpegMeta.JpegFile.prototype._exifHandler = function _exifHandler(mark, pos) {
+           if (this.exif !== undefined) {
+               throw new Error("Multiple JFIF segments found");
+           }
+           
+           /* Parse this TIFF header */
+           var endian;
+           var magic_field;
+           var ifd_offset;
+           var primary_ifd, exif_ifd, gps_ifd;
+           var endian_field = this._binary_data.slice(pos, pos + 2);
+           
+           /* Trivia: This 'I' is for Intel, the 'M' is for Motorola */
+           if (endian_field === "II") {
+               endian = "<";
+           } else if (endian_field === "MM") {
+               endian = ">";
+           } else {
+               throw new Error("Malformed TIFF meta-data. Unknown endianess: " + endian_field);
+           }
+           
+           magic_field = JpegMeta.parseNum(endian, this._binary_data, pos + 2, 2);
+           
+           if (magic_field !== 42) {
+               throw new Error("Malformed TIFF meta-data. Bad magic: " + magic_field);
+           }
+           
+           ifd_offset = JpegMeta.parseNum(endian, this._binary_data, pos + 4, 4);
+           
+           /* Parse 0th IFD */
+           this._parseIfd(endian, this._binary_data, pos, ifd_offset, this._tifftags, "tiff", "TIFF");
+           
+           if (this.tiff.ExifIfdPointer) {
+               this._parseIfd(endian, this._binary_data, pos, this.tiff.ExifIfdPointer.value, this._exiftags, "exif", "Exif");
+           }
+           
+           if (this.tiff.GPSInfoIfdPointer) {
+               this._parseIfd(endian, this._binary_data, pos, this.tiff.GPSInfoIfdPointer.value, this._gpstags, "gps", "GPS");
+               if (this.gps.GPSLatitude) {
+                   var latitude;
+                   latitude = this.gps.GPSLatitude.value[0].asFloat() + 
+                       (1 / 60) * this.gps.GPSLatitude.value[1].asFloat() + 
+                       (1 / 3600) * this.gps.GPSLatitude.value[2].asFloat();
+                   if (this.gps.GPSLatitudeRef.value === "S") {
+                       latitude = -latitude;
+                   }
+                   this.gps._addProperty("latitude", "Dec. Latitude", latitude);
+               }
+               if (this.gps.GPSLongitude) {
+                   var longitude;
+                   longitude = this.gps.GPSLongitude.value[0].asFloat() + 
+                       (1 / 60) * this.gps.GPSLongitude.value[1].asFloat() + 
+                       (1 / 3600) * this.gps.GPSLongitude.value[2].asFloat();
+                   if (this.gps.GPSLongitudeRef.value === "W") {
+                       longitude = -longitude;
+                   }
+                   this.gps._addProperty("longitude", "Dec. Longitude", longitude);
+               }
+           }
+       };
+
+       // MediaWiki: Add mw.libs wrapper
+       mw.libs.jpegmeta = function( fileReaderResult, fileName ) {
+               return new JpegMeta.JpegFile( fileReaderResult, fileName );
+       };
+
+}() );
diff --git a/resources/src/mediawiki.page/mediawiki.page.gallery.js b/resources/src/mediawiki.page/mediawiki.page.gallery.js
new file mode 100644 (file)
index 0000000..f92d372
--- /dev/null
@@ -0,0 +1,253 @@
+/**
+ * Show gallery captions when focused. Copied directly from jquery.mw-jump.js.
+ * Also Dynamically resize images to justify them.
+ */
+( function ( $, mw ) {
+       $( function () {
+               var isTouchScreen,
+                       gettingFocus,
+                       galleries = 'ul.mw-gallery-packed-overlay, ul.mw-gallery-packed-hover, ul.mw-gallery-packed';
+
+               // Is there a better way to detect a touchscreen? Current check taken from stack overflow.
+               isTouchScreen = !!( window.ontouchstart !== undefined || window.DocumentTouch !== undefined && document instanceof window.DocumentTouch );
+
+               if ( isTouchScreen ) {
+                       // Always show the caption for a touch screen.
+                       $( 'ul.mw-gallery-packed-hover' )
+                               .addClass( 'mw-gallery-packed-overlay' )
+                               .removeClass( 'mw-gallery-packed-hover' );
+               } else {
+                       // Note use of just "a", not a.image, since we want this to trigger if a link in
+                       // the caption receives focus
+                       $( 'ul.mw-gallery-packed-hover li.gallerybox' ).on( 'focus blur', 'a', function ( e ) {
+                               // Confusingly jQuery leaves e.type as focusout for delegated blur events
+                               gettingFocus = e.type !== 'blur' && e.type !== 'focusout';
+                               $( this ).closest( 'li.gallerybox' ).toggleClass( 'mw-gallery-focused', gettingFocus );
+                       } );
+               }
+
+               // Now on to justification.
+               // We may still get ragged edges if someone resizes their window. Could bind to
+               // that event, otoh do we really want to constantly be resizing galleries?
+               $( galleries ).each( function () {
+                       var lastTop,
+                               $img,
+                               imgWidth,
+                               imgHeight,
+                               rows = [],
+                               $gallery = $( this );
+
+                       $gallery.children( 'li' ).each( function () {
+                               // Math.floor to be paranoid if things are off by 0.00000000001
+                               var top = Math.floor( $( this ).position().top ),
+                                       $this = $( this );
+
+                               if ( top !== lastTop ) {
+                                       rows[rows.length] = [];
+                                       lastTop = top;
+                               }
+
+                               $img = $this.find( 'div.thumb a.image img' );
+                               if ( $img.length && $img[0].height ) {
+                                       imgHeight = $img[0].height;
+                                       imgWidth = $img[0].width;
+                               } else {
+                                       // If we don't have a real image, get the containing divs width/height.
+                                       // Note that if we do have a real image, using this method will generally
+                                       // give the same answer, but can be different in the case of a very
+                                       // narrow image where extra padding is added.
+                                       imgHeight = $this.children().children( 'div:first' ).height();
+                                       imgWidth = $this.children().children( 'div:first' ).width();
+                               }
+
+                               // Hack to make an edge case work ok
+                               if ( imgHeight < 30 ) {
+                                       // Don't try and resize this item.
+                                       imgHeight = 0;
+                               }
+
+                               rows[rows.length - 1][rows[rows.length - 1].length] = {
+                                       $elm: $this,
+                                       width: $this.outerWidth(),
+                                       imgWidth: imgWidth,
+                                       // XXX: can divide by 0 ever happen?
+                                       aspect: imgWidth / imgHeight,
+                                       captionWidth: $this.children().children( 'div.gallerytextwrapper' ).width(),
+                                       height: imgHeight
+                               };
+                       } );
+
+                       ( function () {
+                               var maxWidth,
+                                       combinedAspect,
+                                       combinedPadding,
+                                       curRow,
+                                       curRowHeight,
+                                       wantedWidth,
+                                       preferredHeight,
+                                       newWidth,
+                                       padding,
+                                       $outerDiv,
+                                       $innerDiv,
+                                       $imageDiv,
+                                       $imageElm,
+                                       imageElm,
+                                       $caption,
+                                       hookInfo,
+                                       i,
+                                       j,
+                                       avgZoom,
+                                       totalZoom = 0;
+
+                               for ( i = 0; i < rows.length; i++ ) {
+                                       maxWidth = $gallery.width();
+                                       combinedAspect = 0;
+                                       combinedPadding = 0;
+                                       curRow = rows[i];
+                                       curRowHeight = 0;
+
+                                       for ( j = 0; j < curRow.length; j++ ) {
+                                               if ( curRowHeight === 0 ) {
+                                                       if ( isFinite( curRow[j].height ) ) {
+                                                               // Get the height of this row, by taking the first
+                                                               // non-out of bounds height
+                                                               curRowHeight = curRow[j].height;
+                                                       }
+                                               }
+
+                                               if ( curRow[j].aspect === 0 || !isFinite( curRow[j].aspect ) ) {
+                                                       mw.log( 'Skipping item ' + j + ' due to aspect: ' + curRow[j].aspect );
+                                                       // One of the dimensions are 0. Probably should
+                                                       // not try to resize.
+                                                       combinedPadding += curRow[j].width;
+                                               } else {
+                                                       combinedAspect += curRow[j].aspect;
+                                                       combinedPadding += curRow[j].width - curRow[j].imgWidth;
+                                               }
+                                       }
+
+                                       // Add some padding for inter-element spacing.
+                                       combinedPadding += 5 * curRow.length;
+                                       wantedWidth = maxWidth - combinedPadding;
+                                       preferredHeight = wantedWidth / combinedAspect;
+
+                                       if ( preferredHeight > curRowHeight * 1.5 ) {
+                                               // Only expand at most 1.5 times current size
+                                               // As that's as high a resolution as we have.
+                                               // Also on the off chance there is a bug in this
+                                               // code, would prevent accidentally expanding to
+                                               // be 10 billion pixels wide.
+                                               mw.log( 'mw.page.gallery: Cannot fit row, aspect is ' + preferredHeight / curRowHeight );
+                                               if ( i === rows.length - 1 ) {
+                                                       // If its the last row, and we can't fit it,
+                                                       // don't make the entire row huge.
+                                                       avgZoom = ( totalZoom / ( rows.length - 1 ) ) * curRowHeight;
+                                                       if ( isFinite( avgZoom ) && avgZoom >= 1 && avgZoom <= 1.5 ) {
+                                                               preferredHeight = avgZoom;
+                                                       } else {
+                                                               // Probably a single row gallery
+                                                               preferredHeight = curRowHeight;
+                                                       }
+                                               } else {
+                                                       preferredHeight = 1.5 * curRowHeight;
+                                               }
+                                       }
+                                       if ( !isFinite( preferredHeight ) ) {
+                                               // This *definitely* should not happen.
+                                               mw.log( 'mw.page.gallery: Trying to resize row ' + i + ' to ' + preferredHeight + '?!' );
+                                               // Skip this row.
+                                               continue;
+                                       }
+                                       if ( preferredHeight < 5 ) {
+                                               // Well something clearly went wrong...
+                                               mw.log( {
+                                                       maxWidth: maxWidth,
+                                                       combinedPadding: combinedPadding,
+                                                       combinedAspect: combinedAspect,
+                                                       wantedWidth: wantedWidth
+                                               } );
+                                               mw.log( 'mw.page.gallery: [BUG!] Fitting row ' + i + ' to too small a size: ' + preferredHeight );
+                                               // Skip this row.
+                                               continue;
+                                       }
+
+                                       if ( preferredHeight / curRowHeight > 1 ) {
+                                               totalZoom += preferredHeight / curRowHeight;
+                                       } else {
+                                               // If we shrink, still consider that a zoom of 1
+                                               totalZoom += 1;
+                                       }
+
+                                       for ( j = 0; j < curRow.length; j++ ) {
+                                               newWidth = preferredHeight * curRow[j].aspect;
+                                               padding = curRow[j].width - curRow[j].imgWidth;
+                                               $outerDiv = curRow[j].$elm;
+                                               $innerDiv = $outerDiv.children( 'div' ).first();
+                                               $imageDiv = $innerDiv.children( 'div.thumb' );
+                                               $imageElm = $imageDiv.find( 'img' ).first();
+                                               imageElm = $imageElm.length ? $imageElm[0] : null;
+                                               $caption = $outerDiv.find( 'div.gallerytextwrapper' );
+
+                                               // Since we are going to re-adjust the height, the vertical
+                                               // centering margins need to be reset.
+                                               $imageDiv.children( 'div' ).css( 'margin', '0px auto' );
+
+                                               if ( newWidth < 60 || !isFinite( newWidth ) ) {
+                                                       // Making something skinnier than this will mess up captions,
+                                                       mw.log( 'mw.page.gallery: Tried to make image ' + newWidth + 'px wide but too narrow.' );
+                                                       if ( newWidth < 1 || !isFinite( newWidth ) ) {
+                                                               $innerDiv.height( preferredHeight );
+                                                               // Don't even try and touch the image size if it could mean
+                                                               // making it disappear.
+                                                               continue;
+                                                       }
+                                               } else {
+                                                       $outerDiv.width( newWidth + padding );
+                                                       $innerDiv.width( newWidth + padding );
+                                                       $imageDiv.width( newWidth );
+                                                       $caption.width( curRow[j].captionWidth + ( newWidth - curRow[j].imgWidth ) );
+                                               }
+
+                                               hookInfo = {
+                                                       fullWidth: newWidth + padding,
+                                                       imgWidth: newWidth,
+                                                       imgHeight: preferredHeight,
+                                                       $innerDiv: $innerDiv,
+                                                       $imageDiv: $imageDiv,
+                                                       $outerDiv: $outerDiv,
+                                                       // Whether the hook took action
+                                                       resolved: false
+                                               };
+
+                                               /**
+                                                * Gallery resize.
+                                                *
+                                                * If your handler resizes an image, it should also set the resolved
+                                                * property to true. Additionally, because this module only exposes this
+                                                * logic temporarily, you should load your module in position top to
+                                                * ensure it is registered before this runs (FIXME: Don't use mw.hook)
+                                                *
+                                                * See TimedMediaHandler for an example.
+                                                *
+                                                * @event mediawiki_page_gallery_resize
+                                                * @member mw.hook
+                                                * @param {Object} hookInfo
+                                                */
+                                               mw.hook( 'mediawiki.page.gallery.resize' ).fire( hookInfo );
+
+                                               if ( !hookInfo.resolved ) {
+                                                       if ( imageElm ) {
+                                                               // We don't always have an img, e.g. in the case of an invalid file.
+                                                               imageElm.width = newWidth;
+                                                               imageElm.height = preferredHeight;
+                                                       } else {
+                                                               // Not a file box.
+                                                               $imageDiv.height( preferredHeight );
+                                                       }
+                                               }
+                                       }
+                               }
+                       } )();
+               } );
+       } );
+} )( jQuery, mediaWiki );
diff --git a/resources/src/mediawiki.page/mediawiki.page.image.pagination.js b/resources/src/mediawiki.page/mediawiki.page.image.pagination.js
new file mode 100644 (file)
index 0000000..50301bd
--- /dev/null
@@ -0,0 +1,93 @@
+/**
+ * Change multi-page image navigation so that the current page display can be changed
+ * without a page reload. Currently, the only image formats that can be multi-page images are
+ * PDF and DjVu files
+ */
+( function ( mw, $ ) {
+
+       // Initialize ajax request variable
+       var xhr;
+
+       // Use jQuery's load function to specifically select and replace table.multipageimage's child
+       // tr with the new page's table.multipageimage's tr element.
+       // table.multipageimage always has only one row.
+       function loadPage( page, hist ) {
+               if ( xhr ) {
+                       // Abort previous requests to prevent backlog created by
+                       // repeatedly pressing back/forwards buttons
+                       xhr.abort();
+               }
+
+               var $multipageimage = $( 'table.multipageimage' ),
+                       $spinner;
+
+               // Add a new spinner if one doesn't already exist
+               if ( !$multipageimage.find( '.mw-spinner' ).length ) {
+
+                       $spinner = $.createSpinner( {
+                               size: 'large',
+                               type: 'block'
+                       } )
+                               // Set the spinner's dimensions equal to the table's dimensions so that
+                               // the current scroll position is not lost after the table is emptied prior to
+                               // its contents being updated
+                               .css( {
+                                       height: $multipageimage.find( 'tr' ).height(),
+                                       width: $multipageimage.find( 'tr' ).width()
+                               } );
+
+                       $multipageimage.empty().append( $spinner );
+               }
+
+               xhr = $.ajax( {
+                       url: page,
+                       success: function ( data ) {
+                               // Load the page
+                               $multipageimage.empty().append( $( data ).find( 'table.multipageimage tr' ) );
+                               // Fire hook because the page's content has changed
+                               mw.hook( 'wikipage.content' ).fire( $multipageimage );
+                               // Set up the new page for pagination
+                               ajaxifyPageNavigation();
+                               // Add new page of image to history.  To preserve the back-forwards chain in the browser,
+                               // if the user gets here via the back/forward button, don't update the history.
+                               if ( window.history && history.pushState && !hist ) {
+                                       history.pushState( { url: page }, document.title, page );
+                               }
+                       }
+               } );
+       }
+
+       function ajaxifyPageNavigation() {
+               // Intercept the default action of the links in the thumbnail navigation
+               $( '.multipageimagenavbox' ).one( 'click', 'a', function ( e ) {
+                       loadPage( this.href );
+                       e.preventDefault();
+               } );
+
+               // Prevent the submission of the page select form and instead call loadPage
+               $( 'form[name="pageselector"]' ).one( 'change submit', function ( e ) {
+                       loadPage( this.action + '?' + $( this ).serialize() );
+                       e.preventDefault();
+               } );
+       }
+
+       $( document ).ready( function () {
+               // The presence of table.multipageimage signifies that this file is a multi-page image
+               if ( mw.config.get( 'wgNamespaceNumber' ) === 6 && $( 'table.multipageimage' ).length !== 0 ) {
+                       ajaxifyPageNavigation();
+
+                       // Set up history.pushState (if available), so that when the user browses to a new page of
+                       // the same file, the browser's history is updated. If the user clicks the back/forward button
+                       // in the midst of navigating a file's pages, load the page inline.
+                       if ( window.history && history.pushState && history.replaceState ) {
+                               history.replaceState( { url: window.location.href }, '' );
+                               $( window ).on( 'popstate', function ( e ) {
+                                       var state = e.originalEvent.state;
+                                       if ( state ) {
+                                               loadPage( state.url, true );
+                                       }
+                               } );
+                       }
+               }
+       } );
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.page/mediawiki.page.patrol.ajax.js b/resources/src/mediawiki.page/mediawiki.page.patrol.ajax.js
new file mode 100644 (file)
index 0000000..5fb14dd
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * Animate patrol links to use asynchronous API requests to
+ * patrol pages, rather than navigating to a different URI.
+ *
+ * @since 1.21
+ * @author Marius Hoch <hoo@online.de>
+ */
+( function ( mw, $ ) {
+       if ( !mw.user.tokens.exists( 'patrolToken' ) ) {
+               // Current user has no patrol right, or an old cached version of user.tokens
+               // that didn't have patrolToken yet.
+               return;
+       }
+       $( function () {
+               var $patrolLinks = $( '.patrollink a' );
+               $patrolLinks.on( 'click', function ( e ) {
+                       var $spinner, href, rcid, apiRequest;
+
+                       // Start preloading the notification module (normally loaded by mw.notify())
+                       mw.loader.load( ['mediawiki.notification'], null, true );
+
+                       // Hide the link and create a spinner to show it inside the brackets.
+                       $spinner = $.createSpinner( {
+                               size: 'small',
+                               type: 'inline'
+                       } );
+                       $( this ).hide().after( $spinner );
+
+                       href = $( this ).attr( 'href' );
+                       rcid = mw.util.getParamValue( 'rcid', href );
+                       apiRequest = new mw.Api();
+
+                       apiRequest.post( {
+                               action: 'patrol',
+                               token: mw.user.tokens.get( 'patrolToken' ),
+                               rcid: rcid
+                       } )
+                       .done( function ( data ) {
+                               // Remove all patrollinks from the page (including any spinners inside).
+                               $patrolLinks.closest( '.patrollink' ).remove();
+                               if ( data.patrol !== undefined ) {
+                                       // Success
+                                       var title = new mw.Title( data.patrol.title );
+                                       mw.notify( mw.msg( 'markedaspatrollednotify', title.toText() ) );
+                               } else {
+                                       // This should never happen as errors should trigger fail
+                                       mw.notify( mw.msg( 'markedaspatrollederrornotify' ) );
+                               }
+                       } )
+                       .fail( function ( error ) {
+                               $spinner.remove();
+                               // Restore the patrol link. This allows the user to try again
+                               // (or open it in a new window, bypassing this ajax module).
+                               $patrolLinks.show();
+                               if ( error === 'noautopatrol' ) {
+                                       // Can't patrol own
+                                       mw.notify( mw.msg( 'markedaspatrollederror-noautopatrol' ) );
+                               } else {
+                                       mw.notify( mw.msg( 'markedaspatrollederrornotify' ) );
+                               }
+                       } );
+
+                       e.preventDefault();
+               } );
+       } );
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.page/mediawiki.page.ready.js b/resources/src/mediawiki.page/mediawiki.page.ready.js
new file mode 100644 (file)
index 0000000..ccddb3e
--- /dev/null
@@ -0,0 +1,40 @@
+( function ( mw, $ ) {
+       var supportsPlaceholder = 'placeholder' in document.createElement( 'input' );
+
+       mw.hook( 'wikipage.content' ).add( function ( $content ) {
+               var $sortableTables;
+
+               // Run jquery.placeholder polyfill if placeholder is not supported
+               if ( !supportsPlaceholder ) {
+                       $content.find( 'input[placeholder]' ).placeholder();
+               }
+
+               // Run jquery.makeCollapsible
+               $content.find( '.mw-collapsible' ).makeCollapsible();
+
+               // Lazy load jquery.tablesorter
+               $sortableTables = $content.find( 'table.sortable' );
+               if ( $sortableTables.length ) {
+                       mw.loader.using( 'jquery.tablesorter', function () {
+                               $sortableTables.tablesorter();
+                       } );
+               }
+
+               // Run jquery.checkboxShiftClick
+               $content.find( 'input[type="checkbox"]:not(.noshiftselect)' ).checkboxShiftClick();
+       } );
+
+       // Things outside the wikipage content
+       $( function () {
+
+               if ( !supportsPlaceholder ) {
+                       // Exclude content to avoid hitting it twice for the (first) wikipage content
+                       $( 'input[placeholder]' ).not( '#mw-content-text input' ).placeholder();
+               }
+
+               // Add accesskey hints to the tooltips
+               mw.util.updateTooltipAccessKeys();
+
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.page/mediawiki.page.startup.js b/resources/src/mediawiki.page/mediawiki.page.startup.js
new file mode 100644 (file)
index 0000000..c75e59f
--- /dev/null
@@ -0,0 +1,37 @@
+( function ( mw, $ ) {
+
+       mw.page = {};
+
+       // Client profile classes for <html>
+       // Allows for easy hiding/showing of JS or no-JS-specific UI elements
+       $( 'html' )
+               .addClass( 'client-js' )
+               .removeClass( 'client-nojs' );
+
+       $( function () {
+               // Initialize utilities as soon as the document is ready (mw.util.$content).
+               // In the domready here instead of in mediawiki.page.ready to ensure that it gets enqueued
+               // before other modules hook into domready, so that mw.util.$content (defined by
+               // mw.util.init), is defined for them.
+               mw.util.init();
+
+               /**
+                * Fired when wiki content is being added to the DOM
+                *
+                * It is encouraged to fire it before the main DOM is changed (when $content
+                * is still detatched).  However, this order is not defined either way, so you
+                * should only rely on $content itself.
+                *
+                * This includes the ready event on a page load (including post-edit loads)
+                * and when content has been previewed with LivePreview.
+                *
+                * @event wikipage_content
+                * @member mw.hook
+                * @param {jQuery} $content The most appropriate element containing the content,
+                *   such as #mw-content-text (regular content root) or #wikiPreview (live preview
+                *   root)
+                */
+               mw.hook( 'wikipage.content' ).fire( $( '#mw-content-text' ) );
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.page/mediawiki.page.watch.ajax.js b/resources/src/mediawiki.page/mediawiki.page.watch.ajax.js
new file mode 100644 (file)
index 0000000..850177f
--- /dev/null
@@ -0,0 +1,179 @@
+/**
+ * Animate watch/unwatch links to use asynchronous API requests to
+ * watch pages, rather than navigating to a different URI.
+ *
+ * @class mw.page.watch.ajax
+ */
+( function ( mw, $ ) {
+       // The name of the page to watch or unwatch
+       var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) );
+
+       /**
+        * Update the link text, link href attribute and (if applicable)
+        * "loading" class.
+        *
+        * @param {jQuery} $link Anchor tag of (un)watch link
+        * @param {string} action One of 'watch', 'unwatch'
+        * @param {string} [state="idle"] 'idle' or 'loading'. Default is 'idle'
+        */
+       function updateWatchLink( $link, action, state ) {
+               var accesskeyTip, msgKey, $li, otherAction;
+
+               // A valid but empty jQuery object shouldn't throw a TypeError
+               if ( !$link.length ) {
+                       return;
+               }
+
+               // Invalid actions shouldn't silently turn the page in an unrecoverable state
+               if ( action !== 'watch' && action !== 'unwatch' ) {
+                       throw new Error( 'Invalid action' );
+               }
+
+               // message keys 'watch', 'watching', 'unwatch' or 'unwatching'.
+               msgKey = state === 'loading' ? action + 'ing' : action;
+               otherAction = action === 'watch' ? 'unwatch' : 'watch';
+               accesskeyTip = $link.attr( 'title' ).match( mw.util.tooltipAccessKeyRegexp );
+               $li = $link.closest( 'li' );
+
+               // Trigger a 'watchpage' event for this List item.
+               // Announce the otherAction value as the first param.
+               // Used to monitor the state of watch link.
+               // TODO: Revise when system wide hooks are implemented
+               if ( state === undefined ) {
+                       $li.trigger( 'watchpage.mw', otherAction );
+               }
+
+               $link
+                       .text( mw.msg( msgKey ) )
+                       .attr( 'title', mw.msg( 'tooltip-ca-' + action ) +
+                               ( accesskeyTip ? ' ' + accesskeyTip[0] : '' )
+                       )
+                       .attr( 'href', mw.util.wikiScript() + '?' + $.param( {
+                                       title: title,
+                                       action: action
+                               } )
+                       );
+
+               // Most common ID style
+               if ( $li.prop( 'id' ) === 'ca-' + otherAction ) {
+                       $li.prop( 'id', 'ca-' + action );
+               }
+
+               // Special case for vector icon
+               if ( $li.hasClass( 'icon' ) ) {
+                       if ( state === 'loading' ) {
+                               $link.addClass( 'loading' );
+                       } else {
+                               $link.removeClass( 'loading' );
+                       }
+               }
+       }
+
+       /**
+        * TODO: This should be moved somewhere more accessible.
+        *
+        * @private
+        * @param {string} url
+        * @return {string} The extracted action, defaults to 'view'
+        */
+       function mwUriGetAction( url ) {
+               var action, actionPaths, key, i, m, parts;
+
+               // TODO: Does MediaWiki give action path or query param
+               // precedence? If the former, move this to the bottom
+               action = mw.util.getParamValue( 'action', url );
+               if ( action !== null ) {
+                       return action;
+               }
+
+               actionPaths = mw.config.get( 'wgActionPaths' );
+               for ( key in actionPaths ) {
+                       if ( actionPaths.hasOwnProperty( key ) ) {
+                               parts = actionPaths[key].split( '$1' );
+                               for ( i = 0; i < parts.length; i++ ) {
+                                       parts[i] = $.escapeRE( parts[i] );
+                               }
+                               m = new RegExp( parts.join( '(.+)' ) ).exec( url );
+                               if ( m && m[1] ) {
+                                       return key;
+                               }
+
+                       }
+               }
+
+               return 'view';
+       }
+
+       // Expose public methods
+       mw.page.watch = {
+               updateWatchLink: updateWatchLink
+       };
+
+       $( function () {
+               var $links = $( '.mw-watchlink a, a.mw-watchlink, ' +
+                       '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' +
+                       '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' );
+
+               // Allowing people to add inline animated links is a little scary
+               $links = $links.filter( ':not( #bodyContent *, #content * )' );
+
+               $links.click( function ( e ) {
+                       var action, api, $link;
+
+                       // Start preloading the notification module (normally loaded by mw.notify())
+                       mw.loader.load( ['mediawiki.notification'], null, true );
+
+                       action = mwUriGetAction( this.href );
+
+                       if ( action !== 'watch' && action !== 'unwatch' ) {
+                               // Could not extract target action from link url,
+                               // let native browsing handle it further
+                               return true;
+                       }
+                       e.preventDefault();
+                       e.stopPropagation();
+
+                       $link = $( this );
+
+                       updateWatchLink( $link, action, 'loading' );
+
+                       api = new mw.Api();
+
+                       api[action]( title )
+                               .done( function ( watchResponse ) {
+                                       var otherAction = action === 'watch' ? 'unwatch' : 'watch';
+
+                                       mw.notify( $.parseHTML( watchResponse.message ), {
+                                               tag: 'watch-self'
+                                       } );
+
+                                       // Set link to opposite
+                                       updateWatchLink( $link, otherAction );
+
+                                       // Update the "Watch this page" checkbox on action=edit when the
+                                       // page is watched or unwatched via the tab (bug 12395).
+                                       $( '#wpWatchthis' ).prop( 'checked', watchResponse.watched !== undefined );
+                               } )
+                               .fail( function () {
+                                       var cleanTitle, msg, link;
+
+                                       // Reset link to non-loading mode
+                                       updateWatchLink( $link, action );
+
+                                       // Format error message
+                                       cleanTitle = title.replace( /_/g, ' ' );
+                                       link = mw.html.element(
+                                               'a', {
+                                                       href: mw.util.getUrl( title ),
+                                                       title: cleanTitle
+                                               }, cleanTitle
+                                       );
+                                       msg = mw.message( 'watcherrortext', link );
+
+                                       // Report to user about the error
+                                       mw.notify( msg, { tag: 'watch-self' } );
+                               } );
+               } );
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.special/images/glyph-people-large.png b/resources/src/mediawiki.special/images/glyph-people-large.png
new file mode 100644 (file)
index 0000000..0578be0
Binary files /dev/null and b/resources/src/mediawiki.special/images/glyph-people-large.png differ
diff --git a/resources/src/mediawiki.special/images/icon-contributors.png b/resources/src/mediawiki.special/images/icon-contributors.png
new file mode 100644 (file)
index 0000000..f933aa6
Binary files /dev/null and b/resources/src/mediawiki.special/images/icon-contributors.png differ
diff --git a/resources/src/mediawiki.special/images/icon-edits.png b/resources/src/mediawiki.special/images/icon-edits.png
new file mode 100644 (file)
index 0000000..39f4f2d
Binary files /dev/null and b/resources/src/mediawiki.special/images/icon-edits.png differ
diff --git a/resources/src/mediawiki.special/images/icon-lock.png b/resources/src/mediawiki.special/images/icon-lock.png
new file mode 100644 (file)
index 0000000..03f0eec
Binary files /dev/null and b/resources/src/mediawiki.special/images/icon-lock.png differ
diff --git a/resources/src/mediawiki.special/images/icon-pages.png b/resources/src/mediawiki.special/images/icon-pages.png
new file mode 100644 (file)
index 0000000..59513db
Binary files /dev/null and b/resources/src/mediawiki.special/images/icon-pages.png differ
diff --git a/resources/src/mediawiki.special/mediawiki.special.block.css b/resources/src/mediawiki.special/mediawiki.special.block.css
new file mode 100644 (file)
index 0000000..899a9f3
--- /dev/null
@@ -0,0 +1,7 @@
+/**
+ * Styling for Special:Block
+ */
+
+label[for="mw-input-wpConfirm"] {
+       font-weight: bold;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.block.js b/resources/src/mediawiki.special/mediawiki.special.block.js
new file mode 100644 (file)
index 0000000..8dedb9b
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * JavaScript for Special:Block
+ */
+( function ( mw, $ ) {
+       $( function () {
+               var $blockTarget = $( '#mw-bi-target' ),
+                       $anonOnlyRow = $( '#mw-input-wpHardBlock' ).closest( 'tr' ),
+                       $enableAutoblockRow = $( '#mw-input-wpAutoBlock' ).closest( 'tr' ),
+                       $hideUser = $( '#mw-input-wpHideUser' ).closest( 'tr' ),
+                       $watchUser = $( '#mw-input-wpWatch' ).closest( 'tr' );
+
+               function updateBlockOptions( instant ) {
+                       var blocktarget = $.trim( $blockTarget.val() ),
+                               isEmpty = blocktarget === '',
+                               isIp = mw.util.isIPv4Address( blocktarget, true ) || mw.util.isIPv6Address( blocktarget, true ),
+                               isIpRange = isIp && blocktarget.match( /\/\d+$/ );
+
+                       if ( isIp && !isEmpty ) {
+                               $enableAutoblockRow.goOut( instant );
+                               $hideUser.goOut( instant );
+                       } else {
+                               $enableAutoblockRow.goIn( instant );
+                               $hideUser.goIn( instant );
+                       }
+                       if ( !isIp && !isEmpty ) {
+                               $anonOnlyRow.goOut( instant );
+                       } else {
+                               $anonOnlyRow.goIn( instant );
+                       }
+                       if ( isIpRange && !isEmpty ) {
+                               $watchUser.goOut( instant );
+                       } else {
+                               $watchUser.goIn( instant );
+                       }
+               }
+
+               if ( $blockTarget.length ) {
+                       // Bind functions so they're checked whenever stuff changes
+                       $blockTarget.keyup( updateBlockOptions );
+
+                       // Call them now to set initial state (ie. Special:Block/Foobar?wpBlockExpiry=2+hours)
+                       updateBlockOptions( /* instant= */ true );
+               }
+       } );
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.special/mediawiki.special.changeemail.css b/resources/src/mediawiki.special/mediawiki.special.changeemail.css
new file mode 100644 (file)
index 0000000..9461fbd
--- /dev/null
@@ -0,0 +1,19 @@
+#mw-emailaddress-validity {
+       padding: 2px 1em;
+}
+#mw-emailaddress-validity {
+       border-bottom-right-radius: 0.8em;
+       border-top-right-radius: 0.8em;
+}
+
+/** colors also used in mediawiki.special.preferences.css */
+#mw-emailaddress-validity.valid {
+       border: 1px solid #80FF80;
+       background-color: #C0FFC0;
+       color: black;
+}
+#mw-emailaddress-validity.invalid {
+       border: 1px solid #FF8080;
+       background-color: #FFC0C0;
+       color: black;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.changeemail.js b/resources/src/mediawiki.special/mediawiki.special.changeemail.js
new file mode 100644 (file)
index 0000000..bc2a0a2
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+ * JavaScript for Special:ChangeEmail
+ */
+( function ( mw, $ ) {
+       /**
+        * Given an email validity status (true, false, null) update the label CSS class
+        */
+       function updateMailValidityLabel( mail ) {
+               var isValid = mw.util.validateEmail( mail ),
+                       $label = $( '#mw-emailaddress-validity' );
+
+               // Set up the validity notice if it doesn't already exist
+               if ( $label.length === 0 ) {
+                       $label = $( '<label for="wpNewEmail" id="mw-emailaddress-validity"></label>' )
+                               .insertAfter( '#wpNewEmail' );
+               }
+
+               // We allow empty address
+               if ( isValid === null ) {
+                       $label.text( '' ).removeClass( 'valid invalid' );
+
+               // Valid
+               } else if ( isValid ) {
+                       $label.text( mw.msg( 'email-address-validity-valid' ) ).addClass( 'valid' ).removeClass( 'invalid' );
+
+               // Not valid
+               } else {
+                       $label.text( mw.msg( 'email-address-validity-invalid' ) ).addClass( 'invalid' ).removeClass( 'valid' );
+               }
+       }
+
+       $( function () {
+               $( '#wpNewEmail' )
+                       // Lame tip to let user know if its email is valid. See bug 22449.
+                       // Only bind once for 'blur' so that the user can fill it in without errors;
+                       // after that, look at every keypress for immediate feedback.
+                       .one( 'blur', function () {
+                               var $this = $( this );
+                               updateMailValidityLabel( $this.val() );
+                               $this.keyup( function () {
+                                       updateMailValidityLabel( $this.val() );
+                               } );
+                       } )
+                       // Supress built-in validation notice and just call updateMailValidityLabel(),
+                       // to avoid double notice. See bug 40909.
+                       .on( 'invalid', function ( e ) {
+                               e.preventDefault();
+                               updateMailValidityLabel( $( this ).val() );
+                       } );
+       } );
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.special/mediawiki.special.changeslist.css b/resources/src/mediawiki.special/mediawiki.special.changeslist.css
new file mode 100644 (file)
index 0000000..5e4af7b
--- /dev/null
@@ -0,0 +1,7 @@
+/**
+ * Styling for Special:Watchlist and Special:RecentChanges
+ */
+
+.mw-changeslist-line-watched .mw-title {
+       font-weight: bold;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css b/resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css
new file mode 100644 (file)
index 0000000..bed580d
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * Styling for Special:Watchlist and Special:RecentChanges when preference 'usenewrc'
+ * a.k.a. Enhanced Recent Changes is enabled.
+ */
+
+table.mw-enhanced-rc {
+       border: 0;
+       border-spacing: 0;
+}
+
+table.mw-enhanced-rc th,
+table.mw-enhanced-rc td {
+       padding: 0;
+       vertical-align: top;
+}
+
+td.mw-enhanced-rc {
+       white-space: nowrap;
+       font-family: monospace;
+}
+
+.mw-enhanced-rc-time {
+       font-family: monospace;
+}
+
+table.mw-enhanced-rc td.mw-enhanced-rc-nested {
+       padding-left: 1em;
+}
+
+/* Show/hide arrows in enhanced changeslist */
+.mw-enhanced-rc .collapsible-expander {
+       float: none;
+}
+
+/* If JS is disabled, the arrows or the placeholder space shouldn't be shown */
+.client-nojs .mw-enhancedchanges-arrow-space {
+       display: none;
+}
+
+/*
+ * And if it's enabled, let's optimize the collapsing a little: hide the rows
+ * that would be hidden by jquery.makeCollapsible with CSS to save us some
+ * reflows and repaints. This doesn't work on browsers that don't fully support
+ * CSS2 (IE6), but it's okay, this will be done in JavaScript with old degraded
+ * performance instead.
+ */
+.client-js table.mw-enhanced-rc.mw-collapsed tr + tr {
+       display: none;
+}
+
+.mw-enhancedchanges-arrow-space {
+       display: inline-block;
+       *display: inline; /* IE7 and below */
+       zoom: 1;
+       width: 15px;
+       height: 15px;
+}
+
+/* let it look like it is clickable */
+.mw-enhancedchanges-arrow.mw-collapsible-toggle {
+       cursor: pointer;
+}
+
+.mw-enhanced-watched .mw-enhanced-rc-time {
+       font-weight: bold;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css b/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css
new file mode 100644 (file)
index 0000000..54d09b4
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * Styling for changes list legend
+ */
+
+.mw-changeslist-legend {
+       float: right;
+       margin-left: 1em;
+       margin-bottom: 0.5em;
+       clear: right;
+       font-size: 85%;
+       line-height: 1.2em;
+       padding: 0.5em;
+       border: 1px solid #ddd;
+}
+
+.mw-changeslist-legend dl {
+       /* Parent element defines sufficient padding */
+       margin-bottom: 0;
+}
+
+.mw-changeslist-legend dt {
+       float: left;
+       margin-right: 0.5em;
+}
+
+.mw-changeslist-legend dd {
+       margin-left: 1.5em;
+       line-height: 1.3em;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.js b/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.js
new file mode 100644 (file)
index 0000000..0259155
--- /dev/null
@@ -0,0 +1,25 @@
+/**
+ * Script for changes list legend
+ */
+
+/* Remember the collapse state of the legend on recent changes and watchlist pages. */
+jQuery( document ).ready( function ( $ ) {
+       var
+               cookieName = 'changeslist-state',
+               cookieOptions = {
+                       expires: 30,
+                       path: '/'
+               },
+               isCollapsed = $.cookie( cookieName ) === 'collapsed';
+
+       $( '.mw-changeslist-legend' )
+               .makeCollapsible( {
+                       collapsed: isCollapsed
+               } )
+               .on( 'beforeExpand.mw-collapsible', function () {
+                       $.cookie( cookieName, 'expanded', cookieOptions );
+               } )
+               .on( 'beforeCollapse.mw-collapsible', function () {
+                       $.cookie( cookieName, 'collapsed', cookieOptions );
+               } );
+} );
diff --git a/resources/src/mediawiki.special/mediawiki.special.css b/resources/src/mediawiki.special/mediawiki.special.css
new file mode 100644 (file)
index 0000000..eb38936
--- /dev/null
@@ -0,0 +1,284 @@
+
+/**** Special:AllMessages ****/
+#mw-allmessagestable .allmessages-customised td.am_default {
+       background-color: #fcffc4;
+}
+
+#mw-allmessagestable tr.allmessages-customised:hover td.am_default {
+       background-color: #faff90;
+}
+
+#mw-allmessagestable td.am_actual {
+       background-color: #e2ffe2;
+}
+
+#mw-allmessagestable tr.allmessages-customised:hover + tr.allmessages-customised td.am_actual {
+       background-color: #b1ffb1;
+}
+
+/**** Special:Allpages ****/
+table.mw-allpages-table-form, table.mw-allpages-table-chunk {
+       width: 100%;
+}
+td.mw-allpages-alphaindexline {
+       text-align: right;
+}
+.mw-allpages-nav {
+       text-align: right;
+       margin-bottom: 1em;
+}
+table.mw-allpages-table-form tr {
+       vertical-align: top;
+}
+
+/**** Special:Block ****/
+tr.mw-block-hideuser {
+       font-weight: bold;
+}
+
+/**** Special:BlockList ****/
+table.mw-blocklist span.mw-usertoollinks,
+span.mw-blocklist-actions {
+       white-space: nowrap;
+       font-size: 90%;
+}
+
+/**** Special:Contributions ****/
+.mw-uctop {
+       font-weight: bold;
+}
+
+/**** Special:EmailUser ****/
+td#mw-emailuser-sender,
+td#mw-emailuser-recipient {
+       font-weight: bold;
+}
+
+/**** Special:ListGroupRights ****/
+table.mw-listgrouprights-table tr {
+       vertical-align: top;
+}
+.listgrouprights-revoked {
+       text-decoration: line-through;
+}
+
+/**** Special:Prefixindex ****/
+table#mw-prefixindex-list-table, /* HTML backwards-compatibility, to be removed before 1.23 */
+table.mw-prefixindex-list-table,
+table#mw-prefixindex-nav-table {
+       width: 100%;
+}
+td#mw-prefixindex-nav-form {
+       margin-bottom: 1em;
+       vertical-align: top;
+}
+.mw-prefixindex-nav {
+       text-align: right;
+}
+
+
+/**** Special:Search ****/
+.searchresults {
+}
+
+.searchresults p {
+       margin-left: 0.4em;
+       margin-top: 1em;
+       margin-bottom: 1.2em;
+}
+div.searchresult {
+       font-size: 95%;
+       width: 38em;
+}
+.mw-search-results {
+       margin-left: 0.4em;
+}
+.mw-search-results li {
+       padding-bottom: 1.2em;
+       list-style: none;
+       list-style-image: none;
+}
+.mw-search-results li a {
+       font-size: 108%;
+}
+.mw-search-result-data {
+       color: green;
+       font-size: 97%;
+}
+.mw-search-formheader {
+       background-color: #f3f3f3;
+       margin-top: 1em;
+       border: 1px solid silver;
+}
+.mw-search-formheader div.search-types {
+       float: left;
+       padding-left: 0.25em;
+}
+.mw-search-formheader div.search-types ul {
+       margin: 0 !important;
+       padding: 0 !important;
+       list-style: none !important;
+}
+.mw-search-formheader div.search-types ul li {
+       float: left;
+       margin: 0;
+       padding: 0;
+}
+.mw-search-formheader div.search-types ul li a {
+       display: block;
+       padding: 0.5em;
+}
+.mw-search-formheader div.search-types ul li.current a {
+       color: #333333;
+       cursor: default;
+}
+.mw-search-formheader div.search-types ul li.current a:hover {
+       text-decoration: none;
+}
+.mw-search-formheader div.results-info {
+       float: right;
+       padding: 0.5em;
+       padding-right: 0.75em;
+}
+.mw-search-formheader div.results-info ul {
+       margin: 0 !important;
+       padding: 0 !important;
+       list-style: none !important;
+}
+.mw-search-formheader div.results-info ul li {
+       float: right;
+       margin: 0;
+       padding: 0;
+}
+fieldset#mw-searchoptions {
+       margin: 0;
+       padding: 0.5em 0.75em 0.75em 0.75em !important;
+       border: none;
+       background-color: #f9f9f9;
+       border: 1px solid silver !important;
+       border-top-width: 0 !important;
+}
+fieldset#mw-searchoptions legend {
+       display: none;
+}
+fieldset#mw-searchoptions h4 {
+       padding: 0;
+       margin: 0;
+       float: left;
+}
+fieldset#mw-searchoptions div#mw-search-togglebox {
+       float: right;
+}
+fieldset#mw-searchoptions div#mw-search-togglebox label {
+       margin-right: 0.25em;
+}
+fieldset#mw-searchoptions div#mw-search-togglebox input {
+       margin-left: 0.25em;
+}
+fieldset#mw-searchoptions table {
+       float: left;
+       margin-right: 3em;
+}
+fieldset#mw-searchoptions table td {
+       padding-right: 1em;
+}
+fieldset#mw-searchoptions div.divider {
+       clear: both;
+       border-bottom: 1px solid #DDDDDD;
+       padding-top: 0.5em;
+       margin-bottom: 0.5em;
+}
+td#mw-search-menu {
+       padding-left:6em;
+       font-size:85%;
+}
+div#mw-search-interwiki {
+       float: right;
+       width: 18em;
+       border: 1px solid #AAAAAA;
+       margin-top: 2ex;
+}
+div#mw-search-interwiki li {
+       font-size: 95%;
+}
+.mw-search-interwiki-more {
+       float: right;
+       font-size: 90%;
+}
+div#mw-search-interwiki-caption {
+       text-align: center;
+       font-weight: bold;
+       font-size: 95%;
+}
+.mw-search-interwiki-project {
+       font-size: 97%;
+       text-align: left;
+       padding: 0.15em 0.15em 0.2em 0.2em;
+       background-color: #ececec;
+       border-top: 1px solid #BBBBBB;
+}
+span.searchalttitle {
+       font-size: 95%;
+}
+div.searchdidyoumean {
+       font-size: 127%;
+       margin-top: 0.8em;
+       /* Note that this color won't affect the link, as desired. */
+       color: #c00;
+}
+div.searchdidyoumean em {
+       font-weight: bold;
+}
+.searchmatch {
+       font-weight: bold;
+}
+/* Advanced PowerSearch box */
+td#mw-search-togglebox {
+       text-align: right;
+}
+table#mw-search-powertable {
+       width: 100%;
+}
+form#powersearch {
+       clear: both;
+}
+
+/**** Special:Specialpages ****/
+.mw-specialpagerestricted {
+       font-weight: bold;
+}
+
+.mw-specialpages-table {
+       margin-top: -1em;
+       margin-bottom: 1em;
+}
+
+.mw-specialpages-table td {
+       vertical-align: top;
+}
+
+/**** Special:Statistics ****/
+td.mw-statistics-numbers {
+       text-align: right;
+}
+
+/**** Special:ProtectedPages ****/
+table.mw-protectedpages span.mw-usertoollinks,
+span.mw-protectedpages-length,
+span.mw-protectedpages-actions {
+       white-space: nowrap;
+       font-size: 90%;
+}
+span.mw-protectedpages-unknown {
+       color: grey;
+       font-size: 90%;
+}
+
+/**** Special:UserRights ****/
+.mw-userrights-disabled {
+       color: #888;
+}
+table.mw-userrights-groups * td,
+table.mw-userrights-groups * th {
+       padding-right: 1.5em;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.javaScriptTest.js b/resources/src/mediawiki.special/mediawiki.special.javaScriptTest.js
new file mode 100644 (file)
index 0000000..38f256c
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * JavaScript for Special:JavaScriptTest
+ */
+( function ( mw, $ ) {
+       $( function () {
+
+               // Create useskin dropdown menu and reload onchange to the selected skin
+               // (only if a framework was found, not on error pages).
+               $( '#mw-javascripttest-summary.mw-javascripttest-frameworkfound' ).append( function () {
+
+                       var $html = $( '<p><label for="useskin">'
+                                       + mw.message( 'javascripttest-pagetext-skins' ).escaped()
+                                       + ' '
+                                       + '</label></p>' ),
+                               select = '<select name="useskin" id="useskin">';
+
+                       // Build <select> further
+                       $.each( mw.config.get( 'wgAvailableSkins' ), function ( id ) {
+                               select += '<option value="' + id + '"'
+                                       + ( mw.config.get( 'skin' ) === id ? ' selected="selected"' : '' )
+                                       + '>' + mw.message( 'skinname-' + id ).escaped() + '</option>';
+                       } );
+                       select += '</select>';
+
+                       // Bind onchange event handler and append to form
+                       $html.append(
+                               $( select ).change( function () {
+                                       window.location = QUnit.url( { useskin: $( this ).val() } );
+                               } )
+                       );
+
+                       return $html;
+               } );
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.special/mediawiki.special.js b/resources/src/mediawiki.special/mediawiki.special.js
new file mode 100644 (file)
index 0000000..8edb1cb
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * Namespace for mediawiki.special.* modules
+ */
+
+mediaWiki.special = {};
diff --git a/resources/src/mediawiki.special/mediawiki.special.movePage.js b/resources/src/mediawiki.special/mediawiki.special.movePage.js
new file mode 100644 (file)
index 0000000..922eba5
--- /dev/null
@@ -0,0 +1,6 @@
+/**
+ * JavaScript for Special:MovePage
+ */
+jQuery( function ( $ ) {
+       $( '#wpReason, #wpNewTitleMain' ).byteLimit();
+} );
diff --git a/resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css b/resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css
new file mode 100644 (file)
index 0000000..7ef75d0
--- /dev/null
@@ -0,0 +1,4 @@
+/* Distinguish actual data from information about it being hidden visually */
+.prop-value-hidden {
+       font-style: italic;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.preferences.css b/resources/src/mediawiki.special/mediawiki.special.preferences.css
new file mode 100644 (file)
index 0000000..75ae5ca
--- /dev/null
@@ -0,0 +1,21 @@
+/** Reuses colors from mediawiki.special.changeemail.css */
+.mw-email-not-authenticated .mw-input,
+.mw-email-none .mw-input{
+       border: 1px solid #FF8080;
+       background-color: #FFC0C0;
+       color: black;
+}
+/** Authenticated email field has its own class too. Unstyled by default */
+/*
+.mw-email-authenticated .mw-input { }
+*/
+
+/**
+ * Hide, but keep accessible for screen-readers.
+ * Like .mw-jump, #jump-to-nav from skins/common/shared.css
+ */
+.mw-navigation-hint {
+       overflow: hidden;
+       height: 0;
+       zoom: 1;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.preferences.js b/resources/src/mediawiki.special/mediawiki.special.preferences.js
new file mode 100644 (file)
index 0000000..2cd27af
--- /dev/null
@@ -0,0 +1,267 @@
+/**
+ * JavaScript for Special:Preferences
+ */
+jQuery( function ( $ ) {
+       var $preftoc, $preferences, $fieldsets, $legends,
+               hash, labelFunc,
+               $tzSelect, $tzTextbox, $localtimeHolder, servertime,
+               $checkBoxes;
+
+       labelFunc = function () {
+               return this.id.replace( /^mw-prefsection/g, 'preftab' );
+       };
+
+       $( '#prefsubmit' ).attr( 'id', 'prefcontrol' );
+       $preftoc = $( '<ul id="preftoc"></ul>' )
+               .attr( 'role', 'tablist' );
+       $preferences = $( '#preferences' )
+               .addClass( 'jsprefs' )
+               .before( $preftoc );
+       $fieldsets = $preferences.children( 'fieldset' )
+               .hide()
+               .attr( {
+                       role: 'tabpanel',
+                       'aria-hidden': 'true',
+                       'aria-labelledby': labelFunc
+               } )
+               .addClass( 'prefsection' );
+       $legends = $fieldsets
+               .children( 'legend' )
+               .addClass( 'mainLegend' );
+
+       // Make sure the accessibility tip is selectable so that screen reader users take notice,
+       // but hide it per default to reduce interface clutter. Also make sure it becomes visible
+       // when selected. Similar to jquery.mw-jump
+       $( '<div>' ).addClass( 'mw-navigation-hint' )
+               .text( mediaWiki.msg( 'prefs-tabs-navigation-hint' ) )
+               .attr( 'tabIndex', 0 )
+               .on( 'focus blur', function ( e ) {
+                       if ( e.type === 'blur' || e.type === 'focusout' ) {
+                               $( this ).css( 'height', '0' );
+                       } else {
+                               $( this ).css( 'height', 'auto' );
+                       }
+       } ).insertBefore( $preftoc );
+
+       /**
+        * It uses document.getElementById for security reasons (HTML injections in $()).
+        *
+        * @param String name: the name of a tab without the prefix ("mw-prefsection-")
+        * @param String mode: [optional] A hash will be set according to the current
+        * open section. Set mode 'noHash' to surpress this.
+        */
+       function switchPrefTab( name, mode ) {
+               var $tab, scrollTop;
+               // Handle hash manually to prevent jumping,
+               // therefore save and restore scrollTop to prevent jumping.
+               scrollTop = $( window ).scrollTop();
+               if ( mode !== 'noHash' ) {
+                       window.location.hash = '#mw-prefsection-' + name;
+               }
+               $( window ).scrollTop( scrollTop );
+
+               $preftoc.find( 'li' ).removeClass( 'selected' )
+                       .find( 'a' ).attr( {
+                               tabIndex: -1,
+                               'aria-selected': 'false'
+                       } );
+
+               $tab = $( document.getElementById( 'preftab-' + name ) );
+               if ( $tab.length ) {
+                       $tab.attr( {
+                               tabIndex: 0,
+                               'aria-selected': 'true'
+                       } )
+                       .focus()
+                               .parent().addClass( 'selected' );
+
+                       $preferences.children( 'fieldset' ).hide().attr( 'aria-hidden', 'true' );
+                       $( document.getElementById( 'mw-prefsection-' + name ) ).show().attr( 'aria-hidden', 'false' );
+               }
+       }
+
+       // Populate the prefToc
+       $legends.each( function ( i, legend ) {
+               var $legend = $( legend ),
+                       ident, $li, $a;
+               if ( i === 0 ) {
+                       $legend.parent().show();
+               }
+               ident = $legend.parent().attr( 'id' );
+
+               $li = $( '<li>' )
+                       .attr( 'role', 'presentation' )
+                       .addClass( i === 0 ? 'selected' : '' );
+               $a = $( '<a>' )
+                       .attr( {
+                               id: ident.replace( 'mw-prefsection', 'preftab' ),
+                               href: '#' + ident,
+                               role: 'tab',
+                               tabIndex: i === 0 ? 0 : -1,
+                               'aria-selected': i === 0 ? 'true' : 'false',
+                               'aria-controls': ident
+                       } )
+                       .text( $legend.text() );
+               $li.append( $a );
+               $preftoc.append( $li );
+       } );
+
+       // Enable keyboard users to use left and right keys to switch tabs
+       $preftoc.on( 'keydown', function ( event ) {
+               var keyLeft = 37,
+                       keyRight = 39,
+                       $el;
+
+               if ( event.keyCode === keyLeft ) {
+                       $el = $( '#preftoc li.selected' ).prev().find( 'a' );
+               } else if ( event.keyCode === keyRight ) {
+                       $el = $( '#preftoc li.selected' ).next().find( 'a' );
+               } else {
+                       return;
+               }
+               if ( $el.length > 0 ) {
+                       switchPrefTab( $el.attr( 'href' ).replace( '#mw-prefsection-', '' ) );
+               }
+       } );
+
+       // If we've reloaded the page or followed an open-in-new-window,
+       // make the selected tab visible.
+       hash = window.location.hash;
+       if ( hash.match( /^#mw-prefsection-[\w\-]+/ ) ) {
+               switchPrefTab( hash.replace( '#mw-prefsection-', '' ) );
+       }
+
+       // In browsers that support the onhashchange event we will not bind click
+       // handlers and instead let the browser do the default behavior (clicking the
+       // <a href="#.."> will naturally set the hash, handled by onhashchange.
+       // But other things that change the hash will also be catched (e.g. using
+       // the Back and Forward browser navigation).
+       // Note the special check for IE "compatibility" mode.
+       if ( 'onhashchange' in window &&
+               ( document.documentMode === undefined || document.documentMode >= 8 )
+       ) {
+               $( window ).on( 'hashchange', function () {
+                       var hash = window.location.hash;
+                       if ( hash.match( /^#mw-prefsection-[\w\-]+/ ) ) {
+                               switchPrefTab( hash.replace( '#mw-prefsection-', '' ) );
+                       } else if ( hash === '' ) {
+                               switchPrefTab( 'personal', 'noHash' );
+                       }
+               } );
+       // In older browsers we'll bind a click handler as fallback.
+       // We must not have onhashchange *and* the click handlers, other wise
+       // the click handler calls switchPrefTab() which sets the hash value,
+       // which triggers onhashcange and calls switchPrefTab() again.
+       } else {
+               $preftoc.on( 'click', 'li a', function ( e ) {
+                       switchPrefTab( $( this ).attr( 'href' ).replace( '#mw-prefsection-', '' ) );
+                       e.preventDefault();
+               } );
+       }
+
+       /**
+       * Timezone functions.
+       * Guesses Timezone from browser and updates fields onchange
+       */
+
+       $tzSelect = $( '#mw-input-wptimecorrection' );
+       $tzTextbox = $( '#mw-input-wptimecorrection-other' );
+       $localtimeHolder = $( '#wpLocalTime' );
+       servertime = parseInt( $( 'input[name="wpServerTime"]' ).val(), 10 );
+
+       function minutesToHours( min ) {
+               var tzHour = Math.floor( Math.abs( min ) / 60 ),
+                       tzMin = Math.abs( min ) % 60,
+                       tzString = ( ( min >= 0 ) ? '' : '-' ) + ( ( tzHour < 10 ) ? '0' : '' ) + tzHour +
+                               ':' + ( ( tzMin < 10 ) ? '0' : '' ) + tzMin;
+               return tzString;
+       }
+
+       function hoursToMinutes( hour ) {
+               var minutes,
+                       arr = hour.split( ':' );
+
+               arr[0] = parseInt( arr[0], 10 );
+
+               if ( arr.length === 1 ) {
+                       // Specification is of the form [-]XX
+                       minutes = arr[0] * 60;
+               } else {
+                       // Specification is of the form [-]XX:XX
+                       minutes = Math.abs( arr[0] ) * 60 + parseInt( arr[1], 10 );
+                       if ( arr[0] < 0 ) {
+                               minutes *= -1;
+                       }
+               }
+               // Gracefully handle non-numbers.
+               if ( isNaN( minutes ) ) {
+                       return 0;
+               } else {
+                       return minutes;
+               }
+       }
+
+       function updateTimezoneSelection () {
+               var minuteDiff, localTime,
+                       type = $tzSelect.val();
+
+               if ( type === 'guess' ) {
+                       // Get browser timezone & fill it in
+                       minuteDiff = -( new Date().getTimezoneOffset() );
+                       $tzTextbox.val( minutesToHours( minuteDiff ) );
+                       $tzSelect.val( 'other' );
+                       $tzTextbox.prop( 'disabled', false );
+               } else if ( type === 'other' ) {
+                       // Grab data from the textbox, parse it.
+                       minuteDiff = hoursToMinutes( $tzTextbox.val() );
+               } else {
+                       // Grab data from the $tzSelect value
+                       minuteDiff = parseInt( type.split( '|' )[1], 10 ) || 0;
+                       $tzTextbox.val( minutesToHours( minuteDiff ) );
+               }
+
+               // Determine local time from server time and minutes difference, for display.
+               localTime = servertime + minuteDiff;
+
+               // Bring time within the [0,1440) range.
+               while ( localTime < 0 ) {
+                       localTime += 1440;
+               }
+               while ( localTime >= 1440 ) {
+                       localTime -= 1440;
+               }
+               $localtimeHolder.text( mediaWiki.language.convertNumber( minutesToHours( localTime ) ) );
+       }
+
+       if ( $tzSelect.length && $tzTextbox.length ) {
+               $tzSelect.change( updateTimezoneSelection );
+               $tzTextbox.blur( updateTimezoneSelection );
+               updateTimezoneSelection();
+       }
+
+       // Preserve the tab after saving the preferences
+       // Not using cookies, because their deletion results are inconsistent.
+       // Not using jStorage due to its enormous size (for this feature)
+       if ( window.sessionStorage ) {
+               if ( sessionStorage.getItem( 'mediawikiPreferencesTab' ) !== null ) {
+                       switchPrefTab( sessionStorage.getItem( 'mediawikiPreferencesTab' ), 'noHash' );
+               }
+               // Deleting the key, the tab states should be reset until we press Save
+               sessionStorage.removeItem( 'mediawikiPreferencesTab' );
+
+               $( '#mw-prefs-form' ).submit( function () {
+                       var storageData = $( $preftoc ).find( 'li.selected a' ).attr( 'id' ).replace( 'preftab-', '' );
+                       sessionStorage.setItem( 'mediawikiPreferencesTab', storageData );
+               } );
+       }
+
+       // To disable all 'namespace' checkboxes in Search preferences
+       // when 'Search in all namespaces' checkbox is ticked.
+       $checkBoxes = $( '#mw-htmlform-advancedsearchoptions input[id^=mw-input-wpsearchnamespaces]' );
+       if ( $( '#mw-input-wpsearcheverything' ).prop( 'checked' ) ) {
+               $checkBoxes.prop( 'disabled', true );
+       }
+       $( '#mw-input-wpsearcheverything' ).change( function () {
+               $checkBoxes.prop( 'disabled', $( this ).prop( 'checked' ) );
+       } );
+} );
diff --git a/resources/src/mediawiki.special/mediawiki.special.recentchanges.js b/resources/src/mediawiki.special/mediawiki.special.recentchanges.js
new file mode 100644 (file)
index 0000000..79d793a
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * JavaScript for Special:RecentChanges
+ */
+( function ( mw, $ ) {
+       var rc, $checkboxes, $select;
+
+       rc = {
+               /**
+                * Handler to disable/enable the namespace selector checkboxes when the
+                * special 'all' namespace is selected/unselected respectively.
+                */
+               updateCheckboxes: function () {
+                       // The option element for the 'all' namespace has an empty value
+                       var isAllNS = $select.val() === '';
+
+                       // Iterates over checkboxes and propagate the selected option
+                       $checkboxes.prop( 'disabled', isAllNS );
+               },
+
+               init: function () {
+                       $select = $( '#namespace' );
+                       $checkboxes = $( '#nsassociated, #nsinvert' );
+
+                       // Bind to change event, and trigger once to set the initial state of the checkboxes.
+                       rc.updateCheckboxes();
+                       $select.change( rc.updateCheckboxes );
+               }
+       };
+
+       $( rc.init );
+
+       mw.special.recentchanges = rc;
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.special/mediawiki.special.search.css b/resources/src/mediawiki.special/mediawiki.special.search.css
new file mode 100644 (file)
index 0000000..914e47e
--- /dev/null
@@ -0,0 +1,14 @@
+/**
+ * Fixes sister projects box moving down the extract
+ * of the first result (bug #16886).
+ * It only happens when the window is small and
+ * This changes slightly the layout for big screens
+ * where there was space for the extracts and the
+ * sister projects and thus it showed like in any
+ * other browser.
+ *
+ * This will only affect IE 7 and lower
+ */
+.searchresult {
+       display: inline !ie;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.search.js b/resources/src/mediawiki.special/mediawiki.special.search.js
new file mode 100644 (file)
index 0000000..b847f7d
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * JavaScript for Special:Search
+ */
+( function ( mw, $ ) {
+       $( function () {
+               var $checkboxes, $headerLinks;
+
+               // Emulate HTML5 autofocus behavior in non HTML5 compliant browsers
+               if ( !( 'autofocus' in document.createElement( 'input' ) ) ) {
+                       $( 'input[autofocus]' ).eq( 0 ).focus();
+               }
+
+               // Create check all/none button
+               $checkboxes = $( '#powersearch input[id^=mw-search-ns]' );
+               $( '#mw-search-togglebox' ).append(
+                       $( '<label>' )
+                               .text( mw.msg( 'powersearch-togglelabel' ) )
+               ).append(
+                       $( '<input type="button" />' )
+                               .attr( 'id', 'mw-search-toggleall' )
+                               .prop( 'value', mw.msg( 'powersearch-toggleall' ) )
+                               .click( function () {
+                                       $checkboxes.prop( 'checked', true );
+                               } )
+               ).append(
+                       $( '<input type="button" />' )
+                               .attr( 'id', 'mw-search-togglenone' )
+                               .prop( 'value', mw.msg( 'powersearch-togglenone' ) )
+                               .click( function () {
+                                       $checkboxes.prop( 'checked', false );
+                               } )
+               );
+
+               // Change the header search links to what user entered
+               $headerLinks = $( '.search-types a' );
+               $( '#searchText, #powerSearchText' ).change( function () {
+                       var searchterm = $( this ).val();
+                       $headerLinks.each( function () {
+                               var parts = $( this ).attr( 'href' ).split( 'search=' ),
+                                       lastpart = '',
+                                       prefix = 'search=';
+                               if ( parts.length > 1 && parts[1].indexOf( '&' ) >= 0 ) {
+                                       lastpart = parts[1].substring( parts[1].indexOf( '&' ) );
+                               } else {
+                                       prefix = '&search=';
+                               }
+                               this.href = parts[0] + prefix + encodeURIComponent( searchterm ) + lastpart;
+                       } );
+               } ).trigger( 'change' );
+
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.special/mediawiki.special.undelete.js b/resources/src/mediawiki.special/mediawiki.special.undelete.js
new file mode 100644 (file)
index 0000000..0dea3ef
--- /dev/null
@@ -0,0 +1,11 @@
+/**
+ * JavaScript for Special:Undelete
+ */
+jQuery( function ( $ ) {
+       $( '#mw-undelete-invert' ).click( function ( e ) {
+               $( '#undelete input[type="checkbox"]' ).prop( 'checked', function ( i, val ) {
+                       return !val;
+               } );
+               e.preventDefault();
+       } );
+} );
diff --git a/resources/src/mediawiki.special/mediawiki.special.upload.js b/resources/src/mediawiki.special/mediawiki.special.upload.js
new file mode 100644 (file)
index 0000000..8a5ff59
--- /dev/null
@@ -0,0 +1,319 @@
+/**
+ * JavaScript for Special:Upload
+ * Note that additional code still lives in skins/common/upload.js
+ */
+( function ( mw, $ ) {
+       /**
+        * Add a preview to the upload form
+        */
+       $( function () {
+               /**
+                * Is the FileAPI available with sufficient functionality?
+                */
+               function hasFileAPI() {
+                       return window.FileReader !== undefined;
+               }
+
+               /**
+                * Check if this is a recognizable image type...
+                * Also excludes files over 10M to avoid going insane on memory usage.
+                *
+                * @todo is there a way we can ask the browser what's supported in <img>s?
+                * @todo put SVG back after working around Firefox 7 bug <https://bugzilla.wikimedia.org/show_bug.cgi?id=31643>
+                *
+                * @param {File} file
+                * @return boolean
+                */
+               function fileIsPreviewable( file ) {
+                       var known = ['image/png', 'image/gif', 'image/jpeg', 'image/svg+xml'],
+                               tooHuge = 10 * 1024 * 1024;
+                       return ( $.inArray( file.type, known ) !== -1 ) && file.size > 0 && file.size < tooHuge;
+               }
+
+               /**
+                * Show a thumbnail preview of PNG, JPEG, GIF, and SVG files prior to upload
+                * in browsers supporting HTML5 FileAPI.
+                *
+                * As of this writing, known good:
+                * - Firefox 3.6+
+                * - Chrome 7.something
+                *
+                * @todo check file size limits and warn of likely failures
+                *
+                * @param {File} file
+                */
+               function showPreview( file ) {
+                       var $canvas,
+                               ctx,
+                               meta,
+                               previewSize = 180,
+                               thumb = $( '<div id="mw-upload-thumbnail" class="thumb tright">' +
+                                                       '<div class="thumbinner">' +
+                                                               '<div class="mw-small-spinner" style="width: 180px; height: 180px"></div>' +
+                                                               '<div class="thumbcaption"><div class="filename"></div><div class="fileinfo"></div></div>' +
+                                                       '</div>' +
+                                               '</div>' );
+
+                       thumb.find( '.filename' ).text( file.name ).end()
+                               .find( '.fileinfo' ).text( prettySize( file.size ) ).end();
+
+                       $canvas = $( '<canvas width="' + previewSize + '" height="' + previewSize + '" ></canvas>' );
+                       ctx = $canvas[0].getContext( '2d' );
+                       $( '#mw-htmlform-source' ).parent().prepend( thumb );
+
+                       fetchPreview( file, function ( dataURL ) {
+                               var img = new Image(),
+                                       rotation = 0;
+
+                               if ( meta && meta.tiff && meta.tiff.Orientation ) {
+                                       rotation = ( 360 - ( function () {
+                                               // See includes/media/Bitmap.php
+                                               switch ( meta.tiff.Orientation.value ) {
+                                                       case 8:
+                                                               return 90;
+                                                       case 3:
+                                                               return 180;
+                                                       case 6:
+                                                               return 270;
+                                                       default:
+                                                               return 0;
+                                               }
+                                       }() ) ) % 360;
+                               }
+
+                               img.onload = function () {
+                                       var info, width, height, x, y, dx, dy, logicalWidth, logicalHeight;
+
+                                       // Fit the image within the previewSizexpreviewSize box
+                                       if ( img.width > img.height ) {
+                                               width = previewSize;
+                                               height = img.height / img.width * previewSize;
+                                       } else {
+                                               height = previewSize;
+                                               width = img.width / img.height * previewSize;
+                                       }
+                                       // Determine the offset required to center the image
+                                       dx = ( 180 - width ) / 2;
+                                       dy = ( 180 - height ) / 2;
+                                       switch ( rotation ) {
+                                               // If a rotation is applied, the direction of the axis
+                                               // changes as well. You can derive the values below by
+                                               // drawing on paper an axis system, rotate it and see
+                                               // where the positive axis direction is
+                                               case 0:
+                                                       x = dx;
+                                                       y = dy;
+                                                       logicalWidth = img.width;
+                                                       logicalHeight = img.height;
+                                                       break;
+                                               case 90:
+
+                                                       x = dx;
+                                                       y = dy - previewSize;
+                                                       logicalWidth = img.height;
+                                                       logicalHeight = img.width;
+                                                       break;
+                                               case 180:
+                                                       x = dx - previewSize;
+                                                       y = dy - previewSize;
+                                                       logicalWidth = img.width;
+                                                       logicalHeight = img.height;
+                                                       break;
+                                               case 270:
+                                                       x = dx - previewSize;
+                                                       y = dy;
+                                                       logicalWidth = img.height;
+                                                       logicalHeight = img.width;
+                                                       break;
+                                       }
+
+                                       ctx.clearRect( 0, 0, 180, 180 );
+                                       ctx.rotate( rotation / 180 * Math.PI );
+                                       ctx.drawImage( img, x, y, width, height );
+                                       thumb.find( '.mw-small-spinner' ).replaceWith( $canvas );
+
+                                       // Image size
+                                       info = mw.msg( 'widthheight', logicalWidth, logicalHeight ) +
+                                               ', ' + prettySize( file.size );
+
+                                       $( '#mw-upload-thumbnail .fileinfo' ).text( info );
+                               };
+                               img.src = dataURL;
+                       }, mw.config.get( 'wgFileCanRotate' ) ? function ( data ) {
+                               /*jshint camelcase:false, nomen:false */
+                               try {
+                                       meta = mw.libs.jpegmeta( data, file.fileName );
+                                       meta._binary_data = null;
+                               } catch ( e ) {
+                                       meta = null;
+                               }
+                       } : null );
+               }
+
+               /**
+                * Start loading a file into memory; when complete, pass it as a
+                * data URL to the callback function. If the callbackBinary is set it will
+                * first be read as binary and afterwards as data URL. Useful if you want
+                * to do preprocessing on the binary data first.
+                *
+                * @param {File} file
+                * @param {function} callback
+                * @param {function} callbackBinary
+                */
+               function fetchPreview( file, callback, callbackBinary ) {
+                       var reader = new FileReader();
+                       if ( callbackBinary && 'readAsBinaryString' in reader ) {
+                               // To fetch JPEG metadata we need a binary string; start there.
+                               // todo:
+                               reader.onload = function () {
+                                       callbackBinary( reader.result );
+
+                                       // Now run back through the regular code path.
+                                       fetchPreview( file, callback );
+                               };
+                               reader.readAsBinaryString( file );
+                       } else if ( callbackBinary && 'readAsArrayBuffer' in reader ) {
+                               // readAsArrayBuffer replaces readAsBinaryString
+                               // However, our JPEG metadata library wants a string.
+                               // So, this is going to be an ugly conversion.
+                               reader.onload = function () {
+                                       var i,
+                                               buffer = new Uint8Array( reader.result ),
+                                               string = '';
+                                       for ( i = 0; i < buffer.byteLength; i++ ) {
+                                               string += String.fromCharCode( buffer[i] );
+                                       }
+                                       callbackBinary( string );
+
+                                       // Now run back through the regular code path.
+                                       fetchPreview( file, callback );
+                               };
+                               reader.readAsArrayBuffer( file );
+                       } else if ( 'URL' in window && 'createObjectURL' in window.URL ) {
+                               // Supported in Firefox 4.0 and above <https://developer.mozilla.org/en/DOM/window.URL.createObjectURL>
+                               // WebKit has it in a namespace for now but that's ok. ;)
+                               //
+                               // Lifetime of this URL is until document close, which is fine
+                               // for Special:Upload -- if this code gets used on longer-running
+                               // pages, add a revokeObjectURL() when it's no longer needed.
+                               //
+                               // Prefer this over readAsDataURL for Firefox 7 due to bug reading
+                               // some SVG files from data URIs <https://bugzilla.mozilla.org/show_bug.cgi?id=694165>
+                               callback( window.URL.createObjectURL( file ) );
+                       } else {
+                               // This ends up decoding the file to base-64 and back again, which
+                               // feels horribly inefficient.
+                               reader.onload = function () {
+                                       callback( reader.result );
+                               };
+                               reader.readAsDataURL( file );
+                       }
+               }
+
+               /**
+                * Format a file size attractively.
+                * @todo match numeric formatting
+                *
+                * @param {number} s
+                * @return string
+                */
+               function prettySize( s ) {
+                       var sizeMsgs = ['size-bytes', 'size-kilobytes', 'size-megabytes', 'size-gigabytes'];
+                       while ( s >= 1024 && sizeMsgs.length > 1 ) {
+                               s /= 1024;
+                               sizeMsgs = sizeMsgs.slice( 1 );
+                       }
+                       return mw.msg( sizeMsgs[0], Math.round( s ) );
+               }
+
+               /**
+                * Clear the file upload preview area.
+                */
+               function clearPreview() {
+                       $( '#mw-upload-thumbnail' ).remove();
+               }
+
+               /**
+                * Check if the file does not exceed the maximum size
+                */
+               function checkMaxUploadSize( file ) {
+                       var maxSize, $error;
+
+                       function getMaxUploadSize( type ) {
+                               var sizes = mw.config.get( 'wgMaxUploadSize' );
+
+                               if ( sizes[type] !== undefined ) {
+                                       return sizes[type];
+                               }
+                               return sizes['*'];
+                       }
+
+                       $( '.mw-upload-source-error' ).remove();
+
+                       maxSize = getMaxUploadSize( 'file' );
+                       if ( file.size > maxSize ) {
+                               $error = $( '<p class="error mw-upload-source-error" id="wpSourceTypeFile-error">' +
+                                       mw.message( 'largefileserver', file.size, maxSize ).escaped() + '</p>' );
+
+                               $( '#wpUploadFile' ).after( $error );
+
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               /**
+                * Initialization
+                */
+               if ( hasFileAPI() ) {
+                       // Update thumbnail when the file selection control is updated.
+                       $( '#wpUploadFile' ).change( function () {
+                               clearPreview();
+                               if ( this.files && this.files.length ) {
+                                       // Note: would need to be updated to handle multiple files.
+                                       var file = this.files[0];
+
+                                       if ( !checkMaxUploadSize( file ) ) {
+                                               return;
+                                       }
+
+                                       if ( fileIsPreviewable( file ) ) {
+                                               showPreview( file );
+                                       }
+                               }
+                       } );
+               }
+       } );
+
+       /**
+        * Disable all upload source fields except the selected one
+        */
+       $( function () {
+               var i, $row,
+                       $rows = $( '.mw-htmlform-field-UploadSourceField' );
+
+               function createHandler( $currentRow ) {
+                       /**
+                        * @param {jQuery.Event}
+                        */
+                       return function () {
+                               $( '.mw-upload-source-error' ).remove();
+                               if ( this.checked ) {
+                                       // Disable all inputs
+                                       $rows.find( 'input[name!="wpSourceType"]' ).prop( 'disabled', true );
+                                       // Re-enable the current one
+                                       $currentRow.find( 'input' ).prop( 'disabled', false );
+                               }
+                       };
+               }
+
+               for ( i = $rows.length; i; i-- ) {
+                       $row = $rows.eq( i - 1 );
+                       $row
+                               .find( 'input[name="wpSourceType"]' )
+                               .change( createHandler( $row ) );
+               }
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.special/mediawiki.special.userlogin.common.css b/resources/src/mediawiki.special/mediawiki.special.userlogin.common.css
new file mode 100644 (file)
index 0000000..d5fd2b8
--- /dev/null
@@ -0,0 +1,65 @@
+/* Styles for user login and signup forms */
+#mw-userlogin-help {
+       text-align: center;
+}
+
+.mw-ui-vform .mw-secure {
+       /* @embed */
+       background: url(images/icon-lock.png) no-repeat scroll left center transparent;
+       margin: 0 0 0 1px;
+       padding: 0 0 0 11px;
+}
+
+/*
+ * When inside the VForm style, disable the border that Vector and other skins
+ * put on the div surrounding the login/create account form.
+ * Also disable the margin and padding that Vector puts around the form.
+ */
+.mw-ui-container #userloginForm,
+.mw-ui-container #userlogin {
+       border: 0;
+       margin: 0;
+       padding: 0;
+}
+
+/* Reposition and resize language links, which appear on a per-wiki basis */
+.mw-ui-container #languagelinks {
+       margin-bottom: 2em;
+       font-size: 0.8em;
+}
+
+/* Put some space under template's header, which may contain CAPTCHA HTML.*/
+section.mw-form-header {
+       margin-bottom: 10px;
+}
+
+/**** shuffled CAPTCHA ****/
+#wpCaptchaWord {
+       margin-top: 6px;
+}
+
+.mw-createacct-captcha-container {
+       background-color: #f8f8f8;
+       border: 1px solid #c9c9c9;
+       padding: 10px;
+       text-align: center;
+}
+
+.mw-createacct-captcha-assisted {
+       display: block;
+       margin-top: 0.5em;
+}
+
+/* Put a border around the fancycaptcha-image-container. */
+.mw-createacct-captcha-and-reload {
+       border: 1px solid #c9c9c9;
+       /* Other display formats end up too wide */
+       display: table-cell;
+       width: 270px;
+       background-color: #FFF;
+}
+
+/* Make the fancycaptcha-image-container full-width within its parent. */
+.fancycaptcha-image-container {
+       width: 100%;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.userlogin.common.js b/resources/src/mediawiki.special/mediawiki.special.userlogin.common.js
new file mode 100644 (file)
index 0000000..a899ae7
--- /dev/null
@@ -0,0 +1,72 @@
+/**
+ * JavaScript for login and signup forms.
+ */
+( function ( mw, $ ) {
+       // Move the FancyCaptcha image into a more attractive container.
+       // The CAPTCHA is in a <div class="captcha"> at the top of the form. If it's a FancyCaptcha,
+       // then we remove it and insert it lower down, in a customized div with just what we need (e.g.
+       // no 'fancycaptcha-createaccount' message).
+       function adjustFancyCaptcha( $content, buttonSubmit ) {
+               var $submit = $content.find( buttonSubmit ),
+                       tabIndex,
+                       $captchaStuff,
+                       $captchaImageContainer,
+                       // JavaScript can't yet parse the message 'createacct-imgcaptcha-help' when it
+                       // contains a MediaWiki transclusion, so PHP parses it and sends the HTML.
+                       // This is only set for the signup form (and undefined for login).
+                       helpMsg = mw.config.get( 'wgCreateacctImgcaptchaHelp' ),
+                       helpHtml = '';
+
+               if ( !$submit.length ) {
+                       return;
+               }
+               tabIndex = $submit.prop( 'tabindex' ) - 1;
+               $captchaStuff = $content.find( '.captcha' );
+
+               if ( $captchaStuff.length ) {
+                       // The FancyCaptcha has this class in the ConfirmEdit extension since 2013-04-18.
+                       $captchaImageContainer = $captchaStuff.find( '.fancycaptcha-image-container' );
+                       if ( $captchaImageContainer.length !== 1 ) {
+                               return;
+                       }
+
+                       $captchaStuff.remove();
+
+                       if ( helpMsg ) {
+                               helpHtml = '<small class="mw-createacct-captcha-assisted">' + helpMsg + '</small>';
+                       }
+
+                       // Insert another div before the submit button that will include the
+                       // repositioned FancyCaptcha div, an input field, and possible help.
+                       $submit.closest( 'div' ).before( [
+                               '<div>',
+                                       '<label for="wpCaptchaWord">' + mw.message( 'createacct-captcha' ).escaped() + '</label>',
+                                       '<div class="mw-createacct-captcha-container">',
+                                               '<div class="mw-createacct-captcha-and-reload" />',
+                                               '<input id="wpCaptchaWord" name="wpCaptchaWord" type="text" placeholder="' +
+                                                       mw.message( 'createacct-imgcaptcha-ph' ).escaped() +
+                                                       '" tabindex="' + tabIndex + '" autocapitalize="off" autocorrect="off">',
+                                                       helpHtml,
+                                       '</div>',
+                               '</div>'
+                       ].join( '' ) );
+
+                       // Stick the FancyCaptcha container inside our bordered and framed parents.
+                       $captchaImageContainer
+                               .prependTo( $content.find( '.mw-createacct-captcha-and-reload' ) );
+
+                       // Find the input field, add the text (if any) of the existing CAPTCHA
+                       // field (although usually it's blanked out on every redisplay),
+                       // and after it move over the hidden field that tells the CAPTCHA
+                       // what to do.
+                       $content.find( '#wpCaptchaWord' )
+                               .val( $captchaStuff.find( '#wpCaptchaWord' ).val() )
+                               .after( $captchaStuff.find( '#wpCaptchaId' ) );
+               }
+       }
+
+       $( function () {
+               // Work with both login and signup form
+               adjustFancyCaptcha( $( '#mw-content-text' ), '#wpCreateaccount, #wpLoginAttempt' );
+       } );
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.special/mediawiki.special.userlogin.login.css b/resources/src/mediawiki.special/mediawiki.special.userlogin.login.css
new file mode 100644 (file)
index 0000000..dc44c84
--- /dev/null
@@ -0,0 +1,24 @@
+/* The login form invites users to create an account */
+#mw-createaccount-cta {
+       width: 20em;
+       height: 10em;
+       /* @embed */
+       background: url(images/glyph-people-large.png) no-repeat 50%;
+       margin: 0 auto;
+       padding-top: 4em;
+}
+
+#mw-createaccount-cta,
+#mw-createaccount-another {
+       font-size: 0.9em;
+       font-weight: normal;
+       text-align: center;
+}
+
+#mw-createaccount-join {
+       margin-left: 0.75em;
+       /* Separate from background image */
+       box-shadow: 4px 4px 4px 4px rgba(255, 255, 255, 1);
+       width: auto;
+       display: inline-block;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css b/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css
new file mode 100644 (file)
index 0000000..0998d4c
--- /dev/null
@@ -0,0 +1,66 @@
+/* Disable the underline that Vector puts on h2 headings, and bold them. */
+.mw-ui-container h2 {
+       border: 0;
+       font-weight: bold;
+}
+
+/* Benefits column CSS to the right (if it fits) of the form. */
+.mw-ui-container #userloginForm {
+       float: left;
+       /* Override the right margin of the form to give space in case a benefits
+        * column appears to the side. */
+       margin-right: 100px;
+}
+
+div.mw-createacct-benefits-container {
+       /* Keeps this column compact and close to the form, but tends to squish contents. */
+       float: left;
+}
+
+div.mw-createacct-benefits-container h2 {
+       margin-bottom: 30px;
+}
+
+.mw-number-text.icon-edits {
+       /* @embed */
+       background: url(images/icon-edits.png) no-repeat left center;
+}
+
+.mw-number-text.icon-pages {
+       /* @embed */
+       background: url(images/icon-pages.png) no-repeat left center;
+}
+
+.mw-number-text.icon-contributors {
+       /* @embed */
+       background: url(images/icon-contributors.png) no-repeat left center;
+}
+
+/*
+ * Special font for numbers in benefits, same as Vector's @content-heading-font-family.
+ * Needs an ID so that it's more specific than Vector's div#content h3.
+ */
+#bodyContent div.mw-number-text h3 {
+       top: 0;
+       margin: 0;
+       padding: 0;
+       color: #252525;
+       font-family: "Linux Libertine", Georgia, Times, serif;
+       font-weight: normal;
+       font-size: 2.2em;
+       line-height: 1.2;
+       text-align: center;
+}
+
+/* Contains a number and explanatory text, with space for an icon */
+div.mw-number-text {
+       display: block;
+       font-size: 1.2em;
+       color: #444;
+       margin-top: 1em;
+       /* 80px wide icon plus "margin" */
+       padding: 0 0 0 95px;
+       /* Matches max icon height, ensures icon emblem is visible */
+       min-height: 75px;
+       text-align: center;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js b/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js
new file mode 100644 (file)
index 0000000..0615932
--- /dev/null
@@ -0,0 +1,140 @@
+/**
+ * JavaScript for signup form.
+ */
+( function ( mw, $ ) {
+       // When sending password by email, hide the password input fields.
+       $( function () {
+               // Always required if checked, otherwise it depends, so we use the original
+               var $emailLabel = $( 'label[for="wpEmail"]' ),
+                       originalText = $emailLabel.text(),
+                       requiredText = mw.message( 'createacct-emailrequired' ).text(),
+                       $createByMailCheckbox = $( '#wpCreateaccountMail' ),
+                       $beforePwds = $( '.mw-row-password:first' ).prev(),
+                       $pwds;
+
+               function updateForCheckbox() {
+                       var checked = $createByMailCheckbox.prop( 'checked' );
+                       if ( checked ) {
+                               $pwds = $( '.mw-row-password' ).detach();
+                               $emailLabel.text( requiredText );
+                       } else {
+                               if ( $pwds ) {
+                                       $beforePwds.after( $pwds );
+                                       $pwds = null;
+                               }
+                               $emailLabel.text( originalText );
+                       }
+               }
+
+               $createByMailCheckbox.on( 'change', updateForCheckbox );
+               updateForCheckbox();
+       } );
+
+       // Check if the username is invalid or already taken
+       $( function () {
+               var
+                       // We need to hook to all of these events to be sure we are notified of all changes to the
+                       // value of an <input type=text> field.
+                       events = 'keyup keydown change mouseup cut paste focus blur',
+                       $input = $( '#wpName2' ),
+                       $statusContainer = $( '#mw-createacct-status-area' ),
+                       api = new mw.Api(),
+                       currentRequest;
+
+               // Hide any present status messages.
+               function clearStatus() {
+                       $statusContainer.slideUp( function () {
+                               $statusContainer
+                                       .removeAttr( 'class' )
+                                       .empty();
+                       } );
+               }
+
+               // Returns a promise receiving a { state:, username: } object, where:
+               // * 'state' is one of 'invalid', 'taken', 'ok'
+               // * 'username' is the validated username if 'state' is 'ok', null otherwise (if it's not
+               //   possible to register such an account)
+               function checkUsername( username ) {
+                       // We could just use .then() if we didn't have to pass on .abort()…
+                       var d, apiPromise;
+
+                       d = $.Deferred();
+                       apiPromise = api.get( {
+                               action: 'query',
+                               list: 'users',
+                               ususers: username // '|' in usernames is handled below
+                       } )
+                               .done( function ( resp ) {
+                                       var userinfo = resp.query.users[0];
+
+                                       if ( resp.query.users.length !== 1 ) {
+                                               // Happens if the user types '|' into the field
+                                               d.resolve( { state: 'invalid', username: null } );
+                                       } else if ( userinfo.invalid !== undefined ) {
+                                               d.resolve( { state: 'invalid', username: null } );
+                                       } else if ( userinfo.userid !== undefined ) {
+                                               d.resolve( { state: 'taken', username: null } );
+                                       } else {
+                                               d.resolve( { state: 'ok', username: username } );
+                                       }
+                               } )
+                               .fail( d.reject );
+
+                       return d.promise( { abort: apiPromise.abort } );
+               }
+
+               function updateUsernameStatus() {
+                       var
+                               username = $.trim( $input.val() ),
+                               currentRequestInternal;
+
+                       // Abort any pending requests.
+                       if ( currentRequest ) {
+                               currentRequest.abort();
+                       }
+
+                       if ( username === '' ) {
+                               clearStatus();
+                               return;
+                       }
+
+                       currentRequest = currentRequestInternal = checkUsername( username ).done( function ( info ) {
+                               var message;
+
+                               // Another request was fired in the meantime, the result we got here is no longer current.
+                               // This shouldn't happen as we abort pending requests, but you never know.
+                               if ( currentRequest !== currentRequestInternal ) {
+                                       return;
+                               }
+                               // If we're here, then the current request has finished, avoid calling .abort() needlessly.
+                               currentRequest = undefined;
+
+                               if ( info.state === 'ok' ) {
+                                       clearStatus();
+                               } else {
+                                       if ( info.state === 'invalid' ) {
+                                               message = mw.message( 'noname' ).text();
+                                       } else if ( info.state === 'taken' ) {
+                                               message = mw.message( 'userexists' ).text();
+                                       }
+
+                                       $statusContainer
+                                               .attr( 'class', 'errorbox' )
+                                               .empty()
+                                               .append(
+                                                       // Ugh…
+                                                       // @todo Change the HTML structure in includes/templates/Usercreate.php
+                                                       $( '<strong>' ).text( mw.message( 'createacct-error' ).text() ),
+                                                       $( '<br>' ),
+                                                       document.createTextNode( message )
+                                               )
+                                               .slideDown();
+                               }
+                       } ).fail( function () {
+                               clearStatus();
+                       } );
+               }
+
+               $input.on( events, $.debounce( 250, updateUsernameStatus ) );
+       } );
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.special/mediawiki.special.version.css b/resources/src/mediawiki.special/mediawiki.special.version.css
new file mode 100644 (file)
index 0000000..917426a
--- /dev/null
@@ -0,0 +1,14 @@
+/**
+ * Adds additional styling to the extension title/version list
+**/
+.mw-version-ext-name {
+       font-weight: bold;
+}
+
+.mw-version-ext-vcs-timestamp {
+       white-space: nowrap;
+}
+
+th.mw-version-ext-col-label {
+       font-size: 0.9em;
+}
\ No newline at end of file
diff --git a/resources/src/mediawiki.ui/components/default/buttons.less b/resources/src/mediawiki.ui/components/default/buttons.less
new file mode 100644 (file)
index 0000000..54d1608
--- /dev/null
@@ -0,0 +1,224 @@
+@import "mediawiki.mixins";
+@import "../../settings/typography";
+@import "../../mixins/effects";
+
+// Buttons
+//
+// All buttons start with mw-ui-button class, modified by other classes.
+// It can be any element.  Due to a lack of a CSS reset, the exact styling of
+// the button depends on what type of element is used.
+// There are two kinds of buttons, the default is a "Call to Action" with an obvious border
+// and there is a quiet kind without a border.
+//
+// Styleguide 2.
+
+@buttonBorderRadius: 3px;
+@transitionDuration: .1s;
+@transitionFunction: ease-in-out;
+
+// Neutral button styling
+//
+// Markup:
+// <button class="mw-ui-button">.mw-ui-button</button>
+// <button class="mw-ui-button" disabled>.mw-ui-button</button>
+//
+// Styleguide 2.1.
+.mw-ui-button {
+       // Container layout
+       display: inline-block;
+       padding: .5em 1em;
+       margin: 0;
+
+       // IE6/IE7 hack
+       // http://stackoverflow.com/a/5838575/365238
+       *display: inline;
+       zoom: 1;
+
+       // Container styling
+       .button-colors(@colorWhite);
+       border-radius: @buttonBorderRadius;
+
+       // Ensure that buttons and inputs are nicely aligned when they have differing heights
+       vertical-align: middle;
+
+       // Content styling
+       text-align: center;
+       font-weight: bold;
+       text-shadow: 0 1px rgba(0, 0, 0, .1);
+
+       // Interaction styling
+       cursor: pointer;
+
+       &:disabled {
+               text-shadow: none;
+               cursor: default;
+       }
+
+       .transition(background @transitionDuration @transitionFunction, color @transitionDuration @transitionFunction, box-shadow @transitionDuration @transitionFunction;);
+
+       // Styling for specific button types
+       // -----------------------------------------
+
+       // Big buttons
+       //
+       // Not all buttons are equal. You can emphasise certain actions over others
+       // using the mw-ui-big class.
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-big">.mw-ui-button</button>
+       // <button class="mw-ui-button mw-ui-progressive mw-ui-big">.mw-ui-progressive</button>
+       // <button class="mw-ui-button mw-ui-constructive mw-ui-big">.mw-ui-constructive</button>
+       // <button class="mw-ui-button mw-ui-destructive mw-ui-big">.mw-ui-destructive</button>
+       //
+       // Styleguide 2.1.6.
+       &.mw-ui-big {
+               font-size: @baseFontSize * 1.3;
+       }
+
+       // Block buttons
+       //
+       // Some buttons might need to be stacked.
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-block">.mw-ui-button</button>
+       // <button class="mw-ui-button mw-ui-progressive mw-ui-block">.mw-ui-progressive</button>
+       // <button class="mw-ui-button mw-ui-constructive mw-ui-block">.mw-ui-constructive</button>
+       // <button class="mw-ui-button mw-ui-destructive mw-ui-block">.mw-ui-destructive</button>
+       //
+       // Styleguide 2.1.5.
+       &.mw-ui-block {
+               display: block;
+               width: 100%;
+       }
+
+       // Progressive buttons
+       //
+       // Use progressive buttons for actions which lead to a next step in the process.
+       // .mw-ui-primary is deprecated, kept for compatibility.
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-progressive">.mw-ui-progressive</button>
+       // <button class="mw-ui-button mw-ui-progressive" disabled>.mw-ui-progressive</button>
+       //
+       // Styleguide 2.1.1.
+       &.mw-ui-progressive,
+       &.mw-ui-primary {
+               .button-colors(@colorProgressive);
+
+               &.mw-ui-quiet {
+                       .button-colors-quiet(@colorProgressive);
+               }
+       }
+
+       // Constructive buttons
+       //
+       // Use constructive buttons for actions which result in a final action in the process that results
+       // in a change of state.
+       // e.g. save changes button
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-constructive">.mw-ui-constructive</button>
+       // <button class="mw-ui-button mw-ui-constructive" disabled>.mw-ui-constructive</button>
+       //
+       // Styleguide 2.1.2.
+       &.mw-ui-constructive {
+               .button-colors(@colorConstructive);
+
+               &.mw-ui-quiet {
+                       .button-colors-quiet(@colorConstructive);
+               }
+       }
+
+       // Destructive buttons
+       //
+       // Use destructive buttons for actions which result in the destruction of data.
+       // e.g. deleting a page.
+       // This should not be used for cancel buttons.
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-destructive">.mw-ui-destructive</button>
+       // <button class="mw-ui-button mw-ui-destructive" disabled>.mw-ui-destructive</button>
+       //
+       // Styleguide 2.1.3.
+       &.mw-ui-destructive {
+               .button-colors(@colorDestructive);
+
+               &.mw-ui-quiet {
+                       .button-colors-quiet(@colorDestructive);
+               }
+       }
+
+       // Quiet buttons
+       //
+       // Use quiet buttons when they are less important and alongisde other progressive/destructive/progressive buttons.
+       //
+       // Markup:
+       // <button class="mw-ui-button mw-ui-quiet">.mw-ui-button</button>
+       // <button class="mw-ui-button mw-ui-constructive mw-ui-quiet">.mw-ui-constructive</button>
+       // <button class="mw-ui-button mw-ui-constructive mw-ui-quiet" disabled>.mw-ui-constructive</button>
+       // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet">.mw-ui-destructive</button>
+       // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet" disabled>.mw-ui-destructive</button>
+       // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet">.mw-ui-progressive</button>
+       // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet" disabled>.mw-ui-progressive</button>
+       //
+       // Styleguide 2.1.4.
+       &.mw-ui-quiet {
+               background: transparent;
+               border: none;
+               text-shadow: none;
+               .button-colors-quiet(@colorGrayDark);
+
+               &:hover,
+               &:focus {
+                       box-shadow: none;
+               }
+
+               &:active,
+               &:disabled {
+                       background: transparent;
+               }
+       }
+}
+
+a.mw-ui-button {
+       text-decoration: none;
+
+       // This overrides an underline declaration on a:hover and a:focus in
+       // commonElements.css, which the class alone isn't specific enough to do.
+       &:hover,
+       &:focus {
+               text-decoration: none;
+       }
+}
+
+// Button groups
+//
+// Group of buttons. Make sure you clear the floating after using a mw-ui-button-group.
+//
+// Markup:
+// <div class="mw-ui-button-group">
+//   <div class="mw-ui-button">A</div>
+//   <div class="mw-ui-button">B</div>
+//   <div class="mw-ui-button">C</div>
+//   <div class="mw-ui-button">D</div>
+// </div><div style="clear:both"></div>
+//
+// Styleguide 2.2.
+.mw-ui-button-group > * {
+       border-radius: 0;
+       float: left;
+
+       &:first-child {
+               border-top-left-radius: @buttonBorderRadius;
+               border-bottom-left-radius: @buttonBorderRadius;
+       }
+
+       &:not(:first-child) {
+               border-left: none;
+       }
+
+       &:last-child{
+               border-top-right-radius: @buttonBorderRadius;
+               border-bottom-right-radius: @buttonBorderRadius;
+       }
+}
diff --git a/resources/src/mediawiki.ui/components/default/forms.less b/resources/src/mediawiki.ui/components/default/forms.less
new file mode 100644 (file)
index 0000000..6157fa2
--- /dev/null
@@ -0,0 +1,165 @@
+// Form elements and layouts
+
+@import "../../mixins/utilities";
+@import "../../mixins/forms";
+
+// --------------------------------------------------------------------------
+// Layouts
+// --------------------------------------------------------------------------
+
+// The FancyCaptcha image CAPTCHA used on WMF wikis drives the width of the
+// 'VForm' design, the form can't be narrower than this.
+@captchaContainerWidth: 290px;
+@defaultFormWidth: @captchaContainerWidth;
+
+// Forms
+//
+// Styleguide 3.
+
+// VForm
+//
+// Style a compact vertical stacked form ("VForm") and the elements in divs
+// within it. See button section on guidance of how and when to use mw-ui-constructive.
+//
+// Markup:
+// <form class="mw-ui-vform">
+//   <div class="mw-ui-vform-div">This is a form example.</div>
+//   <div>
+//     <label>Username </label>
+//     <input value="input">
+//   </div>
+//   <div>
+//     <button class="mw-ui-button mw-ui-constructive">Button in vform</button>
+//   </div>
+// </form>
+//
+// Styleguide 3.1.
+.mw-ui-vform {
+       .box-sizing(border-box);
+
+       width: @defaultFormWidth;
+
+       // Immediate divs in a vform are block and spaced-out.
+       // XXX: We shouldn't depend on the tag name here...
+       & > div {
+               display: block;
+               margin: 0 0 15px 0;
+               padding: 0;
+               width: 100%;
+       }
+
+       // MW currently doesn't use the type attribute everywhere on inputs.
+       input,
+       .mw-ui-button {
+               display: block;
+               .box-sizing(border-box);
+               margin: 0;
+               width: 100%;
+       }
+
+       // We exclude these because they'll generally use mw-ui-button.
+       // Otherwise, we'll unintentionally override that.
+       input:not([type=button]):not([type=submit]):not([type=file]), {
+               .agora-field-styling(); // mixins/forms.less
+       }
+
+       label {
+               display: block;
+               .box-sizing(border-box);
+               .agora-label-styling();
+               width: auto;
+               margin: 0 0 0.2em;
+               padding: 0;
+       }
+
+       // Override input styling just for checkboxes and radio inputs.
+       input[type="checkbox"],
+       input[type="radio"] {
+               display: inline;
+               .box-sizing(content-box);
+               width: auto;
+       }
+
+
+       // Styles for information boxes
+       //
+       // Regular HTMLForm uses .error class, some special pages like
+       // SpecialUserlogin (login and create account) use .errorbox.
+       //
+       // Markup:
+       // <form class="mw-ui-vform">
+       //   <div class="errorbox">An error occurred</div>
+       //   <div class="warningbox">A warning to be noted</div>
+       //   <div class="successbox">Action successful!</div>
+       //   <div class="error">A different kind of error</div>
+       //   <div>
+       //     <input type="text" value="input" class="mw-ui-input">
+       //   <div>
+       //   </div>
+       //     <button class="mw-ui-button">Button in vform</button>
+       //   </div>
+       // </form>
+       //
+       // Styleguide 3.1.
+       .error {
+               .box-sizing(border-box);
+               font-size: 0.9em;
+               margin: 0 0 1em;
+               padding: 0.5em;
+               color: #cc0000;
+               border: 1px solid #fac5c5;
+               background-color: #fae3e3;
+               text-shadow: 0 1px #fae3e3;
+               word-wrap: break-word;
+       }
+
+       .errorbox,
+       .warningbox,
+       .successbox {
+               .box-sizing(border-box);
+               font-size: 0.9em;
+               margin: 0 0 1em 0;
+               padding: 0.5em;
+               word-wrap: break-word;
+       }
+
+}
+
+// --------------------------------------------------------------------------
+// Elements
+// --------------------------------------------------------------------------
+
+// Apply this to individual elements to style them.
+// You generally don't need to use this class on divs within an Agora
+// form container such as mw-ui-vform
+// XXX DRY: This repeats earlier styling, use an @include agora-div-styling ?
+// XXX: What is this even for?
+.mw-ui-vform-div {
+       display: block;
+       margin: 0 0 15px;
+       padding: 0;
+       width: 100%;
+}
+
+// Apply mw-ui-input to individual input fields to style them.
+// You generally don't need to use this class if <input> is within an Agora
+// form container such as mw-ui-vform
+.mw-ui-input {
+       .agora-field-styling(); // mixins/forms.less
+}
+
+// Apply mw-ui-label to individual elements to style them.
+// You generally don't need to use this class if <label> is within an Agora
+// form container such as mw-ui-vform
+.mw-ui-label {
+       .agora-label-styling(); // mixins/forms.less
+}
+
+// Nesting an input checkbox or radio button inside a label with this class
+// improves alignment, e.g.
+//     <label class="mw-ui-checkbox-label">
+//             <input type="checkbox">The label text
+//     </label>
+.mw-ui-checkbox-label, .mw-ui-radio-label {
+       .agora-inline-label-styling();
+}
diff --git a/resources/src/mediawiki.ui/components/utilities.less b/resources/src/mediawiki.ui/components/utilities.less
new file mode 100644 (file)
index 0000000..9aea429
--- /dev/null
@@ -0,0 +1,19 @@
+// Generic helper classes that could be used in many elements/layouts
+
+// --------------------------------------------------------------------------
+// Positioning
+// --------------------------------------------------------------------------
+
+@import "../mixins/utilities";
+
+.mw-ui-flush-left {
+       .agora-flush-left();
+}
+
+.mw-ui-flush-right {
+       .agora-flush-right();
+}
+
+.mw-ui-center-block {
+       .agora-center-block();
+}
diff --git a/resources/src/mediawiki.ui/components/vector/buttons.less b/resources/src/mediawiki.ui/components/vector/buttons.less
new file mode 100644 (file)
index 0000000..1536338
--- /dev/null
@@ -0,0 +1,6 @@
+@import "../default/buttons"; // Layer Vector on top of the default settings.
+@import "../../mixins/type";
+
+.mw-ui-button {
+       .vector-type();
+}
diff --git a/resources/src/mediawiki.ui/components/vector/containers.less b/resources/src/mediawiki.ui/components/vector/containers.less
new file mode 100644 (file)
index 0000000..1e9ec05
--- /dev/null
@@ -0,0 +1,6 @@
+// No default settings for containers yet.
+@import "../../mixins/type";
+
+.mw-ui-container {
+       .vector-type();
+}
diff --git a/resources/src/mediawiki.ui/components/vector/forms.less b/resources/src/mediawiki.ui/components/vector/forms.less
new file mode 100644 (file)
index 0000000..2bbd8f0
--- /dev/null
@@ -0,0 +1,8 @@
+@import "../default/forms"; // Layer Vector on top of the default settings.
+@import "../../mixins/type";
+
+.mw-ui-vform,
+.mw-ui-vform input,
+.mw-ui-input {
+       .vector-type();
+}
diff --git a/resources/src/mediawiki.ui/default.less b/resources/src/mediawiki.ui/default.less
new file mode 100644 (file)
index 0000000..e576937
--- /dev/null
@@ -0,0 +1,7 @@
+/**
+ * Provide Agora appearance for mw-ui-* classes when using a skin other than
+ * Vector.
+ */
+
+@import "components/utilities";
+@import "components/default/forms";
diff --git a/resources/src/mediawiki.ui/mixins/effects.less b/resources/src/mediawiki.ui/mixins/effects.less
new file mode 100644 (file)
index 0000000..9daad74
--- /dev/null
@@ -0,0 +1,84 @@
+@import "../settings/colors";
+// ----------------------------------------------------------------------------
+// Button styling
+// ----------------------------------------------------------------------------
+
+.button-colors(@bgColor) {
+       background: @bgColor;
+
+       &:hover,
+       &:focus {
+               // The inner bottom bevel should match the active background color.
+               box-shadow: 0 1px rgba(0, 0, 0, 10%), inset 0 -3px rgba(0, 0, 0, 20%);
+               outline: none;
+               // remove outline in Firefox
+               &::-moz-focus-inner {
+                       border-color: transparent;
+               }
+       }
+
+       &:active,
+       &.mw-ui-checked {
+               // lessphp doesn't implement shade (https://github.com/leafo/lessphp/issues/528);
+               // it passes it through, then ResourceLoader drops it.
+               // background: shade(@bgColor, 20%);
+               background: mix(#000, @bgColor, 20%);
+               box-shadow: none;
+       }
+}
+
+.button-colors(@bgColor) when (lightness(@bgColor) >= 70%) {
+       color: @colorGrayDark;
+       border: 1px solid @colorGrayLight;
+
+       &:disabled {
+               color: @colorGrayLight;
+
+               // make sure disabled buttons don't have hover and active states
+               &:hover,
+               &:active {
+                       background: @bgColor;
+                       box-shadow: none;
+               }
+       }
+}
+
+.button-colors(@bgColor) when (lightness(@bgColor) < 70%) {
+       color: @colorWhite;
+       border: none;
+
+       &:disabled {
+               background: @colorGrayLight;
+
+               // make sure disabled buttons don't have hover and active states
+               &:hover,
+               &:active,
+               &.mw-ui-checked {
+                       box-shadow: none;
+               }
+       }
+}
+
+.button-colors-quiet(@textColor) {
+       // Quiet buttons all start gray, and reveal
+       // constructive/progressive/destructive color on hover and active.
+       color: @colorGrayDark;
+
+       &:hover,
+       &:focus {
+               // lessphp doesn't implement tint, see above
+               // color: tint(@textColor, 20%);
+               color: mix(#fff, @textColor, 20%);
+       }
+
+       &:active,
+       &.mw-ui-checked {
+               // lessphp doesn't implement shade, see above
+               // color: shade(@textColor, 20%);
+               color: mix(#000, @textColor, 20%);
+       }
+
+       &:disabled {
+               color: @colorGrayLight;
+       }
+}
diff --git a/resources/src/mediawiki.ui/mixins/forms.less b/resources/src/mediawiki.ui/mixins/forms.less
new file mode 100644 (file)
index 0000000..20f42a0
--- /dev/null
@@ -0,0 +1,54 @@
+@import "../settings/colors";
+
+// Font is not included.
+// For Vector, that should be layered on top with vector-type
+.agora-field-styling() {
+
+       border: 1px solid @colorGrayLight;
+
+       &:focus {
+               // Styling focus of native checkboxes etc on Mac is almost impossible.
+               &:not([type=checkbox]):not([type=radio]) {
+                       outline: 0; // Removes OS field focus
+               }
+
+               box-shadow: @colorProgressiveShadow 0 0 5px;
+
+               border-color: @colorProgressiveShadow;
+       }
+
+       color: @colorText;
+       padding: 0.35em 0.5em 0.35em 0.5em;
+
+       // Ensure that buttons and inputs are nicely aligned when they have differing heights
+       vertical-align: middle;
+}
+
+.agora-label-styling() {
+       //font-weight: bold;
+       font-size: 0.9em;
+       color: darken(@colorGrayLight, 50%);
+
+       * {
+               font-weight: normal;
+       }
+}
+
+.agora-inline-label-styling() {
+       margin-bottom: 0.5em;
+       cursor: pointer;
+       vertical-align: bottom;
+       line-height: normal;
+
+       font-weight: normal;
+
+       & > input[type="checkbox"],
+       & > input[type="radio"] {
+               width: auto;
+               height: auto;
+               margin: 0 0.1em 0 0;
+               padding: 0;
+               border: 1px solid @colorGrayLight;
+               cursor: pointer;
+       }
+}
diff --git a/resources/src/mediawiki.ui/mixins/type.less b/resources/src/mediawiki.ui/mixins/type.less
new file mode 100644 (file)
index 0000000..4a01168
--- /dev/null
@@ -0,0 +1,6 @@
+@import "../settings/typography";
+
+.vector-type() {
+       font-size: @baseFontSize;
+       line-height: @baseLineHeight;
+}
diff --git a/resources/src/mediawiki.ui/mixins/utilities.less b/resources/src/mediawiki.ui/mixins/utilities.less
new file mode 100644 (file)
index 0000000..a201a4e
--- /dev/null
@@ -0,0 +1,23 @@
+.box-sizing(@value) {
+       -moz-box-sizing: @value;
+       -webkit-box-sizing: @value;
+       box-sizing: @value;
+}
+
+.agora-flush-left() {
+       float: left;
+       margin-left: 0;
+       padding-left: 0;
+}
+
+.agora-flush-right() {
+       float: right;
+       margin-right: 0;
+       padding-right: 0;
+}
+
+.agora-center-block() {
+       display: block;
+       margin-left: auto;
+       margin-right: auto;
+}
diff --git a/resources/src/mediawiki.ui/settings/colors.less b/resources/src/mediawiki.ui/settings/colors.less
new file mode 100644 (file)
index 0000000..18661de
--- /dev/null
@@ -0,0 +1,10 @@
+@colorWhite: #fff;
+@colorGrayLight: #ccc;
+@colorGrayDark: #898989;
+@colorText: #252525;
+@colorProgressive: #347bff;
+// FIXME: remove @colorProgressiveShadow (shadows should be generated
+// in LESS by dimming the original colors)
+@colorProgressiveShadow: #4091ed;
+@colorConstructive: #00af89;
+@colorDestructive: #d11d13;
diff --git a/resources/src/mediawiki.ui/settings/typography.less b/resources/src/mediawiki.ui/settings/typography.less
new file mode 100644 (file)
index 0000000..83651ed
--- /dev/null
@@ -0,0 +1,5 @@
+@baseFontSize: 1em;
+@baseLineHeight: 1.4 * @baseFontSize;
+@baseFontColor: @colorText;
+
+@smallFontSize: 0.75em;
diff --git a/resources/src/mediawiki.ui/styleguide.md b/resources/src/mediawiki.ui/styleguide.md
new file mode 100644 (file)
index 0000000..b7eea54
--- /dev/null
@@ -0,0 +1,26 @@
+#Wikimedia projects
+
+This is the living style guide for MediaWiki UI used in Wikimedia Projects. It is generated from existing CSS programmatically. Please use it as a reference when developing code for MediaWiki to ensure your design is consistent with others across the site. Note this document is a work in progress and subject to change.
+
+##Brand
+
+Imagine a world in which every single human being can freely share in the sum of all knowledge.
+
+Sharing knowledge is the heart of our movement. Specifically, we care about sharing the “… highest possible quality to every single person on the planet in their own language” (Jimmy Wales). The focus of our identity is being credible and is moving toward being more inviting. We want our contributors to keep contributing while our assuring our readers that the information on any of the Wikimedia projects is reliable and accurate. Our personality should embody both of those traits with a slight sense of rebellion. We are unlike traditional projects (for instance, Encyclopedias that are only created by a few select individuals). We are a global movement, and as Jimmy Wales puts it: “Wikipedia is like rock’n’roll; it’s a cultural shift."
+
+##Design Philosophy
+
+The Wikimedia movement is a global volunteer community that aims to collect and develop the world's knowledge and to make it available to everyone for free, for any purpose. “Imagine a world in which every single human being can freely share in the sum of all knowledge.” 
+
+###Credible
+We strive for the most accurate, high quality and neutral information on all Wikimedia projects. We are fact-based and honest. We do not take sides. We are fair and impartial. 
+
+###Inviting
+We are geeky about collecting and developing knowledge. We invite and welcome every single human being to share their knowledge with us and the rest of the world. We are open-minded and have a strong sense of community. Our aesthetics should be clean and encourage interaction. 
+
+###Worldly
+We are thoughtful and are aware of cultural differences. We are careful about words, color usage, and images that might offend. We are also aware of limited connectivity in some areas of the world and are thoughtful of image sizes and loading speed. 
+
+###Humble
+We are respectful of contributors’ effort and knowledge. We have a wealth of knowledge on all projects and many people to thank for that. We are humble. We are helpful and welcome help to expand the sum of all knowledge. 
+
diff --git a/resources/src/mediawiki.ui/vector.less b/resources/src/mediawiki.ui/vector.less
new file mode 100644 (file)
index 0000000..08690a3
--- /dev/null
@@ -0,0 +1,25 @@
+/**
+ * Provide Agora appearance for mw-ui-* classes when using the Vector skin.
+ */
+
+// Typography
+//
+// We prefer the usage of Georgia Bold for all headings. Georgia Regular is used to place emphasis on pull-out or short quotations. This latter usage should be used sparingly. 
+//
+// We prefer the use of Helvetica Neue Regular for body copy. Helvetiva Neue Bold for sub-headers. Pull-out quotes within the body copy should use Helvetica Neue Bold. Helvetica Neue is an not open-source font. Hence, below is a list of preferred alternate choices.
+//
+// Second choice: Helvetica
+//
+// Third choice: Arial
+//
+// Our content is predominantly text, hence visual hierarchy must be clear. Use these recommended type sizes to inform and establish information hierarchy and organization. 
+//
+// Unless if you plan to put extra attention and manually adjust spacing, avoid justifying texts and paragraphs as they are harder to read and create unnecessary visual distractions. Along with centered text, they convey a formal and less friendly environment. 
+//
+// It will be important to talk about other languages, scripts and writing direction - with the same level as importance, not as an afterthought.
+//
+// Styleguide 1.
+
+@import "components/utilities";
+@import "components/vector/forms";
+@import "components/vector/containers";
diff --git a/resources/src/mediawiki/images/arrow-collapsed-ltr.png b/resources/src/mediawiki/images/arrow-collapsed-ltr.png
new file mode 100644 (file)
index 0000000..b17e578
Binary files /dev/null and b/resources/src/mediawiki/images/arrow-collapsed-ltr.png differ
diff --git a/resources/src/mediawiki/images/arrow-collapsed-ltr.svg b/resources/src/mediawiki/images/arrow-collapsed-ltr.svg
new file mode 100644 (file)
index 0000000..6233fd5
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path d="M4 1.533v9.671l4.752-4.871z" fill="#797979"/></svg>
\ No newline at end of file
diff --git a/resources/src/mediawiki/images/arrow-collapsed-rtl.png b/resources/src/mediawiki/images/arrow-collapsed-rtl.png
new file mode 100644 (file)
index 0000000..a834548
Binary files /dev/null and b/resources/src/mediawiki/images/arrow-collapsed-rtl.png differ
diff --git a/resources/src/mediawiki/images/arrow-collapsed-rtl.svg b/resources/src/mediawiki/images/arrow-collapsed-rtl.svg
new file mode 100644 (file)
index 0000000..44d5587
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path d="M8 1.533v9.671l-4.752-4.871z" fill="#797979"/></svg>
\ No newline at end of file
diff --git a/resources/src/mediawiki/images/arrow-expanded.png b/resources/src/mediawiki/images/arrow-expanded.png
new file mode 100644 (file)
index 0000000..2bec798
Binary files /dev/null and b/resources/src/mediawiki/images/arrow-expanded.png differ
diff --git a/resources/src/mediawiki/images/arrow-expanded.svg b/resources/src/mediawiki/images/arrow-expanded.svg
new file mode 100644 (file)
index 0000000..a0d217d
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path d="M1.165 3.624h9.671l-4.871 4.752z" fill="#797979"/></svg>
\ No newline at end of file
diff --git a/resources/src/mediawiki/mediawiki.Title.js b/resources/src/mediawiki/mediawiki.Title.js
new file mode 100644 (file)
index 0000000..707f8d5
--- /dev/null
@@ -0,0 +1,588 @@
+/*!
+ * @author Neil Kandalgaonkar, 2010
+ * @author Timo Tijhof, 2011-2013
+ * @since 1.18
+ */
+( function ( mw, $ ) {
+
+       /**
+        * @class mw.Title
+        *
+        * Parse titles into an object struture. Note that when using the constructor
+        * directly, passing invalid titles will result in an exception. Use #newFromText to use the
+        * logic directly and get null for invalid titles which is easier to work with.
+        *
+        * @constructor
+        * @param {string} title Title of the page. If no second argument given,
+        *  this will be searched for a namespace
+        * @param {number} [namespace=NS_MAIN] If given, will used as default namespace for the given title
+        * @throws {Error} When the title is invalid
+        */
+       function Title( title, namespace ) {
+               var parsed = parse( title, namespace );
+               if ( !parsed ) {
+                       throw new Error( 'Unable to parse title' );
+               }
+
+               this.namespace = parsed.namespace;
+               this.title = parsed.title;
+               this.ext = parsed.ext;
+               this.fragment = parsed.fragment;
+
+               return this;
+       }
+
+       /* Private members */
+
+       var
+
+       /**
+        * @private
+        * @static
+        * @property NS_MAIN
+        */
+       NS_MAIN = 0,
+
+       /**
+        * @private
+        * @static
+        * @property NS_TALK
+        */
+       NS_TALK = 1,
+
+       /**
+        * @private
+        * @static
+        * @property NS_SPECIAL
+        */
+       NS_SPECIAL = -1,
+
+       /**
+        * Get the namespace id from a namespace name (either from the localized, canonical or alias
+        * name).
+        *
+        * Example: On a German wiki this would return 6 for any of 'File', 'Datei', 'Image' or
+        * even 'Bild'.
+        *
+        * @private
+        * @static
+        * @method getNsIdByName
+        * @param {string} ns Namespace name (case insensitive, leading/trailing space ignored)
+        * @return {number|boolean} Namespace id or boolean false
+        */
+       getNsIdByName = function ( ns ) {
+               var id;
+
+               // Don't cast non-strings to strings, because null or undefined should not result in
+               // returning the id of a potential namespace called "Null:" (e.g. on null.example.org/wiki)
+               // Also, toLowerCase throws exception on null/undefined, because it is a String method.
+               if ( typeof ns !== 'string' ) {
+                       return false;
+               }
+               ns = ns.toLowerCase();
+               id = mw.config.get( 'wgNamespaceIds' )[ns];
+               if ( id === undefined ) {
+                       return false;
+               }
+               return id;
+       },
+
+       rUnderscoreTrim = /^_+|_+$/g,
+
+       rSplit = /^(.+?)_*:_*(.*)$/,
+
+       // See Title.php#getTitleInvalidRegex
+       rInvalid = new RegExp(
+               '[^' + mw.config.get( 'wgLegalTitleChars' ) + ']' +
+               // URL percent encoding sequences interfere with the ability
+               // to round-trip titles -- you can't link to them consistently.
+               '|%[0-9A-Fa-f]{2}' +
+               // XML/HTML character references produce similar issues.
+               '|&[A-Za-z0-9\u0080-\uFFFF]+;' +
+               '|&#[0-9]+;' +
+               '|&#x[0-9A-Fa-f]+;'
+       ),
+
+       /**
+        * Internal helper for #constructor and #newFromtext.
+        *
+        * Based on Title.php#secureAndSplit
+        *
+        * @private
+        * @static
+        * @method parse
+        * @param {string} title
+        * @param {number} [defaultNamespace=NS_MAIN]
+        * @return {Object|boolean}
+        */
+       parse = function ( title, defaultNamespace ) {
+               var namespace, m, id, i, fragment, ext;
+
+               namespace = defaultNamespace === undefined ? NS_MAIN : defaultNamespace;
+
+               title = title
+                       // Normalise whitespace to underscores and remove duplicates
+                       .replace( /[ _\s]+/g, '_' )
+                       // Trim underscores
+                       .replace( rUnderscoreTrim, '' );
+
+               // Process initial colon
+               if ( title !== '' && title.charAt( 0 ) === ':' ) {
+                       // Initial colon means main namespace instead of specified default
+                       namespace = NS_MAIN;
+                       title = title
+                               // Strip colon
+                               .substr( 1 )
+                               // Trim underscores
+                               .replace( rUnderscoreTrim, '' );
+               }
+
+               if ( title === '' ) {
+                       return false;
+               }
+
+               // Process namespace prefix (if any)
+               m = title.match( rSplit );
+               if ( m ) {
+                       id = getNsIdByName( m[1] );
+                       if ( id !== false ) {
+                               // Ordinary namespace
+                               namespace = id;
+                               title = m[2];
+
+                               // For Talk:X pages, make sure X has no "namespace" prefix
+                               if ( namespace === NS_TALK && ( m = title.match( rSplit ) ) ) {
+                                       // Disallow titles like Talk:File:x (subject should roundtrip: talk:file:x -> file:x -> file_talk:x)
+                                       if ( getNsIdByName( m[1] ) !== false ) {
+                                               return false;
+                                       }
+                               }
+                       }
+               }
+
+               // Process fragment
+               i = title.indexOf( '#' );
+               if ( i === -1 ) {
+                       fragment = null;
+               } else {
+                       fragment = title
+                               // Get segment starting after the hash
+                               .substr( i + 1 )
+                               // Convert to text
+                               // NB: Must not be trimmed ("Example#_foo" is not the same as "Example#foo")
+                               .replace( /_/g, ' ' );
+
+                       title = title
+                               // Strip hash
+                               .substr( 0, i )
+                               // Trim underscores, again (strips "_" from "bar" in "Foo_bar_#quux")
+                               .replace( rUnderscoreTrim, '' );
+               }
+
+               // Reject illegal characters
+               if ( title.match( rInvalid ) ) {
+                       return false;
+               }
+
+               // Disallow titles that browsers or servers might resolve as directory navigation
+               if (
+                       title.indexOf( '.' ) !== -1 && (
+                               title === '.' || title === '..' ||
+                               title.indexOf( './' ) === 0 ||
+                               title.indexOf( '../' ) === 0 ||
+                               title.indexOf( '/./' ) !== -1 ||
+                               title.indexOf( '/../' ) !== -1 ||
+                               title.substr( title.length - 2 ) === '/.' ||
+                               title.substr( title.length - 3 ) === '/..'
+                       )
+               ) {
+                       return false;
+               }
+
+               // Disallow magic tilde sequence
+               if ( title.indexOf( '~~~' ) !== -1 ) {
+                       return false;
+               }
+
+               // Disallow titles exceeding the 255 byte size limit (size of underlying database field)
+               // Except for special pages, e.g. [[Special:Block/Long name]]
+               // Note: The PHP implementation also asserts that even in NS_SPECIAL, the title should
+               // be less than 512 bytes.
+               if ( namespace !== NS_SPECIAL && $.byteLength( title ) > 255 ) {
+                       return false;
+               }
+
+               // Can't make a link to a namespace alone.
+               if ( title === '' && namespace !== NS_MAIN ) {
+                       return false;
+               }
+
+               // Any remaining initial :s are illegal.
+               if ( title.charAt( 0 ) === ':' ) {
+                       return false;
+               }
+
+               // For backwards-compatibility with old mw.Title, we separate the extension from the
+               // rest of the title.
+               i = title.lastIndexOf( '.' );
+               if ( i === -1 || title.length <= i + 1 ) {
+                       // Extensions are the non-empty segment after the last dot
+                       ext = null;
+               } else {
+                       ext = title.substr( i + 1 );
+                       title = title.substr( 0, i );
+               }
+
+               return {
+                       namespace: namespace,
+                       title: title,
+                       ext: ext,
+                       fragment: fragment
+               };
+       },
+
+       /**
+        * Convert db-key to readable text.
+        *
+        * @private
+        * @static
+        * @method text
+        * @param {string} s
+        * @return {string}
+        */
+       text = function ( s ) {
+               if ( s !== null && s !== undefined ) {
+                       return s.replace( /_/g, ' ' );
+               } else {
+                       return '';
+               }
+       },
+
+       // Polyfill for ES5 Object.create
+       createObject = Object.create || ( function () {
+               return function ( o ) {
+                       function Title() {}
+                       if ( o !== Object( o ) ) {
+                               throw new Error( 'Cannot inherit from a non-object' );
+                       }
+                       Title.prototype = o;
+                       return new Title();
+               };
+       }() );
+
+       /* Static members */
+
+       /**
+        * Constructor for Title objects with a null return instead of an exception for invalid titles.
+        *
+        * @static
+        * @method
+        * @param {string} title
+        * @param {number} [namespace=NS_MAIN] Default namespace
+        * @return {mw.Title|null} A valid Title object or null if the title is invalid
+        */
+       Title.newFromText = function ( title, namespace ) {
+               var t, parsed = parse( title, namespace );
+               if ( !parsed ) {
+                       return null;
+               }
+
+               t = createObject( Title.prototype );
+               t.namespace = parsed.namespace;
+               t.title = parsed.title;
+               t.ext = parsed.ext;
+               t.fragment = parsed.fragment;
+
+               return t;
+       };
+
+       /**
+        * Get the file title from an image element
+        *
+        *     var title = mw.Title.newFromImg( $( 'img:first' ) );
+        *
+        * @static
+        * @param {HTMLElement|jQuery} img The image to use as a base
+        * @return {mw.Title|null} The file title or null if unsuccessful
+        */
+       Title.newFromImg = function ( img ) {
+               var matches, i, regex, src, decodedSrc,
+
+                       // thumb.php-generated thumbnails
+                       thumbPhpRegex = /thumb\.php/,
+                       regexes = [
+                               // Thumbnails
+                               /\/[a-f0-9]\/[a-f0-9]{2}\/([^\s\/]+)\/[^\s\/]+-(?:\1|thumbnail)[^\s\/]*$/,
+
+                               // Thumbnails in non-hashed upload directories
+                               /\/([^\s\/]+)\/[^\s\/]+-(?:\1|thumbnail)[^\s\/]*$/,
+
+                               // Full size images
+                               /\/[a-f0-9]\/[a-f0-9]{2}\/([^\s\/]+)$/,
+
+                               // Full-size images in non-hashed upload directories
+                               /\/([^\s\/]+)$/
+                       ],
+
+                       recount = regexes.length;
+
+               src = img.jquery ? img[0].src : img.src;
+
+               matches = src.match( thumbPhpRegex );
+
+               if ( matches ) {
+                       return mw.Title.newFromText( 'File:' + mw.util.getParamValue( 'f', src ) );
+               }
+
+               decodedSrc = decodeURIComponent( src );
+
+               for ( i = 0; i < recount; i++ ) {
+                       regex = regexes[i];
+                       matches = decodedSrc.match( regex );
+
+                       if ( matches && matches[1] ) {
+                               return mw.Title.newFromText( 'File:' + matches[1] );
+                       }
+               }
+
+               return null;
+       };
+
+       /**
+        * Whether this title exists on the wiki.
+        *
+        * @static
+        * @param {string|mw.Title} title prefixed db-key name (string) or instance of Title
+        * @return {boolean|null} Boolean if the information is available, otherwise null
+        */
+       Title.exists = function ( title ) {
+               var match,
+                       type = $.type( title ),
+                       obj = Title.exist.pages;
+
+               if ( type === 'string' ) {
+                       match = obj[title];
+               } else if ( type === 'object' && title instanceof Title ) {
+                       match = obj[title.toString()];
+               } else {
+                       throw new Error( 'mw.Title.exists: title must be a string or an instance of Title' );
+               }
+
+               if ( typeof match === 'boolean' ) {
+                       return match;
+               }
+
+               return null;
+       };
+
+       Title.exist = {
+               /**
+                * Boolean true value indicates page does exist.
+                *
+                * @static
+                * @property {Object} exist.pages Keyed by PrefixedDb title.
+                */
+               pages: {},
+
+               /**
+                * Example to declare existing titles:
+                *
+                *     Title.exist.set( ['User:John_Doe', ...] );
+                *
+                * Example to declare titles nonexistent:
+                *
+                *     Title.exist.set( ['File:Foo_bar.jpg', ...], false );
+                *
+                * @static
+                * @property exist.set
+                * @param {string|Array} titles Title(s) in strict prefixedDb title form
+                * @param {boolean} [state=true] State of the given titles
+                * @return {boolean}
+                */
+               set: function ( titles, state ) {
+                       titles = $.isArray( titles ) ? titles : [titles];
+                       state = state === undefined ? true : !!state;
+                       var pages = this.pages, i, len = titles.length;
+                       for ( i = 0; i < len; i++ ) {
+                               pages[ titles[i] ] = state;
+                       }
+                       return true;
+               }
+       };
+
+       /* Public members */
+
+       Title.prototype = {
+               constructor: Title,
+
+               /**
+                * Get the namespace number
+                *
+                * Example: 6 for "File:Example_image.svg".
+                *
+                * @return {number}
+                */
+               getNamespaceId: function () {
+                       return this.namespace;
+               },
+
+               /**
+                * Get the namespace prefix (in the content language)
+                *
+                * Example: "File:" for "File:Example_image.svg".
+                * In #NS_MAIN this is '', otherwise namespace name plus ':'
+                *
+                * @return {string}
+                */
+               getNamespacePrefix: function () {
+                       return this.namespace === NS_MAIN ?
+                               '' :
+                               ( mw.config.get( 'wgFormattedNamespaces' )[ this.namespace ].replace( / /g, '_' ) + ':' );
+               },
+
+               /**
+                * Get the page name without extension or namespace prefix
+                *
+                * Example: "Example_image" for "File:Example_image.svg".
+                *
+                * For the page title (full page name without namespace prefix), see #getMain.
+                *
+                * @return {string}
+                */
+               getName: function () {
+                       if ( $.inArray( this.namespace, mw.config.get( 'wgCaseSensitiveNamespaces' ) ) !== -1 ) {
+                               return this.title;
+                       } else {
+                               return $.ucFirst( this.title );
+                       }
+               },
+
+               /**
+                * Get the page name (transformed by #text)
+                *
+                * Example: "Example image" for "File:Example_image.svg".
+                *
+                * For the page title (full page name without namespace prefix), see #getMainText.
+                *
+                * @return {string}
+                */
+               getNameText: function () {
+                       return text( this.getName() );
+               },
+
+               /**
+                * Get the extension of the page name (if any)
+                *
+                * @return {string|null} Name extension or null if there is none
+                */
+               getExtension: function () {
+                       return this.ext;
+               },
+
+               /**
+                * Shortcut for appendable string to form the main page name.
+                *
+                * Returns a string like ".json", or "" if no extension.
+                *
+                * @return {string}
+                */
+               getDotExtension: function () {
+                       return this.ext === null ? '' : '.' + this.ext;
+               },
+
+               /**
+                * Get the main page name (transformed by #text)
+                *
+                * Example: "Example_image.svg" for "File:Example_image.svg".
+                *
+                * @return {string}
+                */
+               getMain: function () {
+                       return this.getName() + this.getDotExtension();
+               },
+
+               /**
+                * Get the main page name (transformed by #text)
+                *
+                * Example: "Example image.svg" for "File:Example_image.svg".
+                *
+                * @return {string}
+                */
+               getMainText: function () {
+                       return text( this.getMain() );
+               },
+
+               /**
+                * Get the full page name
+                *
+                * Example: "File:Example_image.svg".
+                * Most useful for API calls, anything that must identify the "title".
+                *
+                * @return {string}
+                */
+               getPrefixedDb: function () {
+                       return this.getNamespacePrefix() + this.getMain();
+               },
+
+               /**
+                * Get the full page name (transformed by #text)
+                *
+                * Example: "File:Example image.svg" for "File:Example_image.svg".
+                *
+                * @return {string}
+                */
+               getPrefixedText: function () {
+                       return text( this.getPrefixedDb() );
+               },
+
+               /**
+                * Get the fragment (if any).
+                *
+                * Note that this method (by design) does not include the hash character and
+                * the value is not url encoded.
+                *
+                * @return {string|null}
+                */
+               getFragment: function () {
+                       return this.fragment;
+               },
+
+               /**
+                * Get the URL to this title
+                *
+                * @see mw.util#getUrl
+                * @param {Object} [params] A mapping of query parameter names to values,
+                *     e.g. `{ action: 'edit' }`.
+                * @return {string}
+                */
+               getUrl: function ( params ) {
+                       return mw.util.getUrl( this.toString(), params );
+               },
+
+               /**
+                * Whether this title exists on the wiki.
+                *
+                * @see #static-method-exists
+                * @return {boolean|null} Boolean if the information is available, otherwise null
+                */
+               exists: function () {
+                       return Title.exists( this );
+               }
+       };
+
+       /**
+        * @alias #getPrefixedDb
+        * @method
+        */
+       Title.prototype.toString = Title.prototype.getPrefixedDb;
+
+       /**
+        * @alias #getPrefixedText
+        * @method
+        */
+       Title.prototype.toText = Title.prototype.getPrefixedText;
+
+       // Expose
+       mw.Title = Title;
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.Uri.js b/resources/src/mediawiki/mediawiki.Uri.js
new file mode 100644 (file)
index 0000000..5566312
--- /dev/null
@@ -0,0 +1,403 @@
+/**
+ * Library for simple URI parsing and manipulation.
+ *
+ * Intended to be minimal, but featureful; do not expect full RFC 3986 compliance. The use cases we
+ * have in mind are constructing 'next page' or 'previous page' URLs, detecting whether we need to
+ * use cross-domain proxies for an API, constructing simple URL-based API calls, etc. Parsing here
+ * is regex-based, so may not work on all URIs, but is good enough for most.
+ *
+ * You can modify the properties directly, then use the #toString method to extract the full URI
+ * string again. Example:
+ *
+ *     var uri = new mw.Uri( 'http://example.com/mysite/mypage.php?quux=2' );
+ *
+ *     if ( uri.host == 'example.com' ) {
+ *         uri.host = 'foo.example.com';
+ *         uri.extend( { bar: 1 } );
+ *
+ *         $( 'a#id1' ).attr( 'href', uri );
+ *         // anchor with id 'id1' now links to http://foo.example.com/mysite/mypage.php?bar=1&quux=2
+ *
+ *         $( 'a#id2' ).attr( 'href', uri.clone().extend( { bar: 3, pif: 'paf' } ) );
+ *         // anchor with id 'id2' now links to http://foo.example.com/mysite/mypage.php?bar=3&quux=2&pif=paf
+ *     }
+ *
+ * Given a URI like
+ * `http://usr:pwd@www.example.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=&test3=value+%28escaped%29&r=1&r=2#top`
+ * the returned object will have the following properties:
+ *
+ *     protocol  'http'
+ *     user      'usr'
+ *     password  'pwd'
+ *     host      'www.example.com'
+ *     port      '81'
+ *     path      '/dir/dir.2/index.htm'
+ *     query     {
+ *                   q1: '0',
+ *                   test1: null,
+ *                   test2: '',
+ *                   test3: 'value (escaped)'
+ *                   r: ['1', '2']
+ *               }
+ *     fragment  'top'
+ *
+ * (N.b., 'password' is technically not allowed for HTTP URIs, but it is possible with other kinds
+ * of URIs.)
+ *
+ * Parsing based on parseUri 1.2.2 (c) Steven Levithan <http://stevenlevithan.com>, MIT License.
+ * <http://stevenlevithan.com/demo/parseuri/js/>
+ *
+ * @class mw.Uri
+ */
+
+( function ( mw, $ ) {
+       /**
+        * Function that's useful when constructing the URI string -- we frequently encounter the pattern
+        * of having to add something to the URI as we go, but only if it's present, and to include a
+        * character before or after if so.
+        *
+        * @private
+        * @static
+        * @param {string|undefined} pre To prepend
+        * @param {string} val To include
+        * @param {string} post To append
+        * @param {boolean} raw If true, val will not be encoded
+        * @return {string} Result
+        */
+       function cat( pre, val, post, raw ) {
+               if ( val === undefined || val === null || val === '' ) {
+                       return '';
+               }
+               return pre + ( raw ? val : mw.Uri.encode( val ) ) + post;
+       }
+
+       /**
+        * Regular expressions to parse many common URIs.
+        *
+        * @private
+        * @static
+        * @property {Object} parser
+        */
+       var parser = {
+               strict: /^(?:([^:\/?#]+):)?(?:\/\/(?:(?:([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?([^:\/?#]*)(?::(\d*))?)?((?:[^?#\/]*\/)*[^?#]*)(?:\?([^#]*))?(?:#(.*))?/,
+               loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?(?:(?:([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?([^:\/?#]*)(?::(\d*))?((?:\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?[^?#\/]*)(?:\?([^#]*))?(?:#(.*))?/
+       },
+
+       /**
+        * The order here matches the order of captured matches in the `parser` property regexes.
+        *
+        * @private
+        * @static
+        * @property {Array} properties
+        */
+       properties = [
+               'protocol',
+               'user',
+               'password',
+               'host',
+               'port',
+               'path',
+               'query',
+               'fragment'
+       ];
+
+       /**
+        * @property {string} protocol For example `http` (always present)
+        */
+       /**
+        * @property {string|undefined} user For example `usr`
+        */
+       /**
+        * @property {string|undefined} password For example `pwd`
+        */
+       /**
+        * @property {string} host For example `www.example.com` (always present)
+        */
+       /**
+        * @property {string|undefined} port For example `81`
+        */
+       /**
+        * @property {string} path For example `/dir/dir.2/index.htm` (always present)
+        */
+       /**
+        * @property {Object} query For example `{ a: '0', b: '', c: 'value' }` (always present)
+        */
+       /**
+        * @property {string|undefined} fragment For example `top`
+        */
+
+       /**
+        * A factory method to create a variation of mw.Uri with a different default location (for
+        * relative URLs, including protocol-relative URLs). Used so the library is still testable &
+        * purely functional.
+        *
+        * @method
+        * @member mw
+        */
+       mw.UriRelative = function ( documentLocation ) {
+               var defaultUri;
+
+               /**
+                * @class mw.Uri
+                * @constructor
+                *
+                * Construct a new URI object. Throws error if arguments are illegal/impossible, or
+                * otherwise don't parse.
+                *
+                * @param {Object|string} [uri] URI string, or an Object with appropriate properties (especially
+                *  another URI object to clone). Object must have non-blank `protocol`, `host`, and `path`
+                *  properties. If omitted (or set to `undefined`, `null` or empty string), then an object
+                *  will be created for the default `uri` of this constructor (`document.location` for
+                *  mw.Uri, other values for other instances -- see mw.UriRelative for details).
+                * @param {Object|boolean} [options] Object with options, or (backwards compatibility) a boolean
+                *  for strictMode
+                * @param {boolean} [options.strictMode=false] Trigger strict mode parsing of the url.
+                * @param {boolean} [options.overrideKeys=false] Whether to let duplicate query parameters
+                *  override each other (`true`) or automagically convert them to an array (`false`).
+                */
+               function Uri( uri, options ) {
+                       options = typeof options === 'object' ? options : { strictMode: !!options };
+                       options = $.extend( {
+                               strictMode: false,
+                               overrideKeys: false
+                       }, options );
+
+                       if ( uri !== undefined && uri !== null && uri !== '' ) {
+                               if ( typeof uri === 'string' ) {
+                                       this.parse( uri, options );
+                               } else if ( typeof uri === 'object' ) {
+                                       // Copy data over from existing URI object
+                                       for ( var prop in uri ) {
+                                               // Only copy direct properties, not inherited ones
+                                               if ( uri.hasOwnProperty( prop ) ) {
+                                                       // Deep copy object properties
+                                                       if ( $.isArray( uri[prop] ) || $.isPlainObject( uri[prop] ) ) {
+                                                               this[prop] = $.extend( true, {}, uri[prop] );
+                                                       } else {
+                                                               this[prop] = uri[prop];
+                                                       }
+                                               }
+                                       }
+                                       if ( !this.query ) {
+                                               this.query = {};
+                                       }
+                               }
+                       } else {
+                               // If we didn't get a URI in the constructor, use the default one.
+                               return defaultUri.clone();
+                       }
+
+                       // protocol-relative URLs
+                       if ( !this.protocol ) {
+                               this.protocol = defaultUri.protocol;
+                       }
+                       // No host given:
+                       if ( !this.host ) {
+                               this.host = defaultUri.host;
+                               // port ?
+                               if ( !this.port ) {
+                                       this.port = defaultUri.port;
+                               }
+                       }
+                       if ( this.path && this.path.charAt( 0 ) !== '/' ) {
+                               // A real relative URL, relative to defaultUri.path. We can't really handle that since we cannot
+                               // figure out whether the last path component of defaultUri.path is a directory or a file.
+                               throw new Error( 'Bad constructor arguments' );
+                       }
+                       if ( !( this.protocol && this.host && this.path ) ) {
+                               throw new Error( 'Bad constructor arguments' );
+                       }
+               }
+
+               /**
+                * Encode a value for inclusion in a url.
+                *
+                * Standard encodeURIComponent, with extra stuff to make all browsers work similarly and more
+                * compliant with RFC 3986. Similar to rawurlencode from PHP and our JS library
+                * mw.util.rawurlencode, except this also replaces spaces with `+`.
+                *
+                * @static
+                * @param {string} s String to encode
+                * @return {string} Encoded string for URI
+                */
+               Uri.encode = function ( s ) {
+                       return encodeURIComponent( s )
+                               .replace( /!/g, '%21' ).replace( /'/g, '%27' ).replace( /\(/g, '%28' )
+                               .replace( /\)/g, '%29' ).replace( /\*/g, '%2A' )
+                               .replace( /%20/g, '+' );
+               };
+
+               /**
+                * Decode a url encoded value.
+                *
+                * Reversed #encode. Standard decodeURIComponent, with addition of replacing
+                * `+` with a space.
+                *
+                * @static
+                * @param {string} s String to decode
+                * @return {string} Decoded string
+                */
+               Uri.decode = function ( s ) {
+                       return decodeURIComponent( s.replace( /\+/g, '%20' ) );
+               };
+
+               Uri.prototype = {
+
+                       /**
+                        * Parse a string and set our properties accordingly.
+                        *
+                        * @private
+                        * @param {string} str URI, see constructor.
+                        * @param {Object} options See constructor.
+                        */
+                       parse: function ( str, options ) {
+                               var q, matches,
+                                       uri = this;
+
+                               // Apply parser regex and set all properties based on the result
+                               matches = parser[ options.strictMode ? 'strict' : 'loose' ].exec( str );
+                               $.each( properties, function ( i, property ) {
+                                       uri[ property ] = matches[ i + 1 ];
+                               } );
+
+                               // uri.query starts out as the query string; we will parse it into key-val pairs then make
+                               // that object the "query" property.
+                               // we overwrite query in uri way to make cloning easier, it can use the same list of properties.
+                               q = {};
+                               // using replace to iterate over a string
+                               if ( uri.query ) {
+                                       uri.query.replace( /(?:^|&)([^&=]*)(?:(=)([^&]*))?/g, function ( $0, $1, $2, $3 ) {
+                                               var k, v;
+                                               if ( $1 ) {
+                                                       k = Uri.decode( $1 );
+                                                       v = ( $2 === '' || $2 === undefined ) ? null : Uri.decode( $3 );
+
+                                                       // If overrideKeys, always (re)set top level value.
+                                                       // If not overrideKeys but this key wasn't set before, then we set it as well.
+                                                       if ( options.overrideKeys || q[ k ] === undefined ) {
+                                                               q[ k ] = v;
+
+                                                       // Use arrays if overrideKeys is false and key was already seen before
+                                                       } else {
+                                                               // Once before, still a string, turn into an array
+                                                               if ( typeof q[ k ] === 'string' ) {
+                                                                       q[ k ] = [ q[ k ] ];
+                                                               }
+                                                               // Add to the array
+                                                               if ( $.isArray( q[ k ] ) ) {
+                                                                       q[ k ].push( v );
+                                                               }
+                                                       }
+                                               }
+                                       } );
+                               }
+                               uri.query = q;
+                       },
+
+                       /**
+                        * Get user and password section of a URI.
+                        *
+                        * @return {string}
+                        */
+                       getUserInfo: function () {
+                               return cat( '', this.user, cat( ':', this.password, '' ) );
+                       },
+
+                       /**
+                        * Get host and port section of a URI.
+                        *
+                        * @return {string}
+                        */
+                       getHostPort: function () {
+                               return this.host + cat( ':', this.port, '' );
+                       },
+
+                       /**
+                        * Get the userInfo, host and port section of the URI.
+                        *
+                        * In most real-world URLs this is simply the hostname, but the definition of 'authority' section is more general.
+                        *
+                        * @return {string}
+                        */
+                       getAuthority: function () {
+                               return cat( '', this.getUserInfo(), '@' ) + this.getHostPort();
+                       },
+
+                       /**
+                        * Get the query arguments of the URL, encoded into a string.
+                        *
+                        * Does not preserve the original order of arguments passed in the URI. Does handle escaping.
+                        *
+                        * @return {string}
+                        */
+                       getQueryString: function () {
+                               var args = [];
+                               $.each( this.query, function ( key, val ) {
+                                       var k = Uri.encode( key ),
+                                               vals = $.isArray( val ) ? val : [ val ];
+                                       $.each( vals, function ( i, v ) {
+                                               if ( v === null ) {
+                                                       args.push( k );
+                                               } else if ( k === 'title' ) {
+                                                       args.push( k + '=' + mw.util.wikiUrlencode( v ) );
+                                               } else {
+                                                       args.push( k + '=' + Uri.encode( v ) );
+                                               }
+                                       } );
+                               } );
+                               return args.join( '&' );
+                       },
+
+                       /**
+                        * Get everything after the authority section of the URI.
+                        *
+                        * @return {string}
+                        */
+                       getRelativePath: function () {
+                               return this.path + cat( '?', this.getQueryString(), '', true ) + cat( '#', this.fragment, '' );
+                       },
+
+                       /**
+                        * Get the entire URI string.
+                        *
+                        * May not be precisely the same as input due to order of query arguments.
+                        *
+                        * @return {string} The URI string
+                        */
+                       toString: function () {
+                               return this.protocol + '://' + this.getAuthority() + this.getRelativePath();
+                       },
+
+                       /**
+                        * Clone this URI
+                        *
+                        * @return {Object} New URI object with same properties
+                        */
+                       clone: function () {
+                               return new Uri( this );
+                       },
+
+                       /**
+                        * Extend the query section of the URI with new parameters.
+                        *
+                        * @param {Object} parameters Query parameters to add to ours (or to override ours with) as an
+                        *  object
+                        * @return {Object} This URI object
+                        */
+                       extend: function ( parameters ) {
+                               $.extend( this.query, parameters );
+                               return this;
+                       }
+               };
+
+               defaultUri = new Uri( documentLocation );
+
+               return Uri;
+       };
+
+       // If we are running in a browser, inject the current document location (for relative URLs).
+       if ( document && document.location && document.location.href ) {
+               mw.Uri = mw.UriRelative( document.location.href );
+       }
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.debug.init.js b/resources/src/mediawiki/mediawiki.debug.init.js
new file mode 100644 (file)
index 0000000..0f85e80
--- /dev/null
@@ -0,0 +1,3 @@
+jQuery( function () {
+       mediaWiki.Debug.init();
+} );
diff --git a/resources/src/mediawiki/mediawiki.debug.js b/resources/src/mediawiki/mediawiki.debug.js
new file mode 100644 (file)
index 0000000..f56f0d9
--- /dev/null
@@ -0,0 +1,388 @@
+( function ( mw, $ ) {
+       'use strict';
+
+       var debug,
+               hovzer = $.getFootHovzer();
+
+       /**
+        * Debug toolbar.
+        *
+        * Enabled server-side through `$wgDebugToolbar`.
+        *
+        * @class mw.Debug
+        * @singleton
+        * @author John Du Hart
+        * @since 1.19
+        */
+       debug = mw.Debug = {
+               /**
+                * Toolbar container element
+                *
+                * @property {jQuery}
+                */
+               $container: null,
+
+               /**
+                * Object containing data for the debug toolbar
+                *
+                * @property {Object}
+                */
+               data: {},
+
+               /**
+                * Initialize the debugging pane
+                *
+                * Shouldn't be called before the document is ready
+                * (since it binds to elements on the page).
+                *
+                * @param {Object} [data] Defaults to 'debugInfo' from mw.config
+                */
+               init: function ( data ) {
+
+                       this.data = data || mw.config.get( 'debugInfo' );
+                       this.buildHtml();
+
+                       // Insert the container into the DOM
+                       hovzer.$.append( this.$container );
+                       hovzer.update();
+
+                       $( '.mw-debug-panelink' ).click( this.switchPane );
+               },
+
+               /**
+                * Switch between panes
+                *
+                * Should be called with an HTMLElement as its thisArg,
+                * because it's meant to be an event handler.
+                *
+                * TODO: Store cookie for last pane open.
+                *
+                * @param {jQuery.Event} e
+                */
+               switchPane: function ( e ) {
+                       var currentPaneId = debug.$container.data( 'currentPane' ),
+                               requestedPaneId = $( this ).prop( 'id' ).substr( 9 ),
+                               $currentPane = $( '#mw-debug-pane-' + currentPaneId ),
+                               $requestedPane = $( '#mw-debug-pane-' + requestedPaneId ),
+                               hovDone = false;
+
+                       function updateHov() {
+                               if ( !hovDone ) {
+                                       hovzer.update();
+                                       hovDone = true;
+                               }
+                       }
+
+                       // Skip hash fragment handling. Prevents screen from jumping.
+                       e.preventDefault();
+
+                       $( this ).addClass( 'current ' );
+                       $( '.mw-debug-panelink' ).not( this ).removeClass( 'current ' );
+
+                       // Hide the current pane
+                       if ( requestedPaneId === currentPaneId ) {
+                               $currentPane.slideUp( updateHov );
+                               debug.$container.data( 'currentPane', null );
+                               return;
+                       }
+
+                       debug.$container.data( 'currentPane', requestedPaneId );
+
+                       if ( currentPaneId === undefined || currentPaneId === null ) {
+                               $requestedPane.slideDown( updateHov );
+                       } else {
+                               $currentPane.hide();
+                               $requestedPane.show();
+                               updateHov();
+                       }
+               },
+
+               /**
+                * Construct the HTML for the debugging toolbar
+                */
+               buildHtml: function () {
+                       var $container, $bits, panes, id, gitInfo;
+
+                       $container = $( '<div id="mw-debug-toolbar" class="mw-debug" lang="en" dir="ltr"></div>' );
+
+                       $bits = $( '<div class="mw-debug-bits"></div>' );
+
+                       /**
+                        * Returns a jQuery element for a debug-bit div
+                        *
+                        * @ignore
+                        * @param {string} id
+                        * @return {jQuery}
+                        */
+                       function bitDiv( id ) {
+                               return $( '<div>' ).prop( {
+                                       id: 'mw-debug-' + id,
+                                       className: 'mw-debug-bit'
+                               } )
+                               .appendTo( $bits );
+                       }
+
+                       /**
+                        * Returns a jQuery element for a pane link
+                        *
+                        * @ignore
+                        * @param {string} id
+                        * @param {string} text
+                        * @return {jQuery}
+                        */
+                       function paneLabel( id, text ) {
+                               return $( '<a>' )
+                                       .prop( {
+                                               className: 'mw-debug-panelabel',
+                                               href: '#mw-debug-pane-' + id
+                                       } )
+                                       .text( text );
+                       }
+
+                       /**
+                        * Returns a jQuery element for a debug-bit div with a for a pane link
+                        *
+                        * @ignore
+                        * @param {string} id CSS id snippet. Will be prefixed with 'mw-debug-'
+                        * @param {string} text Text to show
+                        * @param {string} count Optional count to show
+                        * @return {jQuery}
+                        */
+                       function paneTriggerBitDiv( id, text, count ) {
+                               if ( count ) {
+                                       text = text + ' (' + count + ')';
+                               }
+                               return $( '<div>' ).prop( {
+                                       id: 'mw-debug-' + id,
+                                       className: 'mw-debug-bit mw-debug-panelink'
+                               } )
+                               .append( paneLabel( id, text ) )
+                               .appendTo( $bits );
+                       }
+
+                       paneTriggerBitDiv( 'console', 'Console', this.data.log.length );
+
+                       paneTriggerBitDiv( 'querylist', 'Queries', this.data.queries.length );
+
+                       paneTriggerBitDiv( 'debuglog', 'Debug log', this.data.debugLog.length );
+
+                       paneTriggerBitDiv( 'request', 'Request' );
+
+                       paneTriggerBitDiv( 'includes', 'PHP includes', this.data.includes.length );
+
+                       paneTriggerBitDiv( 'profile', 'Profile', this.data.profile.length );
+
+                       gitInfo = '';
+                       if ( this.data.gitRevision !== false ) {
+                               gitInfo = '(' + this.data.gitRevision.substring( 0, 7 ) + ')';
+                               if ( this.data.gitViewUrl !== false ) {
+                                       gitInfo = $( '<a>' )
+                                               .attr( 'href', this.data.gitViewUrl )
+                                               .text( gitInfo );
+                               }
+                       }
+
+                       bitDiv( 'mwversion' )
+                               .append( $( '<a href="//www.mediawiki.org/">MediaWiki</a>' ) )
+                               .append( document.createTextNode( ': ' + this.data.mwVersion + ' ' ) )
+                               .append( gitInfo );
+
+                       if ( this.data.gitBranch !== false ) {
+                               bitDiv( 'gitbranch' ).text( 'Git branch: ' + this.data.gitBranch );
+                       }
+
+                       bitDiv( 'phpversion' )
+                               .append( $( '<a href="//www.php.net/"></a>' ).text( 'PHP' ) )
+                               .append( ': ' + this.data.phpVersion );
+
+                       bitDiv( 'time' )
+                               .text( 'Time: ' + this.data.time.toFixed( 5 ) );
+
+                       bitDiv( 'memory' )
+                               .text( 'Memory: ' + this.data.memory + ' (Peak: ' + this.data.memoryPeak + ')' );
+
+                       $bits.appendTo( $container );
+
+                       panes = {
+                               console: this.buildConsoleTable(),
+                               querylist: this.buildQueryTable(),
+                               debuglog: this.buildDebugLogTable(),
+                               request: this.buildRequestPane(),
+                               includes: this.buildIncludesPane(),
+                               profile: this.buildProfilePane()
+                       };
+
+                       for ( id in panes ) {
+                               if ( !panes.hasOwnProperty( id ) ) {
+                                       continue;
+                               }
+
+                               $( '<div>' )
+                                       .prop( {
+                                               className: 'mw-debug-pane',
+                                               id: 'mw-debug-pane-' + id
+                                       } )
+                                       .append( panes[id] )
+                                       .appendTo( $container );
+                       }
+
+                       this.$container = $container;
+               },
+
+               /**
+                * Build the console panel
+                */
+               buildConsoleTable: function () {
+                       var $table, entryTypeText, i, length, entry;
+
+                       $table = $( '<table id="mw-debug-console">' );
+
+                       $( '<colgroup>' ).css( 'width', /* padding = */ 20 + ( 10 * /* fontSize = */ 11 ) ).appendTo( $table );
+                       $( '<colgroup>' ).appendTo( $table );
+                       $( '<colgroup>' ).css( 'width', 350 ).appendTo( $table );
+
+                       entryTypeText = function ( entryType ) {
+                               switch ( entryType ) {
+                                       case 'log':
+                                               return 'Log';
+                                       case 'warn':
+                                               return 'Warning';
+                                       case 'deprecated':
+                                               return 'Deprecated';
+                                       default:
+                                               return 'Unknown';
+                               }
+                       };
+
+                       for ( i = 0, length = this.data.log.length; i < length; i += 1 ) {
+                               entry = this.data.log[i];
+                               entry.typeText = entryTypeText( entry.type );
+
+                               $( '<tr>' )
+                                       .append( $( '<td>' )
+                                               .text( entry.typeText )
+                                               .addClass( 'mw-debug-console-' + entry.type )
+                                       )
+                                       .append( $( '<td>' ).html( entry.msg ) )
+                                       .append( $( '<td>' ).text( entry.caller ) )
+                                       .appendTo( $table );
+                       }
+
+                       return $table;
+               },
+
+               /**
+                * Build query list pane
+                *
+                * @return {jQuery}
+                */
+               buildQueryTable: function () {
+                       var $table, i, length, query;
+
+                       $table = $( '<table id="mw-debug-querylist"></table>' );
+
+                       $( '<tr>' )
+                               .append( $( '<th>#</th>' ).css( 'width', '4em' )    )
+                               .append( $( '<th>SQL</th>' ) )
+                               .append( $( '<th>Time</th>' ).css( 'width', '8em'  ) )
+                               .append( $( '<th>Call</th>' ).css( 'width', '18em' ) )
+                       .appendTo( $table );
+
+                       for ( i = 0, length = this.data.queries.length; i < length; i += 1 ) {
+                               query = this.data.queries[i];
+
+                               $( '<tr>' )
+                                       .append( $( '<td>' ).text( i + 1 ) )
+                                       .append( $( '<td>' ).text( query.sql ) )
+                                       .append( $( '<td class="stats">' ).text( ( query.time * 1000 ).toFixed( 4 ) + 'ms' ) )
+                                       .append( $( '<td>' ).text( query['function'] ) )
+                               .appendTo( $table );
+                       }
+
+                       return $table;
+               },
+
+               /**
+                * Build legacy debug log pane
+                *
+                * @return {jQuery}
+                */
+               buildDebugLogTable: function () {
+                       var $list, i, length, line;
+                       $list = $( '<ul>' );
+
+                       for ( i = 0, length = this.data.debugLog.length; i < length; i += 1 ) {
+                               line = this.data.debugLog[i];
+                               $( '<li>' )
+                                       .html( mw.html.escape( line ).replace( /\n/g, '<br />\n' ) )
+                                       .appendTo( $list );
+                       }
+
+                       return $list;
+               },
+
+               /**
+                * Build request information pane
+                *
+                * @return {jQuery}
+                */
+               buildRequestPane: function () {
+
+                       function buildTable( title, data ) {
+                               var $unit, $table, key;
+
+                               $unit = $( '<div>' ).append( $( '<h2>' ).text( title ) );
+
+                               $table = $( '<table>' ).appendTo( $unit );
+
+                               $( '<tr>' )
+                                       .html( '<th>Key</th><th>Value</th>' )
+                                       .appendTo( $table );
+
+                               for ( key in data ) {
+                                       if ( !data.hasOwnProperty( key ) ) {
+                                               continue;
+                                       }
+
+                                       $( '<tr>' )
+                                               .append( $( '<th>' ).text( key ) )
+                                               .append( $( '<td>' ).text( data[key] ) )
+                                               .appendTo( $table );
+                               }
+
+                               return $unit;
+                       }
+
+                       return $( '<div>' )
+                               .text( this.data.request.method + ' ' + this.data.request.url )
+                               .append( buildTable( 'Headers', this.data.request.headers ) )
+                               .append( buildTable( 'Parameters', this.data.request.params ) );
+               },
+
+               /**
+                * Build included files pane
+                *
+                * @return {jQuery}
+                */
+               buildIncludesPane: function () {
+                       var $table, i, length, file;
+
+                       $table = $( '<table>' );
+
+                       for ( i = 0, length = this.data.includes.length; i < length; i += 1 ) {
+                               file = this.data.includes[i];
+                               $( '<tr>' )
+                                       .append( $( '<td>' ).text( file.name ) )
+                                       .append( $( '<td class="nr">' ).text( file.size ) )
+                                       .appendTo( $table );
+                       }
+
+                       return $table;
+               },
+
+               buildProfilePane: function () {
+                       return mw.Debug.profile.init();
+               }
+       };
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.debug.less b/resources/src/mediawiki/mediawiki.debug.less
new file mode 100644 (file)
index 0000000..949c558
--- /dev/null
@@ -0,0 +1,189 @@
+.mw-debug {
+       width: 100%;
+       background-color: #eee;
+       border-top: 1px solid #aaa;
+
+       pre {
+               font-size: 11px;
+               padding: 0;
+               margin: 0;
+               background: none;
+               border: none;
+       }
+
+       table {
+               border-spacing: 0;
+               width: 100%;
+               table-layout: fixed;
+
+               td,
+               th {
+                       padding: 4px 10px;
+               }
+
+               td {
+                       border-bottom: 1px solid #eee;
+                       word-wrap: break-word;
+
+                       &.nr {
+                               text-align: right;
+                       }
+
+                       span.stats {
+                               color: #808080;
+                       }
+               }
+
+               tr {
+                       background-color: #fff;
+
+                       &:nth-child(even) {
+                               background-color: #f9f9f9;
+                       }
+               }
+       }
+
+       ul {
+               margin: 0;
+               list-style: none;
+       }
+
+       li {
+               padding: 4px 0;
+               width: 100%;
+       }
+}
+
+.mw-debug-bits {
+       text-align: center;
+       border-bottom: 1px solid #aaa;
+}
+
+.mw-debug-bit {
+       display: inline-block;
+       padding: 10px 5px;
+       font-size: 13px;
+       /* IE-hack for display: inline-block */
+       zoom: 1;
+       *display:inline;
+}
+
+.mw-debug-panelink {
+       background-color: #eee;
+       border-right: 1px solid #ccc;
+
+       &:first-child {
+               border-left: 1px solid #ccc;
+       }
+
+       &:hover {
+               background-color: #fefefe;
+               cursor: pointer;
+       }
+
+       &.current {
+               background-color: #dedede;
+       }
+}
+
+a.mw-debug-panelabel,
+a.mw-debug-panelabel:visited {
+       color: #000;
+}
+
+.mw-debug-pane {
+       height: 300px;
+       overflow: scroll;
+       display: none;
+       font-size: 11px;
+       background-color: #e1eff2;
+       box-sizing: border-box;
+}
+
+#mw-debug-pane-debuglog,
+#mw-debug-pane-request {
+       padding: 20px;
+}
+
+#mw-debug-pane-request {
+       table {
+               width: 100%;
+               margin: 10px 0 30px;
+       }
+
+       tr,
+       th,
+       td,
+       table {
+               border: 1px solid #D0DBB3;
+               border-collapse: collapse;
+               margin: 0;
+       }
+
+       th,
+       td {
+               font-size: 12px;
+               padding: 8px 10px;
+       }
+
+       th {
+               background-color: #F1F7E2;
+               font-weight: bold;
+       }
+
+       td {
+               background-color: white;
+       }
+}
+
+#mw-debug-console tr td {
+       &:first-child {
+               font-weight: bold;
+               vertical-align: top;
+       }
+
+       &:last-child {
+               vertical-align: top;
+       }
+}
+
+.mw-debug-backtrace {
+       padding: 5px 10px;
+       margin: 5px;
+       background-color: #dedede;
+
+       span {
+               font-weight: bold;
+               color: #111;
+       }
+
+       ul {
+               padding-left: 10px;
+       }
+
+       li {
+               width: auto;
+               padding: 0;
+               color: #333;
+               font-size: 10px;
+               margin-bottom: 0;
+               line-height: 1em;
+       }
+}
+
+.mw-debug-console-log {
+       background-color: #add8e6;
+}
+
+.mw-debug-console-warn {
+       background-color: #ffa07a;
+}
+
+.mw-debug-console-deprecated {
+       background-color: #ffb6c1;
+}
+
+/* Cheapo hack to hide the first 3 lines of the backtrace */
+.mw-debug-backtrace li:nth-child(-n+3) {
+       display: none;
+}
diff --git a/resources/src/mediawiki/mediawiki.debug.profile.css b/resources/src/mediawiki/mediawiki.debug.profile.css
new file mode 100644 (file)
index 0000000..bf49d1a
--- /dev/null
@@ -0,0 +1,46 @@
+
+.mw-debug-profile-tipsy .tipsy-inner {
+       /* undo max-width from vector on .tipsy-inner */
+       max-width: none;
+       /* needed for some browsers to provide space for the scrollbar without wrapping text */
+       min-width: 100%;
+       max-height: 150px;
+       overflow-y: auto;
+}
+
+.mw-debug-profile-underline {
+       stroke-width: 1;
+       stroke: #dfdfdf;
+}
+
+.mw-debug-profile-period {
+       fill: red;
+}
+
+/* connecting line between endpoints on long events */
+.mw-debug-profile-period line {
+       stroke: red;
+       stroke-width: 2;
+}
+
+.mw-debug-profile-tipsy,
+.mw-debug-profile-timeline text {
+       color: #444;
+       fill: #444;
+       /* using em's causes the two locations to have different sizes */
+       font-size: 12px;
+       font-family: sans-serif;
+}
+
+.mw-debug-profile-meta,
+.mw-debug-profile-timeline tspan {
+       /* using em's causes the two locations to have different sizes */
+       font-size: 10px;
+}
+
+.mw-debug-profile-no-data {
+       text-align: center;
+       padding-top: 5em;
+       font-weight: bold;
+       font-size: 1.2em;
+}
diff --git a/resources/src/mediawiki/mediawiki.debug.profile.js b/resources/src/mediawiki/mediawiki.debug.profile.js
new file mode 100644 (file)
index 0000000..f6bc81d
--- /dev/null
@@ -0,0 +1,546 @@
+/*!
+ * JavaScript for the debug toolbar profiler, enabled through $wgDebugToolbar
+ * and StartProfiler.php.
+ *
+ * @author Erik Bernhardson
+ * @since 1.23
+ */
+
+( function ( mw, $ ) {
+       'use strict';
+
+       /**
+        * @singleton
+        * @class mw.Debug.profile
+        */
+       var profile = mw.Debug.profile = {
+               /**
+                * Object containing data for the debug toolbar
+                *
+                * @property ProfileData
+                */
+               data: null,
+
+               /**
+                * @property DOMElement
+                */
+               container: null,
+
+               /**
+                * Initializes the profiling pane.
+                */
+               init: function ( data, width, mergeThresholdPx, dropThresholdPx ) {
+                       data = data || mw.config.get( 'debugInfo' ).profile;
+                       profile.width = width || $(window).width() - 20;
+                       // merge events from same pixel(some events are very granular)
+                       mergeThresholdPx = mergeThresholdPx || 2;
+                       // only drop events if requested
+                       dropThresholdPx = dropThresholdPx || 0;
+
+                       if ( !Array.prototype.map || !Array.prototype.reduce || !Array.prototype.filter ) {
+                               profile.container = profile.buildRequiresES5();
+                       } else if ( data.length === 0 ) {
+                               profile.container = profile.buildNoData();
+                       } else {
+                               // generate a flyout
+                               profile.data = new ProfileData( data, profile.width, mergeThresholdPx, dropThresholdPx );
+                               // draw it
+                               profile.container = profile.buildSvg( profile.container );
+                               profile.attachFlyout();
+                       }
+
+                       return profile.container;
+               },
+
+               buildRequiresES5: function () {
+                       return $( '<div>' )
+                               .text( 'An ES5 compatible javascript engine is required for the profile visualization.' )
+                               .get( 0 );
+               },
+
+               buildNoData: function () {
+                       return $( '<div>' ).addClass( 'mw-debug-profile-no-data' )
+                               .text( 'No events recorded, ensure profiling is enabled in StartProfiler.php.' )
+                               .get( 0 );
+               },
+
+               /**
+                * Creates DOM nodes appropriately namespaced for SVG.
+                *
+                * @param string tag to create
+                * @return DOMElement
+                */
+               createSvgElement: document.createElementNS.bind( document, 'http://www.w3.org/2000/svg' ),
+
+               /**
+                * @param DOMElement|undefined
+                */
+               buildSvg: function ( node ) {
+                       var container, group, i, g,
+                               timespan = profile.data.timespan,
+                               gapPerEvent = 38,
+                               space = 10.5,
+                               currentHeight = space,
+                               totalHeight = 0;
+
+                       profile.ratio = ( profile.width - space * 2 ) / ( timespan.end - timespan.start );
+                       totalHeight += gapPerEvent * profile.data.groups.length;
+
+                       if ( node ) {
+                               $( node ).empty();
+                       } else {
+                               node = profile.createSvgElement( 'svg' );
+                               node.setAttribute( 'version', '1.2' );
+                               node.setAttribute( 'baseProfile', 'tiny' );
+                       }
+                       node.style.height = totalHeight;
+                       node.style.width = profile.width;
+
+                       // use a container that can be transformed
+                       container = profile.createSvgElement( 'g' );
+                       node.appendChild( container );
+
+                       for ( i = 0; i < profile.data.groups.length; i++ ) {
+                               group = profile.data.groups[i];
+                               g = profile.buildTimeline( group );
+
+                               g.setAttribute( 'transform', 'translate( 0 ' + currentHeight + ' )' );
+                               container.appendChild( g );
+
+                               currentHeight += gapPerEvent;
+                       }
+
+                       return node;
+               },
+
+               /**
+                * @param Object group of periods to transform into graphics
+                */
+               buildTimeline: function ( group ) {
+                       var text, tspan, line, i,
+                               sum = group.timespan.sum,
+                               ms = ' ~ ' + ( sum < 1 ? sum.toFixed( 2 ) : sum.toFixed( 0 ) ) + ' ms',
+                               timeline = profile.createSvgElement( 'g' );
+
+                       timeline.setAttribute( 'class', 'mw-debug-profile-timeline' );
+
+                       // draw label
+                       text = profile.createSvgElement( 'text' );
+                       text.setAttribute( 'x', profile.xCoord( group.timespan.start ) );
+                       text.setAttribute( 'y', 0 );
+                       text.textContent = group.name;
+                       timeline.appendChild( text );
+
+                       // draw metadata
+                       tspan = profile.createSvgElement( 'tspan' );
+                       tspan.textContent = ms;
+                       text.appendChild( tspan );
+
+                       // draw timeline periods
+                       for ( i = 0; i < group.periods.length; i++ ) {
+                               timeline.appendChild( profile.buildPeriod( group.periods[i] ) );
+                       }
+
+                       // full-width line under each timeline
+                       line = profile.createSvgElement( 'line' );
+                       line.setAttribute( 'class', 'mw-debug-profile-underline' );
+                       line.setAttribute( 'x1', 0 );
+                       line.setAttribute( 'y1', 28 );
+                       line.setAttribute( 'x2', profile.width );
+                       line.setAttribute( 'y2', 28 );
+                       timeline.appendChild( line );
+
+                       return timeline;
+               },
+
+               /**
+                * @param Object period to transform into graphics
+                */
+               buildPeriod: function ( period ) {
+                       var node,
+                               head = profile.xCoord( period.start ),
+                               tail = profile.xCoord( period.end ),
+                               g = profile.createSvgElement( 'g' );
+
+                       g.setAttribute( 'class', 'mw-debug-profile-period' );
+                       $( g ).data( 'period', period );
+
+                       if ( head + 16 > tail ) {
+                               node = profile.createSvgElement( 'rect' );
+                               node.setAttribute( 'x', head );
+                               node.setAttribute( 'y', 8 );
+                               node.setAttribute( 'width', 2 );
+                               node.setAttribute( 'height', 9 );
+                               g.appendChild( node );
+
+                               node = profile.createSvgElement( 'rect' );
+                               node.setAttribute( 'x', head );
+                               node.setAttribute( 'y', 8 );
+                               node.setAttribute( 'width', ( period.end - period.start ) * profile.ratio || 2 );
+                               node.setAttribute( 'height', 6 );
+                               g.appendChild( node );
+                       } else {
+                               node = profile.createSvgElement( 'polygon' );
+                               node.setAttribute( 'points', pointList( [
+                                       [ head, 8 ],
+                                       [ head, 19 ],
+                                       [ head + 8, 8 ],
+                                       [ head, 8]
+                               ] ) );
+                               g.appendChild( node );
+
+                               node = profile.createSvgElement( 'polygon' );
+                               node.setAttribute( 'points', pointList( [
+                                       [ tail, 8 ],
+                                       [ tail, 19 ],
+                                       [ tail - 8, 8 ],
+                                       [ tail, 8 ],
+                               ] ) );
+                               g.appendChild( node );
+
+                               node = profile.createSvgElement( 'line' );
+                               node.setAttribute( 'x1', head );
+                               node.setAttribute( 'y1', 9 );
+                               node.setAttribute( 'x2', tail );
+                               node.setAttribute( 'y2', 9 );
+                               g.appendChild( node );
+                       }
+
+                       return g;
+               },
+
+               /**
+                * @param Object
+                */
+               buildFlyout: function ( period ) {
+                       var contained, sum, ms, mem, i,
+                               node = $( '<div>' );
+
+                       for ( i = 0; i < period.contained.length; i++ ) {
+                               contained = period.contained[i];
+                               sum = contained.end - contained.start;
+                               ms = '' + ( sum < 1 ? sum.toFixed( 2 ) : sum.toFixed( 0 ) ) + ' ms';
+                               mem = formatBytes( contained.memory );
+
+                               $( '<div>' ).text( contained.source.name )
+                                       .append( $( '<span>' ).text( ' ~ ' + ms + ' / ' + mem ).addClass( 'mw-debug-profile-meta' ) )
+                                       .appendTo( node );
+                       }
+
+                       return node;
+               },
+
+               /**
+                * Attach a hover flyout to all .mw-debug-profile-period groups.
+                */
+               attachFlyout: function () {
+                       // for some reason addClass and removeClass from jQuery
+                       // arn't working on svg elements in chrome <= 33.0 (possibly more)
+                       var $container = $( profile.container ),
+                               addClass = function ( node, value ) {
+                                       var current = node.getAttribute( 'class' ),
+                                               list = current ? current.split( ' ' ) : false,
+                                               idx = list ? list.indexOf( value ) : -1;
+
+                                       if ( idx === -1 ) {
+                                               node.setAttribute( 'class', current ? ( current + ' ' + value ) : value );
+                                       }
+                               },
+                               removeClass = function ( node, value ) {
+                                       var current = node.getAttribute( 'class' ),
+                                               list = current ? current.split( ' ' ) : false,
+                                               idx = list ? list.indexOf( value ) : -1;
+
+                                       if ( idx !== -1 ) {
+                                               list.splice( idx, 1 );
+                                               node.setAttribute( 'class', list.join( ' ' ) );
+                                       }
+                               },
+                               // hide all tipsy flyouts
+                               hide = function () {
+                                       $container.find( '.mw-debug-profile-period.tipsy-visible' )
+                                               .each( function () {
+                                                       removeClass( this, 'tipsy-visible' );
+                                                       $( this ).tipsy( 'hide' );
+                                               } );
+                               };
+
+                       $container.find( '.mw-debug-profile-period' ).tipsy( {
+                               fade: true,
+                               gravity: function () {
+                                       return $.fn.tipsy.autoNS.call( this )
+                                               + $.fn.tipsy.autoWE.call( this );
+                               },
+                               className: 'mw-debug-profile-tipsy',
+                               center: false,
+                               html: true,
+                               trigger: 'manual',
+                               title: function () {
+                                       return profile.buildFlyout( $( this ).data( 'period' ) ).html();
+                               },
+                       } ).on( 'mouseenter', function () {
+                               hide();
+                               addClass( this, 'tipsy-visible' );
+                               $( this ).tipsy( 'show' );
+                       } );
+
+                       $container.on( 'mouseleave', function ( event ) {
+                               var $from = $( event.relatedTarget ),
+                                       $to = $( event.target );
+                               // only close the tipsy if we are not
+                               if ( $from.closest( '.tipsy' ).length === 0 &&
+                                       $to.closest( '.tipsy' ).length === 0 &&
+                                       $to.get( 0 ).namespaceURI !== 'http://www.w4.org/2000/svg'
+                               ) {
+                                       hide();
+                               }
+                       } ).on( 'click', function () {
+                               // convenience method for closing
+                               hide();
+                       } );
+               },
+
+               /**
+                * @return number the x co-ordinate for the specified timestamp
+                */
+               xCoord: function ( msTimestamp ) {
+                       return ( msTimestamp - profile.data.timespan.start ) * profile.ratio;
+               },
+       };
+
+       function ProfileData( data, width, mergeThresholdPx, dropThresholdPx ) {
+               // validate input data
+               this.data = data.map( function ( event ) {
+                       event.periods = event.periods.filter( function ( period ) {
+                               return period.start && period.end
+                                       && period.start < period.end
+                                       // period start must be a reasonable ms timestamp
+                                       && period.start > 1000000;
+                       } );
+                       return event;
+               } ).filter( function ( event ) {
+                       return event.name && event.periods.length > 0;
+               } );
+
+               // start and end time of the data
+               this.timespan = this.data.reduce( function ( result, event ) {
+                       return event.periods.reduce( periodMinMax, result );
+               }, periodMinMax.initial() );
+
+               // transform input data
+               this.groups = this.collate( width, mergeThresholdPx, dropThresholdPx );
+
+               return this;
+       }
+
+       /**
+        * There are too many unique events to display a line for each,
+        * so this does a basic grouping.
+        */
+       ProfileData.groupOf = function ( label ) {
+               var pos, prefix = 'Profile section ended by close(): ';
+               if ( label.indexOf( prefix ) === 0 ) {
+                       label = label.substring( prefix.length );
+               }
+
+               pos = [ '::', ':', '-' ].reduce( function ( result, separator ) {
+                       var pos = label.indexOf( separator );
+                       if ( pos === -1 ) {
+                               return result;
+                       } else if ( result === -1 ) {
+                               return pos;
+                       } else {
+                               return Math.min( result, pos );
+                       }
+               }, -1 );
+
+               if ( pos === -1 ) {
+                       return label;
+               } else {
+                       return label.substring( 0, pos );
+               }
+       };
+
+       /**
+        * @return Array list of objects with `name` and `events` keys
+        */
+       ProfileData.groupEvents = function ( events ) {
+               var group, i,
+                       groups = {};
+
+               // Group events together
+               for ( i = events.length - 1; i >= 0; i-- ) {
+                       group = ProfileData.groupOf( events[i].name );
+                       if ( groups[group] ) {
+                               groups[group].push( events[i] );
+                       } else {
+                               groups[group] = [events[i]];
+                       }
+               }
+
+               // Return an array of groups
+               return Object.keys( groups ).map( function ( group ) {
+                       return {
+                               name: group,
+                               events: groups[group],
+                       };
+               } );
+       };
+
+       ProfileData.periodSorter = function ( a, b ) {
+               if ( a.start === b.start ) {
+                       return a.end - b.end;
+               }
+               return a.start - b.start;
+       };
+
+       ProfileData.genMergePeriodReducer = function ( mergeThresholdMs ) {
+               return function ( result, period ) {
+                       if ( result.length === 0 ) {
+                               // period is first result
+                               return [{
+                                       start: period.start,
+                                       end: period.end,
+                                       contained: [period],
+                               }];
+                       }
+                       var last = result[result.length - 1];
+                       if ( period.end < last.end ) {
+                               // end is contained within previous
+                               result[result.length - 1].contained.push( period );
+                       } else if ( period.start - mergeThresholdMs < last.end ) {
+                               // neighbors within merging distance
+                               result[result.length - 1].end = period.end;
+                               result[result.length - 1].contained.push( period );
+                       } else {
+                               // period is next result
+                               result.push({
+                                       start: period.start,
+                                       end: period.end,
+                                       contained: [period],
+                               });
+                       }
+                       return result;
+               };
+       };
+
+       /**
+        * Collect all periods from the grouped events and apply merge and
+        * drop transformations
+        */
+       ProfileData.extractPeriods = function ( events, mergeThresholdMs, dropThresholdMs ) {
+               // collect the periods from all events
+               return events.reduce( function ( result, event ) {
+                               if ( !event.periods.length ) {
+                                       return result;
+                               }
+                               result.push.apply( result, event.periods.map( function ( period ) {
+                                       // maintain link from period to event
+                                       period.source = event;
+                                       return period;
+                               } ) );
+                               return result;
+                       }, [] )
+                       // sort combined periods
+                       .sort( ProfileData.periodSorter )
+                       // Apply merge threshold. Original periods
+                       // are maintained in the `contained` property
+                       .reduce( ProfileData.genMergePeriodReducer( mergeThresholdMs ), [] )
+                       // Apply drop threshold
+                       .filter( function ( period ) {
+                               return period.end - period.start > dropThresholdMs;
+                       } );
+       };
+
+       /**
+        * runs a callback on all periods in the group.  Only valid after
+        * groups.periods[0..n].contained are populated. This runs against
+        * un-transformed data and is better suited to summing or other
+        * stat collection
+        */
+       ProfileData.reducePeriods = function ( group, callback, result ) {
+               return group.periods.reduce( function ( result, period ) {
+                       return period.contained.reduce( callback, result );
+               }, result );
+       };
+
+       /**
+        * Transforms this.data grouping by labels, merging neighboring
+        * events in the groups, and drops events and groups below the
+        * display threshold. Groups are returned sorted by starting time.
+        */
+       ProfileData.prototype.collate = function ( width, mergeThresholdPx, dropThresholdPx ) {
+               // ms to pixel ratio
+               var ratio = ( this.timespan.end - this.timespan.start ) / width,
+                       // transform thresholds to ms
+                       mergeThresholdMs = mergeThresholdPx * ratio,
+                       dropThresholdMs = dropThresholdPx * ratio;
+
+               return ProfileData.groupEvents( this.data )
+                       // generate data about the grouped events
+                       .map( function ( group ) {
+                               // Cleaned periods from all events
+                               group.periods = ProfileData.extractPeriods( group.events, mergeThresholdMs, dropThresholdMs );
+                               // min and max timestamp per group
+                               group.timespan = ProfileData.reducePeriods( group, periodMinMax, periodMinMax.initial() );
+                               // ms from first call to end of last call
+                               group.timespan.length = group.timespan.end - group.timespan.start;
+                               // collect the un-transformed periods
+                               group.timespan.sum = ProfileData.reducePeriods( group, function ( result, period ) {
+                                               result.push( period );
+                                               return result;
+                                       }, [] )
+                                       // sort by start time
+                                       .sort( ProfileData.periodSorter )
+                                       // merge overlapping
+                                       .reduce( ProfileData.genMergePeriodReducer( 0 ), [] )
+                                       // sum
+                                       .reduce( function ( result, period ) {
+                                               return result + period.end - period.start;
+                                       }, 0 );
+
+                               return group;
+                       }, this )
+                       // remove groups that have had all their periods filtered
+                       .filter( function ( group ) {
+                               return group.periods.length > 0;
+                       } )
+                       // sort events by first start
+                       .sort( function ( a, b ) {
+                               return ProfileData.periodSorter( a.timespan, b.timespan );
+                       } );
+       };
+
+       // reducer to find edges of period array
+       function periodMinMax( result, period ) {
+               if ( period.start < result.start ) {
+                       result.start = period.start;
+               }
+               if ( period.end > result.end ) {
+                       result.end = period.end;
+               }
+               return result;
+       }
+
+       periodMinMax.initial = function () {
+               return { start: Number.POSITIVE_INFINITY, end: Number.NEGATIVE_INFINITY };
+       };
+
+       function formatBytes( bytes ) {
+               var i, sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+               if ( bytes === 0 ) {
+                       return '0 Bytes';
+               }
+               i = parseInt( Math.floor( Math.log( bytes ) / Math.log( 1024 ) ), 10 );
+               return Math.round( bytes / Math.pow( 1024, i ), 2 ) + ' ' + sizes[i];
+       }
+
+       // turns a 2d array into a point list for svg
+       // polygon points attribute
+       // ex: [[1,2],[3,4],[4,2]] = '1,2 3,4 4,2'
+       function pointList( pairs ) {
+               return pairs.map( function ( pair ) {
+                       return pair.join( ',' );
+               } ).join( ' ' );
+       }
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.feedback.css b/resources/src/mediawiki/mediawiki.feedback.css
new file mode 100644 (file)
index 0000000..6bd47bb
--- /dev/null
@@ -0,0 +1,9 @@
+.feedback-spinner {
+       display: inline-block;
+       zoom: 1;
+       *display: inline; /* IE7 and below */
+       /* @embed */
+       background: url(mediawiki.feedback.spinner.gif);
+       width: 18px;
+       height: 18px;
+}
diff --git a/resources/src/mediawiki/mediawiki.feedback.js b/resources/src/mediawiki/mediawiki.feedback.js
new file mode 100644 (file)
index 0000000..90a6425
--- /dev/null
@@ -0,0 +1,316 @@
+/*!
+ * mediawiki.feedback
+ *
+ * @author Ryan Kaldari, 2010
+ * @author Neil Kandalgaonkar, 2010-11
+ * @since 1.19
+ */
+( function ( mw, $ ) {
+       /**
+        * This is a way of getting simple feedback from users. It's useful
+        * for testing new features -- users can give you feedback without
+        * the difficulty of opening a whole new talk page. For this reason,
+        * it also tends to collect a wider range of both positive and negative
+        * comments. However you do need to tend to the feedback page. It will
+        * get long relatively quickly, and you often get multiple messages
+        * reporting the same issue.
+        *
+        * It takes the form of thing on your page which, when clicked, opens a small
+        * dialog box. Submitting that dialog box appends its contents to a
+        * wiki page that you specify, as a new section.
+        *
+        * Not compatible with LiquidThreads.
+        *
+        * Minimal example in how to use it:
+        *
+        *     var feedback = new mw.Feedback();
+        *     $( '#myButton' ).click( function () { feedback.launch(); } );
+        *
+        * You can also launch the feedback form with a prefilled subject and body.
+        * See the docs for the #launch() method.
+        *
+        * @class
+        * @constructor
+        * @param {Object} [options]
+        * @param {mw.Api} [options.api] if omitted, will just create a standard API
+        * @param {mw.Title} [options.title="Feedback"] The title of the page where you collect
+        * feedback.
+        * @param {string} [options.dialogTitleMessageKey="feedback-submit"] Message key for the
+        * title of the dialog box
+        * @param {string} [options.bugsLink="//bugzilla.wikimedia.org/enter_bug.cgi"] URL where
+        * bugs can be posted
+        * @param {mw.Uri|string} [options.bugsListLink="//bugzilla.wikimedia.org/query.cgi"]
+        * URL where bugs can be listed
+        */
+       mw.Feedback = function ( options ) {
+               if ( options === undefined ) {
+                       options = {};
+               }
+
+               if ( options.api === undefined ) {
+                       options.api = new mw.Api();
+               }
+
+               if ( options.title === undefined ) {
+                       options.title = new mw.Title( 'Feedback' );
+               }
+
+               if ( options.dialogTitleMessageKey === undefined ) {
+                       options.dialogTitleMessageKey = 'feedback-submit';
+               }
+
+               if ( options.bugsLink === undefined ) {
+                       options.bugsLink = '//bugzilla.wikimedia.org/enter_bug.cgi';
+               }
+
+               if ( options.bugsListLink === undefined ) {
+                       options.bugsListLink = '//bugzilla.wikimedia.org/query.cgi';
+               }
+
+               $.extend( this, options );
+               this.setup();
+       };
+
+       mw.Feedback.prototype = {
+               /**
+                * Sets up interface
+                */
+               setup: function () {
+                       var $feedbackPageLink,
+                               $bugNoteLink,
+                               $bugsListLink,
+                               fb = this;
+
+                       $feedbackPageLink = $( '<a>' )
+                               .attr( {
+                                       href: fb.title.getUrl(),
+                                       target: '_blank'
+                               } )
+                               .css( {
+                                       whiteSpace: 'nowrap'
+                               } );
+
+                       $bugNoteLink = $( '<a>' ).attr( { href: '#' } ).click( function () {
+                               fb.displayBugs();
+                       } );
+
+                       $bugsListLink = $( '<a>' ).attr( {
+                               href: fb.bugsListLink,
+                               target: '_blank'
+                       } );
+
+                       // TODO: Use a stylesheet instead of these inline styles
+                       this.$dialog =
+                               $( '<div style="position: relative;"></div>' ).append(
+                                       $( '<div class="feedback-mode feedback-form"></div>' ).append(
+                                               $( '<small>' ).append(
+                                                       $( '<p>' ).msg(
+                                                               'feedback-bugornote',
+                                                               $bugNoteLink,
+                                                               fb.title.getNameText(),
+                                                               $feedbackPageLink.clone()
+                                                       )
+                                               ),
+                                               $( '<div style="margin-top: 1em;"></div>' ).append(
+                                                       mw.msg( 'feedback-subject' ),
+                                                       $( '<br>' ),
+                                                       $( '<input type="text" class="feedback-subject" name="subject" maxlength="60" style="width: 100%; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;"/>' )
+                                               ),
+                                               $( '<div style="margin-top: 0.4em;"></div>' ).append(
+                                                       mw.msg( 'feedback-message' ),
+                                                       $( '<br>' ),
+                                                       $( '<textarea name="message" class="feedback-message" rows="5" cols="60"></textarea>' )
+                                               )
+                                       ),
+                                       $( '<div class="feedback-mode feedback-bugs"></div>' ).append(
+                                               $( '<p>' ).msg( 'feedback-bugcheck', $bugsListLink )
+                                       ),
+                                       $( '<div class="feedback-mode feedback-submitting" style="text-align: center; margin: 3em 0;"></div>' ).append(
+                                               mw.msg( 'feedback-adding' ),
+                                               $( '<br>' ),
+                                               $( '<span class="feedback-spinner"></span>' )
+                                       ),
+                                       $( '<div class="feedback-mode feedback-thanks" style="text-align: center; margin:1em"></div>' ).msg(
+                                               'feedback-thanks', fb.title.getNameText(), $feedbackPageLink.clone()
+                                       ),
+                                       $( '<div class="feedback-mode feedback-error" style="position: relative;"></div>' ).append(
+                                               $( '<div class="feedback-error-msg style="color: #990000; margin-top: 0.4em;"></div>' )
+                                       )
+                               );
+
+                               // undo some damage from dialog css
+                               this.$dialog.find( 'a' ).css( {
+                                       color: '#0645ad'
+                               } );
+
+                               this.$dialog.dialog({
+                                       width: 500,
+                                       autoOpen: false,
+                                       title: mw.msg( this.dialogTitleMessageKey ),
+                                       modal: true,
+                                       buttons: fb.buttons
+                               });
+
+                       this.subjectInput = this.$dialog.find( 'input.feedback-subject' ).get(0);
+                       this.messageInput = this.$dialog.find( 'textarea.feedback-message' ).get(0);
+
+               },
+
+               /**
+                * Displays a section of the dialog.
+                *
+                * @param {"form"|"bugs"|"submitting"|"thanks"|"error"} s
+                * The section of the dialog to show.
+                */
+               display: function ( s ) {
+                       // Hide the buttons
+                       this.$dialog.dialog( { buttons: {} } );
+                       // Hide everything
+                       this.$dialog.find( '.feedback-mode' ).hide();
+                       // Show the desired div
+                       this.$dialog.find( '.feedback-' + s ).show();
+               },
+
+               /**
+                * Display the submitting section.
+                */
+               displaySubmitting: function () {
+                       this.display( 'submitting' );
+               },
+
+               /**
+                * Display the bugs section.
+                */
+               displayBugs: function () {
+                       var fb = this,
+                               bugsButtons = {};
+                       this.display( 'bugs' );
+                       bugsButtons[ mw.msg( 'feedback-bugnew' ) ] = function () {
+                               window.open( fb.bugsLink, '_blank' );
+                       };
+                       bugsButtons[ mw.msg( 'feedback-cancel' ) ] = function () {
+                               fb.cancel();
+                       };
+                       this.$dialog.dialog( {
+                               buttons: bugsButtons
+                       } );
+               },
+
+               /**
+                * Display the thanks section.
+                */
+               displayThanks: function () {
+                       var fb = this,
+                               closeButton = {};
+                       this.display( 'thanks' );
+                       closeButton[ mw.msg( 'feedback-close' ) ] = function () {
+                               fb.$dialog.dialog( 'close' );
+                       };
+                       this.$dialog.dialog( {
+                               buttons: closeButton
+                       } );
+               },
+
+               /**
+                * Display the feedback form
+                * @param {Object} [contents] Prefilled contents for the feedback form.
+                * @param {string} [contents.subject] The subject of the feedback
+                * @param {string} [contents.message] The content of the feedback
+                */
+               displayForm: function ( contents ) {
+                       var fb = this,
+                               formButtons = {};
+                       this.subjectInput.value = ( contents && contents.subject ) ? contents.subject : '';
+                       this.messageInput.value = ( contents && contents.message ) ? contents.message : '';
+
+                       this.display( 'form' );
+
+                       // Set up buttons for dialog box. We have to do it the hard way since the json keys are localized
+                       formButtons[ mw.msg( 'feedback-submit' ) ] = function () {
+                               fb.submit();
+                       };
+                       formButtons[ mw.msg( 'feedback-cancel' ) ] = function () {
+                               fb.cancel();
+                       };
+                       this.$dialog.dialog( { buttons: formButtons } ); // put the buttons back
+               },
+
+               /**
+                * Display an error on the form.
+                *
+                * @param {string} message Should be a valid message key.
+                */
+               displayError: function ( message ) {
+                       var fb = this,
+                               closeButton = {};
+                       this.display( 'error' );
+                       this.$dialog.find( '.feedback-error-msg' ).msg( message );
+                       closeButton[ mw.msg( 'feedback-close' ) ] = function () {
+                               fb.$dialog.dialog( 'close' );
+                       };
+                       this.$dialog.dialog( { buttons: closeButton } );
+               },
+
+               /**
+                * Close the feedback form.
+                */
+               cancel: function () {
+                       this.$dialog.dialog( 'close' );
+               },
+
+               /**
+                * Submit the feedback form.
+                */
+               submit: function () {
+                       var subject, message,
+                               fb = this;
+
+                       function ok( result ) {
+                               if ( result.edit !== undefined ) {
+                                       if ( result.edit.result === 'Success' ) {
+                                               fb.displayThanks();
+                                       } else {
+                                               // unknown API result
+                                               fb.displayError( 'feedback-error1' );
+                                       }
+                               } else {
+                                       // edit failed
+                                       fb.displayError( 'feedback-error2' );
+                               }
+                       }
+
+                       function err() {
+                               // ajax request failed
+                               fb.displayError( 'feedback-error3' );
+                       }
+
+                       // Get the values to submit.
+                       subject = this.subjectInput.value;
+
+                       // We used to include "mw.html.escape( navigator.userAgent )" but there are legal issues
+                       // with posting this without their explicit consent
+                       message = this.messageInput.value;
+                       if ( message.indexOf( '~~~' ) === -1 ) {
+                               message += ' ~~~~';
+                       }
+
+                       this.displaySubmitting();
+
+                       this.api.newSection( this.title, subject, message, ok, err );
+               },
+
+               /**
+                * Modify the display form, and then open it, focusing interface on the subject.
+                * @param {Object} [contents] Prefilled contents for the feedback form.
+                * @param {string} [contents.subject] The subject of the feedback
+                * @param {string} [contents.message] The content of the feedback
+                */
+               launch: function ( contents ) {
+                       this.displayForm( contents );
+                       this.$dialog.dialog( 'open' );
+                       this.subjectInput.focus();
+               }
+
+       };
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.feedback.spinner.gif b/resources/src/mediawiki/mediawiki.feedback.spinner.gif
new file mode 100644 (file)
index 0000000..aed0ea4
Binary files /dev/null and b/resources/src/mediawiki/mediawiki.feedback.spinner.gif differ
diff --git a/resources/src/mediawiki/mediawiki.hidpi.js b/resources/src/mediawiki/mediawiki.hidpi.js
new file mode 100644 (file)
index 0000000..ecee450
--- /dev/null
@@ -0,0 +1,5 @@
+jQuery( function ( $ ) {
+       // Apply hidpi images on DOM-ready
+       // Some may have already partly preloaded at low resolution.
+       $( 'body' ).hidpi();
+} );
diff --git a/resources/src/mediawiki/mediawiki.hlist.css b/resources/src/mediawiki/mediawiki.hlist.css
new file mode 100644 (file)
index 0000000..adcb810
--- /dev/null
@@ -0,0 +1,78 @@
+/*!
+ * Stylesheet for mediawiki.hlist module
+ * @author [[User:Edokter]]
+ */
+.hlist dl,
+.hlist ol,
+.hlist ul {
+       margin: 0;
+       padding: 0;
+}
+/* Display list items inline */
+.hlist dd,
+.hlist dt,
+.hlist li {
+       margin: 0;
+       display: inline;
+}
+/* Display nested lists inline */
+.hlist dl dl, .hlist dl ol, .hlist dl ul,
+.hlist ol dl, .hlist ol ol, .hlist ol ul,
+.hlist ul dl, .hlist ul ol, .hlist ul ul {
+       display: inline;
+}
+/* Generate interpuncts */
+.hlist dt:after {
+       content: ":";
+}
+.hlist dd:after,
+.hlist li:after {
+       content: " ·";
+       font-weight: bold;
+}
+.hlist dd:last-child:after,
+.hlist dt:last-child:after,
+.hlist li:last-child:after {
+       content: none;
+}
+/* For IE8 */
+.hlist dd.hlist-last-child:after,
+.hlist dt.hlist-last-child:after,
+.hlist li.hlist-last-child:after {
+       content: none;
+}
+/* Add parentheses around nested lists */
+.hlist dd dd:first-child:before, .hlist dd dt:first-child:before, .hlist dd li:first-child:before,
+.hlist dt dd:first-child:before, .hlist dt dt:first-child:before, .hlist dt li:first-child:before,
+.hlist li dd:first-child:before, .hlist li dt:first-child:before, .hlist li li:first-child:before {
+       content: "(";
+       font-weight: normal;
+}
+.hlist dd dd:last-child:after, .hlist dd dt:last-child:after, .hlist dd li:last-child:after,
+.hlist dt dd:last-child:after, .hlist dt dt:last-child:after, .hlist dt li:last-child:after,
+.hlist li dd:last-child:after, .hlist li dt:last-child:after, .hlist li li:last-child:after {
+       content: ")";
+       font-weight: normal;
+}
+/* For IE8 */
+.hlist dd dd.hlist-last-child:after, .hlist dd dt.hlist-last-child:after, .hlist dd li.hlist-last-child:after,
+.hlist dt dd.hlist-last-child:after, .hlist dt dt.hlist-last-child:after, .hlist dt li.hlist-last-child:after,
+.hlist li dd.hlist-last-child:after, .hlist li dt.hlist-last-child:after, .hlist li li.hlist-last-child:after {
+       content: ")";
+       font-weight: normal;
+}
+/* Put ordinals in front of ordered list items */
+.hlist ol {
+       counter-reset: list-item;
+}
+.hlist ol > li {
+       counter-increment: list-item;
+}
+.hlist ol > li:before {
+       content: counter(list-item) " ";
+}
+.hlist dd ol > li:first-child:before,
+.hlist dt ol > li:first-child:before,
+.hlist li ol > li:first-child:before {
+       content: "(" counter(list-item) " ";
+}
diff --git a/resources/src/mediawiki/mediawiki.hlist.js b/resources/src/mediawiki/mediawiki.hlist.js
new file mode 100644 (file)
index 0000000..0bbf8fa
--- /dev/null
@@ -0,0 +1,31 @@
+/*!
+ * .hlist fallbacks for IE 6, 7 and 8.
+ * @author [[User:Edokter]]
+ */
+( function ( mw, $ ) {
+       var profile = $.client.profile();
+
+       if ( profile.name === 'msie' ) {
+               if ( profile.versionNumber === 8 ) {
+                       /* IE 8: Add pseudo-selector class to last-child list items */
+                       mw.hook( 'wikipage.content' ).add( function ( $content ) {
+                               $content.find( '.hlist' ).find( 'dd:last-child, dt:last-child, li:last-child' )
+                                       .addClass( 'hlist-last-child' );
+                       } );
+               }
+               else if ( profile.versionNumber <= 7 ) {
+                       /* IE 7 and below: Generate interpuncts and parentheses */
+                       mw.hook( 'wikipage.content' ).add( function ( $content ) {
+                               var $hlists = $content.find( '.hlist' );
+                               $hlists.find( 'dt:not(:last-child)' )
+                                       .append( ': ' );
+                               $hlists.find( 'dd:not(:last-child)' )
+                                       .append( '<b>·</b> ' );
+                               $hlists.find( 'li:not(:last-child)' )
+                                       .append( '<b>·</b> ' );
+                               $hlists.find( 'dl dl, dl ol, dl ul, ol dl, ol ol, ol ul, ul dl, ul ol, ul ul' )
+                                       .prepend( '( ' ).append( ') ' );
+                       } );
+               }
+       }
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.htmlform.js b/resources/src/mediawiki/mediawiki.htmlform.js
new file mode 100644 (file)
index 0000000..5ba1a54
--- /dev/null
@@ -0,0 +1,138 @@
+/**
+ * Utility functions for jazzing up HTMLForm elements.
+ *
+ * @class jQuery.plugin.htmlform
+ */
+( function ( mw, $ ) {
+
+       /**
+        * jQuery plugin to fade or snap to visible state.
+        *
+        * @param {boolean} [instantToggle=false]
+        * @return {jQuery}
+        * @chainable
+        */
+       $.fn.goIn = function ( instantToggle ) {
+               if ( instantToggle === true ) {
+                       return $( this ).show();
+               }
+               return $( this ).stop( true, true ).fadeIn();
+       };
+
+       /**
+        * jQuery plugin to fade or snap to hiding state.
+        *
+        * @param {boolean} [instantToggle=false]
+        * @return jQuery
+        * @chainable
+        */
+       $.fn.goOut = function ( instantToggle ) {
+               if ( instantToggle === true ) {
+                       return $( this ).hide();
+               }
+               return $( this ).stop( true, true ).fadeOut();
+       };
+
+       /**
+        * Bind a function to the jQuery object via live(), and also immediately trigger
+        * the function on the objects with an 'instant' parameter set to true.
+        * @param {Function} callback
+        * @param {boolean|jQuery.Event} callback.immediate True when the event is called immediately,
+        *  an event object when triggered from an event.
+        */
+       $.fn.liveAndTestAtStart = function ( callback ) {
+               $( this )
+                       .live( 'change', callback )
+                       .each( function () {
+                               callback.call( this, true );
+                       } );
+       };
+
+       $( function () {
+
+               // Animate the SelectOrOther fields, to only show the text field when
+               // 'other' is selected.
+               $( '.mw-htmlform-select-or-other' ).liveAndTestAtStart( function ( instant ) {
+                       var $other = $( '#' + $( this ).attr( 'id' ) + '-other' );
+                       $other = $other.add( $other.siblings( 'br' ) );
+                       if ( $( this ).val() === 'other' ) {
+                               $other.goIn( instant );
+                       } else {
+                               $other.goOut( instant );
+                       }
+               } );
+
+       } );
+
+       function addMulti( $oldContainer, $container ) {
+               var name = $oldContainer.find( 'input:first-child' ).attr( 'name' ),
+                       oldClass = ( ' ' + $oldContainer.attr( 'class' ) + ' ' ).replace( /(mw-htmlform-field-HTMLMultiSelectField|mw-chosen)/g, '' ),
+                       $select = $( '<select>' ),
+                       dataPlaceholder = mw.message( 'htmlform-chosen-placeholder' );
+               oldClass = $.trim( oldClass );
+               $select.attr( {
+                       name: name,
+                       multiple: 'multiple',
+                       'data-placeholder': dataPlaceholder.plain(),
+                       'class': 'htmlform-chzn-select mw-input ' + oldClass
+               } );
+               $oldContainer.find( 'input' ).each( function () {
+                       var $oldInput = $( this ),
+                       checked = $oldInput.prop( 'checked' ),
+                       $option = $( '<option>' );
+                       $option.prop( 'value', $oldInput.prop( 'value' ) );
+                       if ( checked ) {
+                               $option.prop( 'selected', true );
+                       }
+                       $option.text( $oldInput.prop( 'value' ) );
+                       $select.append( $option );
+               } );
+               $container.append( $select );
+       }
+
+       function convertCheckboxesToMulti( $oldContainer, type ) {
+               var $fieldLabel = $( '<td>' ),
+               $td = $( '<td>' ),
+               $fieldLabelText = $( '<label>' ),
+               $container;
+               if ( type === 'tr' ) {
+                       addMulti( $oldContainer, $td );
+                       $container = $( '<tr>' );
+                       $container.append( $td );
+               } else if ( type === 'div' ) {
+                       $fieldLabel = $( '<div>' );
+                       $container = $( '<div>' );
+                       addMulti( $oldContainer, $container );
+               }
+               $fieldLabel.attr( 'class', 'mw-label' );
+               $fieldLabelText.text( $oldContainer.find( '.mw-label label' ).text() );
+               $fieldLabel.append( $fieldLabelText );
+               $container.prepend( $fieldLabel );
+               $oldContainer.replaceWith( $container );
+               return $container;
+       }
+
+       if ( $( '.mw-chosen' ).length ) {
+               mw.loader.using( 'jquery.chosen', function () {
+                       $( '.mw-chosen' ).each( function () {
+                               var type = this.nodeName.toLowerCase(),
+                                       $converted = convertCheckboxesToMulti( $( this ), type );
+                               $converted.find( '.htmlform-chzn-select' ).chosen( { width: 'auto' } );
+                       } );
+               } );
+       }
+
+       $( function () {
+               var $matrixTooltips = $( '.mw-htmlform-matrix .mw-htmlform-tooltip' );
+               if ( $matrixTooltips.length ) {
+                       mw.loader.using( 'jquery.tipsy', function () {
+                               $matrixTooltips.tipsy( { gravity: 's' } );
+                       } );
+               }
+       } );
+
+       /**
+        * @class jQuery
+        * @mixins jQuery.plugin.htmlform
+        */
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.icon.less b/resources/src/mediawiki/mediawiki.icon.less
new file mode 100644 (file)
index 0000000..49f0f70
--- /dev/null
@@ -0,0 +1,19 @@
+/* General-purpose icons via CSS. Classes here should be named "mw-icon-*". */
+
+@import "mediawiki.mixins";
+
+/* For the collapsed and expanded arrows, we also provide selectors to make it
+ * easy to use them with jquery.makeCollapsible. */
+.mw-icon-arrow-collapsed,
+.mw-collapsible-arrow.mw-collapsible-toggle-collapsed {
+       .background-image-svg('images/arrow-collapsed-ltr.svg', 'images/arrow-collapsed-ltr.png');
+       background-repeat: no-repeat;
+       background-position: left bottom;
+}
+
+.mw-icon-arrow-expanded,
+.mw-collapsible-arrow.mw-collapsible-toggle-expanded {
+       .background-image-svg('images/arrow-expanded.svg', 'images/arrow-expanded.png');
+       background-repeat: no-repeat;
+       background-position: left bottom;
+}
diff --git a/resources/src/mediawiki/mediawiki.inspect.js b/resources/src/mediawiki/mediawiki.inspect.js
new file mode 100644 (file)
index 0000000..62fa410
--- /dev/null
@@ -0,0 +1,284 @@
+/*!
+ * Tools for inspecting page composition and performance.
+ *
+ * @author Ori Livneh
+ * @since 1.22
+ */
+/*jshint devel:true */
+( function ( mw, $ ) {
+
+       function sortByProperty( array, prop, descending ) {
+               var order = descending ? -1 : 1;
+               return array.sort( function ( a, b ) {
+                       return a[prop] > b[prop] ? order : a[prop] < b[prop] ? -order : 0;
+               } );
+       }
+
+       function humanSize( bytes ) {
+               if ( !$.isNumeric( bytes ) || bytes === 0 ) { return bytes; }
+               var i = 0, units = [ '', ' kB', ' MB', ' GB', ' TB', ' PB' ];
+               for ( ; bytes >= 1024; bytes /= 1024 ) { i++; }
+               return bytes.toFixed( 1 ) + units[i];
+       }
+
+       /**
+        * @class mw.inspect
+        * @singleton
+        */
+       var inspect = {
+
+               /**
+                * Return a map of all dependency relationships between loaded modules.
+                *
+                * @return {Object} Maps module names to objects. Each sub-object has
+                *  two properties, 'requires' and 'requiredBy'.
+                */
+               getDependencyGraph: function () {
+                       var modules = inspect.getLoadedModules(), graph = {};
+
+                       $.each( modules, function ( moduleIndex, moduleName ) {
+                               var dependencies = mw.loader.moduleRegistry[moduleName].dependencies || [];
+
+                               graph[moduleName] = graph[moduleName] || { requiredBy: [] };
+                               graph[moduleName].requires = dependencies;
+
+                               $.each( dependencies, function ( depIndex, depName ) {
+                                       graph[depName] = graph[depName] || { requiredBy: [] };
+                                       graph[depName].requiredBy.push( moduleName );
+                               } );
+                       } );
+                       return graph;
+               },
+
+               /**
+                * Calculate the byte size of a ResourceLoader module.
+                *
+                * @param {string} moduleName The name of the module
+                * @return {number|null} Module size in bytes or null
+                */
+               getModuleSize: function ( moduleName ) {
+                       var module = mw.loader.moduleRegistry[ moduleName ],
+                               payload = 0;
+
+                       if ( mw.loader.getState( moduleName ) !== 'ready' ) {
+                               return null;
+                       }
+
+                       if ( !module.style && !module.script ) {
+                               return null;
+                       }
+
+                       // Tally CSS
+                       if ( module.style && $.isArray( module.style.css ) ) {
+                               $.each( module.style.css, function ( i, stylesheet ) {
+                                       payload += $.byteLength( stylesheet );
+                               } );
+                       }
+
+                       // Tally JavaScript
+                       if ( $.isFunction( module.script ) ) {
+                               payload += $.byteLength( module.script.toString() );
+                       }
+
+                       return payload;
+               },
+
+               /**
+                * Given CSS source, count both the total number of selectors it
+                * contains and the number which match some element in the current
+                * document.
+                *
+                * @param {string} css CSS source
+                * @return Selector counts
+                * @return {number} return.selectors Total number of selectors
+                * @return {number} return.matched Number of matched selectors
+                */
+               auditSelectors: function ( css ) {
+                       var selectors = { total: 0, matched: 0 },
+                               style = document.createElement( 'style' ),
+                               sheet, rules;
+
+                       style.textContent = css;
+                       document.body.appendChild( style );
+                       // Standards-compliant browsers use .sheet.cssRules, IE8 uses .styleSheet.rules…
+                       sheet = style.sheet || style.styleSheet;
+                       rules = sheet.cssRules || sheet.rules;
+                       $.each( rules, function ( index, rule ) {
+                               selectors.total++;
+                               if ( document.querySelector( rule.selectorText ) !== null ) {
+                                       selectors.matched++;
+                               }
+                       } );
+                       document.body.removeChild( style );
+                       return selectors;
+               },
+
+               /**
+                * Get a list of all loaded ResourceLoader modules.
+                *
+                * @return {Array} List of module names
+                */
+               getLoadedModules: function () {
+                       return $.grep( mw.loader.getModuleNames(), function ( module ) {
+                               return mw.loader.getState( module ) === 'ready';
+                       } );
+               },
+
+               /**
+                * Print tabular data to the console, using console.table, console.log,
+                * or mw.log (in declining order of preference).
+                *
+                * @param {Array} data Tabular data represented as an array of objects
+                *  with common properties.
+                */
+               dumpTable: function ( data ) {
+                       try {
+                               // Bartosz made me put this here.
+                               if ( window.opera ) { throw window.opera; }
+                               // Use Function.prototype#call to force an exception on Firefox,
+                               // which doesn't define console#table but doesn't complain if you
+                               // try to invoke it.
+                               console.table.call( console, data );
+                               return;
+                       } catch ( e ) {}
+                       try {
+                               console.log( $.toJSON( data, null, 2 ) );
+                               return;
+                       } catch ( e ) {}
+                       mw.log( data );
+               },
+
+               /**
+                * Generate and print one more reports. When invoked with no arguments,
+                * print all reports.
+                *
+                * @param {string...} [reports] Report names to run, or unset to print
+                *  all available reports.
+                */
+               runReports: function () {
+                       var reports = arguments.length > 0 ?
+                               Array.prototype.slice.call( arguments ) :
+                               $.map( inspect.reports, function ( v, k ) { return k; } );
+
+                       $.each( reports, function ( index, name ) {
+                               inspect.dumpTable( inspect.reports[name]() );
+                       } );
+               },
+
+               /**
+                * @class mw.inspect.reports
+                * @singleton
+                */
+               reports: {
+                       /**
+                        * Generate a breakdown of all loaded modules and their size in
+                        * kilobytes. Modules are ordered from largest to smallest.
+                        */
+                       size: function () {
+                               // Map each module to a descriptor object.
+                               var modules = $.map( inspect.getLoadedModules(), function ( module ) {
+                                       return {
+                                               name: module,
+                                               size: inspect.getModuleSize( module )
+                                       };
+                               } );
+
+                               // Sort module descriptors by size, largest first.
+                               sortByProperty( modules, 'size', true );
+
+                               // Convert size to human-readable string.
+                               $.each( modules, function ( i, module ) {
+                                       module.size = humanSize( module.size );
+                               } );
+
+                               return modules;
+                       },
+
+                       /**
+                        * For each module with styles, count the number of selectors, and
+                        * count how many match against some element currently in the DOM.
+                        */
+                       css: function () {
+                               var modules = [];
+
+                               $.each( inspect.getLoadedModules(), function ( index, name ) {
+                                       var css, stats, module = mw.loader.moduleRegistry[name];
+
+                                       try {
+                                               css = module.style.css.join();
+                                       } catch ( e ) { return; } // skip
+
+                                       stats = inspect.auditSelectors( css );
+                                       modules.push( {
+                                               module: name,
+                                               allSelectors: stats.total,
+                                               matchedSelectors: stats.matched,
+                                               percentMatched: stats.total !== 0 ?
+                                                       ( stats.matched / stats.total * 100 ).toFixed( 2 )  + '%' : null
+                                       } );
+                               } );
+                               sortByProperty( modules, 'allSelectors', true );
+                               return modules;
+                       },
+
+                       /**
+                        * Report stats on mw.loader.store: the number of localStorage
+                        * cache hits and misses, the number of items purged from the
+                        * cache, and the total size of the module blob in localStorage.
+                        */
+                       store: function () {
+                               var raw, stats = { enabled: mw.loader.store.enabled };
+                               if ( stats.enabled ) {
+                                       $.extend( stats, mw.loader.store.stats );
+                                       try {
+                                               raw = localStorage.getItem( mw.loader.store.getStoreKey() );
+                                               stats.totalSize = humanSize( $.byteLength( raw ) );
+                                       } catch ( e ) {}
+                               }
+                               return [stats];
+                       }
+               },
+
+               /**
+                * Perform a substring search across the JavaScript and CSS source code
+                * of all loaded modules and return an array of the names of the
+                * modules that matched.
+                *
+                * @param {string|RegExp} pattern String or regexp to match.
+                * @return {Array} Array of the names of modules that matched.
+                */
+               grep: function ( pattern ) {
+                       if ( typeof pattern.test !== 'function' ) {
+                               // Based on Y.Escape.regex from YUI v3.15.0
+                               pattern = new RegExp( pattern.replace( /[\-$\^*()+\[\]{}|\\,.?\s]/g, '\\$&' ), 'g' );
+                       }
+
+                       return $.grep( inspect.getLoadedModules(), function ( moduleName ) {
+                               var module = mw.loader.moduleRegistry[moduleName];
+
+                               // Grep module's JavaScript
+                               if ( $.isFunction( module.script ) && pattern.test( module.script.toString() ) ) {
+                                       return true;
+                               }
+
+                               // Grep module's CSS
+                               if (
+                                       $.isPlainObject( module.style ) && $.isArray( module.style.css )
+                                       && pattern.test( module.style.css.join( '' ) )
+                               ) {
+                                       // Module's CSS source matches
+                                       return true;
+                               }
+
+                               return false;
+                       } );
+               }
+       };
+
+       if ( mw.config.get( 'debug' ) ) {
+               mw.log( 'mw.inspect: reports are not available in debug mode.' );
+       }
+
+       mw.inspect = inspect;
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.jqueryMsg.js b/resources/src/mediawiki/mediawiki.jqueryMsg.js
new file mode 100644 (file)
index 0000000..0a0b4f6
--- /dev/null
@@ -0,0 +1,1237 @@
+/*!
+* Experimental advanced wikitext parser-emitter.
+* See: https://www.mediawiki.org/wiki/Extension:UploadWizard/MessageParser for docs
+*
+* @author neilk@wikimedia.org
+* @author mflaschen@wikimedia.org
+*/
+( function ( mw, $ ) {
+       /**
+        * @class mw.jqueryMsg
+        * @singleton
+        */
+
+       var oldParser,
+               slice = Array.prototype.slice,
+               parserDefaults = {
+                       magic: {
+                               'SITENAME': mw.config.get( 'wgSiteName' )
+                       },
+                       // This is a whitelist based on, but simpler than, Sanitizer.php.
+                       // Self-closing tags are not currently supported.
+                       allowedHtmlElements: [
+                               'b',
+                               'i'
+                       ],
+                       // Key tag name, value allowed attributes for that tag.
+                       // See Sanitizer::setupAttributeWhitelist
+                       allowedHtmlCommonAttributes: [
+                               // HTML
+                               'id',
+                               'class',
+                               'style',
+                               'lang',
+                               'dir',
+                               'title',
+
+                               // WAI-ARIA
+                               'role'
+                       ],
+
+                       // Attributes allowed for specific elements.
+                       // Key is element name in lower case
+                       // Value is array of allowed attributes for that element
+                       allowedHtmlAttributesByElement: {},
+                       messages: mw.messages,
+                       language: mw.language,
+
+                       // Same meaning as in mediawiki.js.
+                       //
+                       // Only 'text', 'parse', and 'escaped' are supported, and the
+                       // actual escaping for 'escaped' is done by other code (generally
+                       // through mediawiki.js).
+                       //
+                       // However, note that this default only
+                       // applies to direct calls to jqueryMsg. The default for mediawiki.js itself
+                       // is 'text', including when it uses jqueryMsg.
+                       format: 'parse'
+
+               };
+
+       /**
+        * Wrapper around jQuery append that converts all non-objects to TextNode so append will not
+        * convert what it detects as an htmlString to an element.
+        *
+        * Object elements of children (jQuery, HTMLElement, TextNode, etc.) will be left as is.
+        *
+        * @private
+        * @param {jQuery} $parent Parent node wrapped by jQuery
+        * @param {Object|string|Array} children What to append, with the same possible types as jQuery
+        * @return {jQuery} $parent
+        */
+       function appendWithoutParsing( $parent, children ) {
+               var i, len;
+
+               if ( !$.isArray( children ) ) {
+                       children = [children];
+               }
+
+               for ( i = 0, len = children.length; i < len; i++ ) {
+                       if ( typeof children[i] !== 'object' ) {
+                               children[i] = document.createTextNode( children[i] );
+                       }
+               }
+
+               return $parent.append( children );
+       }
+
+       /**
+        * Decodes the main HTML entities, those encoded by mw.html.escape.
+        *
+        * @private
+        * @param {string} encoded Encoded string
+        * @return {string} String with those entities decoded
+        */
+       function decodePrimaryHtmlEntities( encoded ) {
+               return encoded
+                       .replace( /&#039;/g, '\'' )
+                       .replace( /&quot;/g, '"' )
+                       .replace( /&lt;/g, '<' )
+                       .replace( /&gt;/g, '>' )
+                       .replace( /&amp;/g, '&' );
+       }
+
+       /**
+        * Given parser options, return a function that parses a key and replacements, returning jQuery object
+        *
+        * Try to parse a key and optional replacements, returning a jQuery object that may be a tree of jQuery nodes.
+        * If there was an error parsing, return the key and the error message (wrapped in jQuery). This should put the error right into
+        * the interface, without causing the page to halt script execution, and it hopefully should be clearer how to fix it.
+        * @private
+        * @param {Object} options Parser options
+        * @return {Function}
+        * @return {Array} return.args First element is the key, replacements may be in array in 2nd element, or remaining elements.
+        * @return {jQuery} return.return
+        */
+       function getFailableParserFn( options ) {
+               var parser = new mw.jqueryMsg.parser( options );
+
+               return function ( args ) {
+                       var key = args[0],
+                               argsArray = $.isArray( args[1] ) ? args[1] : slice.call( args, 1 );
+                       try {
+                               return parser.parse( key, argsArray );
+                       } catch ( e ) {
+                               return $( '<span>' ).text( key + ': ' + e.message );
+                       }
+               };
+       }
+
+       mw.jqueryMsg = {};
+
+       /**
+        * Returns a function suitable for use as a global, to construct strings from the message key (and optional replacements).
+        * e.g.
+        *
+        *       window.gM = mediaWiki.parser.getMessageFunction( options );
+        *       $( 'p#headline' ).html( gM( 'hello-user', username ) );
+        *
+        * Like the old gM() function this returns only strings, so it destroys any bindings. If you want to preserve bindings use the
+        * jQuery plugin version instead. This is only included for backwards compatibility with gM().
+        *
+        * N.B. replacements are variadic arguments or an array in second parameter. In other words:
+        *    somefunction( a, b, c, d )
+        * is equivalent to
+        *    somefunction( a, [b, c, d] )
+        *
+        * @param {Object} options parser options
+        * @return {Function} Function suitable for assigning to window.gM
+        * @return {string} return.key Message key.
+        * @return {Array|Mixed} return.replacements Optional variable replacements (variadically or an array).
+        * @return {string} return.return Rendered HTML.
+        */
+       mw.jqueryMsg.getMessageFunction = function ( options ) {
+               var failableParserFn = getFailableParserFn( options ),
+                       format;
+
+               if ( options && options.format !== undefined ) {
+                       format = options.format;
+               } else {
+                       format = parserDefaults.format;
+               }
+
+               return function () {
+                       var failableResult = failableParserFn( arguments );
+                       if ( format === 'text' || format === 'escaped' ) {
+                               return failableResult.text();
+                       } else {
+                               return failableResult.html();
+                       }
+               };
+       };
+
+       /**
+        * Returns a jQuery plugin which parses the message in the message key, doing replacements optionally, and appends the nodes to
+        * the current selector. Bindings to passed-in jquery elements are preserved. Functions become click handlers for [$1 linktext] links.
+        * e.g.
+        *
+        *        $.fn.msg = mediaWiki.parser.getJqueryPlugin( options );
+        *        var userlink = $( '<a>' ).click( function () { alert( "hello!!" ) } );
+        *        $( 'p#headline' ).msg( 'hello-user', userlink );
+        *
+        * N.B. replacements are variadic arguments or an array in second parameter. In other words:
+        *    somefunction( a, b, c, d )
+        * is equivalent to
+        *    somefunction( a, [b, c, d] )
+        *
+        * We append to 'this', which in a jQuery plugin context will be the selected elements.
+        *
+        * @param {Object} options Parser options
+        * @return {Function} Function suitable for assigning to jQuery plugin, such as jQuery#msg
+        * @return {string} return.key Message key.
+        * @return {Array|Mixed} return.replacements Optional variable replacements (variadically or an array).
+        * @return {jQuery} return.return
+        */
+       mw.jqueryMsg.getPlugin = function ( options ) {
+               var failableParserFn = getFailableParserFn( options );
+
+               return function () {
+                       var $target = this.empty();
+                       // TODO: Simply appendWithoutParsing( $target, failableParserFn( arguments ).contents() )
+                       // or Simply appendWithoutParsing( $target, failableParserFn( arguments ) )
+                       $.each( failableParserFn( arguments ).contents(), function ( i, node ) {
+                               appendWithoutParsing( $target, node );
+                       } );
+                       return $target;
+               };
+       };
+
+       /**
+        * The parser itself.
+        * Describes an object, whose primary duty is to .parse() message keys.
+        *
+        * @class
+        * @private
+        * @param {Object} options
+        */
+       mw.jqueryMsg.parser = function ( options ) {
+               this.settings = $.extend( {}, parserDefaults, options );
+               this.settings.onlyCurlyBraceTransform = ( this.settings.format === 'text' || this.settings.format === 'escaped' );
+
+               this.emitter = new mw.jqueryMsg.htmlEmitter( this.settings.language, this.settings.magic );
+       };
+
+       mw.jqueryMsg.parser.prototype = {
+               /**
+                * Cache mapping MediaWiki message keys and the value onlyCurlyBraceTransform, to the AST of the message.
+                *
+                * In most cases, the message is a string so this is identical.
+                * (This is why we would like to move this functionality server-side).
+                *
+                * The two parts of the key are separated by colon.  For example:
+                *
+                *     "message-key:true": ast
+                *
+                * if they key is "message-key" and onlyCurlyBraceTransform is true.
+                *
+                * This cache is shared by all instances of mw.jqueryMsg.parser.
+                *
+                * NOTE: We promise, it's static - when you create this empty object
+                * in the prototype, each new instance of the class gets a reference
+                * to the same object.
+                *
+                * @static
+                * @property {Object}
+                */
+               astCache: {},
+
+               /**
+                * Where the magic happens.
+                * Parses a message from the key, and swaps in replacements as necessary, wraps in jQuery
+                * If an error is thrown, returns original key, and logs the error
+                * @param {string} key Message key.
+                * @param {Array} replacements Variable replacements for $1, $2... $n
+                * @return {jQuery}
+                */
+               parse: function ( key, replacements ) {
+                       return this.emitter.emit( this.getAst( key ), replacements );
+               },
+
+               /**
+                * Fetch the message string associated with a key, return parsed structure. Memoized.
+                * Note that we pass '[' + key + ']' back for a missing message here.
+                * @param {string} key
+                * @return {string|Array} string of '[key]' if message missing, simple string if possible, array of arrays if needs parsing
+                */
+               getAst: function ( key ) {
+                       var cacheKey = [key, this.settings.onlyCurlyBraceTransform].join( ':' ), wikiText;
+
+                       if ( this.astCache[ cacheKey ] === undefined ) {
+                               wikiText = this.settings.messages.get( key );
+                               if ( typeof wikiText !== 'string' ) {
+                                       wikiText = '\\[' + key + '\\]';
+                               }
+                               this.astCache[ cacheKey ] = this.wikiTextToAst( wikiText );
+                       }
+                       return this.astCache[ cacheKey ];
+               },
+
+               /**
+                * Parses the input wikiText into an abstract syntax tree, essentially an s-expression.
+                *
+                * CAVEAT: This does not parse all wikitext. It could be more efficient, but it's pretty good already.
+                * n.b. We want to move this functionality to the server. Nothing here is required to be on the client.
+                *
+                * @param {string} input Message string wikitext
+                * @throws Error
+                * @return {Mixed} abstract syntax tree
+                */
+               wikiTextToAst: function ( input ) {
+                       var pos, settings = this.settings, concat = Array.prototype.concat,
+                               regularLiteral, regularLiteralWithoutBar, regularLiteralWithoutSpace, regularLiteralWithSquareBrackets,
+                               doubleQuote, singleQuote, backslash, anyCharacter, asciiAlphabetLiteral,
+                               escapedOrLiteralWithoutSpace, escapedOrLiteralWithoutBar, escapedOrRegularLiteral,
+                               whitespace, dollar, digits, htmlDoubleQuoteAttributeValue, htmlSingleQuoteAttributeValue,
+                               htmlAttributeEquals, openHtmlStartTag, optionalForwardSlash, openHtmlEndTag, closeHtmlTag,
+                               openExtlink, closeExtlink, wikilinkPage, wikilinkContents, openWikilink, closeWikilink, templateName, pipe, colon,
+                               templateContents, openTemplate, closeTemplate,
+                               nonWhitespaceExpression, paramExpression, expression, curlyBraceTransformExpression, result;
+
+                       // Indicates current position in input as we parse through it.
+                       // Shared among all parsing functions below.
+                       pos = 0;
+
+                       // =========================================================
+                       // parsing combinators - could be a library on its own
+                       // =========================================================
+
+                       /**
+                        * Try parsers until one works, if none work return null
+                        * @private
+                        * @param {Function[]} ps
+                        * @return {string|null}
+                        */
+                       function choice( ps ) {
+                               return function () {
+                                       var i, result;
+                                       for ( i = 0; i < ps.length; i++ ) {
+                                               result = ps[i]();
+                                               if ( result !== null ) {
+                                                        return result;
+                                               }
+                                       }
+                                       return null;
+                               };
+                       }
+
+                       /**
+                        * Try several ps in a row, all must succeed or return null.
+                        * This is the only eager one.
+                        * @private
+                        * @param {Function[]} ps
+                        * @return {string|null}
+                        */
+                       function sequence( ps ) {
+                               var i, res,
+                                       originalPos = pos,
+                                       result = [];
+                               for ( i = 0; i < ps.length; i++ ) {
+                                       res = ps[i]();
+                                       if ( res === null ) {
+                                               pos = originalPos;
+                                               return null;
+                                       }
+                                       result.push( res );
+                               }
+                               return result;
+                       }
+
+                       /**
+                        * Run the same parser over and over until it fails.
+                        * Must succeed a minimum of n times or return null.
+                        * @private
+                        * @param {number} n
+                        * @param {Function} p
+                        * @return {string|null}
+                        */
+                       function nOrMore( n, p ) {
+                               return function () {
+                                       var originalPos = pos,
+                                               result = [],
+                                               parsed = p();
+                                       while ( parsed !== null ) {
+                                               result.push( parsed );
+                                               parsed = p();
+                                       }
+                                       if ( result.length < n ) {
+                                               pos = originalPos;
+                                               return null;
+                                       }
+                                       return result;
+                               };
+                       }
+
+                       /**
+                        * There is a general pattern -- parse a thing, if that worked, apply transform, otherwise return null.
+                        *
+                        * TODO: But using this as a combinator seems to cause problems when combined with #nOrMore().
+                        * May be some scoping issue
+                        *
+                        * @private
+                        * @param {Function} p
+                        * @param {Function} fn
+                        * @return {string|null}
+                        */
+                       function transform( p, fn ) {
+                               return function () {
+                                       var result = p();
+                                       return result === null ? null : fn( result );
+                               };
+                       }
+
+                       /**
+                        * Just make parsers out of simpler JS builtin types
+                        * @private
+                        * @param {string} s
+                        * @return {Function}
+                        * @return {string} return.return
+                        */
+                       function makeStringParser( s ) {
+                               var len = s.length;
+                               return function () {
+                                       var result = null;
+                                       if ( input.substr( pos, len ) === s ) {
+                                                result = s;
+                                                pos += len;
+                                       }
+                                       return result;
+                               };
+                       }
+
+                       /**
+                        * Makes a regex parser, given a RegExp object.
+                        * The regex being passed in should start with a ^ to anchor it to the start
+                        * of the string.
+                        *
+                        * @private
+                        * @param {RegExp} regex anchored regex
+                        * @return {Function} function to parse input based on the regex
+                        */
+                       function makeRegexParser( regex ) {
+                               return function () {
+                                       var matches = input.substr( pos ).match( regex );
+                                       if ( matches === null ) {
+                                               return null;
+                                       }
+                                       pos += matches[0].length;
+                                       return matches[0];
+                               };
+                       }
+
+                       // ===================================================================
+                       // General patterns above this line -- wikitext specific parsers below
+                       // ===================================================================
+
+                       // Parsing functions follow. All parsing functions work like this:
+                       // They don't accept any arguments.
+                       // Instead, they just operate non destructively on the string 'input'
+                       // As they can consume parts of the string, they advance the shared variable pos,
+                       // and return tokens (or whatever else they want to return).
+                       // some things are defined as closures and other things as ordinary functions
+                       // converting everything to a closure makes it a lot harder to debug... errors pop up
+                       // but some debuggers can't tell you exactly where they come from. Also the mutually
+                       // recursive functions seem not to work in all browsers then. (Tested IE6-7, Opera, Safari, FF)
+                       // This may be because, to save code, memoization was removed
+
+                       regularLiteral = makeRegexParser( /^[^{}\[\]$<\\]/ );
+                       regularLiteralWithoutBar = makeRegexParser( /^[^{}\[\]$\\|]/ );
+                       regularLiteralWithoutSpace = makeRegexParser( /^[^{}\[\]$\s]/ );
+                       regularLiteralWithSquareBrackets = makeRegexParser( /^[^{}$\\]/ );
+
+                       backslash = makeStringParser( '\\' );
+                       doubleQuote = makeStringParser( '"' );
+                       singleQuote = makeStringParser( '\'' );
+                       anyCharacter = makeRegexParser( /^./ );
+
+                       openHtmlStartTag = makeStringParser( '<' );
+                       optionalForwardSlash = makeRegexParser( /^\/?/ );
+                       openHtmlEndTag = makeStringParser( '</' );
+                       htmlAttributeEquals = makeRegexParser( /^\s*=\s*/ );
+                       closeHtmlTag = makeRegexParser( /^\s*>/ );
+
+                       function escapedLiteral() {
+                               var result = sequence( [
+                                       backslash,
+                                       anyCharacter
+                               ] );
+                               return result === null ? null : result[1];
+                       }
+                       escapedOrLiteralWithoutSpace = choice( [
+                               escapedLiteral,
+                               regularLiteralWithoutSpace
+                       ] );
+                       escapedOrLiteralWithoutBar = choice( [
+                               escapedLiteral,
+                               regularLiteralWithoutBar
+                       ] );
+                       escapedOrRegularLiteral = choice( [
+                               escapedLiteral,
+                               regularLiteral
+                       ] );
+                       // Used to define "literals" without spaces, in space-delimited situations
+                       function literalWithoutSpace() {
+                               var result = nOrMore( 1, escapedOrLiteralWithoutSpace )();
+                               return result === null ? null : result.join( '' );
+                       }
+                       // Used to define "literals" within template parameters. The pipe character is the parameter delimeter, so by default
+                       // it is not a literal in the parameter
+                       function literalWithoutBar() {
+                               var result = nOrMore( 1, escapedOrLiteralWithoutBar )();
+                               return result === null ? null : result.join( '' );
+                       }
+
+                       // Used for wikilink page names.  Like literalWithoutBar, but
+                       // without allowing escapes.
+                       function unescapedLiteralWithoutBar() {
+                               var result = nOrMore( 1, regularLiteralWithoutBar )();
+                               return result === null ? null : result.join( '' );
+                       }
+
+                       function literal() {
+                               var result = nOrMore( 1, escapedOrRegularLiteral )();
+                               return result === null ? null : result.join( '' );
+                       }
+
+                       function curlyBraceTransformExpressionLiteral() {
+                               var result = nOrMore( 1, regularLiteralWithSquareBrackets )();
+                               return result === null ? null : result.join( '' );
+                       }
+
+                       asciiAlphabetLiteral = makeRegexParser( /[A-Za-z]+/ );
+                       htmlDoubleQuoteAttributeValue = makeRegexParser( /^[^"]*/ );
+                       htmlSingleQuoteAttributeValue = makeRegexParser( /^[^']*/ );
+
+                       whitespace = makeRegexParser( /^\s+/ );
+                       dollar = makeStringParser( '$' );
+                       digits = makeRegexParser( /^\d+/ );
+
+                       function replacement() {
+                               var result = sequence( [
+                                       dollar,
+                                       digits
+                               ] );
+                               if ( result === null ) {
+                                       return null;
+                               }
+                               return [ 'REPLACE', parseInt( result[1], 10 ) - 1 ];
+                       }
+                       openExtlink = makeStringParser( '[' );
+                       closeExtlink = makeStringParser( ']' );
+                       // this extlink MUST have inner contents, e.g. [foo] not allowed; [foo bar] [foo <i>bar</i>], etc. are allowed
+                       function extlink() {
+                               var result, parsedResult;
+                               result = null;
+                               parsedResult = sequence( [
+                                       openExtlink,
+                                       nonWhitespaceExpression,
+                                       whitespace,
+                                       nOrMore( 1, expression ),
+                                       closeExtlink
+                               ] );
+                               if ( parsedResult !== null ) {
+                                       result = [ 'EXTLINK', parsedResult[1] ];
+                                       // TODO (mattflaschen, 2013-03-22): Clean this up if possible.
+                                       // It's avoiding CONCAT for single nodes, so they at least doesn't get the htmlEmitter span.
+                                       if ( parsedResult[3].length === 1 ) {
+                                               result.push( parsedResult[3][0] );
+                                       } else {
+                                               result.push( ['CONCAT'].concat( parsedResult[3] ) );
+                                       }
+                               }
+                               return result;
+                       }
+                       // this is the same as the above extlink, except that the url is being passed on as a parameter
+                       function extLinkParam() {
+                               var result = sequence( [
+                                       openExtlink,
+                                       dollar,
+                                       digits,
+                                       whitespace,
+                                       expression,
+                                       closeExtlink
+                               ] );
+                               if ( result === null ) {
+                                       return null;
+                               }
+                               return [ 'EXTLINKPARAM', parseInt( result[2], 10 ) - 1, result[4] ];
+                       }
+                       openWikilink = makeStringParser( '[[' );
+                       closeWikilink = makeStringParser( ']]' );
+                       pipe = makeStringParser( '|' );
+
+                       function template() {
+                               var result = sequence( [
+                                       openTemplate,
+                                       templateContents,
+                                       closeTemplate
+                               ] );
+                               return result === null ? null : result[1];
+                       }
+
+                       wikilinkPage = choice( [
+                               unescapedLiteralWithoutBar,
+                               template
+                       ] );
+
+                       function pipedWikilink() {
+                               var result = sequence( [
+                                       wikilinkPage,
+                                       pipe,
+                                       expression
+                               ] );
+                               return result === null ? null : [ result[0], result[2] ];
+                       }
+
+                       wikilinkContents = choice( [
+                               pipedWikilink,
+                               wikilinkPage // unpiped link
+                       ] );
+
+                       function wikilink() {
+                               var result, parsedResult, parsedLinkContents;
+                               result = null;
+
+                               parsedResult = sequence( [
+                                       openWikilink,
+                                       wikilinkContents,
+                                       closeWikilink
+                               ] );
+                               if ( parsedResult !== null ) {
+                                       parsedLinkContents = parsedResult[1];
+                                       result = [ 'WIKILINK' ].concat( parsedLinkContents );
+                               }
+                               return result;
+                       }
+
+                       // TODO: Support data- if appropriate
+                       function doubleQuotedHtmlAttributeValue() {
+                               var parsedResult = sequence( [
+                                       doubleQuote,
+                                       htmlDoubleQuoteAttributeValue,
+                                       doubleQuote
+                               ] );
+                               return parsedResult === null ? null : parsedResult[1];
+                       }
+
+                       function singleQuotedHtmlAttributeValue() {
+                               var parsedResult = sequence( [
+                                       singleQuote,
+                                       htmlSingleQuoteAttributeValue,
+                                       singleQuote
+                               ] );
+                               return parsedResult === null ? null : parsedResult[1];
+                       }
+
+                       function htmlAttribute() {
+                               var parsedResult = sequence( [
+                                       whitespace,
+                                       asciiAlphabetLiteral,
+                                       htmlAttributeEquals,
+                                       choice( [
+                                               doubleQuotedHtmlAttributeValue,
+                                               singleQuotedHtmlAttributeValue
+                                       ] )
+                               ] );
+                               return parsedResult === null ? null : [parsedResult[1], parsedResult[3]];
+                       }
+
+                       /**
+                        * Checks if HTML is allowed
+                        *
+                        * @param {string} startTagName HTML start tag name
+                        * @param {string} endTagName HTML start tag name
+                        * @param {Object} attributes array of consecutive key value pairs,
+                        *  with index 2 * n being a name and 2 * n + 1 the associated value
+                        * @return {boolean} true if this is HTML is allowed, false otherwise
+                        */
+                       function isAllowedHtml( startTagName, endTagName, attributes ) {
+                               var i, len, attributeName;
+
+                               startTagName = startTagName.toLowerCase();
+                               endTagName = endTagName.toLowerCase();
+                               if ( startTagName !== endTagName || $.inArray( startTagName, settings.allowedHtmlElements ) === -1 ) {
+                                       return false;
+                               }
+
+                               for ( i = 0, len = attributes.length; i < len; i += 2 ) {
+                                       attributeName = attributes[i];
+                                       if ( $.inArray( attributeName, settings.allowedHtmlCommonAttributes ) === -1 &&
+                                            $.inArray( attributeName, settings.allowedHtmlAttributesByElement[startTagName] || [] ) === -1 ) {
+                                               return false;
+                                       }
+                               }
+
+                               return true;
+                       }
+
+                       function htmlAttributes() {
+                               var parsedResult = nOrMore( 0, htmlAttribute )();
+                               // Un-nest attributes array due to structure of jQueryMsg operations (see emit).
+                               return concat.apply( ['HTMLATTRIBUTES'], parsedResult );
+                       }
+
+                       // Subset of allowed HTML markup.
+                       // Most elements and many attributes allowed on the server are not supported yet.
+                       function html() {
+                               var result = null, parsedOpenTagResult, parsedHtmlContents,
+                                       parsedCloseTagResult, wrappedAttributes, attributes,
+                                       startTagName, endTagName, startOpenTagPos, startCloseTagPos,
+                                       endOpenTagPos, endCloseTagPos;
+
+                               // Break into three sequence calls.  That should allow accurate reconstruction of the original HTML, and requiring an exact tag name match.
+                               // 1. open through closeHtmlTag
+                               // 2. expression
+                               // 3. openHtmlEnd through close
+                               // This will allow recording the positions to reconstruct if HTML is to be treated as text.
+
+                               startOpenTagPos = pos;
+                               parsedOpenTagResult = sequence( [
+                                       openHtmlStartTag,
+                                       asciiAlphabetLiteral,
+                                       htmlAttributes,
+                                       optionalForwardSlash,
+                                       closeHtmlTag
+                               ] );
+
+                               if ( parsedOpenTagResult === null ) {
+                                       return null;
+                               }
+
+                               endOpenTagPos = pos;
+                               startTagName = parsedOpenTagResult[1];
+
+                               parsedHtmlContents = nOrMore( 0, expression )();
+
+                               startCloseTagPos = pos;
+                               parsedCloseTagResult = sequence( [
+                                       openHtmlEndTag,
+                                       asciiAlphabetLiteral,
+                                       closeHtmlTag
+                               ] );
+
+                               if ( parsedCloseTagResult === null ) {
+                                       // Closing tag failed.  Return the start tag and contents.
+                                       return [ 'CONCAT', input.substring( startOpenTagPos, endOpenTagPos ) ]
+                                               .concat( parsedHtmlContents );
+                               }
+
+                               endCloseTagPos = pos;
+                               endTagName = parsedCloseTagResult[1];
+                               wrappedAttributes = parsedOpenTagResult[2];
+                               attributes = wrappedAttributes.slice( 1 );
+                               if ( isAllowedHtml( startTagName, endTagName, attributes ) ) {
+                                       result = [ 'HTMLELEMENT', startTagName, wrappedAttributes ]
+                                               .concat( parsedHtmlContents );
+                               } else {
+                                       // HTML is not allowed, so contents will remain how
+                                       // it was, while HTML markup at this level will be
+                                       // treated as text
+                                       // E.g. assuming script tags are not allowed:
+                                       //
+                                       // <script>[[Foo|bar]]</script>
+                                       //
+                                       // results in '&lt;script&gt;' and '&lt;/script&gt;'
+                                       // (not treated as an HTML tag), surrounding a fully
+                                       // parsed HTML link.
+                                       //
+                                       // Concatenate everything from the tag, flattening the contents.
+                                       result = [ 'CONCAT', input.substring( startOpenTagPos, endOpenTagPos ) ]
+                                               .concat( parsedHtmlContents, input.substring( startCloseTagPos, endCloseTagPos ) );
+                               }
+
+                               return result;
+                       }
+
+                       templateName = transform(
+                               // see $wgLegalTitleChars
+                               // not allowing : due to the need to catch "PLURAL:$1"
+                               makeRegexParser( /^[ !"$&'()*,.\/0-9;=?@A-Z\^_`a-z~\x80-\xFF+\-]+/ ),
+                               function ( result ) { return result.toString(); }
+                       );
+                       function templateParam() {
+                               var expr, result;
+                               result = sequence( [
+                                       pipe,
+                                       nOrMore( 0, paramExpression )
+                               ] );
+                               if ( result === null ) {
+                                       return null;
+                               }
+                               expr = result[1];
+                               // use a CONCAT operator if there are multiple nodes, otherwise return the first node, raw.
+                               return expr.length > 1 ? [ 'CONCAT' ].concat( expr ) : expr[0];
+                       }
+
+                       function templateWithReplacement() {
+                               var result = sequence( [
+                                       templateName,
+                                       colon,
+                                       replacement
+                               ] );
+                               return result === null ? null : [ result[0], result[2] ];
+                       }
+                       function templateWithOutReplacement() {
+                               var result = sequence( [
+                                       templateName,
+                                       colon,
+                                       paramExpression
+                               ] );
+                               return result === null ? null : [ result[0], result[2] ];
+                       }
+                       function templateWithOutFirstParameter() {
+                               var result = sequence( [
+                                       templateName,
+                                       colon
+                               ] );
+                               return result === null ? null : [ result[0], '' ];
+                       }
+                       colon = makeStringParser( ':' );
+                       templateContents = choice( [
+                               function () {
+                                       var res = sequence( [
+                                               // templates can have placeholders for dynamic replacement eg: {{PLURAL:$1|one car|$1 cars}}
+                                               // or no placeholders eg: {{GRAMMAR:genitive|{{SITENAME}}}
+                                               choice( [ templateWithReplacement, templateWithOutReplacement, templateWithOutFirstParameter ] ),
+                                               nOrMore( 0, templateParam )
+                                       ] );
+                                       return res === null ? null : res[0].concat( res[1] );
+                               },
+                               function () {
+                                       var res = sequence( [
+                                               templateName,
+                                               nOrMore( 0, templateParam )
+                                       ] );
+                                       if ( res === null ) {
+                                               return null;
+                                       }
+                                       return [ res[0] ].concat( res[1] );
+                               }
+                       ] );
+                       openTemplate = makeStringParser( '{{' );
+                       closeTemplate = makeStringParser( '}}' );
+                       nonWhitespaceExpression = choice( [
+                               template,
+                               wikilink,
+                               extLinkParam,
+                               extlink,
+                               replacement,
+                               literalWithoutSpace
+                       ] );
+                       paramExpression = choice( [
+                               template,
+                               wikilink,
+                               extLinkParam,
+                               extlink,
+                               replacement,
+                               literalWithoutBar
+                       ] );
+
+                       expression = choice( [
+                               template,
+                               wikilink,
+                               extLinkParam,
+                               extlink,
+                               replacement,
+                               html,
+                               literal
+                       ] );
+
+                       // Used when only {{-transformation is wanted, for 'text'
+                       // or 'escaped' formats
+                       curlyBraceTransformExpression = choice( [
+                               template,
+                               replacement,
+                               curlyBraceTransformExpressionLiteral
+                       ] );
+
+                       /**
+                        * Starts the parse
+                        *
+                        * @param {Function} rootExpression root parse function
+                        */
+                       function start( rootExpression ) {
+                               var result = nOrMore( 0, rootExpression )();
+                               if ( result === null ) {
+                                       return null;
+                               }
+                               return [ 'CONCAT' ].concat( result );
+                       }
+                       // everything above this point is supposed to be stateless/static, but
+                       // I am deferring the work of turning it into prototypes & objects. It's quite fast enough
+                       // finally let's do some actual work...
+
+                       // If you add another possible rootExpression, you must update the astCache key scheme.
+                       result = start( this.settings.onlyCurlyBraceTransform ? curlyBraceTransformExpression : expression );
+
+                       /*
+                        * For success, the p must have gotten to the end of the input
+                        * and returned a non-null.
+                        * n.b. This is part of language infrastructure, so we do not throw an internationalizable message.
+                        */
+                       if ( result === null || pos !== input.length ) {
+                               throw new Error( 'Parse error at position ' + pos.toString() + ' in input: ' + input );
+                       }
+                       return result;
+               }
+
+       };
+
+       /**
+        * htmlEmitter - object which primarily exists to emit HTML from parser ASTs
+        */
+       mw.jqueryMsg.htmlEmitter = function ( language, magic ) {
+               this.language = language;
+               var jmsg = this;
+               $.each( magic, function ( key, val ) {
+                       jmsg[ key.toLowerCase() ] = function () {
+                               return val;
+                       };
+               } );
+
+               /**
+                * (We put this method definition here, and not in prototype, to make sure it's not overwritten by any magic.)
+                * Walk entire node structure, applying replacements and template functions when appropriate
+                * @param {Mixed} node Abstract syntax tree (top node or subnode)
+                * @param {Array} replacements for $1, $2, ... $n
+                * @return {Mixed} single-string node or array of nodes suitable for jQuery appending
+                */
+               this.emit = function ( node, replacements ) {
+                       var ret, subnodes, operation,
+                               jmsg = this;
+                       switch ( typeof node ) {
+                               case 'string':
+                               case 'number':
+                                       ret = node;
+                                       break;
+                               // typeof returns object for arrays
+                               case 'object':
+                                       // node is an array of nodes
+                                       subnodes = $.map( node.slice( 1 ), function ( n ) {
+                                               return jmsg.emit( n, replacements );
+                                       } );
+                                       operation = node[0].toLowerCase();
+                                       if ( typeof jmsg[operation] === 'function' ) {
+                                               ret = jmsg[ operation ]( subnodes, replacements );
+                                       } else {
+                                               throw new Error( 'Unknown operation "' + operation + '"' );
+                                       }
+                                       break;
+                               case 'undefined':
+                                       // Parsing the empty string (as an entire expression, or as a paramExpression in a template) results in undefined
+                                       // Perhaps a more clever parser can detect this, and return the empty string? Or is that useful information?
+                                       // The logical thing is probably to return the empty string here when we encounter undefined.
+                                       ret = '';
+                                       break;
+                               default:
+                                       throw new Error( 'Unexpected type in AST: ' + typeof node );
+                       }
+                       return ret;
+               };
+       };
+
+       // For everything in input that follows double-open-curly braces, there should be an equivalent parser
+       // function. For instance {{PLURAL ... }} will be processed by 'plural'.
+       // If you have 'magic words' then configure the parser to have them upon creation.
+       //
+       // An emitter method takes the parent node, the array of subnodes and the array of replacements (the values that $1, $2... should translate to).
+       // Note: all such functions must be pure, with the exception of referring to other pure functions via this.language (convertPlural and so on)
+       mw.jqueryMsg.htmlEmitter.prototype = {
+               /**
+                * Parsing has been applied depth-first we can assume that all nodes here are single nodes
+                * Must return a single node to parents -- a jQuery with synthetic span
+                * However, unwrap any other synthetic spans in our children and pass them upwards
+                * @param {Mixed[]} nodes Some single nodes, some arrays of nodes
+                * @return {jQuery}
+                */
+               concat: function ( nodes ) {
+                       var $span = $( '<span>' ).addClass( 'mediaWiki_htmlEmitter' );
+                       $.each( nodes, function ( i, node ) {
+                               if ( node instanceof jQuery && node.hasClass( 'mediaWiki_htmlEmitter' ) ) {
+                                       $.each( node.contents(), function ( j, childNode ) {
+                                               appendWithoutParsing( $span, childNode );
+                                       } );
+                               } else {
+                                       // Let jQuery append nodes, arrays of nodes and jQuery objects
+                                       // other things (strings, numbers, ..) are appended as text nodes (not as HTML strings)
+                                       appendWithoutParsing( $span, node );
+                               }
+                       } );
+                       return $span;
+               },
+
+               /**
+                * Return escaped replacement of correct index, or string if unavailable.
+                * Note that we expect the parsed parameter to be zero-based. i.e. $1 should have become [ 0 ].
+                * if the specified parameter is not found return the same string
+                * (e.g. "$99" -> parameter 98 -> not found -> return "$99" )
+                *
+                * TODO: Throw error if nodes.length > 1 ?
+                *
+                * @param {Array} nodes List of one element, integer, n >= 0
+                * @param {Array} replacements List of at least n strings
+                * @return {String} replacement
+                */
+               replace: function ( nodes, replacements ) {
+                       var index = parseInt( nodes[0], 10 );
+
+                       if ( index < replacements.length ) {
+                               return replacements[index];
+                       } else {
+                               // index not found, fallback to displaying variable
+                               return '$' + ( index + 1 );
+                       }
+               },
+
+               /**
+                * Transform wiki-link
+                *
+                * TODO:
+                * It only handles basic cases, either no pipe, or a pipe with an explicit
+                * anchor.
+                *
+                * It does not attempt to handle features like the pipe trick.
+                * However, the pipe trick should usually not be present in wikitext retrieved
+                * from the server, since the replacement is done at save time.
+                * It may, though, if the wikitext appears in extension-controlled content.
+                *
+                * @param nodes
+                */
+               wikilink: function ( nodes ) {
+                       var page, anchor, url;
+
+                       page = nodes[0];
+                       url = mw.util.getUrl( page );
+
+                       // [[Some Page]] or [[Namespace:Some Page]]
+                       if ( nodes.length === 1 ) {
+                               anchor = page;
+                       }
+
+                       /*
+                        * [[Some Page|anchor text]] or
+                        * [[Namespace:Some Page|anchor]
+                        */
+                       else {
+                               anchor = nodes[1];
+                       }
+
+                       return $( '<a>' ).attr( {
+                               title: page,
+                               href: url
+                       } ).text( anchor );
+               },
+
+               /**
+                * Converts array of HTML element key value pairs to object
+                *
+                * @param {Array} nodes Array of consecutive key value pairs, with index 2 * n being a
+                *  name and 2 * n + 1 the associated value
+                * @return {Object} Object mapping attribute name to attribute value
+                */
+               htmlattributes: function ( nodes ) {
+                       var i, len, mapping = {};
+                       for ( i = 0, len = nodes.length; i < len; i += 2 ) {
+                               mapping[nodes[i]] = decodePrimaryHtmlEntities( nodes[i + 1] );
+                       }
+                       return mapping;
+               },
+
+               /**
+                * Handles an (already-validated) HTML element.
+                *
+                * @param {Array} nodes Nodes to process when creating element
+                * @return {jQuery|Array} jQuery node for valid HTML or array for disallowed element
+                */
+               htmlelement: function ( nodes ) {
+                       var tagName, attributes, contents, $element;
+
+                       tagName = nodes.shift();
+                       attributes = nodes.shift();
+                       contents = nodes;
+                       $element = $( document.createElement( tagName ) ).attr( attributes );
+                       return appendWithoutParsing( $element, contents );
+               },
+
+               /**
+                * Transform parsed structure into external link
+                * If the href is a jQuery object, treat it as "enclosing" the link text.
+                *
+                * - ... function, treat it as the click handler.
+                * - ... string, treat it as a URI.
+                *
+                * TODO: throw an error if nodes.length > 2 ?
+                *
+                * @param {Array} nodes List of two elements, {jQuery|Function|String} and {String}
+                * @return {jQuery}
+                */
+               extlink: function ( nodes ) {
+                       var $el,
+                               arg = nodes[0],
+                               contents = nodes[1];
+                       if ( arg instanceof jQuery ) {
+                               $el = arg;
+                       } else {
+                               $el = $( '<a>' );
+                               if ( typeof arg === 'function' ) {
+                                       $el.click( arg ).attr( 'href', '#' );
+                               } else {
+                                       $el.attr( 'href', arg.toString() );
+                               }
+                       }
+                       return appendWithoutParsing( $el, contents );
+               },
+
+               /**
+                * This is basically use a combination of replace + external link (link with parameter
+                * as url), but we don't want to run the regular replace here-on: inserting a
+                * url as href-attribute of a link will automatically escape it already, so
+                * we don't want replace to (manually) escape it as well.
+                *
+                * TODO: throw error if nodes.length > 1 ?
+                *
+                * @param {Array} nodes List of one element, integer, n >= 0
+                * @param {Array} replacements List of at least n strings
+                * @return {string} replacement
+                */
+               extlinkparam: function ( nodes, replacements ) {
+                       var replacement,
+                               index = parseInt( nodes[0], 10 );
+                       if ( index < replacements.length ) {
+                               replacement = replacements[index];
+                       } else {
+                               replacement = '$' + ( index + 1 );
+                       }
+                       return this.extlink( [ replacement, nodes[1] ] );
+               },
+
+               /**
+                * Transform parsed structure into pluralization
+                * n.b. The first node may be a non-integer (for instance, a string representing an Arabic number).
+                * So convert it back with the current language's convertNumber.
+                * @param {Array} nodes List of nodes, [ {string|number}, {string}, {string} ... ]
+                * @return {string} selected pluralized form according to current language
+                */
+               plural: function ( nodes ) {
+                       var forms, count;
+                       count = parseFloat( this.language.convertNumber( nodes[0], true ) );
+                       forms = nodes.slice( 1 );
+                       return forms.length ? this.language.convertPlural( count, forms ) : '';
+               },
+
+               /**
+                * Transform parsed structure according to gender.
+                *
+                * Usage: {{gender:[ mw.user object | '' | 'male' | 'female' | 'unknown' ] | masculine form | feminine form | neutral form}}.
+                *
+                * The first node must be one of:
+                * - the mw.user object (or a compatible one)
+                * - an empty string - indicating the current user, same effect as passing the mw.user object
+                * - a gender string ('male', 'female' or 'unknown')
+                *
+                * @param {Array} nodes List of nodes, [ {string|mw.user}, {string}, {string}, {string} ]
+                * @return {string} Selected gender form according to current language
+                */
+               gender: function ( nodes ) {
+                       var gender,
+                               maybeUser = nodes[0],
+                               forms = nodes.slice( 1 );
+
+                       if ( maybeUser === '' ) {
+                               maybeUser = mw.user;
+                       }
+
+                       // If we are passed a mw.user-like object, check their gender.
+                       // Otherwise, assume the gender string itself was passed .
+                       if ( maybeUser && maybeUser.options instanceof mw.Map ) {
+                               gender = maybeUser.options.get( 'gender' );
+                       } else {
+                               gender = maybeUser;
+                       }
+
+                       return this.language.gender( gender, forms );
+               },
+
+               /**
+                * Transform parsed structure into grammar conversion.
+                * Invoked by putting `{{grammar:form|word}}` in a message
+                * @param {Array} nodes List of nodes [{Grammar case eg: genitive}, {string word}]
+                * @return {string} selected grammatical form according to current language
+                */
+               grammar: function ( nodes ) {
+                       var form = nodes[0],
+                               word = nodes[1];
+                       return word && form && this.language.convertGrammar( word, form );
+               },
+
+               /**
+                * Tranform parsed structure into a int: (interface language) message include
+                * Invoked by putting `{{int:othermessage}}` into a message
+                * @param {Array} nodes List of nodes
+                * @return {string} Other message
+                */
+               int: function ( nodes ) {
+                       return mw.jqueryMsg.getMessageFunction()( nodes[0].toLowerCase() );
+               },
+
+               /**
+                * Takes an unformatted number (arab, no group separators and . as decimal separator)
+                * and outputs it in the localized digit script and formatted with decimal
+                * separator, according to the current language.
+                * @param {Array} nodes List of nodes
+                * @return {number|string} Formatted number
+                */
+               formatnum: function ( nodes ) {
+                       var isInteger = ( nodes[1] && nodes[1] === 'R' ) ? true : false,
+                               number = nodes[0];
+
+                       return this.language.convertNumber( number, isInteger );
+               }
+       };
+
+       // Deprecated! don't rely on gM existing.
+       // The window.gM ought not to be required - or if required, not required here.
+       // But moving it to extensions breaks it (?!)
+       // Need to fix plugin so it could do attributes as well, then will be okay to remove this.
+       // @deprecated since 1.23
+       mw.log.deprecate( window, 'gM', mw.jqueryMsg.getMessageFunction(), 'Use mw.message( ... ).parse() instead.' );
+
+       /**
+        * @method
+        * @member jQuery
+        * @see mw.jqueryMsg#getPlugin
+        */
+       $.fn.msg = mw.jqueryMsg.getPlugin();
+
+       // Replace the default message parser with jqueryMsg
+       oldParser = mw.Message.prototype.parser;
+       mw.Message.prototype.parser = function () {
+               var messageFunction;
+
+               // TODO: should we cache the message function so we don't create a new one every time? Benchmark this maybe?
+               // Caching is somewhat problematic, because we do need different message functions for different maps, so
+               // we'd have to cache the parser as a member of this.map, which sounds a bit ugly.
+               // Do not use mw.jqueryMsg unless required
+               if ( this.format === 'plain' || !/\{\{|[\[<>]/.test( this.map.get( this.key ) ) ) {
+                       // Fall back to mw.msg's simple parser
+                       return oldParser.apply( this );
+               }
+
+               messageFunction = mw.jqueryMsg.getMessageFunction( {
+                       'messages': this.map,
+                       // For format 'escaped', escaping part is handled by mediawiki.js
+                       'format': this.format
+               } );
+               return messageFunction( this.key, this.parameters );
+       };
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.jqueryMsg.peg b/resources/src/mediawiki/mediawiki.jqueryMsg.peg
new file mode 100644 (file)
index 0000000..716c326
--- /dev/null
@@ -0,0 +1,85 @@
+/* PEG grammar for a subset of wikitext, useful in the MediaWiki frontend */
+
+start
+  = e:expression* { return e.length > 1 ? [ "CONCAT" ].concat(e) : e[0]; }
+
+expression
+  = template
+  / link
+  / extlink
+  / replacement
+  / literal
+
+paramExpression
+  = template
+  / link
+  / extlink
+  / replacement
+  / literalWithoutBar
+
+template
+  = "{{" t:templateContents "}}" { return t; }
+
+templateContents
+  = twr:templateWithReplacement p:templateParam* { return twr.concat(p) }
+  / twr:templateWithOutReplacement p:templateParam* { return twr.concat(p) }
+  / twr:templateWithOutFirstParameter p:templateParam* { return twr.concat(p) }
+  / t:templateName p:templateParam* { return p.length ? [ t, p ] : [ t ] }
+
+templateWithReplacement
+  = t:templateName ":" r:replacement { return [ t, r ] }
+
+templateWithOutReplacement
+  = t:templateName ":" p:paramExpression { return [ t, p ] }
+
+templateWithOutFirstParameter
+  = t:templateName ":" { return [ t, "" ] }
+
+templateParam
+  = "|" e:paramExpression* { return e.length > 1 ? [ "CONCAT" ].concat(e) : e[0]; }
+
+templateName
+  = tn:[A-Za-z_]+ { return tn.join('').toUpperCase() }
+
+/* TODO: Update to reflect separate piped and unpiped handling */
+link
+  = "[[" w:expression "]]" { return [ 'WLINK', w ]; }
+
+extlink
+  = "[" url:url whitespace text:expression "]" { return [ 'LINK', url, text ] }
+
+url
+  = url:[^ ]+ { return url.join(''); }
+
+whitespace
+  = [ ]+
+
+replacement
+  = '$' digits:digits { return [ 'REPLACE', parseInt( digits, 10 ) - 1 ] }
+
+digits
+  = [0-9]+
+
+literal
+  = lit:escapedOrRegularLiteral+ { return lit.join(''); }
+
+literalWithoutBar
+  = lit:escapedOrLiteralWithoutBar+ { return lit.join(''); }
+
+escapedOrRegularLiteral
+  = escapedLiteral
+  / regularLiteral
+
+escapedOrLiteralWithoutBar
+  = escapedLiteral
+  / regularLiteralWithoutBar
+
+escapedLiteral
+  = "\\" escaped:. { return escaped; }
+
+regularLiteral
+  = [^{}\[\]$\\]
+
+regularLiteralWithoutBar
+  = [^{}\[\]$\\|]
+
diff --git a/resources/src/mediawiki/mediawiki.js b/resources/src/mediawiki/mediawiki.js
new file mode 100644 (file)
index 0000000..57f85d8
--- /dev/null
@@ -0,0 +1,2417 @@
+/**
+ * Base library for MediaWiki.
+ *
+ * Exposed as globally as `mediaWiki` with `mw` as shortcut.
+ *
+ * @class mw
+ * @alternateClassName mediaWiki
+ * @singleton
+ */
+
+var mw = ( function ( $, undefined ) {
+       'use strict';
+
+       /* Private Members */
+
+       var hasOwn = Object.prototype.hasOwnProperty,
+               slice = Array.prototype.slice,
+               trackCallbacks = $.Callbacks( 'memory' ),
+               trackQueue = [];
+
+       /**
+        * Log a message to window.console, if possible. Useful to force logging of some
+        * errors that are otherwise hard to detect (I.e., this logs also in production mode).
+        * Gets console references in each invocation, so that delayed debugging tools work
+        * fine. No need for optimization here, which would only result in losing logs.
+        *
+        * @private
+        * @method log_
+        * @param {string} msg text for the log entry.
+        * @param {Error} [e]
+        */
+       function log( msg, e ) {
+               var console = window.console;
+               if ( console && console.log ) {
+                       console.log( msg );
+                       // If we have an exception object, log it through .error() to trigger
+                       // proper stacktraces in browsers that support it. There are no (known)
+                       // browsers that don't support .error(), that do support .log() and
+                       // have useful exception handling through .log().
+                       if ( e && console.error ) {
+                               console.error( String( e ), e );
+                       }
+               }
+       }
+
+       /* Object constructors */
+
+       /**
+        * Creates an object that can be read from or written to from prototype functions
+        * that allow both single and multiple variables at once.
+        *
+        *     @example
+        *
+        *     var addies, wanted, results;
+        *
+        *     // Create your address book
+        *     addies = new mw.Map();
+        *
+        *     // This data could be coming from an external source (eg. API/AJAX)
+        *     addies.set( {
+        *         'John Doe' : '10 Wall Street, New York, USA',
+        *         'Jane Jackson' : '21 Oxford St, London, UK',
+        *         'Dominique van Halen' : 'Kalverstraat 7, Amsterdam, NL'
+        *     } );
+        *
+        *     wanted = ['Dominique van Halen', 'George Johnson', 'Jane Jackson'];
+        *
+        *     // You can detect missing keys first
+        *     if ( !addies.exists( wanted ) ) {
+        *         // One or more are missing (in this case: "George Johnson")
+        *         mw.log( 'One or more names were not found in your address book' );
+        *     }
+        *
+        *     // Or just let it give you what it can
+        *     results = addies.get( wanted, 'Middle of Nowhere, Alaska, US' );
+        *     mw.log( results['Jane Jackson'] ); // "21 Oxford St, London, UK"
+        *     mw.log( results['George Johnson'] ); // "Middle of Nowhere, Alaska, US"
+        *
+        * @class mw.Map
+        *
+        * @constructor
+        * @param {Object|boolean} [values] Value-bearing object to map, or boolean
+        *  true to map over the global object. Defaults to an empty object.
+        */
+       function Map( values ) {
+               this.values = values === true ? window : ( values || {} );
+               return this;
+       }
+
+       Map.prototype = {
+               /**
+                * Get the value of one or multiple a keys.
+                *
+                * If called with no arguments, all values will be returned.
+                *
+                * @param {string|Array} selection String key or array of keys to get values for.
+                * @param {Mixed} [fallback] Value to use in case key(s) do not exist.
+                * @return mixed If selection was a string returns the value or null,
+                *  If selection was an array, returns an object of key/values (value is null if not found),
+                *  If selection was not passed or invalid, will return the 'values' object member (be careful as
+                *  objects are always passed by reference in JavaScript!).
+                * @return {string|Object|null} Values as a string or object, null if invalid/inexistant.
+                */
+               get: function ( selection, fallback ) {
+                       var results, i;
+                       // If we only do this in the `return` block, it'll fail for the
+                       // call to get() from the mutli-selection block.
+                       fallback = arguments.length > 1 ? fallback : null;
+
+                       if ( $.isArray( selection ) ) {
+                               selection = slice.call( selection );
+                               results = {};
+                               for ( i = 0; i < selection.length; i++ ) {
+                                       results[selection[i]] = this.get( selection[i], fallback );
+                               }
+                               return results;
+                       }
+
+                       if ( typeof selection === 'string' ) {
+                               if ( !hasOwn.call( this.values, selection ) ) {
+                                       return fallback;
+                               }
+                               return this.values[selection];
+                       }
+
+                       if ( selection === undefined ) {
+                               return this.values;
+                       }
+
+                       // invalid selection key
+                       return null;
+               },
+
+               /**
+                * Sets one or multiple key/value pairs.
+                *
+                * @param {string|Object} selection String key to set value for, or object mapping keys to values.
+                * @param {Mixed} [value] Value to set (optional, only in use when key is a string)
+                * @return {Boolean} This returns true on success, false on failure.
+                */
+               set: function ( selection, value ) {
+                       var s;
+
+                       if ( $.isPlainObject( selection ) ) {
+                               for ( s in selection ) {
+                                       this.values[s] = selection[s];
+                               }
+                               return true;
+                       }
+                       if ( typeof selection === 'string' && arguments.length > 1 ) {
+                               this.values[selection] = value;
+                               return true;
+                       }
+                       return false;
+               },
+
+               /**
+                * Checks if one or multiple keys exist.
+                *
+                * @param {Mixed} selection String key or array of keys to check
+                * @return {boolean} Existence of key(s)
+                */
+               exists: function ( selection ) {
+                       var s;
+
+                       if ( $.isArray( selection ) ) {
+                               for ( s = 0; s < selection.length; s++ ) {
+                                       if ( typeof selection[s] !== 'string' || !hasOwn.call( this.values, selection[s] ) ) {
+                                               return false;
+                                       }
+                               }
+                               return true;
+                       }
+                       return typeof selection === 'string' && hasOwn.call( this.values, selection );
+               }
+       };
+
+       /**
+        * Object constructor for messages.
+        *
+        * Similar to the Message class in MediaWiki PHP.
+        *
+        * Format defaults to 'text'.
+        *
+        *     @example
+        *
+        *     var obj, str;
+        *     mw.messages.set( {
+        *         'hello': 'Hello world',
+        *         'hello-user': 'Hello, $1!',
+        *         'welcome-user': 'Welcome back to $2, $1! Last visit by $1: $3'
+        *     } );
+        *
+        *     obj = new mw.Message( mw.messages, 'hello' );
+        *     mw.log( obj.text() );
+        *     // Hello world
+        *
+        *     obj = new mw.Message( mw.messages, 'hello-user', [ 'John Doe' ] );
+        *     mw.log( obj.text() );
+        *     // Hello, John Doe!
+        *
+        *     obj = new mw.Message( mw.messages, 'welcome-user', [ 'John Doe', 'Wikipedia', '2 hours ago' ] );
+        *     mw.log( obj.text() );
+        *     // Welcome back to Wikipedia, John Doe! Last visit by John Doe: 2 hours ago
+        *
+        *     // Using mw.message shortcut
+        *     obj = mw.message( 'hello-user', 'John Doe' );
+        *     mw.log( obj.text() );
+        *     // Hello, John Doe!
+        *
+        *     // Using mw.msg shortcut
+        *     str = mw.msg( 'hello-user', 'John Doe' );
+        *     mw.log( str );
+        *     // Hello, John Doe!
+        *
+        *     // Different formats
+        *     obj = new mw.Message( mw.messages, 'hello-user', [ 'John "Wiki" <3 Doe' ] );
+        *
+        *     obj.format = 'text';
+        *     str = obj.toString();
+        *     // Same as:
+        *     str = obj.text();
+        *
+        *     mw.log( str );
+        *     // Hello, John "Wiki" <3 Doe!
+        *
+        *     mw.log( obj.escaped() );
+        *     // Hello, John &quot;Wiki&quot; &lt;3 Doe!
+        *
+        * @class mw.Message
+        *
+        * @constructor
+        * @param {mw.Map} map Message storage
+        * @param {string} key
+        * @param {Array} [parameters]
+        */
+       function Message( map, key, parameters ) {
+               this.format = 'text';
+               this.map = map;
+               this.key = key;
+               this.parameters = parameters === undefined ? [] : slice.call( parameters );
+               return this;
+       }
+
+       Message.prototype = {
+               /**
+                * Simple message parser, does $N replacement and nothing else.
+                *
+                * This may be overridden to provide a more complex message parser.
+                *
+                * The primary override is in mediawiki.jqueryMsg.
+                *
+                * This function will not be called for nonexistent messages.
+                */
+               parser: function () {
+                       var parameters = this.parameters;
+                       return this.map.get( this.key ).replace( /\$(\d+)/g, function ( str, match ) {
+                               var index = parseInt( match, 10 ) - 1;
+                               return parameters[index] !== undefined ? parameters[index] : '$' + match;
+                       } );
+               },
+
+               /**
+                * Appends (does not replace) parameters for replacement to the .parameters property.
+                *
+                * @param {Array} parameters
+                * @chainable
+                */
+               params: function ( parameters ) {
+                       var i;
+                       for ( i = 0; i < parameters.length; i += 1 ) {
+                               this.parameters.push( parameters[i] );
+                       }
+                       return this;
+               },
+
+               /**
+                * Converts message object to its string form based on the state of format.
+                *
+                * @return {string} Message as a string in the current form or `<key>` if key does not exist.
+                */
+               toString: function () {
+                       var text;
+
+                       if ( !this.exists() ) {
+                               // Use <key> as text if key does not exist
+                               if ( this.format === 'escaped' || this.format === 'parse' ) {
+                                       // format 'escaped' and 'parse' need to have the brackets and key html escaped
+                                       return mw.html.escape( '<' + this.key + '>' );
+                               }
+                               return '<' + this.key + '>';
+                       }
+
+                       if ( this.format === 'plain' || this.format === 'text' || this.format === 'parse' ) {
+                               text = this.parser();
+                       }
+
+                       if ( this.format === 'escaped' ) {
+                               text = this.parser();
+                               text = mw.html.escape( text );
+                       }
+
+                       return text;
+               },
+
+               /**
+                * Changes format to 'parse' and converts message to string
+                *
+                * If jqueryMsg is loaded, this parses the message text from wikitext
+                * (where supported) to HTML
+                *
+                * Otherwise, it is equivalent to plain.
+                *
+                * @return {string} String form of parsed message
+                */
+               parse: function () {
+                       this.format = 'parse';
+                       return this.toString();
+               },
+
+               /**
+                * Changes format to 'plain' and converts message to string
+                *
+                * This substitutes parameters, but otherwise does not change the
+                * message text.
+                *
+                * @return {string} String form of plain message
+                */
+               plain: function () {
+                       this.format = 'plain';
+                       return this.toString();
+               },
+
+               /**
+                * Changes format to 'text' and converts message to string
+                *
+                * If jqueryMsg is loaded, {{-transformation is done where supported
+                * (such as {{plural:}}, {{gender:}}, {{int:}}).
+                *
+                * Otherwise, it is equivalent to plain.
+                */
+               text: function () {
+                       this.format = 'text';
+                       return this.toString();
+               },
+
+               /**
+                * Changes the format to 'escaped' and converts message to string
+                *
+                * This is equivalent to using the 'text' format (see text method), then
+                * HTML-escaping the output.
+                *
+                * @return {string} String form of html escaped message
+                */
+               escaped: function () {
+                       this.format = 'escaped';
+                       return this.toString();
+               },
+
+               /**
+                * Checks if message exists
+                *
+                * @see mw.Map#exists
+                * @return {boolean}
+                */
+               exists: function () {
+                       return this.map.exists( this.key );
+               }
+       };
+
+       /**
+        * @class mw
+        */
+       return {
+               /* Public Members */
+
+               /**
+                * Get the current time, measured in milliseconds since January 1, 1970 (UTC).
+                *
+                * On browsers that implement the Navigation Timing API, this function will produce floating-point
+                * values with microsecond precision that are guaranteed to be monotonic. On all other browsers,
+                * it will fall back to using `Date`.
+                *
+                * @return {number} Current time
+                */
+               now: ( function () {
+                       var perf = window.performance,
+                               navStart = perf && perf.timing && perf.timing.navigationStart;
+                       return navStart && typeof perf.now === 'function' ?
+                               function () { return navStart + perf.now(); } :
+                               function () { return +new Date(); };
+               }() ),
+
+               /**
+                * Track an analytic event.
+                *
+                * This method provides a generic means for MediaWiki JavaScript code to capture state
+                * information for analysis. Each logged event specifies a string topic name that describes
+                * the kind of event that it is. Topic names consist of dot-separated path components,
+                * arranged from most general to most specific. Each path component should have a clear and
+                * well-defined purpose.
+                *
+                * Data handlers are registered via `mw.trackSubscribe`, and receive the full set of
+                * events that match their subcription, including those that fired before the handler was
+                * bound.
+                *
+                * @param {string} topic Topic name
+                * @param {Object} [data] Data describing the event, encoded as an object
+                */
+               track: function ( topic, data ) {
+                       trackQueue.push( { topic: topic, timeStamp: mw.now(), data: data } );
+                       trackCallbacks.fire( trackQueue );
+               },
+
+               /**
+                * Register a handler for subset of analytic events, specified by topic
+                *
+                * Handlers will be called once for each tracked event, including any events that fired before the
+                * handler was registered; 'this' is set to a plain object with a 'timeStamp' property indicating
+                * the exact time at which the event fired, a string 'topic' property naming the event, and a
+                * 'data' property which is an object of event-specific data. The event topic and event data are
+                * also passed to the callback as the first and second arguments, respectively.
+                *
+                * @param {string} topic Handle events whose name starts with this string prefix
+                * @param {Function} callback Handler to call for each matching tracked event
+                */
+               trackSubscribe: function ( topic, callback ) {
+                       var seen = 0;
+
+                       trackCallbacks.add( function ( trackQueue ) {
+                               var event;
+                               for ( ; seen < trackQueue.length; seen++ ) {
+                                       event = trackQueue[ seen ];
+                                       if ( event.topic.indexOf( topic ) === 0 ) {
+                                               callback.call( event, event.topic, event.data );
+                                       }
+                               }
+                       } );
+               },
+
+               // Make the Map constructor publicly available.
+               Map: Map,
+
+               // Make the Message constructor publicly available.
+               Message: Message,
+
+               /**
+                * Map of configuration values
+                *
+                * Check out [the complete list of configuration values](https://www.mediawiki.org/wiki/Manual:Interface/JavaScript#mw.config)
+                * on mediawiki.org.
+                *
+                * If `$wgLegacyJavaScriptGlobals` is true, this Map will add its values to the
+                * global `window` object.
+                *
+                * @property {mw.Map} config
+                */
+               // Dummy placeholder. Re-assigned in ResourceLoaderStartupModule to an instance of `mw.Map`.
+               config: null,
+
+               /**
+                * Empty object that plugins can be installed in.
+                * @property
+                */
+               libs: {},
+
+               /**
+                * Access container for deprecated functionality that can be moved from
+                * from their legacy location and attached to this object (e.g. a global
+                * function that is deprecated and as stop-gap can be exposed through here).
+                *
+                * This was reserved for future use but never ended up being used.
+                *
+                * @deprecated since 1.22: Let deprecated identifiers keep their original name
+                *  and use mw.log#deprecate to create an access container for tracking.
+                * @property
+                */
+               legacy: {},
+
+               /**
+                * Localization system
+                * @property {mw.Map}
+                */
+               messages: new Map(),
+
+               /* Public Methods */
+
+               /**
+                * Get a message object.
+                *
+                * Shorcut for `new mw.Message( mw.messages, key, parameters )`.
+                *
+                * @see mw.Message
+                * @param {string} key Key of message to get
+                * @param {Mixed...} parameters Parameters for the $N replacements in messages.
+                * @return {mw.Message}
+                */
+               message: function ( key ) {
+                       // Variadic arguments
+                       var parameters = slice.call( arguments, 1 );
+                       return new Message( mw.messages, key, parameters );
+               },
+
+               /**
+                * Get a message string using the (default) 'text' format.
+                *
+                * Shortcut for `mw.message( key, parameters... ).text()`.
+                *
+                * @see mw.Message
+                * @param {string} key Key of message to get
+                * @param {Mixed...} parameters Parameters for the $N replacements in messages.
+                * @return {string}
+                */
+               msg: function () {
+                       return mw.message.apply( mw.message, arguments ).toString();
+               },
+
+               /**
+                * Dummy placeholder for {@link mw.log}
+                * @method
+                */
+               log: ( function () {
+                       // Also update the restoration of methods in mediawiki.log.js
+                       // when adding or removing methods here.
+                       var log = function () {};
+
+                       /**
+                        * @class mw.log
+                        * @singleton
+                        */
+
+                       /**
+                        * Write a message the console's warning channel.
+                        * Also logs a stacktrace for easier debugging.
+                        * Each action is silently ignored if the browser doesn't support it.
+                        *
+                        * @param {string...} msg Messages to output to console
+                        */
+                       log.warn = function () {
+                               var console = window.console;
+                               if ( console && console.warn ) {
+                                       console.warn.apply( console, arguments );
+                                       if ( console.trace ) {
+                                               console.trace();
+                                       }
+                               }
+                       };
+
+                       /**
+                        * Create a property in a host object that, when accessed, will produce
+                        * a deprecation warning in the console with backtrace.
+                        *
+                        * @param {Object} obj Host object of deprecated property
+                        * @param {string} key Name of property to create in `obj`
+                        * @param {Mixed} val The value this property should return when accessed
+                        * @param {string} [msg] Optional text to include in the deprecation message.
+                        */
+                       log.deprecate = !Object.defineProperty ? function ( obj, key, val ) {
+                               obj[key] = val;
+                       } : function ( obj, key, val, msg ) {
+                               msg = 'Use of "' + key + '" is deprecated.' + ( msg ? ( ' ' + msg ) : '' );
+                               try {
+                                       Object.defineProperty( obj, key, {
+                                               configurable: true,
+                                               enumerable: true,
+                                               get: function () {
+                                                       mw.track( 'mw.deprecate', key );
+                                                       mw.log.warn( msg );
+                                                       return val;
+                                               },
+                                               set: function ( newVal ) {
+                                                       mw.track( 'mw.deprecate', key );
+                                                       mw.log.warn( msg );
+                                                       val = newVal;
+                                               }
+                                       } );
+                               } catch ( err ) {
+                                       // IE8 can throw on Object.defineProperty
+                                       obj[key] = val;
+                               }
+                       };
+
+                       return log;
+               }() ),
+
+               /**
+                * Client-side module loader which integrates with the MediaWiki ResourceLoader
+                * @class mw.loader
+                * @singleton
+                */
+               loader: ( function () {
+
+                       /* Private Members */
+
+                       /**
+                        * Mapping of registered modules
+                        *
+                        * The jquery module is pre-registered, because it must have already
+                        * been provided for this object to have been built, and in debug mode
+                        * jquery would have been provided through a unique loader request,
+                        * making it impossible to hold back registration of jquery until after
+                        * mediawiki.
+                        *
+                        * For exact details on support for script, style and messages, look at
+                        * mw.loader.implement.
+                        *
+                        * Format:
+                        *     {
+                        *         'moduleName': {
+                        *             'version': ############## (unix timestamp),
+                        *             'dependencies': ['required.foo', 'bar.also', ...], (or) function () {}
+                        *             'group': 'somegroup', (or) null,
+                        *             'source': 'local', 'someforeignwiki', (or) null
+                        *             'state': 'registered', 'loaded', 'loading', 'ready', 'error' or 'missing'
+                        *             'script': ...,
+                        *             'style': ...,
+                        *             'messages': { 'key': 'value' },
+                        *         }
+                        *     }
+                        *
+                        * @property
+                        * @private
+                        */
+                       var registry = {},
+                               //
+                               // Mapping of sources, keyed by source-id, values are objects.
+                               // Format:
+                               //      {
+                               //              'sourceId': {
+                               //                      'loadScript': 'http://foo.bar/w/load.php'
+                               //              }
+                               //      }
+                               //
+                               sources = {},
+                               // List of modules which will be loaded as when ready
+                               batch = [],
+                               // List of modules to be loaded
+                               queue = [],
+                               // List of callback functions waiting for modules to be ready to be called
+                               jobs = [],
+                               // Selector cache for the marker element. Use getMarker() to get/use the marker!
+                               $marker = null,
+                               // Buffer for addEmbeddedCSS.
+                               cssBuffer = '',
+                               // Callbacks for addEmbeddedCSS.
+                               cssCallbacks = $.Callbacks();
+
+                       /* Private methods */
+
+                       function getMarker() {
+                               // Cached ?
+                               if ( $marker ) {
+                                       return $marker;
+                               }
+
+                               $marker = $( 'meta[name="ResourceLoaderDynamicStyles"]' );
+                               if ( $marker.length ) {
+                                       return $marker;
+                               }
+                               mw.log( 'getMarker> No <meta name="ResourceLoaderDynamicStyles"> found, inserting dynamically.' );
+                               $marker = $( '<meta>' ).attr( 'name', 'ResourceLoaderDynamicStyles' ).appendTo( 'head' );
+
+                               return $marker;
+                       }
+
+                       /**
+                        * Create a new style tag and add it to the DOM.
+                        *
+                        * @private
+                        * @param {string} text CSS text
+                        * @param {HTMLElement|jQuery} [nextnode=document.head] The element where the style tag should be
+                        *  inserted before. Otherwise it will be appended to `<head>`.
+                        * @return {HTMLElement} Reference to the created `<style>` element.
+                        */
+                       function newStyleTag( text, nextnode ) {
+                               var s = document.createElement( 'style' );
+                               // Insert into document before setting cssText (bug 33305)
+                               if ( nextnode ) {
+                                       // Must be inserted with native insertBefore, not $.fn.before.
+                                       // When using jQuery to insert it, like $nextnode.before( s ),
+                                       // then IE6 will throw "Access is denied" when trying to append
+                                       // to .cssText later. Some kind of weird security measure.
+                                       // http://stackoverflow.com/q/12586482/319266
+                                       // Works: jsfiddle.net/zJzMy/1
+                                       // Fails: jsfiddle.net/uJTQz
+                                       // Works again: http://jsfiddle.net/Azr4w/ (diff: the next 3 lines)
+                                       if ( nextnode.jquery ) {
+                                               nextnode = nextnode.get( 0 );
+                                       }
+                                       nextnode.parentNode.insertBefore( s, nextnode );
+                               } else {
+                                       document.getElementsByTagName( 'head' )[0].appendChild( s );
+                               }
+                               if ( s.styleSheet ) {
+                                       // IE
+                                       s.styleSheet.cssText = text;
+                               } else {
+                                       // Other browsers.
+                                       // (Safari sometimes borks on non-string values,
+                                       // play safe by casting to a string, just in case.)
+                                       s.appendChild( document.createTextNode( String( text ) ) );
+                               }
+                               return s;
+                       }
+
+                       /**
+                        * Checks whether it is safe to add this css to a stylesheet.
+                        *
+                        * @private
+                        * @param {string} cssText
+                        * @return {boolean} False if a new one must be created.
+                        */
+                       function canExpandStylesheetWith( cssText ) {
+                               // Makes sure that cssText containing `@import`
+                               // rules will end up in a new stylesheet (as those only work when
+                               // placed at the start of a stylesheet; bug 35562).
+                               return cssText.indexOf( '@import' ) === -1;
+                       }
+
+                       /**
+                        * Add a bit of CSS text to the current browser page.
+                        *
+                        * The CSS will be appended to an existing ResourceLoader-created `<style>` tag
+                        * or create a new one based on whether the given `cssText` is safe for extension.
+                        *
+                        * @param {string} [cssText=cssBuffer] If called without cssText,
+                        *  the internal buffer will be inserted instead.
+                        * @param {Function} [callback]
+                        */
+                       function addEmbeddedCSS( cssText, callback ) {
+                               var $style, styleEl;
+
+                               if ( callback ) {
+                                       cssCallbacks.add( callback );
+                               }
+
+                               // Yield once before inserting the <style> tag. There are likely
+                               // more calls coming up which we can combine this way.
+                               // Appending a stylesheet and waiting for the browser to repaint
+                               // is fairly expensive, this reduces it (bug 45810)
+                               if ( cssText ) {
+                                       // Be careful not to extend the buffer with css that needs a new stylesheet
+                                       if ( !cssBuffer || canExpandStylesheetWith( cssText ) ) {
+                                               // Linebreak for somewhat distinguishable sections
+                                               // (the rl-cachekey comment separating each)
+                                               cssBuffer += '\n' + cssText;
+                                               // TODO: Use requestAnimationFrame in the future which will
+                                               // perform even better by not injecting styles while the browser
+                                               // is paiting.
+                                               setTimeout( function () {
+                                                       // Can't pass addEmbeddedCSS to setTimeout directly because Firefox
+                                                       // (below version 13) has the non-standard behaviour of passing a
+                                                       // numerical "lateness" value as first argument to this callback
+                                                       // http://benalman.com/news/2009/07/the-mysterious-firefox-settime/
+                                                       addEmbeddedCSS();
+                                               } );
+                                               return;
+                                       }
+
+                               // This is a delayed call and we got a buffer still
+                               } else if ( cssBuffer ) {
+                                       cssText = cssBuffer;
+                                       cssBuffer = '';
+                               } else {
+                                       // This is a delayed call, but buffer is already cleared by
+                                       // another delayed call.
+                                       return;
+                               }
+
+                               // By default, always create a new <style>. Appending text to a <style>
+                               // tag is bad as it means the contents have to be re-parsed (bug 45810).
+                               //
+                               // Except, of course, in IE 9 and below. In there we default to re-using and
+                               // appending to a <style> tag due to the IE stylesheet limit (bug 31676).
+                               if ( 'documentMode' in document && document.documentMode <= 9 ) {
+
+                                       $style = getMarker().prev();
+                                       // Verify that the the element before Marker actually is a
+                                       // <style> tag and one that came from ResourceLoader
+                                       // (not some other style tag or even a `<meta>` or `<script>`).
+                                       if ( $style.data( 'ResourceLoaderDynamicStyleTag' ) === true ) {
+                                               // There's already a dynamic <style> tag present and
+                                               // canExpandStylesheetWith() gave a green light to append more to it.
+                                               styleEl = $style.get( 0 );
+                                               if ( styleEl.styleSheet ) {
+                                                       try {
+                                                               styleEl.styleSheet.cssText += cssText; // IE
+                                                       } catch ( e ) {
+                                                               log( 'addEmbeddedCSS fail', e );
+                                                       }
+                                               } else {
+                                                       styleEl.appendChild( document.createTextNode( String( cssText ) ) );
+                                               }
+                                               cssCallbacks.fire().empty();
+                                               return;
+                                       }
+                               }
+
+                               $( newStyleTag( cssText, getMarker() ) ).data( 'ResourceLoaderDynamicStyleTag', true );
+
+                               cssCallbacks.fire().empty();
+                       }
+
+                       /**
+                        * Generates an ISO8601 "basic" string from a UNIX timestamp
+                        * @private
+                        */
+                       function formatVersionNumber( timestamp ) {
+                               var     d = new Date();
+                               function pad( a, b, c ) {
+                                       return [a < 10 ? '0' + a : a, b < 10 ? '0' + b : b, c < 10 ? '0' + c : c].join( '' );
+                               }
+                               d.setTime( timestamp * 1000 );
+                               return [
+                                       pad( d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate() ), 'T',
+                                       pad( d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds() ), 'Z'
+                               ].join( '' );
+                       }
+
+                       /**
+                        * Resolves dependencies and detects circular references.
+                        *
+                        * @private
+                        * @param {string} module Name of the top-level module whose dependencies shall be
+                        *   resolved and sorted.
+                        * @param {Array} resolved Returns a topological sort of the given module and its
+                        *   dependencies, such that later modules depend on earlier modules. The array
+                        *   contains the module names. If the array contains already some module names,
+                        *   this function appends its result to the pre-existing array.
+                        * @param {Object} [unresolved] Hash used to track the current dependency
+                        *   chain; used to report loops in the dependency graph.
+                        * @throws {Error} If any unregistered module or a dependency loop is encountered
+                        */
+                       function sortDependencies( module, resolved, unresolved ) {
+                               var n, deps, len;
+
+                               if ( registry[module] === undefined ) {
+                                       throw new Error( 'Unknown dependency: ' + module );
+                               }
+                               // Resolves dynamic loader function and replaces it with its own results
+                               if ( $.isFunction( registry[module].dependencies ) ) {
+                                       registry[module].dependencies = registry[module].dependencies();
+                                       // Ensures the module's dependencies are always in an array
+                                       if ( typeof registry[module].dependencies !== 'object' ) {
+                                               registry[module].dependencies = [registry[module].dependencies];
+                                       }
+                               }
+                               if ( $.inArray( module, resolved ) !== -1 ) {
+                                       // Module already resolved; nothing to do.
+                                       return;
+                               }
+                               // unresolved is optional, supply it if not passed in
+                               if ( !unresolved ) {
+                                       unresolved = {};
+                               }
+                               // Tracks down dependencies
+                               deps = registry[module].dependencies;
+                               len = deps.length;
+                               for ( n = 0; n < len; n += 1 ) {
+                                       if ( $.inArray( deps[n], resolved ) === -1 ) {
+                                               if ( unresolved[deps[n]] ) {
+                                                       throw new Error(
+                                                               'Circular reference detected: ' + module +
+                                                               ' -> ' + deps[n]
+                                                       );
+                                               }
+
+                                               // Add to unresolved
+                                               unresolved[module] = true;
+                                               sortDependencies( deps[n], resolved, unresolved );
+                                               delete unresolved[module];
+                                       }
+                               }
+                               resolved[resolved.length] = module;
+                       }
+
+                       /**
+                        * Gets a list of module names that a module depends on in their proper dependency
+                        * order.
+                        *
+                        * @private
+                        * @param {string} module Module name or array of string module names
+                        * @return {Array} list of dependencies, including 'module'.
+                        * @throws {Error} If circular reference is detected
+                        */
+                       function resolve( module ) {
+                               var m, resolved;
+
+                               // Allow calling with an array of module names
+                               if ( $.isArray( module ) ) {
+                                       resolved = [];
+                                       for ( m = 0; m < module.length; m += 1 ) {
+                                               sortDependencies( module[m], resolved );
+                                       }
+                                       return resolved;
+                               }
+
+                               if ( typeof module === 'string' ) {
+                                       resolved = [];
+                                       sortDependencies( module, resolved );
+                                       return resolved;
+                               }
+
+                               throw new Error( 'Invalid module argument: ' + module );
+                       }
+
+                       /**
+                        * Narrows a list of module names down to those matching a specific
+                        * state (see comment on top of this scope for a list of valid states).
+                        * One can also filter for 'unregistered', which will return the
+                        * modules names that don't have a registry entry.
+                        *
+                        * @private
+                        * @param {string|string[]} states Module states to filter by
+                        * @param {Array} [modules] List of module names to filter (optional, by default the entire
+                        * registry is used)
+                        * @return {Array} List of filtered module names
+                        */
+                       function filter( states, modules ) {
+                               var list, module, s, m;
+
+                               // Allow states to be given as a string
+                               if ( typeof states === 'string' ) {
+                                       states = [states];
+                               }
+                               // If called without a list of modules, build and use a list of all modules
+                               list = [];
+                               if ( modules === undefined ) {
+                                       modules = [];
+                                       for ( module in registry ) {
+                                               modules[modules.length] = module;
+                                       }
+                               }
+                               // Build a list of modules which are in one of the specified states
+                               for ( s = 0; s < states.length; s += 1 ) {
+                                       for ( m = 0; m < modules.length; m += 1 ) {
+                                               if ( registry[modules[m]] === undefined ) {
+                                                       // Module does not exist
+                                                       if ( states[s] === 'unregistered' ) {
+                                                               // OK, undefined
+                                                               list[list.length] = modules[m];
+                                                       }
+                                               } else {
+                                                       // Module exists, check state
+                                                       if ( registry[modules[m]].state === states[s] ) {
+                                                               // OK, correct state
+                                                               list[list.length] = modules[m];
+                                                       }
+                                               }
+                                       }
+                               }
+                               return list;
+                       }
+
+                       /**
+                        * Determine whether all dependencies are in state 'ready', which means we may
+                        * execute the module or job now.
+                        *
+                        * @private
+                        * @param {Array} dependencies Dependencies (module names) to be checked.
+                        * @return {boolean} True if all dependencies are in state 'ready', false otherwise
+                        */
+                       function allReady( dependencies ) {
+                               return filter( 'ready', dependencies ).length === dependencies.length;
+                       }
+
+                       /**
+                        * A module has entered state 'ready', 'error', or 'missing'. Automatically update pending jobs
+                        * and modules that depend upon this module. if the given module failed, propagate the 'error'
+                        * state up the dependency tree; otherwise, execute all jobs/modules that now have all their
+                        * dependencies satisfied. On jobs depending on a failed module, run the error callback, if any.
+                        *
+                        * @private
+                        * @param {string} module Name of module that entered one of the states 'ready', 'error', or 'missing'.
+                        */
+                       function handlePending( module ) {
+                               var j, job, hasErrors, m, stateChange;
+
+                               // Modules.
+                               if ( $.inArray( registry[module].state, ['error', 'missing'] ) !== -1 ) {
+                                       // If the current module failed, mark all dependent modules also as failed.
+                                       // Iterate until steady-state to propagate the error state upwards in the
+                                       // dependency tree.
+                                       do {
+                                               stateChange = false;
+                                               for ( m in registry ) {
+                                                       if ( $.inArray( registry[m].state, ['error', 'missing'] ) === -1 ) {
+                                                               if ( filter( ['error', 'missing'], registry[m].dependencies ).length > 0 ) {
+                                                                       registry[m].state = 'error';
+                                                                       stateChange = true;
+                                                               }
+                                                       }
+                                               }
+                                       } while ( stateChange );
+                               }
+
+                               // Execute all jobs whose dependencies are either all satisfied or contain at least one failed module.
+                               for ( j = 0; j < jobs.length; j += 1 ) {
+                                       hasErrors = filter( ['error', 'missing'], jobs[j].dependencies ).length > 0;
+                                       if ( hasErrors || allReady( jobs[j].dependencies ) ) {
+                                               // All dependencies satisfied, or some have errors
+                                               job = jobs[j];
+                                               jobs.splice( j, 1 );
+                                               j -= 1;
+                                               try {
+                                                       if ( hasErrors ) {
+                                                               if ( $.isFunction( job.error ) ) {
+                                                                       job.error( new Error( 'Module ' + module + ' has failed dependencies' ), [module] );
+                                                               }
+                                                       } else {
+                                                               if ( $.isFunction( job.ready ) ) {
+                                                                       job.ready();
+                                                               }
+                                                       }
+                                               } catch ( e ) {
+                                                       // A user-defined callback raised an exception.
+                                                       // Swallow it to protect our state machine!
+                                                       log( 'Exception thrown by job.error', e );
+                                               }
+                                       }
+                               }
+
+                               if ( registry[module].state === 'ready' ) {
+                                       // The current module became 'ready'. Set it in the module store, and recursively execute all
+                                       // dependent modules that are loaded and now have all dependencies satisfied.
+                                       mw.loader.store.set( module, registry[module] );
+                                       for ( m in registry ) {
+                                               if ( registry[m].state === 'loaded' && allReady( registry[m].dependencies ) ) {
+                                                       execute( m );
+                                               }
+                                       }
+                               }
+                       }
+
+                       /**
+                        * Adds a script tag to the DOM, either using document.write or low-level DOM manipulation,
+                        * depending on whether document-ready has occurred yet and whether we are in async mode.
+                        *
+                        * @private
+                        * @param {string} src URL to script, will be used as the src attribute in the script tag
+                        * @param {Function} [callback] Callback which will be run when the script is done
+                        * @param {boolean} [async=false] Whether to load modules asynchronously.
+                        *  Ignored (and defaulted to `true`) if the document-ready event has already occurred.
+                        */
+                       function addScript( src, callback, async ) {
+                               /*jshint evil:true */
+                               var script, head, done;
+
+                               // Using isReady directly instead of storing it locally from
+                               // a $.fn.ready callback (bug 31895).
+                               if ( $.isReady || async ) {
+                                       // Can't use jQuery.getScript because that only uses <script> for cross-domain,
+                                       // it uses XHR and eval for same-domain scripts, which we don't want because it
+                                       // messes up line numbers.
+                                       // The below is based on jQuery ([jquery@1.9.1]/src/ajax/script.js)
+
+                                       // IE-safe way of getting an append target. In old IE document.head isn't supported
+                                       // and its getElementsByTagName can't find <head> until </head> is parsed.
+                                       done = false;
+                                       head = document.head || document.getElementsByTagName( 'head' )[0] || document.documentElement;
+
+                                       script = document.createElement( 'script' );
+                                       script.async = true;
+                                       script.src = src;
+                                       if ( $.isFunction( callback ) ) {
+                                               script.onload = script.onreadystatechange = function () {
+                                                       if (
+                                                               !done
+                                                               && (
+                                                                       !script.readyState
+                                                                       || /loaded|complete/.test( script.readyState )
+                                                               )
+                                                       ) {
+                                                               done = true;
+
+                                                               // Handle memory leak in IE
+                                                               script.onload = script.onreadystatechange = null;
+
+                                                               // Detach the element from the document
+                                                               if ( script.parentNode ) {
+                                                                       script.parentNode.removeChild( script );
+                                                               }
+
+                                                               // Dereference the element from javascript
+                                                               script = undefined;
+
+                                                               callback();
+                                                       }
+                                               };
+                                       }
+
+                                       if ( window.opera ) {
+                                               // Appending to the <head> blocks rendering completely in Opera,
+                                               // so append to the <body> after document ready. This means the
+                                               // scripts only start loading after the document has been rendered,
+                                               // but so be it. Opera users don't deserve faster web pages if their
+                                               // browser makes it impossible.
+                                               $( function () {
+                                                       document.body.appendChild( script );
+                                               } );
+                                       } else {
+                                               // Circumvent IE6 bugs with base elements (jqbug.com/2709, jqbug.com/4378)
+                                               // by prepending instead of appending.
+                                               head.insertBefore( script, head.firstChild );
+                                       }
+                               } else {
+                                       document.write( mw.html.element( 'script', { 'src': src }, '' ) );
+                                       if ( $.isFunction( callback ) ) {
+                                               // Document.write is synchronous, so this is called when it's done
+                                               // FIXME: that's a lie. doc.write isn't actually synchronous
+                                               callback();
+                                       }
+                               }
+                       }
+
+                       /**
+                        * Executes a loaded module, making it ready to use
+                        *
+                        * @private
+                        * @param {string} module Module name to execute
+                        */
+                       function execute( module ) {
+                               var key, value, media, i, urls, cssHandle, checkCssHandles,
+                                       cssHandlesRegistered = false;
+
+                               if ( registry[module] === undefined ) {
+                                       throw new Error( 'Module has not been registered yet: ' + module );
+                               } else if ( registry[module].state === 'registered' ) {
+                                       throw new Error( 'Module has not been requested from the server yet: ' + module );
+                               } else if ( registry[module].state === 'loading' ) {
+                                       throw new Error( 'Module has not completed loading yet: ' + module );
+                               } else if ( registry[module].state === 'ready' ) {
+                                       throw new Error( 'Module has already been executed: ' + module );
+                               }
+
+                               /**
+                                * Define loop-function here for efficiency
+                                * and to avoid re-using badly scoped variables.
+                                * @ignore
+                                */
+                               function addLink( media, url ) {
+                                       var el = document.createElement( 'link' );
+                                       // For IE: Insert in document *before* setting href
+                                       getMarker().before( el );
+                                       el.rel = 'stylesheet';
+                                       if ( media && media !== 'all' ) {
+                                               el.media = media;
+                                       }
+                                       // If you end up here from an IE exception "SCRIPT: Invalid property value.",
+                                       // see #addEmbeddedCSS, bug 31676, and bug 47277 for details.
+                                       el.href = url;
+                               }
+
+                               function runScript() {
+                                       var script, markModuleReady, nestedAddScript;
+                                       try {
+                                               script = registry[module].script;
+                                               markModuleReady = function () {
+                                                       registry[module].state = 'ready';
+                                                       handlePending( module );
+                                               };
+                                               nestedAddScript = function ( arr, callback, async, i ) {
+                                                       // Recursively call addScript() in its own callback
+                                                       // for each element of arr.
+                                                       if ( i >= arr.length ) {
+                                                               // We're at the end of the array
+                                                               callback();
+                                                               return;
+                                                       }
+
+                                                       addScript( arr[i], function () {
+                                                               nestedAddScript( arr, callback, async, i + 1 );
+                                                       }, async );
+                                               };
+
+                                               if ( $.isArray( script ) ) {
+                                                       nestedAddScript( script, markModuleReady, registry[module].async, 0 );
+                                               } else if ( $.isFunction( script ) ) {
+                                                       registry[module].state = 'ready';
+                                                       // Pass jQuery twice so that the signature of the closure which wraps
+                                                       // the script can bind both '$' and 'jQuery'.
+                                                       script( $, $ );
+                                                       handlePending( module );
+                                               }
+                                       } catch ( e ) {
+                                               // This needs to NOT use mw.log because these errors are common in production mode
+                                               // and not in debug mode, such as when a symbol that should be global isn't exported
+                                               log( 'Exception thrown by ' + module, e );
+                                               registry[module].state = 'error';
+                                               handlePending( module );
+                                       }
+                               }
+
+                               // This used to be inside runScript, but since that is now fired asychronously
+                               // (after CSS is loaded) we need to set it here right away. It is crucial that
+                               // when execute() is called this is set synchronously, otherwise modules will get
+                               // executed multiple times as the registry will state that it isn't loading yet.
+                               registry[module].state = 'loading';
+
+                               // Add localizations to message system
+                               if ( $.isPlainObject( registry[module].messages ) ) {
+                                       mw.messages.set( registry[module].messages );
+                               }
+
+                               if ( $.isReady || registry[module].async ) {
+                                       // Make sure we don't run the scripts until all (potentially asynchronous)
+                                       // stylesheet insertions have completed.
+                                       ( function () {
+                                               var pending = 0;
+                                               checkCssHandles = function () {
+                                                       // cssHandlesRegistered ensures we don't take off too soon, e.g. when
+                                                       // one of the cssHandles is fired while we're still creating more handles.
+                                                       if ( cssHandlesRegistered && pending === 0 && runScript ) {
+                                                               runScript();
+                                                               runScript = undefined; // Revoke
+                                                       }
+                                               };
+                                               cssHandle = function () {
+                                                       var check = checkCssHandles;
+                                                       pending++;
+                                                       return function () {
+                                                               if (check) {
+                                                                       pending--;
+                                                                       check();
+                                                                       check = undefined; // Revoke
+                                                               }
+                                                       };
+                                               };
+                                       }() );
+                               } else {
+                                       // We are in blocking mode, and so we can't afford to wait for CSS
+                                       cssHandle = function () {};
+                                       // Run immediately
+                                       checkCssHandles = runScript;
+                               }
+
+                               // Process styles (see also mw.loader.implement)
+                               // * back-compat: { <media>: css }
+                               // * back-compat: { <media>: [url, ..] }
+                               // * { "css": [css, ..] }
+                               // * { "url": { <media>: [url, ..] } }
+                               if ( $.isPlainObject( registry[module].style ) ) {
+                                       for ( key in registry[module].style ) {
+                                               value = registry[module].style[key];
+                                               media = undefined;
+
+                                               if ( key !== 'url' && key !== 'css' ) {
+                                                       // Backwards compatibility, key is a media-type
+                                                       if ( typeof value === 'string' ) {
+                                                               // back-compat: { <media>: css }
+                                                               // Ignore 'media' because it isn't supported (nor was it used).
+                                                               // Strings are pre-wrapped in "@media". The media-type was just ""
+                                                               // (because it had to be set to something).
+                                                               // This is one of the reasons why this format is no longer used.
+                                                               addEmbeddedCSS( value, cssHandle() );
+                                                       } else {
+                                                               // back-compat: { <media>: [url, ..] }
+                                                               media = key;
+                                                               key = 'bc-url';
+                                                       }
+                                               }
+
+                                               // Array of css strings in key 'css',
+                                               // or back-compat array of urls from media-type
+                                               if ( $.isArray( value ) ) {
+                                                       for ( i = 0; i < value.length; i += 1 ) {
+                                                               if ( key === 'bc-url' ) {
+                                                                       // back-compat: { <media>: [url, ..] }
+                                                                       addLink( media, value[i] );
+                                                               } else if ( key === 'css' ) {
+                                                                       // { "css": [css, ..] }
+                                                                       addEmbeddedCSS( value[i], cssHandle() );
+                                                               }
+                                                       }
+                                               // Not an array, but a regular object
+                                               // Array of urls inside media-type key
+                                               } else if ( typeof value === 'object' ) {
+                                                       // { "url": { <media>: [url, ..] } }
+                                                       for ( media in value ) {
+                                                               urls = value[media];
+                                                               for ( i = 0; i < urls.length; i += 1 ) {
+                                                                       addLink( media, urls[i] );
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               // Kick off.
+                               cssHandlesRegistered = true;
+                               checkCssHandles();
+                       }
+
+                       /**
+                        * Adds a dependencies to the queue with optional callbacks to be run
+                        * when the dependencies are ready or fail
+                        *
+                        * @private
+                        * @param {string|string[]} dependencies Module name or array of string module names
+                        * @param {Function} [ready] Callback to execute when all dependencies are ready
+                        * @param {Function} [error] Callback to execute when any dependency fails
+                        * @param {boolean} [async=false] Whether to load modules asynchronously.
+                        *  Ignored (and defaulted to `true`) if the document-ready event has already occurred.
+                        */
+                       function request( dependencies, ready, error, async ) {
+                               var n;
+
+                               // Allow calling by single module name
+                               if ( typeof dependencies === 'string' ) {
+                                       dependencies = [dependencies];
+                               }
+
+                               // Add ready and error callbacks if they were given
+                               if ( ready !== undefined || error !== undefined ) {
+                                       jobs[jobs.length] = {
+                                               'dependencies': filter(
+                                                       ['registered', 'loading', 'loaded'],
+                                                       dependencies
+                                               ),
+                                               'ready': ready,
+                                               'error': error
+                                       };
+                               }
+
+                               // Queue up any dependencies that are registered
+                               dependencies = filter( ['registered'], dependencies );
+                               for ( n = 0; n < dependencies.length; n += 1 ) {
+                                       if ( $.inArray( dependencies[n], queue ) === -1 ) {
+                                               queue[queue.length] = dependencies[n];
+                                               if ( async ) {
+                                                       // Mark this module as async in the registry
+                                                       registry[dependencies[n]].async = true;
+                                               }
+                                       }
+                               }
+
+                               // Work the queue
+                               mw.loader.work();
+                       }
+
+                       function sortQuery( o ) {
+                               var sorted = {}, key, a = [];
+                               for ( key in o ) {
+                                       if ( hasOwn.call( o, key ) ) {
+                                               a.push( key );
+                                       }
+                               }
+                               a.sort();
+                               for ( key = 0; key < a.length; key += 1 ) {
+                                       sorted[a[key]] = o[a[key]];
+                               }
+                               return sorted;
+                       }
+
+                       /**
+                        * Converts a module map of the form { foo: [ 'bar', 'baz' ], bar: [ 'baz, 'quux' ] }
+                        * to a query string of the form foo.bar,baz|bar.baz,quux
+                        * @private
+                        */
+                       function buildModulesString( moduleMap ) {
+                               var arr = [], p, prefix;
+                               for ( prefix in moduleMap ) {
+                                       p = prefix === '' ? '' : prefix + '.';
+                                       arr.push( p + moduleMap[prefix].join( ',' ) );
+                               }
+                               return arr.join( '|' );
+                       }
+
+                       /**
+                        * Asynchronously append a script tag to the end of the body
+                        * that invokes load.php
+                        * @private
+                        * @param {Object} moduleMap Module map, see #buildModulesString
+                        * @param {Object} currReqBase Object with other parameters (other than 'modules') to use in the request
+                        * @param {string} sourceLoadScript URL of load.php
+                        * @param {boolean} async Whether to load modules asynchronously.
+                        *  Ignored (and defaulted to `true`) if the document-ready event has already occurred.
+                        */
+                       function doRequest( moduleMap, currReqBase, sourceLoadScript, async ) {
+                               var request = $.extend(
+                                       { modules: buildModulesString( moduleMap ) },
+                                       currReqBase
+                               );
+                               request = sortQuery( request );
+                               // Append &* to avoid triggering the IE6 extension check
+                               addScript( sourceLoadScript + '?' + $.param( request ) + '&*', null, async );
+                       }
+
+                       /* Public Members */
+                       return {
+                               /**
+                                * The module registry is exposed as an aid for debugging and inspecting page
+                                * state; it is not a public interface for modifying the registry.
+                                *
+                                * @see #registry
+                                * @property
+                                * @private
+                                */
+                               moduleRegistry: registry,
+
+                               /**
+                                * @inheritdoc #newStyleTag
+                                * @method
+                                */
+                               addStyleTag: newStyleTag,
+
+                               /**
+                                * Batch-request queued dependencies from the server.
+                                */
+                               work: function () {
+                                       var     reqBase, splits, maxQueryLength, q, b, bSource, bGroup, bSourceGroup,
+                                               source, concatSource, origBatch, group, g, i, modules, maxVersion, sourceLoadScript,
+                                               currReqBase, currReqBaseLength, moduleMap, l,
+                                               lastDotIndex, prefix, suffix, bytesAdded, async;
+
+                                       // Build a list of request parameters common to all requests.
+                                       reqBase = {
+                                               skin: mw.config.get( 'skin' ),
+                                               lang: mw.config.get( 'wgUserLanguage' ),
+                                               debug: mw.config.get( 'debug' )
+                                       };
+                                       // Split module batch by source and by group.
+                                       splits = {};
+                                       maxQueryLength = mw.config.get( 'wgResourceLoaderMaxQueryLength', -1 );
+
+                                       // Appends a list of modules from the queue to the batch
+                                       for ( q = 0; q < queue.length; q += 1 ) {
+                                               // Only request modules which are registered
+                                               if ( registry[queue[q]] !== undefined && registry[queue[q]].state === 'registered' ) {
+                                                       // Prevent duplicate entries
+                                                       if ( $.inArray( queue[q], batch ) === -1 ) {
+                                                               batch[batch.length] = queue[q];
+                                                               // Mark registered modules as loading
+                                                               registry[queue[q]].state = 'loading';
+                                                       }
+                                               }
+                                       }
+
+                                       mw.loader.store.init();
+                                       if ( mw.loader.store.enabled ) {
+                                               concatSource = [];
+                                               origBatch = batch;
+                                               batch = $.grep( batch, function ( module ) {
+                                                       var source = mw.loader.store.get( module );
+                                                       if ( source ) {
+                                                               concatSource.push( source );
+                                                               return false;
+                                                       }
+                                                       return true;
+                                               } );
+                                               try {
+                                                       $.globalEval( concatSource.join( ';' ) );
+                                               } catch ( err ) {
+                                                       // Not good, the cached mw.loader.implement calls failed! This should
+                                                       // never happen, barring ResourceLoader bugs, browser bugs and PEBKACs.
+                                                       // Depending on how corrupt the string is, it is likely that some
+                                                       // modules' implement() succeeded while the ones after the error will
+                                                       // never run and leave their modules in the 'loading' state forever.
+
+                                                       // Since this is an error not caused by an individual module but by
+                                                       // something that infected the implement call itself, don't take any
+                                                       // risks and clear everything in this cache.
+                                                       mw.loader.store.clear();
+                                                       // Re-add the ones still pending back to the batch and let the server
+                                                       // repopulate these modules to the cache.
+                                                       // This means that at most one module will be useless (the one that had
+                                                       // the error) instead of all of them.
+                                                       log( 'Error while evaluating data from mw.loader.store', err );
+                                                       origBatch = $.grep( origBatch, function ( module ) {
+                                                               return registry[module].state === 'loading';
+                                                       } );
+                                                       batch = batch.concat( origBatch );
+                                               }
+                                       }
+
+                                       // Early exit if there's nothing to load...
+                                       if ( !batch.length ) {
+                                               return;
+                                       }
+
+                                       // The queue has been processed into the batch, clear up the queue.
+                                       queue = [];
+
+                                       // Always order modules alphabetically to help reduce cache
+                                       // misses for otherwise identical content.
+                                       batch.sort();
+
+                                       // Split batch by source and by group.
+                                       for ( b = 0; b < batch.length; b += 1 ) {
+                                               bSource = registry[batch[b]].source;
+                                               bGroup = registry[batch[b]].group;
+                                               if ( splits[bSource] === undefined ) {
+                                                       splits[bSource] = {};
+                                               }
+                                               if ( splits[bSource][bGroup] === undefined ) {
+                                                       splits[bSource][bGroup] = [];
+                                               }
+                                               bSourceGroup = splits[bSource][bGroup];
+                                               bSourceGroup[bSourceGroup.length] = batch[b];
+                                       }
+
+                                       // Clear the batch - this MUST happen before we append any
+                                       // script elements to the body or it's possible that a script
+                                       // will be locally cached, instantly load, and work the batch
+                                       // again, all before we've cleared it causing each request to
+                                       // include modules which are already loaded.
+                                       batch = [];
+
+                                       for ( source in splits ) {
+
+                                               sourceLoadScript = sources[source].loadScript;
+
+                                               for ( group in splits[source] ) {
+
+                                                       // Cache access to currently selected list of
+                                                       // modules for this group from this source.
+                                                       modules = splits[source][group];
+
+                                                       // Calculate the highest timestamp
+                                                       maxVersion = 0;
+                                                       for ( g = 0; g < modules.length; g += 1 ) {
+                                                               if ( registry[modules[g]].version > maxVersion ) {
+                                                                       maxVersion = registry[modules[g]].version;
+                                                               }
+                                                       }
+
+                                                       currReqBase = $.extend( { version: formatVersionNumber( maxVersion ) }, reqBase );
+                                                       // For user modules append a user name to the request.
+                                                       if ( group === 'user' && mw.config.get( 'wgUserName' ) !== null ) {
+                                                               currReqBase.user = mw.config.get( 'wgUserName' );
+                                                       }
+                                                       currReqBaseLength = $.param( currReqBase ).length;
+                                                       async = true;
+                                                       // We may need to split up the request to honor the query string length limit,
+                                                       // so build it piece by piece.
+                                                       l = currReqBaseLength + 9; // '&modules='.length == 9
+
+                                                       moduleMap = {}; // { prefix: [ suffixes ] }
+
+                                                       for ( i = 0; i < modules.length; i += 1 ) {
+                                                               // Determine how many bytes this module would add to the query string
+                                                               lastDotIndex = modules[i].lastIndexOf( '.' );
+                                                               // Note that these substr() calls work even if lastDotIndex == -1
+                                                               prefix = modules[i].substr( 0, lastDotIndex );
+                                                               suffix = modules[i].substr( lastDotIndex + 1 );
+                                                               bytesAdded = moduleMap[prefix] !== undefined
+                                                                       ? suffix.length + 3 // '%2C'.length == 3
+                                                                       : modules[i].length + 3; // '%7C'.length == 3
+
+                                                               // If the request would become too long, create a new one,
+                                                               // but don't create empty requests
+                                                               if ( maxQueryLength > 0 && !$.isEmptyObject( moduleMap ) && l + bytesAdded > maxQueryLength ) {
+                                                                       // This request would become too long, create a new one
+                                                                       // and fire off the old one
+                                                                       doRequest( moduleMap, currReqBase, sourceLoadScript, async );
+                                                                       moduleMap = {};
+                                                                       async = true;
+                                                                       l = currReqBaseLength + 9;
+                                                               }
+                                                               if ( moduleMap[prefix] === undefined ) {
+                                                                       moduleMap[prefix] = [];
+                                                               }
+                                                               moduleMap[prefix].push( suffix );
+                                                               if ( !registry[modules[i]].async ) {
+                                                                       // If this module is blocking, make the entire request blocking
+                                                                       // This is slightly suboptimal, but in practice mixing of blocking
+                                                                       // and async modules will only occur in debug mode.
+                                                                       async = false;
+                                                               }
+                                                               l += bytesAdded;
+                                                       }
+                                                       // If there's anything left in moduleMap, request that too
+                                                       if ( !$.isEmptyObject( moduleMap ) ) {
+                                                               doRequest( moduleMap, currReqBase, sourceLoadScript, async );
+                                                       }
+                                               }
+                                       }
+                               },
+
+                               /**
+                                * Register a source.
+                                *
+                                * The #work method will use this information to split up requests by source.
+                                *
+                                *     mw.loader.addSource( 'mediawikiwiki', { loadScript: '//www.mediawiki.org/w/load.php' } );
+                                *
+                                * @param {string} id Short string representing a source wiki, used internally for
+                                *  registered modules to indicate where they should be loaded from (usually lowercase a-z).
+                                * @param {Object} props
+                                * @param {string} props.loadScript Url to the load.php entry point of the source wiki.
+                                * @return {boolean}
+                                */
+                               addSource: function ( id, props ) {
+                                       var source;
+                                       // Allow multiple additions
+                                       if ( typeof id === 'object' ) {
+                                               for ( source in id ) {
+                                                       mw.loader.addSource( source, id[source] );
+                                               }
+                                               return true;
+                                       }
+
+                                       if ( sources[id] !== undefined ) {
+                                               throw new Error( 'source already registered: ' + id );
+                                       }
+
+                                       sources[id] = props;
+
+                                       return true;
+                               },
+
+                               /**
+                                * Register a module, letting the system know about it and its
+                                * properties. Startup modules contain calls to this function.
+                                *
+                                * @param {string} module Module name
+                                * @param {number} version Module version number as a timestamp (falls backs to 0)
+                                * @param {string|Array|Function} dependencies One string or array of strings of module
+                                *  names on which this module depends, or a function that returns that array.
+                                * @param {string} [group=null] Group which the module is in
+                                * @param {string} [source='local'] Name of the source
+                                */
+                               register: function ( module, version, dependencies, group, source ) {
+                                       var m;
+                                       // Allow multiple registration
+                                       if ( typeof module === 'object' ) {
+                                               for ( m = 0; m < module.length; m += 1 ) {
+                                                       // module is an array of module names
+                                                       if ( typeof module[m] === 'string' ) {
+                                                               mw.loader.register( module[m] );
+                                                       // module is an array of arrays
+                                                       } else if ( typeof module[m] === 'object' ) {
+                                                               mw.loader.register.apply( mw.loader, module[m] );
+                                                       }
+                                               }
+                                               return;
+                                       }
+                                       // Validate input
+                                       if ( typeof module !== 'string' ) {
+                                               throw new Error( 'module must be a string, not a ' + typeof module );
+                                       }
+                                       if ( registry[module] !== undefined ) {
+                                               throw new Error( 'module already registered: ' + module );
+                                       }
+                                       // List the module as registered
+                                       registry[module] = {
+                                               version: version !== undefined ? parseInt( version, 10 ) : 0,
+                                               dependencies: [],
+                                               group: typeof group === 'string' ? group : null,
+                                               source: typeof source === 'string' ? source: 'local',
+                                               state: 'registered'
+                                       };
+                                       if ( typeof dependencies === 'string' ) {
+                                               // Allow dependencies to be given as a single module name
+                                               registry[module].dependencies = [ dependencies ];
+                                       } else if ( typeof dependencies === 'object' || $.isFunction( dependencies ) ) {
+                                               // Allow dependencies to be given as an array of module names
+                                               // or a function which returns an array
+                                               registry[module].dependencies = dependencies;
+                                       }
+                               },
+
+                               /**
+                                * Implement a module given the components that make up the module.
+                                *
+                                * When #load or #using requests one or more modules, the server
+                                * response contain calls to this function.
+                                *
+                                * All arguments are required.
+                                *
+                                * @param {string} module Name of module
+                                * @param {Function|Array} script Function with module code or Array of URLs to
+                                *  be used as the src attribute of a new `<script>` tag.
+                                * @param {Object} style Should follow one of the following patterns:
+                                *
+                                *     { "css": [css, ..] }
+                                *     { "url": { <media>: [url, ..] } }
+                                *
+                                * And for backwards compatibility (needs to be supported forever due to caching):
+                                *
+                                *     { <media>: css }
+                                *     { <media>: [url, ..] }
+                                *
+                                * The reason css strings are not concatenated anymore is bug 31676. We now check
+                                * whether it's safe to extend the stylesheet (see #canExpandStylesheetWith).
+                                *
+                                * @param {Object} msgs List of key/value pairs to be added to mw#messages.
+                                */
+                               implement: function ( module, script, style, msgs ) {
+                                       // Validate input
+                                       if ( typeof module !== 'string' ) {
+                                               throw new Error( 'module must be a string, not a ' + typeof module );
+                                       }
+                                       if ( !$.isFunction( script ) && !$.isArray( script ) ) {
+                                               throw new Error( 'script must be a function or an array, not a ' + typeof script );
+                                       }
+                                       if ( !$.isPlainObject( style ) ) {
+                                               throw new Error( 'style must be an object, not a ' + typeof style );
+                                       }
+                                       if ( !$.isPlainObject( msgs ) ) {
+                                               throw new Error( 'msgs must be an object, not a ' + typeof msgs );
+                                       }
+                                       // Automatically register module
+                                       if ( registry[module] === undefined ) {
+                                               mw.loader.register( module );
+                                       }
+                                       // Check for duplicate implementation
+                                       if ( registry[module] !== undefined && registry[module].script !== undefined ) {
+                                               throw new Error( 'module already implemented: ' + module );
+                                       }
+                                       // Attach components
+                                       registry[module].script = script;
+                                       registry[module].style = style;
+                                       registry[module].messages = msgs;
+                                       // The module may already have been marked as erroneous
+                                       if ( $.inArray( registry[module].state, ['error', 'missing'] ) === -1 ) {
+                                               registry[module].state = 'loaded';
+                                               if ( allReady( registry[module].dependencies ) ) {
+                                                       execute( module );
+                                               }
+                                       }
+                               },
+
+                               /**
+                                * Execute a function as soon as one or more required modules are ready.
+                                *
+                                * Example of inline dependency on OOjs:
+                                *
+                                *     mw.loader.using( 'oojs', function () {
+                                *         OO.compare( [ 1 ], [ 1 ] );
+                                *     } );
+                                *
+                                * @param {string|Array} dependencies Module name or array of modules names the callback
+                                *  dependends on to be ready before executing
+                                * @param {Function} [ready] Callback to execute when all dependencies are ready
+                                * @param {Function} [error] Callback to execute if one or more dependencies failed
+                                * @return {jQuery.Promise}
+                                */
+                               using: function ( dependencies, ready, error ) {
+                                       var deferred = $.Deferred();
+
+                                       // Allow calling with a single dependency as a string
+                                       if ( typeof dependencies === 'string' ) {
+                                               dependencies = [ dependencies ];
+                                       } else if ( !$.isArray( dependencies ) ) {
+                                               // Invalid input
+                                               throw new Error( 'Dependencies must be a string or an array' );
+                                       }
+
+                                       if ( ready ) {
+                                               deferred.done( ready );
+                                       }
+                                       if ( error ) {
+                                               deferred.fail( error );
+                                       }
+
+                                       // Resolve entire dependency map
+                                       dependencies = resolve( dependencies );
+                                       if ( allReady( dependencies ) ) {
+                                               // Run ready immediately
+                                               deferred.resolve();
+                                       } else if ( filter( ['error', 'missing'], dependencies ).length ) {
+                                               // Execute error immediately if any dependencies have errors
+                                               deferred.reject(
+                                                       new Error( 'One or more dependencies failed to load' ),
+                                                       dependencies
+                                               );
+                                       } else {
+                                               // Not all dependencies are ready: queue up a request
+                                               request( dependencies, deferred.resolve, deferred.reject );
+                                       }
+
+                                       return deferred.promise();
+                               },
+
+                               /**
+                                * Load an external script or one or more modules.
+                                *
+                                * @param {string|Array} modules Either the name of a module, array of modules,
+                                *  or a URL of an external script or style
+                                * @param {string} [type='text/javascript'] mime-type to use if calling with a URL of an
+                                *  external script or style; acceptable values are "text/css" and
+                                *  "text/javascript"; if no type is provided, text/javascript is assumed.
+                                * @param {boolean} [async] Whether to load modules asynchronously.
+                                *  Ignored (and defaulted to `true`) if the document-ready event has already occurred.
+                                *  Defaults to `true` if loading a URL, `false` otherwise.
+                                */
+                               load: function ( modules, type, async ) {
+                                       var filtered, m, module, l;
+
+                                       // Validate input
+                                       if ( typeof modules !== 'object' && typeof modules !== 'string' ) {
+                                               throw new Error( 'modules must be a string or an array, not a ' + typeof modules );
+                                       }
+                                       // Allow calling with an external url or single dependency as a string
+                                       if ( typeof modules === 'string' ) {
+                                               // Support adding arbitrary external scripts
+                                               if ( /^(https?:)?\/\//.test( modules ) ) {
+                                                       if ( async === undefined ) {
+                                                               // Assume async for bug 34542
+                                                               async = true;
+                                                       }
+                                                       if ( type === 'text/css' ) {
+                                                               // IE7-8 throws security warnings when inserting a <link> tag
+                                                               // with a protocol-relative URL set though attributes (instead of
+                                                               // properties) - when on HTTPS. See also bug 41331.
+                                                               l = document.createElement( 'link' );
+                                                               l.rel = 'stylesheet';
+                                                               l.href = modules;
+                                                               $( 'head' ).append( l );
+                                                               return;
+                                                       }
+                                                       if ( type === 'text/javascript' || type === undefined ) {
+                                                               addScript( modules, null, async );
+                                                               return;
+                                                       }
+                                                       // Unknown type
+                                                       throw new Error( 'invalid type for external url, must be text/css or text/javascript. not ' + type );
+                                               }
+                                               // Called with single module
+                                               modules = [ modules ];
+                                       }
+
+                                       // Filter out undefined modules, otherwise resolve() will throw
+                                       // an exception for trying to load an undefined module.
+                                       // Undefined modules are acceptable here in load(), because load() takes
+                                       // an array of unrelated modules, whereas the modules passed to
+                                       // using() are related and must all be loaded.
+                                       for ( filtered = [], m = 0; m < modules.length; m += 1 ) {
+                                               module = registry[modules[m]];
+                                               if ( module !== undefined ) {
+                                                       if ( $.inArray( module.state, ['error', 'missing'] ) === -1 ) {
+                                                               filtered[filtered.length] = modules[m];
+                                                       }
+                                               }
+                                       }
+
+                                       if ( filtered.length === 0 ) {
+                                               return;
+                                       }
+                                       // Resolve entire dependency map
+                                       filtered = resolve( filtered );
+                                       // If all modules are ready, nothing to be done
+                                       if ( allReady( filtered ) ) {
+                                               return;
+                                       }
+                                       // If any modules have errors: also quit.
+                                       if ( filter( ['error', 'missing'], filtered ).length ) {
+                                               return;
+                                       }
+                                       // Since some modules are not yet ready, queue up a request.
+                                       request( filtered, undefined, undefined, async );
+                               },
+
+                               /**
+                                * Change the state of one or more modules.
+                                *
+                                * @param {string|Object} module Module name or object of module name/state pairs
+                                * @param {string} state State name
+                                */
+                               state: function ( module, state ) {
+                                       var m;
+
+                                       if ( typeof module === 'object' ) {
+                                               for ( m in module ) {
+                                                       mw.loader.state( m, module[m] );
+                                               }
+                                               return;
+                                       }
+                                       if ( registry[module] === undefined ) {
+                                               mw.loader.register( module );
+                                       }
+                                       if ( $.inArray( state, ['ready', 'error', 'missing'] ) !== -1
+                                               && registry[module].state !== state ) {
+                                               // Make sure pending modules depending on this one get executed if their
+                                               // dependencies are now fulfilled!
+                                               registry[module].state = state;
+                                               handlePending( module );
+                                       } else {
+                                               registry[module].state = state;
+                                       }
+                               },
+
+                               /**
+                                * Get the version of a module.
+                                *
+                                * @param {string} module Name of module to get version for
+                                * @return {string|null} The version, or null if the module (or its version) is not
+                                *  in the registry.
+                                */
+                               getVersion: function ( module ) {
+                                       if ( registry[module] !== undefined && registry[module].version !== undefined ) {
+                                               return formatVersionNumber( registry[module].version );
+                                       }
+                                       return null;
+                               },
+
+                               /**
+                                * Get the state of a module.
+                                *
+                                * @param {string} module Name of module to get state for
+                                */
+                               getState: function ( module ) {
+                                       if ( registry[module] !== undefined && registry[module].state !== undefined ) {
+                                               return registry[module].state;
+                                       }
+                                       return null;
+                               },
+
+                               /**
+                                * Get the names of all registered modules.
+                                *
+                                * @return {Array}
+                                */
+                               getModuleNames: function () {
+                                       return $.map( registry, function ( i, key ) {
+                                               return key;
+                                       } );
+                               },
+
+                               /**
+                                * @inheritdoc mw.inspect#runReports
+                                * @method
+                                */
+                               inspect: function () {
+                                       var args = slice.call( arguments );
+                                       mw.loader.using( 'mediawiki.inspect', function () {
+                                               mw.inspect.runReports.apply( mw.inspect, args );
+                                       } );
+                               },
+
+                               /**
+                                * On browsers that implement the localStorage API, the module store serves as a
+                                * smart complement to the browser cache. Unlike the browser cache, the module store
+                                * can slice a concatenated response from ResourceLoader into its constituent
+                                * modules and cache each of them separately, using each module's versioning scheme
+                                * to determine when the cache should be invalidated.
+                                *
+                                * @singleton
+                                * @class mw.loader.store
+                                */
+                               store: {
+                                       // Whether the store is in use on this page.
+                                       enabled: null,
+
+                                       // The contents of the store, mapping '[module name]@[version]' keys
+                                       // to module implementations.
+                                       items: {},
+
+                                       // Cache hit stats
+                                       stats: { hits: 0, misses: 0, expired: 0 },
+
+                                       /**
+                                        * Construct a JSON-serializable object representing the content of the store.
+                                        * @return {Object} Module store contents.
+                                        */
+                                       toJSON: function () {
+                                               return { items: mw.loader.store.items, vary: mw.loader.store.getVary() };
+                                       },
+
+                                       /**
+                                        * Get the localStorage key for the entire module store. The key references
+                                        * $wgDBname to prevent clashes between wikis which share a common host.
+                                        *
+                                        * @return {string} localStorage item key
+                                        */
+                                       getStoreKey: function () {
+                                               return 'MediaWikiModuleStore:' + mw.config.get( 'wgDBname' );
+                                       },
+
+                                       /**
+                                        * Get a string key on which to vary the module cache.
+                                        * @return {string} String of concatenated vary conditions.
+                                        */
+                                       getVary: function () {
+                                               return [
+                                                       mw.config.get( 'skin' ),
+                                                       mw.config.get( 'wgResourceLoaderStorageVersion' ),
+                                                       mw.config.get( 'wgUserLanguage' )
+                                               ].join( ':' );
+                                       },
+
+                                       /**
+                                        * Get a string key for a specific module. The key format is '[name]@[version]'.
+                                        *
+                                        * @param {string} module Module name
+                                        * @return {string|null} Module key or null if module does not exist
+                                        */
+                                       getModuleKey: function ( module ) {
+                                               return typeof registry[module] === 'object' ?
+                                                       ( module + '@' + registry[module].version ) : null;
+                                       },
+
+                                       /**
+                                        * Initialize the store.
+                                        *
+                                        * Retrieves store from localStorage and (if successfully retrieved) decoding
+                                        * the stored JSON value to a plain object.
+                                        *
+                                        * The try / catch block is used for JSON & localStorage feature detection.
+                                        * See the in-line documentation for Modernizr's localStorage feature detection
+                                        * code for a full account of why we need a try / catch:
+                                        * <https://github.com/Modernizr/Modernizr/blob/v2.7.1/modernizr.js#L771-L796>.
+                                        */
+                                       init: function () {
+                                               var raw, data;
+
+                                               if ( mw.loader.store.enabled !== null ) {
+                                                       // Init already ran
+                                                       return;
+                                               }
+
+                                               if ( !mw.config.get( 'wgResourceLoaderStorageEnabled' ) || mw.config.get( 'debug' ) ) {
+                                                       // Disabled by configuration, or because debug mode is set
+                                                       mw.loader.store.enabled = false;
+                                                       return;
+                                               }
+
+                                               try {
+                                                       raw = localStorage.getItem( mw.loader.store.getStoreKey() );
+                                                       // If we get here, localStorage is available; mark enabled
+                                                       mw.loader.store.enabled = true;
+                                                       data = JSON.parse( raw );
+                                                       if ( data && typeof data.items === 'object' && data.vary === mw.loader.store.getVary() ) {
+                                                               mw.loader.store.items = data.items;
+                                                               return;
+                                                       }
+                                               } catch ( e ) {}
+
+                                               if ( raw === undefined ) {
+                                                       // localStorage failed; disable store
+                                                       mw.loader.store.enabled = false;
+                                               } else {
+                                                       mw.loader.store.update();
+                                               }
+                                       },
+
+                                       /**
+                                        * Retrieve a module from the store and update cache hit stats.
+                                        *
+                                        * @param {string} module Module name
+                                        * @return {string|boolean} Module implementation or false if unavailable
+                                        */
+                                       get: function ( module ) {
+                                               var key;
+
+                                               if ( !mw.loader.store.enabled ) {
+                                                       return false;
+                                               }
+
+                                               key = mw.loader.store.getModuleKey( module );
+                                               if ( key in mw.loader.store.items ) {
+                                                       mw.loader.store.stats.hits++;
+                                                       return mw.loader.store.items[key];
+                                               }
+                                               mw.loader.store.stats.misses++;
+                                               return false;
+                                       },
+
+                                       /**
+                                        * Stringify a module and queue it for storage.
+                                        *
+                                        * @param {string} module Module name
+                                        * @param {Object} descriptor The module's descriptor as set in the registry
+                                        */
+                                       set: function ( module, descriptor ) {
+                                               var args, key;
+
+                                               if ( !mw.loader.store.enabled ) {
+                                                       return false;
+                                               }
+
+                                               key = mw.loader.store.getModuleKey( module );
+
+                                               if (
+                                                       // Already stored a copy of this exact version
+                                                       key in mw.loader.store.items ||
+                                                       // Module failed to load
+                                                       descriptor.state !== 'ready' ||
+                                                       // Unversioned, private, or site-/user-specific
+                                                       ( !descriptor.version || $.inArray( descriptor.group, [ 'private', 'user', 'site' ] ) !== -1 ) ||
+                                                       // Partial descriptor
+                                                       $.inArray( undefined, [ descriptor.script, descriptor.style, descriptor.messages ] ) !== -1
+                                               ) {
+                                                       // Decline to store
+                                                       return false;
+                                               }
+
+                                               try {
+                                                       args = [
+                                                               JSON.stringify( module ),
+                                                               typeof descriptor.script === 'function' ?
+                                                                       String( descriptor.script ) :
+                                                                       JSON.stringify( descriptor.script ),
+                                                               JSON.stringify( descriptor.style ),
+                                                               JSON.stringify( descriptor.messages )
+                                                       ];
+                                                       // Attempted workaround for a possible Opera bug (bug 57567).
+                                                       // This regex should never match under sane conditions.
+                                                       if ( /^\s*\(/.test( args[1] ) ) {
+                                                               args[1] = 'function' + args[1];
+                                                               log( 'Detected malformed function stringification (bug 57567)' );
+                                                       }
+                                               } catch ( e ) {
+                                                       return;
+                                               }
+
+                                               mw.loader.store.items[key] = 'mw.loader.implement(' + args.join( ',' ) + ');';
+                                               mw.loader.store.update();
+                                       },
+
+                                       /**
+                                        * Iterate through the module store, removing any item that does not correspond
+                                        * (in name and version) to an item in the module registry.
+                                        */
+                                       prune: function () {
+                                               var key, module;
+
+                                               if ( !mw.loader.store.enabled ) {
+                                                       return false;
+                                               }
+
+                                               for ( key in mw.loader.store.items ) {
+                                                       module = key.substring( 0, key.indexOf( '@' ) );
+                                                       if ( mw.loader.store.getModuleKey( module ) !== key ) {
+                                                               mw.loader.store.stats.expired++;
+                                                               delete mw.loader.store.items[key];
+                                                       }
+                                               }
+                                       },
+
+                                       /**
+                                        * Clear the entire module store right now.
+                                        */
+                                       clear: function () {
+                                               mw.loader.store.items = {};
+                                               localStorage.removeItem( mw.loader.store.getStoreKey() );
+                                       },
+
+                                       /**
+                                        * Sync modules to localStorage.
+                                        *
+                                        * This function debounces localStorage updates. When called multiple times in
+                                        * quick succession, the calls are coalesced into a single update operation.
+                                        * This allows us to call #update without having to consider the module load
+                                        * queue; the call to localStorage.setItem will be naturally deferred until the
+                                        * page is quiescent.
+                                        *
+                                        * Because localStorage is shared by all pages with the same origin, if multiple
+                                        * pages are loaded with different module sets, the possibility exists that
+                                        * modules saved by one page will be clobbered by another. But the impact would
+                                        * be minor and the problem would be corrected by subsequent page views.
+                                        *
+                                        * @method
+                                        */
+                                       update: ( function () {
+                                               var timer;
+
+                                               function flush() {
+                                                       var data,
+                                                               key = mw.loader.store.getStoreKey();
+
+                                                       if ( !mw.loader.store.enabled ) {
+                                                               return false;
+                                                       }
+                                                       mw.loader.store.prune();
+                                                       try {
+                                                               // Replacing the content of the module store might fail if the new
+                                                               // contents would exceed the browser's localStorage size limit. To
+                                                               // avoid clogging the browser with stale data, always remove the old
+                                                               // value before attempting to set the new one.
+                                                               localStorage.removeItem( key );
+                                                               data = JSON.stringify( mw.loader.store );
+                                                               localStorage.setItem( key, data );
+                                                       } catch ( e ) {}
+                                               }
+
+                                               return function () {
+                                                       clearTimeout( timer );
+                                                       timer = setTimeout( flush, 2000 );
+                                               };
+                                       }() )
+                               }
+                       };
+               }() ),
+
+               /**
+                * HTML construction helper functions
+                *
+                *     @example
+                *
+                *     var Html, output;
+                *
+                *     Html = mw.html;
+                *     output = Html.element( 'div', {}, new Html.Raw(
+                *         Html.element( 'img', { src: '<' } )
+                *     ) );
+                *     mw.log( output ); // <div><img src="&lt;"/></div>
+                *
+                * @class mw.html
+                * @singleton
+                */
+               html: ( function () {
+                       function escapeCallback( s ) {
+                               switch ( s ) {
+                                       case '\'':
+                                               return '&#039;';
+                                       case '"':
+                                               return '&quot;';
+                                       case '<':
+                                               return '&lt;';
+                                       case '>':
+                                               return '&gt;';
+                                       case '&':
+                                               return '&amp;';
+                               }
+                       }
+
+                       return {
+                               /**
+                                * Escape a string for HTML.
+                                *
+                                * Converts special characters to HTML entities.
+                                *
+                                *     mw.html.escape( '< > \' & "' );
+                                *     // Returns &lt; &gt; &#039; &amp; &quot;
+                                *
+                                * @param {string} s The string to escape
+                                * @return {string} HTML
+                                */
+                               escape: function ( s ) {
+                                       return s.replace( /['"<>&]/g, escapeCallback );
+                               },
+
+                               /**
+                                * Create an HTML element string, with safe escaping.
+                                *
+                                * @param {string} name The tag name.
+                                * @param {Object} attrs An object with members mapping element names to values
+                                * @param {Mixed} contents The contents of the element. May be either:
+                                *
+                                *  - string: The string is escaped.
+                                *  - null or undefined: The short closing form is used, e.g. `<br/>`.
+                                *  - this.Raw: The value attribute is included without escaping.
+                                *  - this.Cdata: The value attribute is included, and an exception is
+                                *   thrown if it contains an illegal ETAGO delimiter.
+                                *   See <http://www.w3.org/TR/1999/REC-html401-19991224/appendix/notes.html#h-B.3.2>.
+                                * @return {string} HTML
+                                */
+                               element: function ( name, attrs, contents ) {
+                                       var v, attrName, s = '<' + name;
+
+                                       for ( attrName in attrs ) {
+                                               v = attrs[attrName];
+                                               // Convert name=true, to name=name
+                                               if ( v === true ) {
+                                                       v = attrName;
+                                               // Skip name=false
+                                               } else if ( v === false ) {
+                                                       continue;
+                                               }
+                                               s += ' ' + attrName + '="' + this.escape( String( v ) ) + '"';
+                                       }
+                                       if ( contents === undefined || contents === null ) {
+                                               // Self close tag
+                                               s += '/>';
+                                               return s;
+                                       }
+                                       // Regular open tag
+                                       s += '>';
+                                       switch ( typeof contents ) {
+                                               case 'string':
+                                                       // Escaped
+                                                       s += this.escape( contents );
+                                                       break;
+                                               case 'number':
+                                               case 'boolean':
+                                                       // Convert to string
+                                                       s += String( contents );
+                                                       break;
+                                               default:
+                                                       if ( contents instanceof this.Raw ) {
+                                                               // Raw HTML inclusion
+                                                               s += contents.value;
+                                                       } else if ( contents instanceof this.Cdata ) {
+                                                               // CDATA
+                                                               if ( /<\/[a-zA-z]/.test( contents.value ) ) {
+                                                                       throw new Error( 'mw.html.element: Illegal end tag found in CDATA' );
+                                                               }
+                                                               s += contents.value;
+                                                       } else {
+                                                               throw new Error( 'mw.html.element: Invalid type of contents' );
+                                                       }
+                                       }
+                                       s += '</' + name + '>';
+                                       return s;
+                               },
+
+                               /**
+                                * Wrapper object for raw HTML passed to mw.html.element().
+                                * @class mw.html.Raw
+                                */
+                               Raw: function ( value ) {
+                                       this.value = value;
+                               },
+
+                               /**
+                                * Wrapper object for CDATA element contents passed to mw.html.element()
+                                * @class mw.html.Cdata
+                                */
+                               Cdata: function ( value ) {
+                                       this.value = value;
+                               }
+                       };
+               }() ),
+
+               // Skeleton user object. mediawiki.user.js extends this
+               user: {
+                       options: new Map(),
+                       tokens: new Map()
+               },
+
+               /**
+                * Registry and firing of events.
+                *
+                * MediaWiki has various interface components that are extended, enhanced
+                * or manipulated in some other way by extensions, gadgets and even
+                * in core itself.
+                *
+                * This framework helps streamlining the timing of when these other
+                * code paths fire their plugins (instead of using document-ready,
+                * which can and should be limited to firing only once).
+                *
+                * Features like navigating to other wiki pages, previewing an edit
+                * and editing itself – without a refresh – can then retrigger these
+                * hooks accordingly to ensure everything still works as expected.
+                *
+                * Example usage:
+                *
+                *     mw.hook( 'wikipage.content' ).add( fn ).remove( fn );
+                *     mw.hook( 'wikipage.content' ).fire( $content );
+                *
+                * Handlers can be added and fired for arbitrary event names at any time. The same
+                * event can be fired multiple times. The last run of an event is memorized
+                * (similar to `$(document).ready` and `$.Deferred().done`).
+                * This means if an event is fired, and a handler added afterwards, the added
+                * function will be fired right away with the last given event data.
+                *
+                * Like Deferreds and Promises, the mw.hook object is both detachable and chainable.
+                * Thus allowing flexible use and optimal maintainability and authority control.
+                * You can pass around the `add` and/or `fire` method to another piece of code
+                * without it having to know the event name (or `mw.hook` for that matter).
+                *
+                *     var h = mw.hook( 'bar.ready' );
+                *     new mw.Foo( .. ).fetch( { callback: h.fire } );
+                *
+                * Note: Events are documented with an underscore instead of a dot in the event
+                * name due to jsduck not supporting dots in that position.
+                *
+                * @class mw.hook
+                */
+               hook: ( function () {
+                       var lists = {};
+
+                       /**
+                        * Create an instance of mw.hook.
+                        *
+                        * @method hook
+                        * @member mw
+                        * @param {string} name Name of hook.
+                        * @return {mw.hook}
+                        */
+                       return function ( name ) {
+                               var list = lists[name] || ( lists[name] = $.Callbacks( 'memory' ) );
+
+                               return {
+                                       /**
+                                        * Register a hook handler
+                                        * @param {Function...} handler Function to bind.
+                                        * @chainable
+                                        */
+                                       add: list.add,
+
+                                       /**
+                                        * Unregister a hook handler
+                                        * @param {Function...} handler Function to unbind.
+                                        * @chainable
+                                        */
+                                       remove: list.remove,
+
+                                       /**
+                                        * Run a hook.
+                                        * @param {Mixed...} data
+                                        * @chainable
+                                        */
+                                       fire: function () {
+                                               return list.fireWith.call( this, null, slice.call( arguments ) );
+                                       }
+                               };
+                       };
+               }() )
+       };
+
+}( jQuery ) );
+
+// Alias $j to jQuery for backwards compatibility
+// @deprecated since 1.23 Use $ or jQuery instead
+mw.log.deprecate( window, '$j', jQuery, 'Use $ or jQuery instead.' );
+
+// Attach to window and globally alias
+window.mw = window.mediaWiki = mw;
+
+// Auto-register from pre-loaded startup scripts
+if ( jQuery.isFunction( window.startUp ) ) {
+       window.startUp();
+       window.startUp = undefined;
+}
diff --git a/resources/src/mediawiki/mediawiki.log.js b/resources/src/mediawiki/mediawiki.log.js
new file mode 100644 (file)
index 0000000..2ca0bbd
--- /dev/null
@@ -0,0 +1,84 @@
+/*!
+ * Logger for MediaWiki javascript.
+ * Implements the stub left by the main 'mediawiki' module.
+ *
+ * @author Michael Dale <mdale@wikimedia.org>
+ * @author Trevor Parscal <tparscal@wikimedia.org>
+ */
+
+( function ( mw, $ ) {
+
+       // Reference to dummy
+       // We don't need the dummy, but it has other methods on it
+       // that we need to restore afterwards.
+       var original = mw.log,
+               slice = Array.prototype.slice;
+
+       /**
+        * Logs a message to the console in debug mode.
+        *
+        * In the case the browser does not have a console API, a console is created on-the-fly by appending
+        * a `<div id="mw-log-console">` element to the bottom of the body and then appending this and future
+        * messages to that, instead of the console.
+        *
+        * @member mw.log
+        * @param {string...} msg Messages to output to console.
+        */
+       mw.log = function () {
+               // Turn arguments into an array
+               var args = slice.call( arguments ),
+                       // Allow log messages to use a configured prefix to identify the source window (ie. frame)
+                       prefix = mw.config.exists( 'mw.log.prefix' ) ? mw.config.get( 'mw.log.prefix' ) + '> ' : '';
+
+               // Try to use an existing console
+               // Generally we can cache this, but in this case we want to re-evaluate this as a
+               // global property live so that things like Firebug Lite can take precedence.
+               if ( window.console && window.console.log && window.console.log.apply ) {
+                       args.unshift( prefix );
+                       window.console.log.apply( window.console, args );
+                       return;
+               }
+
+               // If there is no console, use our own log box
+               mw.loader.using( 'jquery.footHovzer', function () {
+
+                       var     hovzer,
+                               d = new Date(),
+                               // Create HH:MM:SS.MIL timestamp
+                               time = ( d.getHours() < 10 ? '0' + d.getHours() : d.getHours() ) +
+                                ':' + ( d.getMinutes() < 10 ? '0' + d.getMinutes() : d.getMinutes() ) +
+                                ':' + ( d.getSeconds() < 10 ? '0' + d.getSeconds() : d.getSeconds() ) +
+                                '.' + ( d.getMilliseconds() < 10 ? '00' + d.getMilliseconds() : ( d.getMilliseconds() < 100 ? '0' + d.getMilliseconds() : d.getMilliseconds() ) ),
+                                $log = $( '#mw-log-console' );
+
+                       if ( !$log.length ) {
+                               $log = $( '<div id="mw-log-console"></div>' ).css( {
+                                               overflow: 'auto',
+                                               height: '150px',
+                                               backgroundColor: 'white',
+                                               borderTop: 'solid 2px #ADADAD'
+                                       } );
+                               hovzer = $.getFootHovzer();
+                               hovzer.$.append( $log );
+                               hovzer.update();
+                       }
+                       $log.append(
+                               $( '<div>' )
+                                       .css( {
+                                               borderBottom: 'solid 1px #DDDDDD',
+                                               fontSize: 'small',
+                                               fontFamily: 'monospace',
+                                               whiteSpace: 'pre-wrap',
+                                               padding: '0.125em 0.25em'
+                                       } )
+                                       .text( prefix + args.join( ', ' ) )
+                                       .prepend( '<span style="float: right;">[' + time + ']</span>' )
+                       );
+               } );
+       };
+
+       // Restore original methods
+       mw.log.warn = original.warn;
+       mw.log.deprecate = original.deprecate;
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.notification.css b/resources/src/mediawiki/mediawiki.notification.css
new file mode 100644 (file)
index 0000000..0c8152e
--- /dev/null
@@ -0,0 +1,32 @@
+.mw-notification-area {
+       position: absolute;
+       top: 0;
+       right: 0;
+       padding: 1em 1em 0 0;
+       width: 20em;
+       line-height: 1.35;
+       z-index: 10000;
+}
+
+.mw-notification-area-floating {
+       position: fixed;
+}
+
+* html .mw-notification-area-floating {
+       /* Make it at least 'absolute' in IE6 since 'fixed' is not supported */
+       position: absolute;
+}
+
+.mw-notification {
+       padding: 0.25em 1em;
+       margin-bottom: 0.5em;
+       border: solid 1px #ddd;
+       background-color: #fcfcfc;
+       /* Message hides on-click */
+       /* See also mediawiki.notification.js */
+       cursor: pointer;
+}
+
+.mw-notification-title {
+       font-weight: bold;
+}
diff --git a/resources/src/mediawiki/mediawiki.notification.hideForPrint.css b/resources/src/mediawiki/mediawiki.notification.hideForPrint.css
new file mode 100644 (file)
index 0000000..4f9162e
--- /dev/null
@@ -0,0 +1,3 @@
+.mw-notification-area {
+       display: none;
+}
diff --git a/resources/src/mediawiki/mediawiki.notification.js b/resources/src/mediawiki/mediawiki.notification.js
new file mode 100644 (file)
index 0000000..b5fd69c
--- /dev/null
@@ -0,0 +1,522 @@
+( function ( mw, $ ) {
+       'use strict';
+
+       var notification,
+               // The #mw-notification-area div that all notifications are contained inside.
+               $area,
+               // Number of open notification boxes at any time
+               openNotificationCount = 0,
+               isPageReady = false,
+               preReadyNotifQueue = [];
+
+       /**
+        * A Notification object for 1 message.
+        *
+        * The "_" in the name is to avoid a bug (http://github.com/senchalabs/jsduck/issues/304).
+        * It is not part of the actual class name.
+        *
+        * @class mw.Notification_
+        * @alternateClassName mw.Notification
+        *
+        * @constructor The constructor is not publicly accessible; use mw.notification#notify instead.
+        *  This does not insert anything into the document (see #start).
+        * @private
+        */
+       function Notification( message, options ) {
+               var $notification, $notificationTitle, $notificationContent;
+
+               $notification = $( '<div class="mw-notification"></div>' )
+                       .data( 'mw.notification', this )
+                       .addClass( options.autoHide ? 'mw-notification-autohide' : 'mw-notification-noautohide' );
+
+               if ( options.tag ) {
+                       // Sanitize options.tag before it is used by any code. (Including Notification class methods)
+                       options.tag = options.tag.replace( /[ _\-]+/g, '-' ).replace( /[^\-a-z0-9]+/ig, '' );
+                       if ( options.tag ) {
+                               $notification.addClass( 'mw-notification-tag-' + options.tag );
+                       } else {
+                               delete options.tag;
+                       }
+               }
+
+               if ( options.title ) {
+                       $notificationTitle = $( '<div class="mw-notification-title"></div>' )
+                               .text( options.title )
+                               .appendTo( $notification );
+               }
+
+               $notificationContent = $( '<div class="mw-notification-content"></div>' );
+
+               if ( typeof message === 'object' ) {
+                       // Handle mw.Message objects separately from DOM nodes and jQuery objects
+                       if ( message instanceof mw.Message ) {
+                               $notificationContent.html( message.parse() );
+                       } else {
+                               $notificationContent.append( message );
+                       }
+               } else {
+                       $notificationContent.text( message );
+               }
+
+               $notificationContent.appendTo( $notification );
+
+               // Private state parameters, meant for internal use only
+               // isOpen: Set to true after .start() is called to avoid double calls.
+               //         Set back to false after .close() to avoid duplicating the close animation.
+               // isPaused: false after .resume(), true after .pause(). Avoids duplicating or breaking the hide timeouts.
+               //           Set to true initially so .start() can call .resume().
+               // message: The message passed to the notification. Unused now but may be used in the future
+               //          to stop replacement of a tagged notification with another notification using the same message.
+               // options: The options passed to the notification with a little sanitization. Used by various methods.
+               // $notification: jQuery object containing the notification DOM node.
+               this.isOpen = false;
+               this.isPaused = true;
+               this.message = message;
+               this.options = options;
+               this.$notification = $notification;
+       }
+
+       /**
+        * Start the notification. Called automatically by mw.notification#notify
+        * (possibly asynchronously on document-ready).
+        *
+        * This inserts the notification into the page, closes any matching tagged notifications,
+        * handles the fadeIn animations and replacement transitions, and starts autoHide timers.
+        *
+        * @private
+        */
+       Notification.prototype.start = function () {
+               var
+                       // Local references
+                       $notification, options,
+                       // Original opacity so that we can animate back to it later
+                       opacity,
+                       // Other notification elements matching the same tag
+                       $tagMatches,
+                       outerHeight,
+                       placeholderHeight,
+                       autohideCount,
+                       notif;
+
+               $area.show();
+
+               if ( this.isOpen ) {
+                       return;
+               }
+
+               this.isOpen = true;
+               openNotificationCount++;
+
+               options = this.options;
+               $notification = this.$notification;
+
+               opacity = this.$notification.css( 'opacity' );
+
+               // Set the opacity to 0 so we can fade in later.
+               $notification.css( 'opacity', 0 );
+
+               if ( options.tag ) {
+                       // Check to see if there are any tagged notifications with the same tag as the new one
+                       $tagMatches = $area.find( '.mw-notification-tag-' + options.tag );
+               }
+
+               // If we found a tagged notification use the replacement pattern instead of the new
+               // notification fade-in pattern.
+               if ( options.tag && $tagMatches.length ) {
+
+                       // Iterate over the tag matches to find the outerHeight we should use
+                       // for the placeholder.
+                       outerHeight = 0;
+                       $tagMatches.each( function () {
+                               var notif = $( this ).data( 'mw.notification' );
+                               if ( notif ) {
+                                       // Use the notification's height + padding + border + margins
+                                       // as the placeholder height.
+                                       outerHeight = notif.$notification.outerHeight( true );
+                                       if ( notif.$replacementPlaceholder ) {
+                                               // Grab the height of a placeholder that has not finished animating.
+                                               placeholderHeight = notif.$replacementPlaceholder.height();
+                                               // Remove any placeholders added by a previous tagged
+                                               // notification that was in the middle of replacing another.
+                                               // This also makes sure that we only grab the placeholderHeight
+                                               // for the most recent notification.
+                                               notif.$replacementPlaceholder.remove();
+                                               delete notif.$replacementPlaceholder;
+                                       }
+                                       // Close the previous tagged notification
+                                       // Since we're replacing it do this with a fast speed and don't output a placeholder
+                                       // since we're taking care of that transition ourselves.
+                                       notif.close( { speed: 'fast', placeholder: false } );
+                               }
+                       } );
+                       if ( placeholderHeight !== undefined ) {
+                               // If the other tagged notification was in the middle of replacing another
+                               // tagged notification, continue from the placeholder's height instead of
+                               // using the outerHeight of the notification.
+                               outerHeight = placeholderHeight;
+                       }
+
+                       $notification
+                               // Insert the new notification before the tagged notification(s)
+                               .insertBefore( $tagMatches.first() )
+                               .css( {
+                                       // Use an absolute position so that we can use a placeholder to gracefully push other notifications
+                                       // into the right spot.
+                                       position: 'absolute',
+                                       width: $notification.width()
+                               } )
+                               // Fade-in the notification
+                               .animate( { opacity: opacity },
+                                       {
+                                               duration: 'slow',
+                                               complete: function () {
+                                                       // After we've faded in clear the opacity and let css take over
+                                                       $( this ).css( { opacity: '' } );
+                                               }
+                                       } );
+
+                       notif = this;
+
+                       // Create a clear placeholder we can use to make the notifications around the notification that is being
+                       // replaced expand or contract gracefully to fit the height of the new notification.
+                       notif.$replacementPlaceholder = $( '<div>' )
+                               // Set the height to the space the previous notification or placeholder took
+                               .css( 'height', outerHeight )
+                               // Make sure that this placeholder is at the very end of this tagged notification group
+                               .insertAfter( $tagMatches.eq( -1 ) )
+                               // Animate the placeholder height to the space that this new notification will take up
+                               .animate( { height: $notification.outerHeight( true ) },
+                                       {
+                                               // Do space animations fast
+                                               speed: 'fast',
+                                               complete: function () {
+                                                       // Reset the notification position after we've finished the space animation
+                                                       // However do not do it if the placeholder was removed because another tagged
+                                                       // notification went and closed this one.
+                                                       if ( notif.$replacementPlaceholder ) {
+                                                               $notification.css( 'position', '' );
+                                                       }
+                                                       // Finally, remove the placeholder from the DOM
+                                                       $( this ).remove();
+                                               }
+                                       } );
+               } else {
+                       // Append to the notification area and fade in to the original opacity.
+                       $notification
+                               .appendTo( $area )
+                               .animate( { opacity: opacity },
+                                       {
+                                               duration: 'fast',
+                                               complete: function () {
+                                                       // After we've faded in clear the opacity and let css take over
+                                                       $( this ).css( 'opacity', '' );
+                                               }
+                                       }
+                               );
+               }
+
+               // By default a notification is paused.
+               // If this notification is within the first {autoHideLimit} notifications then
+               // start the auto-hide timer as soon as it's created.
+               autohideCount = $area.find( '.mw-notification-autohide' ).length;
+               if ( autohideCount <= notification.autoHideLimit ) {
+                       this.resume();
+               }
+       };
+
+       /**
+        * Pause any running auto-hide timer for this notification
+        */
+       Notification.prototype.pause = function () {
+               if ( this.isPaused ) {
+                       return;
+               }
+               this.isPaused = true;
+
+               if ( this.timeout ) {
+                       clearTimeout( this.timeout );
+                       delete this.timeout;
+               }
+       };
+
+       /**
+        * Start autoHide timer if not already started.
+        * Does nothing if autoHide is disabled.
+        * Either to resume from pause or to make the first start.
+        */
+       Notification.prototype.resume = function () {
+               var notif = this;
+               if ( !notif.isPaused ) {
+                       return;
+               }
+               // Start any autoHide timeouts
+               if ( notif.options.autoHide ) {
+                       notif.isPaused = false;
+                       notif.timeout = setTimeout( function () {
+                               // Already finished, so don't try to re-clear it
+                               delete notif.timeout;
+                               notif.close();
+                       }, notification.autoHideSeconds * 1000 );
+               }
+       };
+
+       /**
+        * Close/hide the notification.
+        *
+        * @param {Object} options An object containing options for the closing of the notification.
+        *
+        *  - speed: Use a close speed different than the default 'slow'.
+        *  - placeholder: Set to false to disable the placeholder transition.
+        */
+       Notification.prototype.close = function ( options ) {
+               if ( !this.isOpen ) {
+                       return;
+               }
+               this.isOpen = false;
+               openNotificationCount--;
+               // Clear any remaining timeout on close
+               this.pause();
+
+               options = $.extend( {
+                       speed: 'slow',
+                       placeholder: true
+               }, options );
+
+               // Remove the mw-notification-autohide class from the notification to avoid
+               // having a half-closed notification counted as a notification to resume
+               // when handling {autoHideLimit}.
+               this.$notification.removeClass( 'mw-notification-autohide' );
+
+               // Now that a notification is being closed. Start auto-hide timers for any
+               // notification that has now become one of the first {autoHideLimit} notifications.
+               notification.resume();
+
+               this.$notification
+                       .css( {
+                               // Don't trigger any mouse events while fading out, just in case the cursor
+                               // happens to be right above us when we transition upwards.
+                               pointerEvents: 'none',
+                               // Set an absolute position so we can move upwards in the animation.
+                               // Notification replacement doesn't look right unless we use an animation like this.
+                               position: 'absolute',
+                               // We must fix the width to avoid it shrinking horizontally.
+                               width: this.$notification.width()
+                       } )
+                       // Fix the top/left position to the current computed position from which we
+                       // can animate upwards.
+                       .css( this.$notification.position() );
+
+               // This needs to be done *after* notification's position has been made absolute.
+               if ( options.placeholder ) {
+                       // Insert a placeholder with a height equal to the height of the
+                       // notification plus it's vertical margins in place of the notification
+                       var $placeholder = $( '<div>' )
+                               .css( 'height', this.$notification.outerHeight( true ) )
+                               .insertBefore( this.$notification );
+               }
+
+               // Animate opacity and top to create fade upwards animation for notification closing
+               this.$notification
+                       .animate( {
+                               opacity: 0,
+                               top: '-=35'
+                       }, {
+                               duration: options.speed,
+                               complete: function () {
+                                       // Remove the notification
+                                       $( this ).remove();
+                                       // Hide the area manually after closing the last notification, since it has padding,
+                                       // causing it to obscure whatever is behind it in spite of being invisible (bug 52659).
+                                       // It's okay to do this before getting rid of the placeholder, as it's invisible as well.
+                                       if ( openNotificationCount === 0 ) {
+                                               $area.hide();
+                                       }
+                                       if ( options.placeholder ) {
+                                               // Use a fast slide up animation after closing to make it look like the notifications
+                                               // below slide up into place when the notification disappears
+                                               $placeholder.slideUp( 'fast', function () {
+                                                       // Remove the placeholder
+                                                       $( this ).remove();
+                                               } );
+                                       }
+                               }
+                       } );
+       };
+
+       /**
+        * Helper function, take a list of notification divs and call
+        * a function on the Notification instance attached to them.
+        *
+        * @private
+        * @static
+        * @param {jQuery} $notifications A jQuery object containing notification divs
+        * @param {string} fn The name of the function to call on the Notification instance
+        */
+       function callEachNotification( $notifications, fn ) {
+               $notifications.each( function () {
+                       var notif = $( this ).data( 'mw.notification' );
+                       if ( notif ) {
+                               notif[fn]();
+                       }
+               } );
+       }
+
+       /**
+        * Initialisation.
+        * Must only be called once, and not before the document is ready.
+        * @ignore
+        */
+       function init() {
+               var offset, $window = $( window );
+
+               $area = $( '<div id="mw-notification-area" class="mw-notification-area mw-notification-area-layout"></div>' )
+                       // Pause auto-hide timers when the mouse is in the notification area.
+                       .on( {
+                               mouseenter: notification.pause,
+                               mouseleave: notification.resume
+                       } )
+                       // When clicking on a notification close it.
+                       .on( 'click', '.mw-notification', function () {
+                               var notif = $( this ).data( 'mw.notification' );
+                               if ( notif ) {
+                                       notif.close();
+                               }
+                       } )
+                       // Stop click events from <a> tags from propogating to prevent clicking.
+                       // on links from hiding a notification.
+                       .on( 'click', 'a', function ( e ) {
+                               e.stopPropagation();
+                       } );
+
+               // Prepend the notification area to the content area and save it's object.
+               mw.util.$content.prepend( $area );
+               offset = $area.offset();
+
+               function updateAreaMode() {
+                       var isFloating = $window.scrollTop() > offset.top;
+                       $area
+                               .toggleClass( 'mw-notification-area-floating', isFloating )
+                               .toggleClass( 'mw-notification-area-layout', !isFloating );
+               }
+
+               $window.on( 'scroll', updateAreaMode );
+
+               // Initial mode
+               updateAreaMode();
+       }
+
+       /**
+        * @class mw.notification
+        * @singleton
+        */
+       notification = {
+               /**
+                * Pause auto-hide timers for all notifications.
+                * Notifications will not auto-hide until resume is called.
+                * @see mw.Notification#pause
+                */
+               pause: function () {
+                       callEachNotification(
+                               $area.children( '.mw-notification' ),
+                               'pause'
+                       );
+               },
+
+               /**
+                * Resume any paused auto-hide timers from the beginning.
+                * Only the first #autoHideLimit timers will be resumed.
+                */
+               resume: function () {
+                       callEachNotification(
+                               // Only call resume on the first #autoHideLimit notifications.
+                               // Exclude noautohide notifications to avoid bugs where #autoHideLimit
+                               // `{ autoHide: false }` notifications are at the start preventing any
+                               // auto-hide notifications from being autohidden.
+                               $area.children( '.mw-notification-autohide' ).slice( 0, notification.autoHideLimit ),
+                               'resume'
+                       );
+               },
+
+               /**
+                * Display a notification message to the user.
+                *
+                * @param {HTMLElement|jQuery|mw.Message|string} message
+                * @param {Object} options The options to use for the notification.
+                *  See #defaults for details.
+                * @return {mw.Notification} Notification object
+                */
+               notify: function ( message, options ) {
+                       var notif;
+                       options = $.extend( {}, notification.defaults, options );
+
+                       notif = new Notification( message, options );
+
+                       if ( isPageReady ) {
+                               notif.start();
+                       } else {
+                               preReadyNotifQueue.push( notif );
+                       }
+
+                       return notif;
+               },
+
+               /**
+                * @property {Object}
+                * The defaults for #notify options parameter.
+                *
+                * - autoHide:
+                *   A boolean indicating whether the notifification should automatically
+                *   be hidden after shown. Or if it should persist.
+                *
+                * - tag:
+                *   An optional string. When a notification is tagged only one message
+                *   with that tag will be displayed. Trying to display a new notification
+                *   with the same tag as one already being displayed will cause the other
+                *   notification to be closed and this new notification to open up inside
+                *   the same place as the previous notification.
+                *
+                * - title:
+                *   An optional title for the notification. Will be displayed above the
+                *   content. Usually in bold.
+                */
+               defaults: {
+                       autoHide: true,
+                       tag: false,
+                       title: undefined
+               },
+
+               /**
+                * @property {number}
+                * Number of seconds to wait before auto-hiding notifications.
+                */
+               autoHideSeconds: 5,
+
+               /**
+                * @property {number}
+                * Maximum number of notifications to count down auto-hide timers for.
+                * Only the first #autoHideLimit notifications being displayed will
+                * auto-hide. Any notifications further down in the list will only start
+                * counting down to auto-hide after the first few messages have closed.
+                *
+                * This basically represents the number of notifications the user should
+                * be able to process in #autoHideSeconds time.
+                */
+               autoHideLimit: 3
+       };
+
+       $( function () {
+               var notif;
+
+               init();
+
+               // Handle pre-ready queue.
+               isPageReady = true;
+               while ( preReadyNotifQueue.length ) {
+                       notif = preReadyNotifQueue.shift();
+                       notif.start();
+               }
+       } );
+
+       mw.notification = notification;
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.notify.js b/resources/src/mediawiki/mediawiki.notify.js
new file mode 100644 (file)
index 0000000..743d651
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * @class mw.plugin.notify
+ */
+( function ( mw, $ ) {
+       'use strict';
+
+       /**
+        * @see mw.notification#notify
+        * @param message
+        * @param options
+        * @return {jQuery.Promise}
+        */
+       mw.notify = function ( message, options ) {
+               var d = $.Deferred();
+               // Don't bother loading the whole notification system if we never use it.
+               mw.loader.using( 'mediawiki.notification', function () {
+                       // Call notify with the notification the user requested of us.
+                       d.resolve( mw.notification.notify( message, options ) );
+               }, d.reject );
+               return d.promise();
+       };
+
+       /**
+        * @class mw
+        * @mixins mw.plugin.notify
+        */
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.searchSuggest.css b/resources/src/mediawiki/mediawiki.searchSuggest.css
new file mode 100644 (file)
index 0000000..df144ce
--- /dev/null
@@ -0,0 +1,24 @@
+/* Make sure the links are not underlined or colored, ever. */
+/* There is already a :focus / :hover indication on the <div>. */
+.suggestions a.mw-searchSuggest-link,
+.suggestions a.mw-searchSuggest-link:hover,
+.suggestions a.mw-searchSuggest-link:active,
+.suggestions a.mw-searchSuggest-link:focus {
+       color: black;
+       text-decoration: none;
+}
+
+.suggestions-result-current a.mw-searchSuggest-link,
+.suggestions-result-current a.mw-searchSuggest-link:hover,
+.suggestions-result-current a.mw-searchSuggest-link:active,
+.suggestions-result-current a.mw-searchSuggest-link:focus {
+       color: white;
+}
+
+.suggestions a.mw-searchSuggest-link .special-query {
+       /* Apply ellipsis to suggestions */
+       overflow: hidden;
+       -o-text-overflow: ellipsis; /* Opera 9 to 10 */
+       text-overflow: ellipsis;
+       white-space: nowrap;
+}
diff --git a/resources/src/mediawiki/mediawiki.searchSuggest.js b/resources/src/mediawiki/mediawiki.searchSuggest.js
new file mode 100644 (file)
index 0000000..8a8871d
--- /dev/null
@@ -0,0 +1,201 @@
+/*!
+ * Add search suggestions to the search form.
+ */
+( function ( mw, $ ) {
+       $( function () {
+               var map, resultRenderCache, searchboxesSelectors,
+                       // Region where the suggestions box will appear directly below
+                       // (using the same width). Can be a container element or the input
+                       // itself, depending on what suits best in the environment.
+                       // For Vector the suggestion box should align with the simpleSearch
+                       // container's borders, in other skins it should align with the input
+                       // element (not the search form, as that would leave the buttons
+                       // vertically between the input and the suggestions).
+                       $searchRegion = $( '#simpleSearch, #searchInput' ).first(),
+                       $searchInput = $( '#searchInput' );
+
+               // Compatibility map
+               map = {
+                       // SimpleSearch is broken in Opera < 9.6
+                       opera: [['>=', 9.6]],
+                       // Older Konquerors are unable to position the suggestions correctly (bug 50805)
+                       konqueror: [['>=', '4.11']],
+                       docomo: false,
+                       blackberry: false,
+                       ipod: false,
+                       iphone: false
+               };
+
+               if ( !$.client.test( map ) ) {
+                       return;
+               }
+
+               // Compute form data for search suggestions functionality.
+               function computeResultRenderCache( context ) {
+                       var $form, baseHref, linkParams;
+
+                       // Compute common parameters for links' hrefs
+                       $form = context.config.$region.closest( 'form' );
+
+                       baseHref = $form.attr( 'action' );
+                       baseHref += baseHref.indexOf( '?' ) > -1 ? '&' : '?';
+
+                       linkParams = {};
+                       $.each( $form.serializeArray(), function ( idx, obj ) {
+                               linkParams[ obj.name ] = obj.value;
+                       } );
+
+                       return {
+                               textParam: context.data.$textbox.attr( 'name' ),
+                               linkParams: linkParams,
+                               baseHref: baseHref
+                       };
+               }
+
+               // The function used to render the suggestions.
+               function renderFunction( text, context ) {
+                       if ( !resultRenderCache ) {
+                               resultRenderCache = computeResultRenderCache( context );
+                       }
+
+                       // linkParams object is modified and reused
+                       resultRenderCache.linkParams[ resultRenderCache.textParam ] = text;
+
+                       // this is the container <div>, jQueryfied
+                       this.text( text )
+                               .wrap(
+                                       $( '<a>' )
+                                               .attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) )
+                                               .addClass( 'mw-searchSuggest-link' )
+                               );
+               }
+
+               function specialRenderFunction( query, context ) {
+                       var $el = this;
+
+                       if ( !resultRenderCache ) {
+                               resultRenderCache = computeResultRenderCache( context );
+                       }
+
+                       // linkParams object is modified and reused
+                       resultRenderCache.linkParams[ resultRenderCache.textParam ] = query;
+
+                       if ( $el.children().length === 0 ) {
+                               $el
+                                       .append(
+                                               $( '<div>' )
+                                                       .addClass( 'special-label' )
+                                                       .text( mw.msg( 'searchsuggest-containing' ) ),
+                                               $( '<div>' )
+                                                       .addClass( 'special-query' )
+                                                       .text( query )
+                                       )
+                                       .show();
+                       } else {
+                               $el.find( '.special-query' )
+                                       .text( query );
+                       }
+
+                       if ( $el.parent().hasClass( 'mw-searchSuggest-link' ) ) {
+                               $el.parent().attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) + '&fulltext=1' );
+                       } else {
+                               $el.wrap(
+                                       $( '<a>' )
+                                               .attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) + '&fulltext=1' )
+                                               .addClass( 'mw-searchSuggest-link' )
+                               );
+                       }
+               }
+
+               // General suggestions functionality for all search boxes
+               searchboxesSelectors = [
+                       // Primary searchbox on every page in standard skins
+                       '#searchInput',
+                       // Special:Search
+                       '#powerSearchText',
+                       '#searchText',
+                       // Generic selector for skins with multiple searchboxes (used by CologneBlue)
+                       '.mw-searchInput'
+               ];
+               $( searchboxesSelectors.join( ', ' ) )
+                       .suggestions( {
+                               fetch: function ( query ) {
+                                       var $el;
+
+                                       if ( query.length !== 0 ) {
+                                               $el = $( this );
+                                               $el.data( 'request', ( new mw.Api() ).get( {
+                                                       action: 'opensearch',
+                                                       search: query,
+                                                       namespace: 0,
+                                                       suggest: ''
+                                               } ).done( function ( data ) {
+                                                       $el.suggestions( 'suggestions', data[1] );
+                                               } ) );
+                                       }
+                               },
+                               cancel: function () {
+                                       var apiPromise = $( this ).data( 'request' );
+                                       // If the delay setting has caused the fetch to have not even happened
+                                       // yet, the apiPromise object will have never been set.
+                                       if ( apiPromise && $.isFunction( apiPromise.abort ) ) {
+                                               apiPromise.abort();
+                                               $( this ).removeData( 'request' );
+                                       }
+                               },
+                               result: {
+                                       render: renderFunction,
+                                       select: function () {
+                                               return true; // allow the form to be submitted
+                                       }
+                               },
+                               delay: 120,
+                               highlightInput: true
+                       } )
+                       .bind( 'paste cut drop', function () {
+                               // make sure paste and cut events from the mouse and drag&drop events
+                               // trigger the keypress handler and cause the suggestions to update
+                               $( this ).trigger( 'keypress' );
+                       } );
+
+               // Ensure that the thing is actually present!
+               if ( $searchRegion.length === 0 ) {
+                       // Don't try to set anything up if simpleSearch is disabled sitewide.
+                       // The loader code loads us if the option is present, even if we're
+                       // not actually enabled (anymore).
+                       return;
+               }
+
+               // Special suggestions functionality for skin-provided search box
+               $searchInput.suggestions( {
+                       result: {
+                               render: renderFunction,
+                               select: function () {
+                                       return true; // allow the form to be submitted
+                               }
+                       },
+                       special: {
+                               render: specialRenderFunction,
+                               select: function ( $input ) {
+                                       $input.closest( 'form' )
+                                               .append( $( '<input type="hidden" name="fulltext" value="1"/>' ) );
+                                       return true; // allow the form to be submitted
+                               }
+                       },
+                       $region: $searchRegion
+               } );
+
+               // If the form includes any fallback fulltext search buttons, remove them
+               $searchInput.closest( 'form' ).find( '.mw-fallbackSearchButton' ).remove();
+
+               // In most skins (at least Monobook and Vector), the font-size is messed up in <body>.
+               // (they use 2 elements to get a sane font-height). So, instead of making exceptions for
+               // each skin or adding more stylesheets, just copy it from the active element so auto-fit.
+               $searchInput
+                       .data( 'suggestions-context' )
+                       .data.$container
+                               .css( 'fontSize', $searchInput.css( 'fontSize' ) );
+
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.toc.js b/resources/src/mediawiki/mediawiki.toc.js
new file mode 100644 (file)
index 0000000..6eb8552
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ * @private
+ * @singleton
+ * @class mw.toc
+ */
+( function ( mw, $ ) {
+       'use strict';
+
+       // Table of contents toggle
+       mw.hook( 'wikipage.content' ).add( function ( $content ) {
+
+               /**
+                * Hide/show the table of contents element
+                *
+                * @param {jQuery} $toggleLink A jQuery object of the toggle link.
+                */
+               function toggleToc( $toggleLink ) {
+                       var $tocList = $content.find( '#toc ul:first' );
+
+                       // This function shouldn't be called if there's no TOC,
+                       // but just in case...
+                       if ( $tocList.length ) {
+                               if ( $tocList.is( ':hidden' ) ) {
+                                       $tocList.slideDown( 'fast' );
+                                       $toggleLink.text( mw.msg( 'hidetoc' ) );
+                                       $content.find( '#toc' ).removeClass( 'tochidden' );
+                                       $.cookie( 'mw_hidetoc', null, {
+                                               expires: 30,
+                                               path: '/'
+                                       } );
+                               } else {
+                                       $tocList.slideUp( 'fast' );
+                                       $toggleLink.text( mw.msg( 'showtoc' ) );
+                                       $content.find( '#toc' ).addClass( 'tochidden' );
+                                       $.cookie( 'mw_hidetoc', '1', {
+                                               expires: 30,
+                                               path: '/'
+                                       } );
+                               }
+                       }
+               }
+
+               var $tocTitle, $tocToggleLink, hideTocCookie;
+               $tocTitle = $content.find( '#toctitle' );
+               $tocToggleLink = $content.find( '#togglelink' );
+               // Only add it if there is a TOC and there is no toggle added already
+               if ( $content.find( '#toc' ).length && $tocTitle.length && !$tocToggleLink.length ) {
+                       hideTocCookie = $.cookie( 'mw_hidetoc' );
+                       $tocToggleLink = $( '<a href="#" class="internal" id="togglelink"></a>' )
+                               .text( mw.msg( 'hidetoc' ) )
+                               .click( function ( e ) {
+                                       e.preventDefault();
+                                       toggleToc( $( this ) );
+                               } );
+                       $tocTitle.append(
+                               $tocToggleLink
+                                       .wrap( '<span class="toctoggle"></span>' )
+                                       .parent()
+                                               .prepend( '&nbsp;[' )
+                                               .append( ']&nbsp;' )
+                       );
+
+                       if ( hideTocCookie === '1' ) {
+                               toggleToc( $tocToggleLink );
+                       }
+               }
+       } );
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.user.js b/resources/src/mediawiki/mediawiki.user.js
new file mode 100644 (file)
index 0000000..8344111
--- /dev/null
@@ -0,0 +1,261 @@
+/**
+ * @class mw.user
+ * @singleton
+ */
+( function ( mw, $ ) {
+       var user,
+               deferreds = {},
+               // Extend the skeleton mw.user from mediawiki.js
+               // This is kind of ugly but we're stuck with this for b/c reasons
+               options = mw.user.options || new mw.Map(),
+               tokens = mw.user.tokens || new mw.Map();
+
+       /**
+        * Get the current user's groups or rights
+        *
+        * @private
+        * @param {string} info One of 'groups' or 'rights'
+        * @param {Function} [callback]
+        * @return {jQuery.Promise}
+        */
+       function getUserInfo( info, callback ) {
+               var api;
+               if ( !deferreds[info] ) {
+
+                       deferreds.rights = $.Deferred();
+                       deferreds.groups = $.Deferred();
+
+                       api = new mw.Api();
+                       api.get( {
+                               action: 'query',
+                               meta: 'userinfo',
+                               uiprop: 'rights|groups'
+                       } ).always( function ( data ) {
+                               var rights, groups;
+                               if ( data.query && data.query.userinfo ) {
+                                       rights = data.query.userinfo.rights;
+                                       groups = data.query.userinfo.groups;
+                               }
+                               deferreds.rights.resolve( rights || [] );
+                               deferreds.groups.resolve( groups || [] );
+                       } );
+
+               }
+
+               return deferreds[info].done( callback ).promise();
+       }
+
+       mw.user = user = {
+               options: options,
+               tokens: tokens,
+
+               /**
+                * Generate a random user session ID (32 alpha-numeric characters)
+                *
+                * This information would potentially be stored in a cookie to identify a user during a
+                * session or series of sessions. Its uniqueness should not be depended on.
+                *
+                * @return {string} Random set of 32 alpha-numeric characters
+                */
+               generateRandomSessionId: function () {
+                       var i, r,
+                               id = '',
+                               seed = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+                       for ( i = 0; i < 32; i++ ) {
+                               r = Math.floor( Math.random() * seed.length );
+                               id += seed.substring( r, r + 1 );
+                       }
+                       return id;
+               },
+
+               /**
+                * Get the current user's database id
+                *
+                * Not to be confused with #id.
+                *
+                * @return {number} Current user's id, or 0 if user is anonymous
+                */
+               getId: function () {
+                       return mw.config.get( 'wgUserId', 0 );
+               },
+
+               /**
+                * Get the current user's name
+                *
+                * @return {string|null} User name string or null if user is anonymous
+                */
+               getName: function () {
+                       return mw.config.get( 'wgUserName' );
+               },
+
+               /**
+                * @inheritdoc #getName
+                * @deprecated since 1.20 use #getName instead
+                */
+               name: function () {
+                       return user.getName();
+               },
+
+               /**
+                * Get date user registered, if available
+                *
+                * @return {Date|boolean|null} Date user registered, or false for anonymous users, or
+                *  null when data is not available
+                */
+               getRegistration: function () {
+                       var registration = mw.config.get( 'wgUserRegistration' );
+                       if ( user.isAnon() ) {
+                               return false;
+                       } else if ( registration === null ) {
+                               // Information may not be available if they signed up before
+                               // MW began storing this.
+                               return null;
+                       } else {
+                               return new Date( registration );
+                       }
+               },
+
+               /**
+                * Whether the current user is anonymous
+                *
+                * @return {boolean}
+                */
+               isAnon: function () {
+                       return user.getName() === null;
+               },
+
+               /**
+                * @inheritdoc #isAnon
+                * @deprecated since 1.20 use #isAnon instead
+                */
+               anonymous: function () {
+                       return user.isAnon();
+               },
+
+               /**
+                * Get an automatically generated random ID (stored in a session cookie)
+                *
+                * This ID is ephemeral for everyone, staying in their browser only until they close
+                * their browser.
+                *
+                * @return {string} Random session ID
+                */
+               sessionId: function () {
+                       var sessionId = $.cookie( 'mediaWiki.user.sessionId' );
+                       if ( sessionId === undefined || sessionId === null ) {
+                               sessionId = user.generateRandomSessionId();
+                               $.cookie( 'mediaWiki.user.sessionId', sessionId, { expires: null, path: '/' } );
+                       }
+                       return sessionId;
+               },
+
+               /**
+                * Get the current user's name or the session ID
+                *
+                * Not to be confused with #getId.
+                *
+                * @return {string} User name or random session ID
+                */
+               id: function () {
+                       return user.getName() || user.sessionId();
+               },
+
+               /**
+                * Get the user's bucket (place them in one if not done already)
+                *
+                *     mw.user.bucket( 'test', {
+                *         buckets: { ignored: 50, control: 25, test: 25 },
+                *         version: 1,
+                *         expires: 7
+                *     } );
+                *
+                * @deprecated since 1.23
+                * @param {string} key Name of bucket
+                * @param {Object} options Bucket configuration options
+                * @param {Object} options.buckets List of bucket-name/relative-probability pairs (required,
+                *  must have at least one pair)
+                * @param {number} [options.version=0] Version of bucket test, changing this forces
+                *  rebucketing
+                * @param {number} [options.expires=30] Length of time (in days) until the user gets
+                *  rebucketed
+                * @return {string} Bucket name - the randomly chosen key of the `options.buckets` object
+                */
+               bucket: function ( key, options ) {
+                       var cookie, parts, version, bucket,
+                               range, k, rand, total;
+
+                       options = $.extend( {
+                               buckets: {},
+                               version: 0,
+                               expires: 30
+                       }, options || {} );
+
+                       cookie = $.cookie( 'mediaWiki.user.bucket:' + key );
+
+                       // Bucket information is stored as 2 integers, together as version:bucket like: "1:2"
+                       if ( typeof cookie === 'string' && cookie.length > 2 && cookie.indexOf( ':' ) !== -1 ) {
+                               parts = cookie.split( ':' );
+                               if ( parts.length > 1 && Number( parts[0] ) === options.version ) {
+                                       version = Number( parts[0] );
+                                       bucket = String( parts[1] );
+                               }
+                       }
+
+                       if ( bucket === undefined ) {
+                               if ( !$.isPlainObject( options.buckets ) ) {
+                                       throw new Error( 'Invalid bucket. Object expected for options.buckets.' );
+                               }
+
+                               version = Number( options.version );
+
+                               // Find range
+                               range = 0;
+                               for ( k in options.buckets ) {
+                                       range += options.buckets[k];
+                               }
+
+                               // Select random value within range
+                               rand = Math.random() * range;
+
+                               // Determine which bucket the value landed in
+                               total = 0;
+                               for ( k in options.buckets ) {
+                                       bucket = k;
+                                       total += options.buckets[k];
+                                       if ( total >= rand ) {
+                                               break;
+                                       }
+                               }
+
+                               $.cookie(
+                                       'mediaWiki.user.bucket:' + key,
+                                       version + ':' + bucket,
+                                       { path: '/', expires: Number( options.expires ) }
+                               );
+                       }
+
+                       return bucket;
+               },
+
+               /**
+                * Get the current user's groups
+                *
+                * @param {Function} [callback]
+                * @return {jQuery.Promise}
+                */
+               getGroups: function ( callback ) {
+                       return getUserInfo( 'groups', callback );
+               },
+
+               /**
+                * Get the current user's rights
+                *
+                * @param {Function} [callback]
+                * @return {jQuery.Promise}
+                */
+               getRights: function ( callback ) {
+                       return getUserInfo( 'rights', callback );
+               }
+       };
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki/mediawiki.util.js b/resources/src/mediawiki/mediawiki.util.js
new file mode 100644 (file)
index 0000000..2234238
--- /dev/null
@@ -0,0 +1,601 @@
+( function ( mw, $ ) {
+       'use strict';
+
+       /**
+        * Utility library
+        * @class mw.util
+        * @singleton
+        */
+       var util = {
+
+               /**
+                * Initialisation
+                * (don't call before document ready)
+                */
+               init: function () {
+                       /* Fill $content var */
+                       util.$content = ( function () {
+                               var i, l, $content, selectors;
+                               selectors = [
+                                       // The preferred standard for setting $content (class="mw-body")
+                                       // You may also use (class="mw-body mw-body-primary") if you use
+                                       // mw-body in multiple locations.
+                                       // Or class="mw-body-primary" if you want $content to be deeper
+                                       // in the dom than mw-body
+                                       '.mw-body-primary',
+                                       '.mw-body',
+
+                                       /* Legacy fallbacks for setting the content */
+                                       // Vector, Monobook, Chick, etc... based skins
+                                       '#bodyContent',
+
+                                       // Modern based skins
+                                       '#mw_contentholder',
+
+                                       // Standard, CologneBlue
+                                       '#article',
+
+                                       // #content is present on almost all if not all skins. Most skins (the above cases)
+                                       // have #content too, but as an outer wrapper instead of the article text container.
+                                       // The skins that don't have an outer wrapper do have #content for everything
+                                       // so it's a good fallback
+                                       '#content',
+
+                                       // If nothing better is found fall back to our bodytext div that is guaranteed to be here
+                                       '#mw-content-text',
+
+                                       // Should never happen... well, it could if someone is not finished writing a skin and has
+                                       // not inserted bodytext yet. But in any case <body> should always exist
+                                       'body'
+                               ];
+                               for ( i = 0, l = selectors.length; i < l; i++ ) {
+                                       $content = $( selectors[i] ).first();
+                                       if ( $content.length ) {
+                                               return $content;
+                                       }
+                               }
+
+                               // Make sure we don't unset util.$content if it was preset and we don't find anything
+                               return util.$content;
+                       } )();
+               },
+
+               /* Main body */
+
+               /**
+                * Encode the string like PHP's rawurlencode
+                *
+                * @param {string} str String to be encoded.
+                */
+               rawurlencode: function ( str ) {
+                       str = String( str );
+                       return encodeURIComponent( str )
+                               .replace( /!/g, '%21' ).replace( /'/g, '%27' ).replace( /\(/g, '%28' )
+                               .replace( /\)/g, '%29' ).replace( /\*/g, '%2A' ).replace( /~/g, '%7E' );
+               },
+
+               /**
+                * Encode page titles for use in a URL
+                * We want / and : to be included as literal characters in our title URLs
+                * as they otherwise fatally break the title
+                *
+                * @param {string} str String to be encoded.
+                */
+               wikiUrlencode: function ( str ) {
+                       return util.rawurlencode( str )
+                               .replace( /%20/g, '_' ).replace( /%3A/g, ':' ).replace( /%2F/g, '/' );
+               },
+
+               /**
+                * Get the link to a page name (relative to `wgServer`),
+                *
+                * @param {string} str Page name
+                * @param {Object} [params] A mapping of query parameter names to values,
+                *  e.g. `{ action: 'edit' }`
+                * @return {string} Url of the page with name of `str`
+                */
+               getUrl: function ( str, params ) {
+                       var url = mw.config.get( 'wgArticlePath' ).replace(
+                               '$1',
+                               util.wikiUrlencode( typeof str === 'string' ? str : mw.config.get( 'wgPageName' ) )
+                       );
+
+                       if ( params && !$.isEmptyObject( params ) ) {
+                               url += ( url.indexOf( '?' ) !== -1 ? '&' : '?' ) + $.param( params );
+                       }
+
+                       return url;
+               },
+
+               /**
+                * Get address to a script in the wiki root.
+                * For index.php use `mw.config.get( 'wgScript' )`.
+                *
+                * @since 1.18
+                * @param str string Name of script (eg. 'api'), defaults to 'index'
+                * @return string Address to script (eg. '/w/api.php' )
+                */
+               wikiScript: function ( str ) {
+                       str = str || 'index';
+                       if ( str === 'index' ) {
+                               return mw.config.get( 'wgScript' );
+                       } else if ( str === 'load' ) {
+                               return mw.config.get( 'wgLoadScript' );
+                       } else {
+                               return mw.config.get( 'wgScriptPath' ) + '/' + str +
+                                       mw.config.get( 'wgScriptExtension' );
+                       }
+               },
+
+               /**
+                * Append a new style block to the head and return the CSSStyleSheet object.
+                * Use .ownerNode to access the `<style>` element, or use mw.loader#addStyleTag.
+                * This function returns the styleSheet object for convience (due to cross-browsers
+                * difference as to where it is located).
+                *
+                *     var sheet = mw.util.addCSS( '.foobar { display: none; }' );
+                *     $( foo ).click( function () {
+                *         // Toggle the sheet on and off
+                *         sheet.disabled = !sheet.disabled;
+                *     } );
+                *
+                * @param {string} text CSS to be appended
+                * @return {CSSStyleSheet} Use .ownerNode to get to the `<style>` element.
+                */
+               addCSS: function ( text ) {
+                       var s = mw.loader.addStyleTag( text );
+                       return s.sheet || s.styleSheet || s;
+               },
+
+               /**
+                * Hide/show the table of contents element
+                *
+                * @param {jQuery} $toggleLink A jQuery object of the toggle link.
+                * @param {Function} [callback] Function to be called after the toggle is
+                *  completed (including the animation).
+                * @return {Mixed} Boolean visibility of the toc (true if it's visible)
+                * or Null if there was no table of contents.
+                * @deprecated since 1.23 Use jQuery
+                */
+               toggleToc: function ( $toggleLink, callback ) {
+                       var ret, $tocList = $( '#toc ul:first' );
+
+                       // This function shouldn't be called if there's no TOC,
+                       // but just in case...
+                       if ( !$tocList.length ) {
+                               return null;
+                       }
+                       ret = $tocList.is( ':hidden' );
+                       $toggleLink.click();
+                       $tocList.promise().done( callback );
+                       return ret;
+               },
+
+               /**
+                * Grab the URL parameter value for the given parameter.
+                * Returns null if not found.
+                *
+                * @param {string} param The parameter name.
+                * @param {string} [url=document.location.href] URL to search through, defaulting to the current document's URL.
+                * @return {Mixed} Parameter value or null.
+                */
+               getParamValue: function ( param, url ) {
+                       if ( url === undefined ) {
+                               url = document.location.href;
+                       }
+                       // Get last match, stop at hash
+                       var     re = new RegExp( '^[^#]*[&?]' + $.escapeRE( param ) + '=([^&#]*)' ),
+                               m = re.exec( url );
+                       if ( m ) {
+                               // Beware that decodeURIComponent is not required to understand '+'
+                               // by spec, as encodeURIComponent does not produce it.
+                               return decodeURIComponent( m[1].replace( /\+/g, '%20' ) );
+                       }
+                       return null;
+               },
+
+               /**
+                * @property {string}
+                * Access key prefix.
+                */
+               tooltipAccessKeyPrefix: ( function () {
+                       var profile = $.client.profile();
+
+                       // Opera on any platform
+                       if ( profile.name === 'opera' ) {
+                               return 'shift-esc-';
+                       }
+
+                       // Chrome on any platform
+                       if ( profile.name === 'chrome' ) {
+                               if ( profile.platform === 'mac' ) {
+                                       // Chrome on Mac
+                                       return 'ctrl-option-';
+                               }
+                               // Chrome on Windows or Linux
+                               // (both alt- and alt-shift work, but alt with E, D, F etc does not
+                               // work since they are browser shortcuts)
+                               return 'alt-shift-';
+                       }
+
+                       // Non-Windows Safari with webkit_version > 526
+                       if ( profile.platform !== 'win'
+                               && profile.name === 'safari'
+                               && profile.layoutVersion > 526
+                       ) {
+                               return 'ctrl-alt-';
+                       }
+
+                       // Firefox 14+ on Mac
+                       if ( profile.platform === 'mac'
+                               && profile.name === 'firefox'
+                               && profile.versionNumber >= 14
+                       ) {
+                               return 'ctrl-option-';
+                       }
+
+                       // Safari/Konqueror on any platform, or any browser on Mac
+                       // (but not Safari on Windows)
+                       if ( !( profile.platform === 'win' && profile.name === 'safari' )
+                               && ( profile.name === 'safari'
+                               || profile.platform === 'mac'
+                               || profile.name === 'konqueror' )
+                       ) {
+                               return 'ctrl-';
+                       }
+
+                       // Firefox/Iceweasel 2.x and later
+                       if ( ( profile.name === 'firefox' || profile.name === 'iceweasel' )
+                               && profile.versionBase > '1' ) {
+                               return 'alt-shift-';
+                       }
+
+                       return 'alt-';
+               } )(),
+
+               /**
+                * @property {RegExp}
+                * Regex to match accesskey tooltips.
+                *
+                * Should match:
+                *
+                * - "ctrl-option-"
+                * - "alt-shift-"
+                * - "ctrl-alt-"
+                * - "ctrl-"
+                *
+                * The accesskey is matched in group $6.
+                */
+               tooltipAccessKeyRegexp: /\[(ctrl-)?(option-)?(alt-)?(shift-)?(esc-)?(.)\]$/,
+
+               /**
+                * Add the appropriate prefix to the accesskey shown in the tooltip.
+                *
+                * If the `$nodes` parameter is given, only those nodes are updated;
+                * otherwise, depending on browser support, we update either all elements
+                * with accesskeys on the page or a bunch of elements which are likely to
+                * have them on core skins.
+                *
+                * @param {Array|jQuery} [$nodes] A jQuery object, or array of nodes to update.
+                */
+               updateTooltipAccessKeys: function ( $nodes ) {
+                       if ( !$nodes ) {
+                               if ( document.querySelectorAll ) {
+                                       // If we're running on a browser where we can do this efficiently,
+                                       // just find all elements that have accesskeys. We can't use jQuery's
+                                       // polyfill for the selector since looping over all elements on page
+                                       // load might be too slow.
+                                       $nodes = $( document.querySelectorAll( '[accesskey]' ) );
+                               } else {
+                                       // Otherwise go through some elements likely to have accesskeys rather
+                                       // than looping over all of them. Unfortunately this will not fully
+                                       // work for custom skins with different HTML structures. Input, label
+                                       // and button should be rare enough that no optimizations are needed.
+                                       $nodes = $( '#column-one a, #mw-head a, #mw-panel a, #p-logo a, input, label, button' );
+                               }
+                       } else if ( !( $nodes instanceof $ ) ) {
+                               $nodes = $( $nodes );
+                       }
+
+                       $nodes.attr( 'title', function ( i, val ) {
+                               if ( val && util.tooltipAccessKeyRegexp.test( val ) ) {
+                                       return val.replace( util.tooltipAccessKeyRegexp,
+                                               '[' + util.tooltipAccessKeyPrefix + '$6]' );
+                               }
+                               return val;
+                       } );
+               },
+
+               /*
+                * @property {jQuery}
+                * A jQuery object that refers to the content area element.
+                * Populated by #init.
+                */
+               $content: null,
+
+               /**
+                * Add a link to a portlet menu on the page, such as:
+                *
+                * p-cactions (Content actions), p-personal (Personal tools),
+                * p-navigation (Navigation), p-tb (Toolbox)
+                *
+                * The first three paramters are required, the others are optional and
+                * may be null. Though providing an id and tooltip is recommended.
+                *
+                * By default the new link will be added to the end of the list. To
+                * add the link before a given existing item, pass the DOM node
+                * (e.g. `document.getElementById( 'foobar' )`) or a jQuery-selector
+                * (e.g. `'#foobar'`) for that item.
+                *
+                *     mw.util.addPortletLink(
+                *         'p-tb', 'http://mediawiki.org/',
+                *         'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org ', 'm', '#t-print'
+                *     );
+                *
+                * @param {string} portlet ID of the target portlet ( 'p-cactions' or 'p-personal' etc.)
+                * @param {string} href Link URL
+                * @param {string} text Link text
+                * @param {string} [id] ID of the new item, should be unique and preferably have
+                *  the appropriate prefix ( 'ca-', 'pt-', 'n-' or 't-' )
+                * @param {string} [tooltip] Text to show when hovering over the link, without accesskey suffix
+                * @param {string} [accesskey] Access key to activate this link (one character, try
+                *  to avoid conflicts. Use `$( '[accesskey=x]' ).get()` in the console to
+                *  see if 'x' is already used.
+                * @param {HTMLElement|jQuery|string} [nextnode] Element or jQuery-selector string to the item that
+                *  the new item should be added before, should be another item in the same
+                *  list, it will be ignored otherwise
+                *
+                * @return {HTMLElement|null} The added element (a ListItem or Anchor element,
+                * depending on the skin) or null if no element was added to the document.
+                */
+               addPortletLink: function ( portlet, href, text, id, tooltip, accesskey, nextnode ) {
+                       var $item, $link, $portlet, $ul;
+
+                       // Check if there's atleast 3 arguments to prevent a TypeError
+                       if ( arguments.length < 3 ) {
+                               return null;
+                       }
+                       // Setup the anchor tag
+                       $link = $( '<a>' ).attr( 'href', href ).text( text );
+                       if ( tooltip ) {
+                               $link.attr( 'title', tooltip );
+                       }
+
+                       // Select the specified portlet
+                       $portlet = $( '#' + portlet );
+                       if ( $portlet.length === 0 ) {
+                               return null;
+                       }
+                       // Select the first (most likely only) unordered list inside the portlet
+                       $ul = $portlet.find( 'ul' ).eq( 0 );
+
+                       // If it didn't have an unordered list yet, create it
+                       if ( $ul.length === 0 ) {
+
+                               $ul = $( '<ul>' );
+
+                               // If there's no <div> inside, append it to the portlet directly
+                               if ( $portlet.find( 'div:first' ).length === 0 ) {
+                                       $portlet.append( $ul );
+                               } else {
+                                       // otherwise if there's a div (such as div.body or div.pBody)
+                                       // append the <ul> to last (most likely only) div
+                                       $portlet.find( 'div' ).eq( -1 ).append( $ul );
+                               }
+                       }
+                       // Just in case..
+                       if ( $ul.length === 0 ) {
+                               return null;
+                       }
+
+                       // Unhide portlet if it was hidden before
+                       $portlet.removeClass( 'emptyPortlet' );
+
+                       // Wrap the anchor tag in a list item (and a span if $portlet is a Vector tab)
+                       // and back up the selector to the list item
+                       if ( $portlet.hasClass( 'vectorTabs' ) ) {
+                               $item = $link.wrap( '<li><span></span></li>' ).parent().parent();
+                       } else {
+                               $item = $link.wrap( '<li></li>' ).parent();
+                       }
+
+                       // Implement the properties passed to the function
+                       if ( id ) {
+                               $item.attr( 'id', id );
+                       }
+
+                       if ( tooltip ) {
+                               // Trim any existing accesskey hint and the trailing space
+                               tooltip = $.trim( tooltip.replace( util.tooltipAccessKeyRegexp, '' ) );
+                               if ( accesskey ) {
+                                       tooltip += ' [' + accesskey + ']';
+                               }
+                               $link.attr( 'title', tooltip );
+                               if ( accesskey ) {
+                                       util.updateTooltipAccessKeys( $link );
+                               }
+                       }
+
+                       if ( accesskey ) {
+                               $link.attr( 'accesskey', accesskey );
+                       }
+
+                       if ( nextnode ) {
+                               if ( nextnode.nodeType || typeof nextnode === 'string' ) {
+                                       // nextnode is a DOM element (was the only option before MW 1.17, in wikibits.js)
+                                       // or nextnode is a CSS selector for jQuery
+                                       nextnode = $ul.find( nextnode );
+                               } else if ( !nextnode.jquery || ( nextnode.length && nextnode[0].parentNode !== $ul[0] ) ) {
+                                       // Fallback
+                                       $ul.append( $item );
+                                       return $item[0];
+                               }
+                               if ( nextnode.length === 1 ) {
+                                       // nextnode is a jQuery object that represents exactly one element
+                                       nextnode.before( $item );
+                                       return $item[0];
+                               }
+                       }
+
+                       // Fallback (this is the default behavior)
+                       $ul.append( $item );
+                       return $item[0];
+
+               },
+
+               /**
+                * Add a little box at the top of the screen to inform the user of
+                * something, replacing any previous message.
+                * Calling with no arguments, with an empty string or null will hide the message
+                *
+                * @param {Mixed} message The DOM-element, jQuery object or HTML-string to be put inside the message box.
+                * to allow CSS/JS to hide different boxes. null = no class used.
+                * @deprecated since 1.20 Use mw#notify
+                */
+               jsMessage: function ( message ) {
+                       if ( !arguments.length || message === '' || message === null ) {
+                               return true;
+                       }
+                       if ( typeof message !== 'object' ) {
+                               message = $.parseHTML( message );
+                       }
+                       mw.notify( message, { autoHide: true, tag: 'legacy' } );
+                       return true;
+               },
+
+               /**
+                * Validate a string as representing a valid e-mail address
+                * according to HTML5 specification. Please note the specification
+                * does not validate a domain with one character.
+                *
+                * FIXME: should be moved to or replaced by a validation module.
+                *
+                * @param {string} mailtxt E-mail address to be validated.
+                * @return {boolean|null} Null if `mailtxt` was an empty string, otherwise true/false
+                * as determined by validation.
+                */
+               validateEmail: function ( mailtxt ) {
+                       var rfc5322Atext, rfc1034LdhStr, html5EmailRegexp;
+
+                       if ( mailtxt === '' ) {
+                               return null;
+                       }
+
+                       // HTML5 defines a string as valid e-mail address if it matches
+                       // the ABNF:
+                       //      1 * ( atext / "." ) "@" ldh-str 1*( "." ldh-str )
+                       // With:
+                       // - atext   : defined in RFC 5322 section 3.2.3
+                       // - ldh-str : defined in RFC 1034 section 3.5
+                       //
+                       // (see STD 68 / RFC 5234 http://tools.ietf.org/html/std68)
+                       // First, define the RFC 5322 'atext' which is pretty easy:
+                       // atext = ALPHA / DIGIT / ; Printable US-ASCII
+                       //     "!" / "#" /    ; characters not including
+                       //     "$" / "%" /    ; specials. Used for atoms.
+                       //     "&" / "'" /
+                       //     "*" / "+" /
+                       //     "-" / "/" /
+                       //     "=" / "?" /
+                       //     "^" / "_" /
+                       //     "`" / "{" /
+                       //     "|" / "}" /
+                       //     "~"
+                       rfc5322Atext = 'a-z0-9!#$%&\'*+\\-/=?^_`{|}~';
+
+                       // Next define the RFC 1034 'ldh-str'
+                       //      <domain> ::= <subdomain> | " "
+                       //      <subdomain> ::= <label> | <subdomain> "." <label>
+                       //      <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
+                       //      <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
+                       //      <let-dig-hyp> ::= <let-dig> | "-"
+                       //      <let-dig> ::= <letter> | <digit>
+                       rfc1034LdhStr = 'a-z0-9\\-';
+
+                       html5EmailRegexp = new RegExp(
+                               // start of string
+                               '^'
+                               +
+                               // User part which is liberal :p
+                               '[' + rfc5322Atext + '\\.]+'
+                               +
+                               // 'at'
+                               '@'
+                               +
+                               // Domain first part
+                               '[' + rfc1034LdhStr + ']+'
+                               +
+                               // Optional second part and following are separated by a dot
+                               '(?:\\.[' + rfc1034LdhStr + ']+)*'
+                               +
+                               // End of string
+                               '$',
+                               // RegExp is case insensitive
+                               'i'
+                       );
+                       return ( null !== mailtxt.match( html5EmailRegexp ) );
+               },
+
+               /**
+                * Note: borrows from IP::isIPv4
+                *
+                * @param {string} address
+                * @param {boolean} allowBlock
+                * @return {boolean}
+                */
+               isIPv4Address: function ( address, allowBlock ) {
+                       if ( typeof address !== 'string' ) {
+                               return false;
+                       }
+
+                       var     block = allowBlock ? '(?:\\/(?:3[0-2]|[12]?\\d))?' : '',
+                               RE_IP_BYTE = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])',
+                               RE_IP_ADD = '(?:' + RE_IP_BYTE + '\\.){3}' + RE_IP_BYTE;
+
+                       return address.search( new RegExp( '^' + RE_IP_ADD + block + '$' ) ) !== -1;
+               },
+
+               /**
+                * Note: borrows from IP::isIPv6
+                *
+                * @param {string} address
+                * @param {boolean} allowBlock
+                * @return {boolean}
+                */
+               isIPv6Address: function ( address, allowBlock ) {
+                       if ( typeof address !== 'string' ) {
+                               return false;
+                       }
+
+                       var     block = allowBlock ? '(?:\\/(?:12[0-8]|1[01][0-9]|[1-9]?\\d))?' : '',
+                               RE_IPV6_ADD =
+                       '(?:' + // starts with "::" (including "::")
+                       ':(?::|(?::' + '[0-9A-Fa-f]{1,4}' + '){1,7})' +
+                       '|' + // ends with "::" (except "::")
+                       '[0-9A-Fa-f]{1,4}' + '(?::' + '[0-9A-Fa-f]{1,4}' + '){0,6}::' +
+                       '|' + // contains no "::"
+                       '[0-9A-Fa-f]{1,4}' + '(?::' + '[0-9A-Fa-f]{1,4}' + '){7}' +
+                       ')';
+
+                       if ( address.search( new RegExp( '^' + RE_IPV6_ADD + block + '$' ) ) !== -1 ) {
+                               return true;
+                       }
+
+                       RE_IPV6_ADD = // contains one "::" in the middle (single '::' check below)
+                               '[0-9A-Fa-f]{1,4}' + '(?:::?' + '[0-9A-Fa-f]{1,4}' + '){1,6}';
+
+                       return address.search( new RegExp( '^' + RE_IPV6_ADD + block + '$' ) ) !== -1
+                               && address.search( /::/ ) !== -1 && address.search( /::.*::/ ) === -1;
+               }
+       };
+
+       /**
+        * @method wikiGetlink
+        * @inheritdoc #getUrl
+        * @deprecated since 1.23 Use #getUrl instead.
+        */
+       mw.log.deprecate( util, 'wikiGetlink', util.getUrl, 'Use mw.util.getUrl instead.' );
+
+       mw.util = util;
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/startup.js b/resources/src/startup.js
new file mode 100644 (file)
index 0000000..cd21ecc
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * This script provides a function which is run to evaluate whether or not to
+ * continue loading jQuery and the MediaWiki modules. This code should work on
+ * even the most ancient of browsers, so be very careful when editing.
+ */
+
+var mediaWikiLoadStart = ( new Date() ).getTime();
+
+/**
+ * Returns false when run in a black-listed browser
+ *
+ * This function will be deleted after it's used, so do not expand it to be
+ * generally useful beyond startup.
+ *
+ * See also:
+ * - https://www.mediawiki.org/wiki/Compatibility#Browser
+ * - http://jquerymobile.com/gbs/
+ * - http://jquery.com/browser-support/
+ */
+
+/*jshint unused: false */
+function isCompatible( ua ) {
+       if ( ua === undefined ) {
+               ua = navigator.userAgent;
+       }
+
+       // MediaWiki JS or jQuery is known to have issues with:
+       return !(
+               // Internet Explorer < 6
+               ( ua.indexOf( 'MSIE' ) !== -1 && parseFloat( ua.split( 'MSIE' )[1] ) < 6 ) ||
+               // Firefox < 3
+               ( ua.indexOf( 'Firefox/' ) !== -1 && parseFloat( ua.split( 'Firefox/' )[1] ) < 3 ) ||
+               // BlackBerry < 6
+               ua.match( /BlackBerry[^\/]*\/[1-5]\./ ) ||
+               // Open WebOS < 1.5
+               ua.match( /webOS\/1\.[0-4]/ ) ||
+               // Anything PlayStation based.
+               ua.match( /PlayStation/i ) ||
+               // Any Symbian based browsers
+               ua.match( /SymbianOS|Series60/ ) ||
+               // Any NetFront based browser
+               ua.match( /NetFront/ ) ||
+               // Opera Mini, all versions
+               ua.match( /Opera Mini/ ) ||
+               // Nokia's Ovi Browser
+               ua.match( /S40OviBrowser/ ) ||
+               // Google Glass browser groks JS but UI is too limited
+               ( ua.match( /Glass/ ) && ua.match( /Android/ ) )
+       );
+}
+
+/**
+ * The startUp() function will be auto-generated and added below.
+ */
diff --git a/resources/startup.js b/resources/startup.js
deleted file mode 100644 (file)
index cd21ecc..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * This script provides a function which is run to evaluate whether or not to
- * continue loading jQuery and the MediaWiki modules. This code should work on
- * even the most ancient of browsers, so be very careful when editing.
- */
-
-var mediaWikiLoadStart = ( new Date() ).getTime();
-
-/**
- * Returns false when run in a black-listed browser
- *
- * This function will be deleted after it's used, so do not expand it to be
- * generally useful beyond startup.
- *
- * See also:
- * - https://www.mediawiki.org/wiki/Compatibility#Browser
- * - http://jquerymobile.com/gbs/
- * - http://jquery.com/browser-support/
- */
-
-/*jshint unused: false */
-function isCompatible( ua ) {
-       if ( ua === undefined ) {
-               ua = navigator.userAgent;
-       }
-
-       // MediaWiki JS or jQuery is known to have issues with:
-       return !(
-               // Internet Explorer < 6
-               ( ua.indexOf( 'MSIE' ) !== -1 && parseFloat( ua.split( 'MSIE' )[1] ) < 6 ) ||
-               // Firefox < 3
-               ( ua.indexOf( 'Firefox/' ) !== -1 && parseFloat( ua.split( 'Firefox/' )[1] ) < 3 ) ||
-               // BlackBerry < 6
-               ua.match( /BlackBerry[^\/]*\/[1-5]\./ ) ||
-               // Open WebOS < 1.5
-               ua.match( /webOS\/1\.[0-4]/ ) ||
-               // Anything PlayStation based.
-               ua.match( /PlayStation/i ) ||
-               // Any Symbian based browsers
-               ua.match( /SymbianOS|Series60/ ) ||
-               // Any NetFront based browser
-               ua.match( /NetFront/ ) ||
-               // Opera Mini, all versions
-               ua.match( /Opera Mini/ ) ||
-               // Nokia's Ovi Browser
-               ua.match( /S40OviBrowser/ ) ||
-               // Google Glass browser groks JS but UI is too limited
-               ( ua.match( /Glass/ ) && ua.match( /Android/ ) )
-       );
-}
-
-/**
- * The startUp() function will be auto-generated and added below.
- */
diff --git a/resources/styleguide-template/index.html b/resources/styleguide-template/index.html
deleted file mode 100644 (file)
index 99f3e4f..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<!DOCTYPE html>
-<html class="no-js" lang="en">
-<head>
-       <meta charset="utf-8">
-       <title>MediaWiki Living Styleguide</title>
-       <meta name="description" content="">
-       <meta name="generator" content="kss-node" />
-       <meta name="viewport" content="width=device-width">
-       <link rel="stylesheet" href="public/kss.css">
-       <link rel="stylesheet" href="public/style.css">
-</head>
-<body><div id="kss-wrapper">
-       <header id="kss-header">
-               <hgroup><h1>MediaWiki Living Styleguide</h1></hgroup>
-       </header>
-       <nav class="content">
-               <ul>
-               <li><a href="index.html">0.0: Overview</a></li>
-               {{#eachRoot}}
-               <li>
-                       <a href="section-{{reference}}.html">{{reference}}.0: {{header}}</a>
-               </li>
-               {{/eachRoot}}
-               </ul>
-       </nav>
-       <article>
-               {{#if overview}}
-                       {{html overview}}
-               {{else}}
-                       {{#eachSection rootNumber}}
-                               {{#whenDepth 1}}
-                                       <h1>{{ reference }}.0 - {{ header }}</h1>
-                               {{else}}
-                                       {{#whenDepth 2}}
-                                       <h2>{{ reference }} - {{ header }}</h2>
-                                       {{/whenDepth}}
-                                       {{#whenDepth 3}}
-                                       <h3>{{ reference }} - {{ header }}</h3>
-                                       {{/whenDepth}}
-                               {{/whenDepth}}
-                               {{#ifAny markup modifiers}}
-                                               <div>{{html description}}</div>
-                                               <strong>Default styling</strong><br>
-                                               {{modifierMarkup}}
-                                               {{#eachModifier}}
-                                               {{html description}}<br>
-                                               <p>{{name}}</p>
-                                               {{modifierMarkup}}
-                                               {{/eachModifier}}
-                                               <pre class="prettyprint lang-html">{{markup}}</pre>
-                               {{else}}
-                                               {{#if description}}
-                                                       {{html description}}
-                                               {{/if}}
-                               {{/ifAny}}
-                       {{/eachSection}}
-               {{/if}}
-       </article>
-</div></body>
-</html>
diff --git a/resources/styleguide-template/public/kss.less b/resources/styleguide-template/public/kss.less
deleted file mode 100644 (file)
index 431303d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-header {
-       padding: .8em 16px 0;
-}
-
-nav {
-       float: left;
-       width: 200px;
-}
-
-article {
-       margin-left: 250px;
-}
-
-.content.kss-no-margin {
-       margin: 0;
-}
-
-// FIXME: Remove when typography module in mediawiki-ui
-body {
-       font-family: "Nimbus Sans L", "Liberation Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
-}
-h1,h2,h3,h4,h5 {
-       font-family: "DejaVu Serif", Georgia, serif;
-}
diff --git a/resources/styleguide-template/public/less.js b/resources/styleguide-template/public/less.js
deleted file mode 100644 (file)
index 89b7637..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-//
-// LESS - Leaner CSS v1.2.1
-// http://lesscss.org
-// 
-// Copyright (c) 2009-2011, Alexis Sellier
-// Licensed under the Apache 2.0 License.
-//
-(function(a,b){function c(b){return a.less[b.split("/")[1]]}function m(){var a=document.getElementsByTagName("style");for(var b=0;b<a.length;b++)a[b].type.match(k)&&(new d.Parser).parse(a[b].innerHTML||"",function(c,d){var e=d.toCSS(),f=a[b];f.type="text/css",f.styleSheet?f.styleSheet.cssText=e:f.innerHTML=e})}function n(a,b){for(var c=0;c<d.sheets.length;c++)o(d.sheets[c],a,b,d.sheets.length-(c+1))}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i);var m=i.match(/([^\/]+)$/)[1];s(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())r(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type,filename:m})).parse(a,function(d,e){if(d)return w(d,i);try{c(d,e,a,b,{local:!1,lastModified:g,remaining:f}),u(document.getElementById("less-error-message:"+q(i)))}catch(d){w(d,i)}})}catch(h){w(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function q(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function r(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||q(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(v("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function s(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=t(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0||f.status>=200&&f.status<300?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function t(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return v("browser doesn't support AJAX."),null}}function u(a){return a&&a.parentNode.removeChild(a)}function v(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function w(a,b){var c="less-error-message:"+q(b),e='<li><label>{line}</label><pre class="{class}">{content}</pre></li>',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="<h3>"+(a.message||"There is an error in your .less file")+"</h3>"+'<p>in <a href="'+j+'">'+j+"</a> ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="<br/>"+a.stack.split("\n").slice(1).join("<br/>"):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":</p>"+"<ul>"+i.join("")+"</ul>"),f.innerHTML=h,r([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d<c;d++)d in this&&a.call(b,this[d],d,this)}),Array.prototype.map||(Array.prototype.map=function(a){var b=this.length>>>0,c=new Array(b),d=arguments[1];for(var e=0;e<b;e++)e in this&&(c[e]=a.call(d,this[e],e,this));return c}),Array.prototype.filter||(Array.prototype.filter=function(a){var b=[],c=arguments[1];for(var d=0;d<this.length;d++)a.call(c,this[d])&&b.push(this[d]);return b}),Array.prototype.reduce||(Array.prototype.reduce=function(a){var b=this.length>>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c<b;c++)c in this&&(d=a.call(null,d,this[c],c,this));return d}),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){var b=this.length,c=arguments[1]||0;if(!b)return-1;if(c>=b)return-1;c<0&&(c+=b);for(;c<b;c++){if(!Object.prototype.hasOwnProperty.call(this,c))continue;if(a===this[c])return c}return-1}),Object.keys||(Object.keys=function(a){var b=[];for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&b.push(c);return b}),String.prototype.trim||(String.prototype.trim=function(){return String(this).replace(/^\s\s*/,"").replace(/\s\s*$/,"")});var d,f;typeof environment=="object"&&{}.toString.call(environment)==="[object Environment]"?(typeof a=="undefined"?d={}:d=a.less={},f=d.tree={},d.mode="rhino"):typeof a=="undefined"?(d=exports,f=c("./tree"),d.mode="node"):(typeof a.less=="undefined"&&(a.less={}),d=a.less,f=a.less.tree={},d.mode="browser"),d.Parser=function(b){function t(){j=m[i],k=h,n=h}function u(){m[i]=j,h=k,n=h}function v(){h>n&&(m[i]=m[i].slice(h-n),n=h)}function w(a){var b,c,d,e,f,j,k,l;if(a instanceof Function)return a.call(o.parsers);if(typeof a=="string")b=g.charAt(h)===a?a:null,d=1,v();else{v();if(!(b=a.exec(m[i])))return null;d=b[0].length}if(b){l=h+=d,j=h+m[i].length-d;while(h<j){e=g.charCodeAt(h);if(e!==32&&e!==10&&e!==9)break;h++}return m[i]=m[i].slice(d+(h-l)),n=h,m[i].length===0&&i<m.length-1&&i++,typeof b=="string"?b:b.length===1?b[0]:b}}function x(a,b){var c=w(a);if(!!c)return c;y(b||(typeof a=="string"?"expected '"+a+"' got '"+g.charAt(h)+"'":"unexpected token"))}function y(a,b){throw{index:h,type:b||"Syntax",message:a}}function z(a){return typeof a=="string"?g.charAt(h)===a:a.test(m[i])?!0:!1}function A(a,b){return a.filename&&b.filename&&a.filename!==b.filename?o.imports.contents[a.filename]:g}function B(a,b){for(var c=a,d=-1;c>=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function C(a,b){var c=A(a,b),d=B(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&B(a.call,c)+1,this.callExtract=g[B(a.call,c)],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var g,h,i,j,k,l,m,n,o,q=this,r=function(){},s=this.imports={paths:b&&b.paths||[],queue:[],files:{},contents:{},mime:b&&b.mime,error:null,push:function(a,c){var e=this;this.queue.push(a),d.Parser.importer(a,this.paths,function(b,d,f){e.queue.splice(e.queue.indexOf(a),1),e.files[a]=d,e.contents[a]=f,b&&!e.error&&(e.error=b),c(b,d),e.queue.length===0&&r()},b)}};return this.env=b=b||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,o={imports:s,parse:function(a,e){var j,k,p,q,s,t,u=[],v,x=null;h=i=n=l=0,m=[],g=a.replace(/\r\n/g,"\n"),m=function(a){var c=0,d=/[^"'`\{\}\/\(\)]+/g,e=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,f=0,h,i=a[0],j,k;for(var l=0,m,n;l<g.length;l++){d.lastIndex=l,(h=d.exec(g))&&h.index===l&&(l+=h[0].length,i.push(h[0])),m=g.charAt(l),e.lastIndex=l,!k&&!j&&m==="/"&&(n=g.charAt(l+1),(n==="/"||n==="*")&&(h=e.exec(g))&&h.index===l&&(l+=h[0].length,i.push(h[0]),m=g.charAt(l)));if(m==="{"&&!k&&!j)f++,i.push(m);else if(m==="}"&&!k&&!j)f--,i.push(m),a[++c]=i=[];else if(m==="("&&!k&&!j)i.push(m),j=!0;else if(m===")"&&!k&&j)i.push(m),j=!1;else{if(m==='"'||m==="'"||m==="`")k?k=k===m?!1:k:k=m;i.push(m)}}if(f>0)throw{type:"Syntax",message:"Missing closing `}`",filename:b.filename};return a.map(function(a){return a.join("")})}([[]]);try{j=new f.Ruleset([],w(this.parsers.primary)),j.root=!0}catch(y){return e(new C(y,b))}j.toCSS=function(a){var e,g,h;return function(e,g){var h=[],i;e=e||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,!1,0)}),h=[new f.Ruleset(null,g)]);try{var j=a.call(this,{frames:h}).toCSS([],{compress:e.compress||!1})}catch(k){throw new C(k,b)}if(i=o.imports.error)throw i instanceof C?i:new C(i,b);return e.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):e.compress?j.replace(/(\s)+/g,"$1"):j}}(j.eval);if(h<g.length-1){h=l,t=g.split("\n"),s=(g.slice(0,h).match(/\n/g)||"").length+1;for(var z=h,A=-1;z>=0&&g.charAt(z)!=="\n";z--)A++;x={type:"Parse",message:"Syntax Error on line "+s,index:h,filename:b.filename,line:s,column:A,extract:[t[s-2],t[s-1],t[s]]}}this.imports.queue.length>0?r=function(){e(x,j)}:e(x,j)},parsers:{primary:function(){var a,b=[];while((a=w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(g.charAt(h)!=="/")return;if(g.charAt(h+1)==="/")return new f.Comment(w(/^\/\/.*/),!0);if(a=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new f.Comment(a)},entities:{quoted:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=='"'&&g.charAt(b)!=="'")return;c&&w("~");if(a=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new f.Quoted(a[0],a[1]||a[2],c)},keyword:function(){var a;if(a=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return f.colors.hasOwnProperty(a)?new f.Color(f.colors[a].slice(1)):new f.Keyword(a)},call:function(){var a,c,d=h;if(!(a=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(m[i])))return;a=a[1].toLowerCase();if(a==="url")return null;h+=a.length;if(a==="alpha")return w(this.alpha);w("("),c=w(this.entities.arguments);if(!w(")"))return;if(a)return new f.Call(a,c,d,b.filename)},arguments:function(){var a=[],b;while(b=w(this.entities.assignment)||w(this.expression)){a.push(b);if(!w(","))break}return a},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)},assignment:function(){var a,b;if((a=w(/^\w+(?=\s?=)/i))&&w("=")&&(b=w(this.entity)))return new f.Assignment(a,b)},url:function(){var a;if(g.charAt(h)!=="u"||!w(/^url\(/))return;return a=w(this.entities.quoted)||w(this.entities.variable)||w(this.entities.dataURI)||w(/^[-\w%@$\/.&=:;#+?~]+/)||"",x(")"),new f.URL(a.value||a.data||a instanceof f.Variable?a:new f.Anonymous(a),s.paths)},dataURI:function(){var a;if(w(/^data:/)){a={},a.mime=w(/^[^\/]+\/[^,;)]+/)||"",a.charset=w(/^;\s*charset=[^,;)]+/)||"",a.base64=w(/^;\s*base64/)||"",a.data=w(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,c=h;if(g.charAt(h)==="@"&&(a=w(/^@@?[\w-]+/)))return new f.Variable(a,c,b.filename)},color:function(){var a;if(g.charAt(h)==="#"&&(a=w(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new f.Color(a[1])},dimension:function(){var a,b=g.charCodeAt(h);if(b>57||b<45||b===47)return;if(a=w(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new f.Dimension(a[1],a[2])},javascript:function(){var a,b=h,c;g.charAt(b)==="~"&&(b++,c=!0);if(g.charAt(b)!=="`")return;c&&w("~");if(a=w(/^`([^`]*)`/))return new f.JavaScript(a[1],h,c)}},variable:function(){var a;if(g.charAt(h)==="@"&&(a=w(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!z(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=w(this.entity))&&w("/")&&(b=w(this.entity)))return new f.Shorthand(a,b)},mixin:{call:function(){var a=[],c,d,e,i=h,j=g.charAt(h),k=!1;if(j!=="."&&j!=="#")return;while(c=w(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new f.Element(d,c,h)),d=w(">");w("(")&&(e=w(this.entities.arguments))&&w(")"),w(this.important)&&(k=!0);if(a.length>0&&(w(";")||z("}")))return new f.mixin.Call(a,e,i,b.filename,k)},definition:function(){var a,b=[],c,d,e,i,j;if(g.charAt(h)!=="."&&g.charAt(h)!=="#"||z(/^[^{]*(;|})/))return;t();if(c=w(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=c[1];while(e=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)){e instanceof f.Variable?w(":")?(i=x(this.expression,"expected expression"),b.push({name:e.name,value:i})):b.push({name:e.name}):b.push({value:e});if(!w(","))break}x(")"),w(/^when/)&&(j=x(this.conditions,"expected condition")),d=w(this.block);if(d)return new f.mixin.Definition(a,b,d,j);u()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||z("}")},alpha:function(){var a;if(!w(/^\(opacity=/i))return;if(a=w(/^\d+/)||w(this.entities.variable))return x(")"),new f.Alpha(a)},element:function(){var a,b,c,d;c=w(this.combinator),a=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||w("*")||w(this.attribute)||w(/^\([^)@]+\)/),a||w("(")&&(d=w(this.entities.variable))&&w(")")&&(a=new f.Paren(d));if(a)return new f.Element(c,a,h);if(c.value&&c.value.charAt(0)==="&")return new f.Element(c,null,h)},combinator:function(){var a,b=g.charAt(h);if(b===">"||b==="+"||b==="~"){h++;while(g.charAt(h)===" ")h++;return new f.Combinator(b)}if(b==="&"){a="&",h++,g.charAt(h)===" "&&(a="& ");while(g.charAt(h)===" ")h++;return new f.Combinator(a)}if(b===":"&&g.charAt(h+1)===":"){h+=2;while(g.charAt(h)===" ")h++;return new f.Combinator("::")}return g.charAt(h-1)===" "?new f.Combinator(" "):new f.Combinator(null)},selector:function(){var a,b,c=[],d,e;while(b=w(this.element)){d=g.charAt(h),c.push(b);if(d==="{"||d==="}"||d===";"||d===",")break}if(c.length>0)return new f.Selector(c)},tag:function(){return w(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||w("*")},attribute:function(){var a="",b,c,d;if(!w("["))return;if(b=w(/^[a-zA-Z-]+/)||w(this.entities.quoted))(d=w(/^[|~*$^]?=/))&&(c=w(this.entities.quoted)||w(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!w("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(w("{")&&(a=w(this.primary))&&w("}"))return a},ruleset:function(){var a=[],b,c,d;t();while(b=w(this.selector)){a.push(b),w(this.comment);if(!w(","))break;w(this.comment)}if(a.length>0&&(c=w(this.block)))return new f.Ruleset(a,c);l=h,u()},rule:function(){var a,b,c=g.charAt(h),d,e;t();if(c==="."||c==="#"||c==="&")return;if(a=w(this.variable)||w(this.property)){a.charAt(0)!="@"&&(e=/^([^@+\/'"*`(;{}-]*);/.exec(m[i]))?(h+=e[0].length-1,b=new f.Anonymous(e[1])):a==="font"?b=w(this.font):b=w(this.value),d=w(this.important);if(b&&w(this.end))return new f.Rule(a,b,d,k);l=h,u()}},"import":function(){var a,b,c=h;if(w(/^@import\s+/)&&(a=w(this.entities.quoted)||w(this.entities.url))){b=w(this.mediaFeatures);if(w(";"))return new f.Import(a,s,b,c)}},mediaFeature:function(){var a=[];do if(e=w(this.entities.keyword))a.push(e);else if(w("(")){p=w(this.property),e=w(this.entity);if(!w(")"))return null;if(p&&e)a.push(new f.Paren(new f.Rule(p,e,null,h,!0)));else{if(!e)return null;a.push(new f.Paren(e))}}while(e);if(a.length>0)return new f.Expression(a)},mediaFeatures:function(){var a,b=[];while(a=w(this.mediaFeature)){b.push(a);if(!w(","))break}return b.length>0?b:null},media:function(){var a;if(w(/^@media/)){a=w(this.mediaFeatures);if(rules=w(this.block))return new f.Directive("@media",rules,a)}},directive:function(){var a,b,c,d,e,i;if(g.charAt(h)!=="@")return;if(b=w(this["import"])||w(this.media))return b;if(a=w(/^@page|@keyframes/)||w(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){d=(w(/^[^{]+/)||"").trim();if(c=w(this.block))return new f.Directive(a+" "+d,c)}else if(a=w(/^@[-a-z]+/))if(a==="@font-face"){if(c=w(this.block))return new f.Directive(a,c)}else if((b=w(this.entity))&&w(";"))return new f.Directive(a,b)},font:function(){var a=[],b=[],c,d,e,g;while(g=w(this.shorthand)||w(this.entity))b.push(g);a.push(new f.Expression(b));if(w(","))while(g=w(this.expression)){a.push(g);if(!w(","))break}return new f.Value(a)},value:function(){var a,b=[],c;while(a=w(this.expression)){b.push(a);if(!w(","))break}if(b.length>0)return new f.Value(b)},important:function(){if(g.charAt(h)==="!")return w(/^! *important/)},sub:function(){var a;if(w("(")&&(a=w(this.expression))&&w(")"))return a},multiplication:function(){var a,b,c,d;if(a=w(this.operand)){while(!z(/^\/\*/)&&(c=w("/")||w("*"))&&(b=w(this.operand)))d=new f.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,b,c,d;if(a=w(this.multiplication)){while((c=w(/^[-+]\s+/)||g.charAt(h-1)!=" "&&(w("+")||w("-")))&&(b=w(this.multiplication)))d=new f.Operation(c,[d||a,b]);return d||a}},conditions:function(){var a,b,c=h,d;if(a=w(this.condition)){while(w(",")&&(b=w(this.condition)))d=new f.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,e=h,g=!1;w(/^not/)&&(g=!0),x("(");if(a=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(d=w(/^(?:>=|=<|[<=>])/))?(b=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?c=new f.Condition(d,a,b,e,g):y("expected expression"):c=new f.Condition("=",a,new f.Keyword("true"),e,g),x(")"),w(/^and/)?new f.Condition("and",c,w(this.condition)):c},operand:function(){var a,b=g.charAt(h+1);g.charAt(h)==="-"&&(b==="@"||b==="(")&&(a=w("-"));var c=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return a?new f.Operation("*",[new f.Dimension(-1),c]):c},expression:function(){var a,b,c=[],d;while(a=w(this.addition)||w(this.entity))c.push(a);if(c.length>0)return new f.Expression(c)},property:function(){var a;if(a=w(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e<c.length;e++)d=d.replace(/%[sda]/i,function(a){var b=a.match(/s/i)?c[e].value:c[e].toCSS();return a.match(/[A-Z]$/)?encodeURIComponent(b):b});return d=d.replace(/%%/g,"%"),new a.Quoted('"'+d+'"',d)},round:function(a){return this._math("round",a)},ceil:function(a){return this._math("ceil",a)},floor:function(a){return this._math("floor",a)},_math:function(b,d){if(d instanceof a.Dimension)return new a.Dimension(Math[b](c(d)),d.unit);if(typeof d=="number")return Math[b](d);throw{type:"Argument",message:"argument must be a number"}},argb:function(b){return new a.Anonymous(b.toARGB())},percentage:function(b){return new a.Dimension(b.value*100,"%")},color:function(b){if(b instanceof a.Quoted)return new a.Color(b.value.slice(1));throw{type:"Argument",message:"argument must be a string"}},iscolor:function(b){return this._isa(b,a.Color)},isnumber:function(b){return this._isa(b,a.Dimension)},isstring:function(b){return this._isa(b,a.Quoted)},iskeyword:function(b){return this._isa(b,a.Keyword)},isurl:function(b){return this._isa(b,a.URL)},ispixel:function(b){return b instanceof a.Dimension&&b.unit==="px"?a.True:a.False},ispercentage:function(b){return b instanceof a.Dimension&&b.unit==="%"?a.True:a.False},isem:function(b){return b instanceof a.Dimension&&b.unit==="em"?a.True:a.False},_isa:function(b,c){return b instanceof c?a.True:a.False}}})(c("./tree")),function(a){a.colors={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgrey:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",grey:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgrey:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"}}(c("./tree")),function(a){a.Alpha=function(a){this.value=a},a.Alpha.prototype={toCSS:function(){return"alpha(opacity="+(this.value.toCSS?this.value.toCSS():this.value)+")"},eval:function(a){return this.value.eval&&(this.value=this.value.eval(a)),this}}}(c("../tree")),function(a){a.Anonymous=function(a){this.value=a.value||a},a.Anonymous.prototype={toCSS:function(){return this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Assignment=function(a,b){this.key=a,this.value=b},a.Assignment.prototype={toCSS:function(){return this.key+"="+(this.value.toCSS?this.value.toCSS():this.value)},eval:function(a){return this.value.eval&&(this.value=this.value.eval(a)),this}}}(c("../tree")),function(a){a.Call=function(a,b,c,d){this.name=a,this.args=b,this.index=c,this.filename=d},a.Call.prototype={eval:function(b){var c=this.args.map(function(a){return a.eval(b)});if(!(this.name in a.functions))return new a.Anonymous(this.name+"("+c.map(function(a){return a.toCSS()}).join(", ")+")");try{return a.functions[this.name].apply(a.functions,c)}catch(d){throw{type:d.type||"Runtime",message:"error evaluating function `"+this.name+"`"+(d.message?": "+d.message:""),index:this.index,filename:this.filename}}},toCSS:function(a){return this.eval(a).toCSS()}}}(c("../tree")),function(a){a.Color=function(a,b){Array.isArray(a)?this.rgb=a:a.length==6?this.rgb=a.match(/.{2}/g).map(function(a){return parseInt(a,16)}):this.rgb=a.split("").map(function(a){return parseInt(a+a,16)}),this.alpha=typeof b=="number"?b:1},a.Color.prototype={eval:function(){return this},toCSS:function(){return this.alpha<1?"rgba("+this.rgb.map(function(a){return Math.round(a)}).concat(this.alpha).join(", ")+")":"#"+this.rgb.map(function(a){return a=Math.round(a),a=(a>255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b<c?6:0);break;case b:g=(c-a)/j+2;break;case c:g=(a-b)/j+4}g/=6}return{h:g*360,s:h,l:i,a:d}},toARGB:function(){var a=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+a.map(function(a){return a=Math.round(a),a=(a>255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else{if(!c.compare)throw{type:"Type",message:"Unable to perform comparison",index:d};e=c.compare(b)}switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value<this.value?1:0:-1}}}(c("../tree")),function(a){a.Directive=function(b,c,d){this.name=b,this.features=d&&new a.Value(d),Array.isArray(c)?(this.ruleset=new a.Ruleset([],c),this.ruleset.allowImports=!0):this.value=c},a.Directive.prototype={toCSS:function(a,b){var c=this.features?" "+this.features.toCSS(b):"";return this.ruleset?(this.ruleset.root=!0,this.name+c+(b.compress?"{":" {\n  ")+this.ruleset.toCSS(a,b).trim().replace(/\n/g,"\n  ")+(b.compress?"}":"\n}\n")):this.name+" "+this.value.toCSS()+";\n"},eval:function(a){return this.features=this.features&&this.features.eval(a),a.frames.unshift(this),this.ruleset=this.ruleset&&this.ruleset.eval(a),a.frames.shift(),this},variable:function(b){return a.Ruleset.prototype.variable.call(this.ruleset,b)},find:function(){return a.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.ruleset)}}}(c("../tree")),function(a){a.Element=function(b,c,d){this.combinator=b instanceof a.Combinator?b:new a.Combinator(b),typeof c=="string"?this.value=c.trim():c?this.value=c:this.value="",this.index=d},a.Element.prototype.eval=function(b){return new a.Element(this.combinator,this.value.eval?this.value.eval(b):this.value,this.index)},a.Element.prototype.toCSS=function(a){return this.combinator.toCSS(a||{})+(this.value.toCSS?this.value.toCSS(a):this.value)},a.Combinator=function(a){a===" "?this.value=" ":a==="& "?this.value="& ":this.value=a?a.trim():""},a.Combinator.prototype.toCSS=function(a){return{"":""," ":" ","&":"","& ":" ",":":" :","::":"::","+":a.compress?"+":" + ","~":a.compress?"~":" ~ ",">":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e<c.rules.length;e++)c.rules[e]instanceof a.Import&&Array.prototype.splice.apply(c.rules,[e,1].concat(c.rules[e].eval(b)));return this.features?new a.Directive("@media",c.rules,this.features.value):c.rules}}}(c("../tree")),function(a){a.JavaScript=function(a,b,c){this.escaped=c,this.expression=a,this.index=b},a.JavaScript.prototype={eval:function(b){var c,d=this,e={},f=this.expression.replace(/@\{([\w-]+)\}/g,function(c,e){return a.jsify((new a.Variable("@"+e,d.index)).eval(b))});try{f=new Function("return ("+f+")")}catch(g){throw{message:"JavaScript evaluation error: `"+
-f+"`",index:this.index}}for(var h in b.frames[0].variables())e[h.slice(1)]={value:b.frames[0].variables()[h].value,toJS:function(){return this.value.eval(b).toCSS()}};try{c=f.call(e)}catch(g){throw{message:"JavaScript evaluation error: '"+g.name+": "+g.message+"'",index:this.index}}return typeof c=="string"?new a.Quoted('"'+c+'"',c,this.escaped,this.index):Array.isArray(c)?new a.Anonymous(c.join(", ")):new a.Anonymous(c)}}}(c("../tree")),function(a){a.Keyword=function(a){this.value=a},a.Keyword.prototype={eval:function(){return this},toCSS:function(){return this.value},compare:function(b){return b instanceof a.Keyword?b.value===this.value?0:1:-1}},a.True=new a.Keyword("true"),a.False=new a.Keyword("false")}(c("../tree")),function(a){a.mixin={},a.mixin.Call=function(b,c,d,e,f){this.selector=new a.Selector(b),this.arguments=c,this.index=d,this.filename=e,this.important=f},a.mixin.Call.prototype={eval:function(a){var b,c,d=[],e=!1;for(var f=0;f<a.frames.length;f++)if((b=a.frames[f].find(this.selector)).length>0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g<b.length;g++)if(b[g].match(c,a))try{Array.prototype.push.apply(d,b[g].eval(a,this.arguments,this.important).rules),e=!0}catch(h){throw{message:h.message,index:h.index,filename:this.filename,stack:h.stack,call:this.index}}if(e)return d;throw{type:"Runtime",message:"No matching definition was found for `"+this.selector.toCSS().trim()+"("+this.arguments.map(function(a){return a.toCSS()}).join(", ")+")`",index:this.index,filename:this.filename}}throw{type:"Name",message:this.selector.toCSS().trim()+" is undefined",index:this.index,filename:this.filename}}},a.mixin.Definition=function(b,c,d,e){this.name=b,this.selectors=[new a.Selector([new a.Element(null,b)])],this.params=c,this.condition=e,this.arity=c.length,this.rules=d,this._lookups={},this.required=c.reduce(function(a,b){return!b.name||b.name&&!b.value?a+1:a},0),this.parent=a.Ruleset.prototype,this.frames=[]},a.mixin.Definition.prototype={toCSS:function(){return""},variable:function(a){return this.parent.variable.call(this,a)},variables:function(){return this.parent.variables.call(this)},find:function(){return this.parent.find.apply(this,arguments)},rulesets:function(){return this.parent.rulesets.apply(this)},evalParams:function(b,c){var d=new a.Ruleset(null,[]);for(var e=0,f;e<this.params.length;e++)if(this.params[e].name){if(!(f=c&&c[e]||this.params[e].value))throw{type:"Runtime",message:"wrong number of arguments for "+this.name+" ("+c.length+" for "+this.arity+")"};d.rules.unshift(new a.Rule(this.params[e].name,f.eval(b)))}return d},eval:function(b,c,d){var e=this.evalParams(b,c),f,g=[],h;for(var i=0;i<Math.max(this.params.length,c&&c.length);i++)g.push(c[i]||this.params[i].value);return e.rules.unshift(new a.Rule("@arguments",(new a.Expression(g)).eval(b))),h=d?this.rules.map(function(b){return new a.Rule(b.name,b.value,"!important",b.index)}):this.rules.slice(0),(new a.Ruleset(null,h)).eval({frames:[this,e].concat(this.frames,b.frames)})},match:function(a,b){var c=a&&a.length||0,d,e;if(c<this.required)return!1;if(this.required>0&&c>this.params.length)return!1;if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;f<d;f++)if(!this.params[f].name&&a[f].eval(b).toCSS()!=this.params[f].value.eval(b).toCSS())return!1;return!0}}}(c("../tree")),function(a){a.Operation=function(a,b){this.op=a.trim(),this.operands=b},a.Operation.prototype.eval=function(b){var c=this.operands[0].eval(b),d=this.operands[1].eval(b),e;if(c instanceof a.Dimension&&d instanceof a.Color){if(this.op!=="*"&&this.op!=="+")throw{name:"OperationError",message:"Can't substract or divide a color from a number"};e=d,d=c,c=e}return c.operate(this.op,d)},a.operate=function(a,b,c){switch(a){case"+":return b+c;case"-":return b-c;case"*":return b*c;case"/":return b/c}}}(c("../tree")),function(a){a.Paren=function(a){this.value=a},a.Paren.prototype={toCSS:function(a){return"("+this.value.toCSS(a)+")"},eval:function(b){return new a.Paren(this.value.eval(b))}}}(c("../tree")),function(a){a.Quoted=function(a,b,c,d){this.escaped=c,this.value=b||"",this.quote=a.charAt(0),this.index=d},a.Quoted.prototype={toCSS:function(){return this.escaped?this.value:this.quote+this.value+this.quote},eval:function(b){var c=this,d=this.value.replace(/`([^`]+)`/g,function(d,e){return(new a.JavaScript(e,c.index,!0)).eval(b).value}).replace(/@\{([\w-]+)\}/g,function(d,e){var f=(new a.Variable("@"+e,c.index)).eval(b);return"value"in f?f.value:f.toCSS()});return new a.Quoted(this.quote+d+this.quote,d,this.escaped,this.index)}}}(c("../tree")),function(a){a.Rule=function(b,c,d,e,f){this.name=b,this.value=c instanceof a.Value?c:new a.Value([c]),this.important=d?" "+d.trim():"",this.index=e,this.inline=f||!1,b.charAt(0)==="@"?this.variable=!0:this.variable=!1},a.Rule.prototype.toCSS=function(a){return this.variable?"":this.name+(a.compress?":":": ")+this.value.toCSS(a)+this.important+(this.inline?"":";")},a.Rule.prototype.eval=function(b){return new a.Rule(this.name,this.value.eval(b),this.important,this.index,this.inline)},a.Shorthand=function(a,b){this.a=a,this.b=b},a.Shorthand.prototype={toCSS:function(a){return this.a.toCSS(a)+"/"+this.b.toCSS(a)},eval:function(){return this}}}(c("../tree")),function(a){a.Ruleset=function(a,b){this.selectors=a,this.rules=b,this._lookups={}},a.Ruleset.prototype={eval:function(b){var c=this.selectors&&this.selectors.map(function(a){return a.eval(b)}),d=new a.Ruleset(c,this.rules.slice(0));d.root=this.root,d.allowImports=this.allowImports,b.frames.unshift(d);if(d.root||d.allowImports)for(var e=0;e<d.rules.length;e++)d.rules[e]instanceof a.Import&&Array.prototype.splice.apply(d.rules,[e,1].concat(d.rules[e].eval(b)));for(var e=0;e<d.rules.length;e++)d.rules[e]instanceof a.mixin.Definition&&(d.rules[e].frames=b.frames.slice(0));for(var e=0;e<d.rules.length;e++)d.rules[e]instanceof a.mixin.Call&&Array.prototype.splice.apply(d.rules,[e,1].concat(d.rules[e].eval(b)));for(var e=0,f;e<d.rules.length;e++)f=d.rules[e],f instanceof a.mixin.Definition||(d.rules[e]=f.eval?f.eval(b):f);return b.frames.shift(),d},match:function(a){return!a||a.length===0},variables:function(){return this._variables?this._variables:this._variables=this.rules.reduce(function(b,c){return c instanceof a.Rule&&c.variable===!0&&(b[c.name]=c),b},{})},variable:function(a){return this.variables()[a]},rulesets:function(){return this._rulesets?this._rulesets:this._rulesets=this.rules.filter(function(b){return b instanceof a.Ruleset||b instanceof a.mixin.Definition})},find:function(b,c){c=c||this;var d=[],e,f,g=b.toCSS();return g in this._lookups?this._lookups[g]:(this.rulesets().forEach(function(e){if(e!==c)for(var g=0;g<e.selectors.length;g++)if(f=b.match(e.selectors[g])){b.elements.length>e.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j<this.rules.length;j++)i=this.rules[j],i.rules||i instanceof a.Directive?f.push(i.toCSS(g,c)):i instanceof a.Comment?i.silent||(this.root?f.push(i.toCSS(c)):e.push(i.toCSS(c))):i.toCSS&&!i.variable?e.push(i.toCSS(c)):i.value&&!i.variable&&e.push(i.value.toString());return f=f.join(""),this.root?d.push(e.join(c.compress?"":"\n")):e.length>0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n  ")+e.join(c.compress?"":"\n  ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d<c.length;d++)this.joinSelector(a,b,c[d])},joinSelector:function(b,c,d){var e=[],f=[],g=[],h=[],i=!1,j;for(var k=0;k<d.elements.length;k++)j=d.elements[k],j.combinator.value.charAt(0)==="&"&&(i=!0),i?h.push(j):g.push(j);i||(h=g,g=[]),g.length>0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l<c.length;l++)b.push(e.concat(c[l]).concat(f))}}}(c("../tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){var b=this.elements.length,c=a.elements.length,d=Math.min(b,c);if(b<c)return!1;for(var e=0;e<d;e++)if(this.elements[e].value!==a.elements[e].value)return!1;return!0},a.Selector.prototype.eval=function(b){return new a.Selector(this.elements.map(function(a){return a.eval(b)}))},a.Selector.prototype.toCSS=function(a){return this._css?this._css:this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("../tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(typeof a!="undefined"&&!/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(b.value)&&c.length>0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c<a.length;c++)if(d=b.call(a,a[c]))return d;return null},a.jsify=function(a){return Array.isArray(a.value)&&a.value.length>1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c,d,e){b&&r(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l<j.length;l++)(j[l].rel==="stylesheet/less"||j[l].rel.match(/stylesheet/)&&j[l].type.match(k))&&d.sheets.push(j[l]);d.refresh=function(a){var b,c;b=c=new Date,n(function(a,d,e,f,g){g.local?v("loading "+f.href+" from cache."):(v("parsed "+f.href+" successfully."),r(d.toCSS(),f,g.lastModified)),v("css for "+f.href+" generated in "+(new Date-c)+"ms"),g.remaining===0&&v("css generated in "+(new Date-b)+"ms"),c=new Date},a),m()},d.refreshStyles=m,d.refresh(d.env==="development")})(window);
\ No newline at end of file
index 06f5eba..ad7942a 100644 (file)
@@ -185,12 +185,6 @@ table {
        font-size: 100%;
 }
 
-/* Prevent citations and subscripts from interfering with the line-height */
-sup,
-sub {
-       line-height: 1;
-}
-
 /* Forms */
 fieldset {
        border: 1px solid #2f6fab;
diff --git a/skins/common/images/button_math.png b/skins/common/images/button_math.png
deleted file mode 100644 (file)
index 507e4b5..0000000
Binary files a/skins/common/images/button_math.png and /dev/null differ
index 0aa76f5..6e5f570 100644 (file)
@@ -1,18 +1 @@
-<?xml version="1.0"?>\r
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\r
-<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="128px" height="128px" id="RSSicon" viewBox="0 0 256 256">\r
-<defs>\r
-<linearGradient x1="0.085" y1="0.085" x2="0.915" y2="0.915" id="RSSg">\r
-<stop  offset="0.0" stop-color="#E3702D"/><stop  offset="0.1071" stop-color="#EA7D31"/>\r
-<stop  offset="0.3503" stop-color="#F69537"/><stop  offset="0.5" stop-color="#FB9E3A"/>\r
-<stop  offset="0.7016" stop-color="#EA7C31"/><stop  offset="0.8866" stop-color="#DE642B"/>\r
-<stop  offset="1.0" stop-color="#D95B29"/>\r
-</linearGradient>\r
-</defs>\r
-<rect width="256" height="256" rx="55" ry="55" x="0"  y="0"  fill="#CC5D15"/>\r
-<rect width="246" height="246" rx="50" ry="50" x="5"  y="5"  fill="#F49C52"/>\r
-<rect width="236" height="236" rx="47" ry="47" x="10" y="10" fill="url(#RSSg)"/>\r
-<circle cx="68" cy="189" r="24" fill="#FFF"/>\r
-<path d="M160 213h-34a82 82 0 0 0 -82 -82v-34a116 116 0 0 1 116 116z" fill="#FFF"/>\r
-<path d="M184 213A140 140 0 0 0 44 73 V 38a175 175 0 0 1 175 175z" fill="#FFF"/>\r
-</svg>\r
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 256 256"><defs><linearGradient x1=".085" y1=".085" x2=".915" y2=".915" id="a"><stop offset="0" stop-color="#E3702D"/><stop offset=".107" stop-color="#EA7D31"/><stop offset=".35" stop-color="#F69537"/><stop offset=".5" stop-color="#FB9E3A"/><stop offset=".702" stop-color="#EA7C31"/><stop offset=".887" stop-color="#DE642B"/><stop offset="1" stop-color="#D95B29"/></linearGradient></defs><rect width="256" height="256" rx="55" ry="55" fill="#CC5D15"/><rect width="246" height="246" rx="50" ry="50" x="5" y="5" fill="#F49C52"/><rect width="236" height="236" rx="47" ry="47" x="10" y="10" fill="url(#a)"/><circle cx="68" cy="189" r="24" fill="#FFF"/><path d="M160 213h-34a82 82 0 0 0-82-82v-34a116 116 0 0 1 116 116zM184 213a140 140 0 0 0-140-140v-35a175 175 0 0 1 175 175z" fill="#FFF"/></svg>
\ No newline at end of file
index 2797305..98fbe8d 100644 (file)
@@ -1,12 +1 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->\r
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\r
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"\r
-        width="21.059px" height="21.06px" viewBox="0 0 21.059 21.06" enable-background="new 0 0 21.059 21.06" xml:space="preserve">\r
-<path fill="#575757" d="M10.529,0C4.715,0,0,4.714,0,10.529s4.715,10.53,10.529,10.53c5.816,0,10.529-4.715,10.529-10.53\r
-       S16.346,0,10.529,0z M10.527,16.767c-0.861,0-1.498-0.688-1.498-1.516c0-0.862,0.637-1.534,1.498-1.534c0.828,0,1.5,0.672,1.5,1.534\r
-       C12.027,16.078,11.355,16.767,10.527,16.767z M12.664,10.255c-0.723,0.568-1,0.931-1,1.739v0.5H9.459v-0.603\r
-       c0-1.517,0.449-2.136,1.154-2.688c0.707-0.552,1.139-0.845,1.139-1.637c0-0.672-0.414-1.051-1.24-1.051\r
-       c-0.707,0-1.328,0.189-1.982,0.638L7.479,5.346c0.861-0.604,1.93-1.034,3.342-1.034c1.912,0,3.516,1.051,3.516,3.066\r
-       C14.336,8.808,13.543,9.566,12.664,10.255z"/>\r
-</svg>\r
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="21.059" height="21.06"><path fill="#575757" d="M10.529 0c-5.814 0-10.529 4.714-10.529 10.529s4.715 10.53 10.529 10.53c5.816 0 10.529-4.715 10.529-10.53s-4.712-10.529-10.529-10.529zm-.002 16.767c-.861 0-1.498-.688-1.498-1.516 0-.862.637-1.534 1.498-1.534.828 0 1.5.672 1.5 1.534 0 .827-.672 1.516-1.5 1.516zm2.137-6.512c-.723.568-1 .931-1 1.739v.5h-2.205v-.603c0-1.517.449-2.136 1.154-2.688.707-.552 1.139-.845 1.139-1.637 0-.672-.414-1.051-1.24-1.051-.707 0-1.328.189-1.982.638l-1.051-1.807c.861-.604 1.93-1.034 3.342-1.034 1.912 0 3.516 1.051 3.516 3.066-.001 1.43-.794 2.188-1.673 2.877z"/></svg>
\ No newline at end of file
index 942cbac..6b052b3 100644 (file)
@@ -881,10 +881,8 @@ ul.mw-gallery-packed-hover li.gallerybox:hover div.gallerytextwrapper,
 ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper,
 ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper {
        position:absolute;
-       opacity:.8;
-       filter:alpha(opacity=80);
-       zoom: 1;
-       background-color:white;
+       background: white;
+       background: rgba(255, 255, 255, 0.8);
        padding: 5px 10px;
        bottom: 0;
        left: 0; /* Needed for IE */
@@ -899,13 +897,6 @@ ul.mw-gallery-packed {
        text-align: center;
 }
 
-ul.mw-gallery-packed-hover div.gallerytext,
-ul.mw-gallery-packed-overlay div.gallerytext {
-       opacity: 1;
-       position: relative; /* Resets opacity in old IE */
-}
-
-
 .mw-ajax-loader {
        /* @embed */
        background-image: url(images/ajax-loader.gif);
@@ -1217,3 +1208,9 @@ table.floatleft {
 .mw-content-ltr .mw-content-rtl .mw-editsection {
        margin-right: 1em;
 }
+
+/* Prevent citations and subscripts from interfering with the line-height */
+sup,
+sub {
+       line-height: 1;
+}
index df5682e..0ccf115 100644 (file)
@@ -62,7 +62,7 @@ mw.log.deprecate( win, 'redirectToFragment', function ( fragment ) {
  * @deprecated since 1.17 Use jquery.client instead
  */
 
-msg = 'Use feature detection or module jquery.client instead';
+msg = 'Use feature detection or module jquery.client instead.';
 
 mw.log.deprecate( win, 'clientPC', ua, msg );
 
@@ -93,7 +93,7 @@ mw.log.deprecate( win, 'ie6_bugs', false, msg );
  *
  * @deprecated since 1.17 Use jQuery instead
  */
-msg = 'Use jQuery instead';
+msg = 'Use jQuery instead.';
 
 // Ignored dummy values
 mw.log.deprecate( win, 'doneOnloadHook', undefined, msg );
@@ -146,7 +146,7 @@ $( win ).on( 'load', function () {
  *
  * @deprecated since 1.17 Use jquery.checkboxShiftClick instead
  */
-msg = 'Use jquery.checkboxShiftClick instead';
+msg = 'Use jquery.checkboxShiftClick instead.';
 mw.log.deprecate( win, 'checkboxes', [], msg );
 mw.log.deprecate( win, 'lastCheckbox', null, msg );
 mw.log.deprecate( win, 'setupCheckboxShiftClick', $.noop, msg );
@@ -160,8 +160,8 @@ mw.log.deprecate( win, 'checkboxClickHandler', $.noop, msg );
  *
  * @deprecated since 1.17 Use mw.toolbar instead
  */
-mw.log.deprecate( win, 'mwEditButtons', [], 'Use mw.toolbar instead' );
-mw.log.deprecate( win, 'mwCustomEditButtons', [], 'Use mw.toolbar instead' );
+mw.log.deprecate( win, 'mwEditButtons', [], 'Use mw.toolbar instead.' );
+mw.log.deprecate( win, 'mwCustomEditButtons', [], 'Use mw.toolbar instead.' );
 
 /**
  * Spinner creation, injection and removal
@@ -170,8 +170,8 @@ mw.log.deprecate( win, 'mwCustomEditButtons', [], 'Use mw.toolbar instead' );
  *
  * @deprecated since 1.18 Use jquery.spinner instead
  */
-mw.log.deprecate( win, 'injectSpinner', $.noop, 'Use jquery.spinner instead' );
-mw.log.deprecate( win, 'removeSpinner', $.noop, 'Use jquery.spinner instead' );
+mw.log.deprecate( win, 'injectSpinner', $.noop, 'Use jquery.spinner instead.' );
+mw.log.deprecate( win, 'removeSpinner', $.noop, 'Use jquery.spinner instead.' );
 
 /**
  * Escape utilities
@@ -180,8 +180,8 @@ mw.log.deprecate( win, 'removeSpinner', $.noop, 'Use jquery.spinner instead' );
  *
  * @deprecated since 1.18 Use mw.html instead
  */
-mw.log.deprecate( win, 'escapeQuotes', $.noop,'Use mw.html instead' );
-mw.log.deprecate( win, 'escapeQuotesHTML', $.noop,'Use mw.html instead' );
+mw.log.deprecate( win, 'escapeQuotes', $.noop, 'Use mw.html instead.' );
+mw.log.deprecate( win, 'escapeQuotesHTML', $.noop, 'Use mw.html instead.' );
 
 /**
  * Display a message to the user
@@ -191,7 +191,7 @@ mw.log.deprecate( win, 'escapeQuotesHTML', $.noop,'Use mw.html instead' );
  * @deprecated since 1.17 Use mediawiki.notify instead
  * @param {string|HTMLElement} message To be put inside the message box
  */
-mw.log.deprecate( win, 'jsMsg', mw.util.jsMessage, 'Use mediawiki.notify instead' );
+mw.log.deprecate( win, 'jsMsg', mw.util.jsMessage, 'Use mediawiki.notify instead.' );
 
 /**
  * Misc. utilities
@@ -200,7 +200,7 @@ mw.log.deprecate( win, 'jsMsg', mw.util.jsMessage, 'Use mediawiki.notify instead
  *
  * @deprecated since 1.17 Use mediawiki.util instead
  */
-msg = 'Use mediawiki.util instead';
+msg = 'Use mediawiki.util instead.';
 mw.log.deprecate( win, 'tooltipAccessKeyPrefix', 'alt-', msg );
 mw.log.deprecate( win, 'tooltipAccessKeyRegexp', /\[(alt-)?(.)\]$/, msg );
 mw.log.deprecate( win, 'updateTooltipAccessKeys', mw.util.updateTooltipAccessKeys, msg );
index 3e26a22..60792d5 100644 (file)
@@ -1,75 +1,9 @@
 // FIXME: This size of this CSS is ridiculous. Please refactor (see bug 54604)
 @import "mediawiki.mixins.less";
-
-div#content a.external {
+// External links
+.external {
        background-position: center right;
        background-repeat: no-repeat;
-       .background-image-svg('images/external-link-ltr-icon.svg', 'images/external-link-ltr-icon.png');
-       padding-right: 13px;
-}
-div#content a.external[href ^="https://"],
-.link-https {
-       background-position: center right;
-       background-repeat: no-repeat;
-       .background-image-svg('images/lock-icon.svg', 'images/lock-icon.png');
-       padding-right: 13px;
-}
-div#content a.external[href ^="mailto:"],
-.link-mailto {
-       background-position: center right;
-       background-repeat: no-repeat;
-       .background-image-svg('images/mail-icon.svg', 'images/mail-icon.png');
-       padding-right: 13px;
-}
-div#content a.external[href ^="news:"] {
-       background-position: center right;
-       background-repeat: no-repeat;
-       .background-image-svg('images/news-icon.svg', 'images/news-icon.png');
-       padding-right: 13px;
-}
-div#content a.external[href ^="ftp://"],
-.link-ftp {
-       background-position: center right;
-       background-repeat: no-repeat;
-       .background-image-svg('images/file-icon.svg', 'images/file-icon.png');
-       padding-right: 13px;
-}
-div#content a.external[href ^="irc://"],
-div#content a.external[href ^="ircs://"],
-.link-irc {
-       background-position: center right;
-       background-repeat: no-repeat;
-       .background-image-svg('images/talk-icon.svg', 'images/talk-icon.png');
-       padding-right: 13px;
-}
-div#content a.external[href $=".ogg"], div#content a.external[href $=".OGG"],
-div#content a.external[href $=".mid"], div#content a.external[href $=".MID"],
-div#content a.external[href $=".midi"], div#content a.external[href $=".MIDI"],
-div#content a.external[href $=".mp3"], div#content a.external[href $=".MP3"],
-div#content a.external[href $=".wav"], div#content a.external[href $=".WAV"],
-div#content a.external[href $=".wma"], div#content a.external[href $=".WMA"],
-.link-audio {
-       background-position: center right;
-       background-repeat: no-repeat;
-       .background-image-svg('images/audio-icon.svg', 'images/audio-icon.png');
-       padding-right: 13px;
-}
-div#content a.external[href $=".ogm"], div#content a.external[href $=".OGM"],
-div#content a.external[href $=".avi"], div#content a.external[href $=".AVI"],
-div#content a.external[href $=".mpeg"], div#content a.external[href $=".MPEG"],
-div#content a.external[href $=".mpg"], div#content a.external[href $=".MPG"],
-.link-video {
-       background-position: center right;
-       background-repeat: no-repeat;
-       .background-image-svg('images/video-icon.svg', 'images/video-icon.png');
-       padding-right: 13px;
-}
-div#content a.external[href $=".pdf"], div#content a.external[href $=".PDF"],
-div#content a.external[href *=".pdf#"], div#content a.external[href *=".PDF#"],
-div#content a.external[href *=".pdf?"], div#content a.external[href *=".PDF?"],
-.link-document {
-       background-position: center right;
-       background-repeat: no-repeat;
-       .background-image-svg('images/document-icon.svg', 'images/document-icon.png');
+       .background-image-svg('images/external-link-ltr-icon.svg', 'images/external-link-ltr-icon.png' );
        padding-right: 13px;
 }
index 64a449f..b943caa 100644 (file)
@@ -1,33 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   version="1.1"
-   width="16"
-   height="16"
-   id="svg2">
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(0,-1036.0288)"
-     id="layer1">
-    <path
-       d="M 10.028624,3.7729932 8.1976442,6.9443424 6.3666649,3.7729932 z"
-       transform="matrix(0,-2.7307791,1.576616,0,0.05143855,1066.4148)"
-       id="path2985"
-       style="fill:#797979;fill-opacity:1;stroke:none" />
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M6.001 2.998l5.001 5-5.001 5z" fill="#797979"/></svg>
\ No newline at end of file
index 938494b..5faf356 100644 (file)
@@ -1,33 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   version="1.1"
-   width="16"
-   height="16"
-   id="svg2">
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(0,-1036.0288)"
-     id="layer1">
-    <path
-       d="M 10.028624,3.7729932 8.1976442,6.9443424 6.3666649,3.7729932 z"
-       transform="matrix(0,2.7307791,-1.576616,0,15.948561,1021.6428)"
-       id="path2985"
-       style="fill:#797979;fill-opacity:1;stroke:none" />
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M9.999 13.002l-5.001-5 5.001-5z" fill="#797979"/></svg>
\ No newline at end of file
index be1ad89..826c280 100644 (file)
@@ -1,33 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   version="1.1"
-   width="22"
-   height="16"
-   id="svg2">
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(0,-1036.3622)"
-     id="layer1">
-    <path
-       d="M 10.028624,3.7729932 8.1976442,6.9443424 6.3666649,3.7729932 z"
-       transform="matrix(2.7307791,0,0,1.576616,-11.885956,1036.4136)"
-       id="path2985"
-       style="fill:#929292;fill-opacity:1;stroke:none" />
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="22" height="16"><path d="M15.502 6.001l-5 5.001-5-5.001z" fill="#929292"/></svg>
\ No newline at end of file
index a991501..8e31b2f 100644 (file)
@@ -1,33 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   version="1.1"
-   width="22"
-   height="16"
-   id="svg2">
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(0,-1036.3622)"
-     id="layer1">
-    <path
-       d="M 10.028624,3.7729932 8.1976442,6.9443424 6.3666649,3.7729932 z"
-       transform="matrix(2.7307791,0,0,1.576616,-11.885956,1036.4136)"
-       id="path2985"
-       style="fill:#797979;fill-opacity:1;stroke:none" />
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="22" height="16"><path d="M15.502 6.001l-5 5.001-5-5.001z" fill="#797979"/></svg>
\ No newline at end of file
index a1b58e5..e744ec3 100644 (file)
@@ -1,33 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   version="1.1"
-   width="16"
-   height="16"
-   id="svg2">
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(0,-1036.3622)"
-     id="layer1">
-    <path
-       d="M 10.028624,3.7729932 8.1976442,6.9443424 6.3666649,3.7729932 z"
-       transform="matrix(2.7307791,0,0,1.576616,-14.385956,1036.4136)"
-       id="path2985"
-       style="fill:#797979;fill-opacity:1;stroke:none" />
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.002 6.001l-5 5.001-5-5.001z" fill="#797979"/></svg>
\ No newline at end of file
diff --git a/skins/vector/images/audio-icon.png b/skins/vector/images/audio-icon.png
deleted file mode 100644 (file)
index 5a1d2f4..0000000
Binary files a/skins/vector/images/audio-icon.png and /dev/null differ
diff --git a/skins/vector/images/audio-icon.svg b/skins/vector/images/audio-icon.svg
deleted file mode 100644 (file)
index 91ca5c4..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="10"
-   height="10"
-   id="svg6167">
-  <defs
-     id="defs6169">
-    <linearGradient
-       id="linearGradient6707">
-      <stop
-         id="stop6709"
-         style="stop-color:#b2bf46;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop6711"
-         style="stop-color:#c8d17b;stop-opacity:1"
-         offset="1" />
-    </linearGradient>
-    <linearGradient
-       x1="22.262903"
-       y1="9.1418257"
-       x2="22.262903"
-       y2="5.3889236"
-       id="linearGradient6713"
-       xlink:href="#linearGradient6707"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.96979296,0,0,0.96979296,858.75554,710.2631)" />
-  </defs>
-  <metadata
-     id="metadata6172">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-877.85712,-710.2193)"
-     id="layer1">
-    <path
-       d="m 880.63649,710.74799 0,5.78845 c -0.30291,0.0337 -0.60613,0.10534 -0.90918,0.24245 -1.08747,0.49204 -1.62536,1.48002 -1.21224,2.21234 0.41311,0.73233 1.60977,0.91632 2.69723,0.42429 0.87694,-0.39677 1.37959,-1.10894 1.33347,-1.75775 l 0,-0.15153 0,-3.81856 2.93968,0 0,2.84876 c -0.30894,0.0309 -0.62965,0.10227 -0.93948,0.24245 -1.07493,0.48636 -1.6206,1.48846 -1.21225,2.21234 0.40836,0.72389 1.59201,0.91065 2.66694,0.42429 0.87404,-0.39547 1.38893,-1.11233 1.33346,-1.75775 l 0,-0.15153 0,-6.75825 -6.69763,0 z"
-       id="path6186"
-       style="fill:url(#linearGradient6713);fill-opacity:1;stroke:#757f2a;stroke-width:0.96979296px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-  </g>
-</svg>
diff --git a/skins/vector/images/document-icon.png b/skins/vector/images/document-icon.png
deleted file mode 100644 (file)
index 4d56572..0000000
Binary files a/skins/vector/images/document-icon.png and /dev/null differ
diff --git a/skins/vector/images/document-icon.svg b/skins/vector/images/document-icon.svg
deleted file mode 100644 (file)
index fd05df8..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="10"
-   height="10"
-   id="svg7339">
-  <defs
-     id="defs7341">
-    <linearGradient
-       id="linearGradient7918">
-      <stop
-         id="stop7920"
-         style="stop-color:#e2e2e2;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop7922"
-         style="stop-color:#f8f8f8;stop-opacity:1"
-         offset="1" />
-    </linearGradient>
-    <radialGradient
-       cx="-16.71875"
-       cy="3.344311"
-       r="2"
-       fx="-16.71875"
-       fy="3.344311"
-       id="radialGradient7968"
-       xlink:href="#linearGradient7918"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.4065972,0,0,2.1428629,810.35359,682.73485)" />
-  </defs>
-  <metadata
-     id="metadata7344">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-783.57141,-687.36218)"
-     id="layer1">
-    <path
-       d="m 785.05579,687.85437 0,9.09375 7.03125,0 0,-6.84375 -2.25,-2.25 -4.78125,0 z"
-       id="rect7358"
-       style="fill:#ffffff;fill-opacity:1;stroke:#878787;stroke-width:0.89999998;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-    <path
-       d="m 786.52454,689.44812 0,6.09375 4,0 0,-5.28125 -0.84375,0 0,-0.8125 -3.15625,0 z"
-       id="rect7896"
-       style="fill:url(#radialGradient7968);fill-opacity:1;stroke:none" />
-    <path
-       d="m 790.33911,693.22626 c -0.0498,0.19786 0.33032,0.17787 0.003,0.27815 -0.16998,0.24799 0.39939,0.51157 -0.0311,0.38026 -0.0547,-0.17272 -0.19121,-0.57992 0.0276,-0.65857 m -0.23638,0.40635 c -0.1524,0.0463 -0.6328,0.0553 -0.24172,0.21827 0.48594,0.05 -0.34395,0.2177 -0.26091,-0.17076 -0.08,-0.37141 0.5251,-0.43406 0.50275,-0.0476 m -0.0898,-0.0264 c 0.0121,-0.34938 -0.523,0.0801 -0.0661,1.6e-4 0.022,-3e-5 0.0441,-7e-5 0.0661,-1e-4 M 789.086,693.4864 c 0.29829,-0.46808 0.54605,0.50739 0.27992,0.36129 0.16156,-0.25017 -0.25661,-0.58879 -0.25488,-0.19318 0.0618,0.20786 -0.16306,0.36284 -0.0814,0.0576 0.0107,-0.40895 -0.3951,-0.2098 -0.28228,0.0968 -0.10398,0.30793 -0.19195,-0.59656 0.0363,-0.38389 0.11037,-0.0424 0.2633,-0.11931 0.3025,0.062 m -0.79072,0.16676 c -0.35692,-0.0559 0.0391,0.45637 0.0912,0.0607 0.0111,-0.0474 -0.0478,-0.0975 -0.0913,-0.0606 m 0.1792,-0.0371 c 0.0389,0.27609 4.8e-4,0.31202 -0.23096,0.30993 -0.40958,0.0339 -0.12848,-0.45975 0.12931,-0.3933 -0.0182,-0.14721 -0.50917,-0.032 -0.16875,-0.16893 0.13714,-0.0119 0.30604,0.0969 0.27048,0.25186 m -1.04972,-0.38964 c -0.0498,0.19787 0.33033,0.17786 0.003,0.27815 -0.16997,0.24801 0.39941,0.51157 -0.0312,0.38026 -0.0548,-0.17265 -0.1912,-0.5799 0.0275,-0.65857 m -0.36616,0.15537 c 0.24316,0.0804 0.005,0.86043 -0.008,0.29992 0.004,-0.10008 0.0106,-0.19944 0.008,-0.29992 z m 0,-0.21289 c 0.22907,-0.0248 -0.0564,0.25715 0,0 z m -0.17285,0.229 c -0.0882,0.10339 -0.47525,0.0905 -0.12796,0.20033 0.32998,0.11579 -0.0901,0.56917 -0.25377,0.26243 0.35714,0.0875 0.26894,-0.20613 0.0291,-0.26075 -0.0991,-0.20406 0.219,-0.31306 0.35275,-0.20238 m 2.10283,-1.18179 c -0.31133,-0.19291 -0.2311,0.78642 -0.32232,0.2231 -0.003,-0.21834 -0.0409,-0.33207 0.20367,-0.28984 0.0532,-0.0761 0.16542,-0.007 0.1188,0.0663 m -0.71625,-0.0206 c -0.45977,0.0927 0.20216,0.73875 0.1549,0.16183 -0.008,-0.0784 -0.0689,-0.16424 -0.1549,-0.16175 m 0,-0.0762 c 0.53548,0.0229 0.0809,0.95772 -0.22515,0.4264 -0.0799,-0.16794 0.006,-0.44314 0.22515,-0.4264 z m -0.48925,-0.19976 c 0.18272,0.15398 0.0847,0.54861 0.0579,0.75376 -0.12668,-0.16038 -0.0274,-0.52657 -0.0579,-0.75376 z m -0.39942,0.27588 c -0.45976,0.0927 0.20217,0.73874 0.15491,0.16183 -0.008,-0.0784 -0.0689,-0.16425 -0.15491,-0.16175 m 0,-0.0762 c 0.53548,0.0229 0.0809,0.95772 -0.22514,0.4264 -0.0799,-0.16793 0.006,-0.44314 0.22514,-0.4264 z m -0.4868,0.0961 c -0.0625,-0.16476 0.0794,-0.45885 0.09,-0.12059 -0.0239,0.26428 0.11747,0.64725 -0.22523,0.59616 -0.43366,0.0367 -0.28113,-0.79293 0.1054,-0.51731 l 0.0299,0.0419 m -0.30616,0.19092 c 0.047,0.51755 0.63135,-0.23866 0.10766,-0.19898 -0.0793,0.0264 -0.13034,0.11753 -0.10766,0.19898 z m 2.44043,-1.41901 c 0.29826,-0.46803 0.54607,0.50725 0.27992,0.36136 0.16147,-0.25014 -0.25659,-0.58875 -0.25486,-0.19318 0.0619,0.20787 -0.16304,0.36286 -0.0814,0.0576 0.0107,-0.40895 -0.3951,-0.2098 -0.28228,0.0968 -0.10398,0.30793 -0.19195,-0.59655 0.0362,-0.3839 0.11037,-0.0424 0.26328,-0.11929 0.30249,0.062 m -1.07,0.22585 c -0.0292,-0.18312 0.0291,-0.522 0.10111,-0.12385 -0.10501,0.40792 0.38701,0.2743 0.27403,-0.0627 0.0564,-0.3908 0.20452,0.56128 -0.0268,0.36504 -0.17034,0.0747 -0.37234,0.0484 -0.34922,-0.17885 m -0.16355,-0.31494 c -0.0882,0.10339 -0.47525,0.0905 -0.12796,0.20033 0.32998,0.11579 -0.0901,0.56917 -0.25377,0.26243 0.35714,0.0875 0.26894,-0.20613 0.0291,-0.26075 -0.0991,-0.20406 0.219,-0.31306 0.35275,-0.20238 m -0.89668,0.44906 c 0.0709,0.22245 -0.11848,0.41831 -0.0905,0.067 -0.0102,-0.29611 -0.0793,-0.68343 0.34185,-0.49802 0.37303,0.11125 0.0193,0.78296 -0.25134,0.43095 m 0.30567,-0.19091 c -0.0477,-0.51709 -0.63035,0.23885 -0.1077,0.199 0.0793,-0.0265 0.1303,-0.11753 0.1077,-0.199 z m -0.66993,-0.2739 c 0.24336,0.0802 0.006,0.86052 -0.008,0.29994 0.004,-0.10009 0.0107,-0.19945 0.008,-0.29994 z m 0,-0.21289 c 0.22926,-0.0249 -0.0564,0.25727 0,0 z m 2.58203,-0.93213 c 0.29827,-0.46803 0.54607,0.50727 0.27992,0.36136 0.16146,-0.25013 -0.25657,-0.58874 -0.25484,-0.19316 0.0618,0.20786 -0.16306,0.36284 -0.0814,0.0576 0.0107,-0.40895 -0.3951,-0.2098 -0.28228,0.0968 -0.10398,0.30793 -0.19195,-0.59655 0.0363,-0.38389 0.11037,-0.0424 0.26329,-0.11932 0.30249,0.062 m -0.57342,0.14577 c -0.15244,0.0463 -0.6328,0.0553 -0.24172,0.21831 0.48594,0.0499 -0.34396,0.21764 -0.26091,-0.1708 -0.08,-0.37142 0.52507,-0.43399 0.50275,-0.0476 m -0.0898,-0.0264 c 0.0121,-0.34938 -0.52298,0.0801 -0.066,1.6e-4 0.022,-3e-5 0.0441,-7e-5 0.0661,-10e-5 m -0.4519,-0.14058 c -0.31132,-0.1929 -0.23109,0.78642 -0.32231,0.2231 -0.003,-0.21839 -0.0409,-0.33204 0.20369,-0.28978 0.0533,-0.0761 0.16541,-0.007 0.11871,0.0664 m -0.71627,-0.0206 c -0.45977,0.0927 0.20216,0.73875 0.1549,0.16183 -0.008,-0.0784 -0.0689,-0.16424 -0.1549,-0.16175 m 0,-0.0762 c 0.53548,0.0229 0.0809,0.95772 -0.22514,0.4264 -0.0799,-0.16794 0.006,-0.44314 0.22514,-0.4264 z m -0.74706,-0.169 c 0.25031,0.19128 -0.10354,0.79515 0.43395,0.67146 -0.24652,0.23651 -0.54896,-0.0523 -0.43399,-0.36033 0,-0.10371 0,-0.20743 0,-0.31114"
-       id="path3041"
-       style="fill:#000000;fill-opacity:1;stroke:none" />
-    <path
-       d="m 789.74329,687.77624 0,2.35938 2.34375,0"
-       id="path7894"
-       style="fill:none;stroke:#878787;stroke-width:0.89999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-  </g>
-</svg>
index 3918bef..5969d03 100644 (file)
@@ -1,47 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   version="1.1"
-   width="10"
-   height="10"
-   id="svg2">
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-826.42859,-698.79077)"
-     id="layer1">
-    <rect
-       width="5.9821429"
-       height="5.9821429"
-       x="826.92859"
-       y="702.30865"
-       id="rect2996"
-       style="fill:#ffffff;fill-opacity:1;stroke:#0066cc;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-    <g
-       transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,762.87,-359.88339)"
-       id="g4815">
-      <path
-         d="m 796.90819,700.28317 3.70127,-3.70126 3.81174,3.81175 -0.0189,2.20336 -1.85234,0 0,3.8543 -3.80233,0 0,-3.97108 -1.8536,0 z"
-         id="path4777"
-         style="fill:#0066ff;fill-opacity:1;stroke:none" />
-      <path
-         d="m 800.60946,698.00244 3.46986,3.43865 -2.5702,0 0,4.07436 -1.7362,0 0,-4.07436 -2.61754,-3.6e-4 z"
-         id="path4779"
-         style="fill:#ffffff;fill-opacity:1;stroke:none" />
-    </g>
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"><g transform="translate(-826.429 -698.791)"><rect width="5.982" height="5.982" x="826.929" y="702.309" fill="#fff" stroke="#06c"/><g><path d="M831.194 698.791h5.234v5.391l-1.571 1.545-1.31-1.31-2.725 2.725-2.689-2.689 2.808-2.808-1.311-1.311z" fill="#06f"/><path d="M835.424 699.795l.022 4.885-1.817-1.817-2.881 2.881-1.228-1.228 2.881-2.881-1.851-1.851z" fill="#fff"/></g></g></svg>
\ No newline at end of file
index 326a425..75a7025 100644 (file)
@@ -1,50 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   version="1.1"
-   width="10"
-   height="10"
-   id="svg2">
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-826.42859,-698.79077)"
-     id="layer1">
-    <rect
-       width="5.9821429"
-       height="5.9821429"
-       x="-835.92859"
-       y="702.30865"
-       transform="scale(-1,1)"
-       id="rect2996"
-       style="fill:#ffffff;fill-opacity:1;stroke:#0066cc;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-    <g
-       transform="matrix(-0.70710678,0.70710678,0.70710678,0.70710678,899.98717,-359.88339)"
-       id="g4815">
-      <path
-         d="m 796.90819,700.28317 3.70127,-3.70126 3.81174,3.81175 -0.0189,2.20336 -1.85234,0 0,3.8543 -3.80233,0 0,-3.97108 -1.8536,0 z"
-         id="path4777"
-         style="fill:#0066ff;fill-opacity:1;stroke:none" />
-      <path
-         d="m 800.60946,698.00244 3.46986,3.43865 -2.5702,0 0,4.07436 -1.7362,0 0,-4.07436 -2.61754,-3.6e-4 z"
-         id="path4779"
-         style="fill:#ffffff;fill-opacity:1;stroke:none" />
-    </g>
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"><g transform="translate(-826.429 -698.791)"><rect width="5.982" height="5.982" x="-835.929" y="702.309" transform="scale(-1 1)" fill="#fff" stroke="#06c"/><g><path d="M831.663 698.791h-5.234v5.391l1.571 1.545 1.31-1.31 2.725 2.725 2.689-2.689-2.808-2.808 1.311-1.311z" fill="#06f"/><path d="M827.433 699.795l-.022 4.885 1.817-1.817 2.881 2.881 1.228-1.228-2.881-2.881 1.851-1.851z" fill="#fff"/></g></g></svg>
\ No newline at end of file
diff --git a/skins/vector/images/file-icon.png b/skins/vector/images/file-icon.png
deleted file mode 100644 (file)
index ed24669..0000000
Binary files a/skins/vector/images/file-icon.png and /dev/null differ
diff --git a/skins/vector/images/file-icon.svg b/skins/vector/images/file-icon.svg
deleted file mode 100644 (file)
index 98d9041..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="10"
-   height="10"
-   id="svg7339">
-  <defs
-     id="defs7341">
-    <linearGradient
-       id="linearGradient7918">
-      <stop
-         id="stop7920"
-         style="stop-color:#e2e2e2;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop7922"
-         style="stop-color:#f8f8f8;stop-opacity:1"
-         offset="1" />
-    </linearGradient>
-    <radialGradient
-       cx="-16.71875"
-       cy="3.344311"
-       r="2"
-       fx="-16.71875"
-       fy="3.344311"
-       id="radialGradient7931"
-       xlink:href="#linearGradient7918"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.4065972,0,0,2.1428629,6.7977966,-4.7132748)" />
-  </defs>
-  <metadata
-     id="metadata7344">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-783.57141,-687.36218)"
-     id="layer1">
-    <g
-       transform="translate(19.984375,0.08593751)"
-       id="g7926">
-      <path
-         d="m -18.5,0.40625 0,9.09375 7.03125,0 0,-6.84375 -2.25,-2.25 -4.78125,0 z"
-         transform="translate(783.57141,687.36218)"
-         id="rect7358"
-         style="fill:#ffffff;fill-opacity:1;stroke:#878787;stroke-width:0.89999998;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-      <path
-         d="m -17.03125,2 0,6.09375 4,0 0,-5.28125 -0.84375,0 0,-0.8125 -3.15625,0 z"
-         transform="translate(783.57141,687.36218)"
-         id="rect7896"
-         style="fill:url(#radialGradient7931);fill-opacity:1;stroke:none" />
-      <path
-         d="m -13.8125,0.32812497 0,2.35937503 2.34375,0"
-         transform="translate(783.57141,687.36218)"
-         id="path7894"
-         style="fill:none;stroke:#878787;stroke-width:0.89999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-    </g>
-  </g>
-</svg>
diff --git a/skins/vector/images/lock-icon.png b/skins/vector/images/lock-icon.png
deleted file mode 100644 (file)
index a9ba8a7..0000000
Binary files a/skins/vector/images/lock-icon.png and /dev/null differ
diff --git a/skins/vector/images/lock-icon.svg b/skins/vector/images/lock-icon.svg
deleted file mode 100644 (file)
index bad5daf..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="10"
-   height="10"
-   id="svg3813">
-  <defs
-     id="defs3815">
-    <linearGradient
-       id="linearGradient4348">
-      <stop
-         id="stop4350"
-         style="stop-color:#fff8bb;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop4352"
-         style="stop-color:#e9d84d;stop-opacity:1"
-         offset="1" />
-    </linearGradient>
-    <radialGradient
-       cx="806.97711"
-       cy="720.04266"
-       r="4.5721774"
-       fx="806.97711"
-       fy="720.04266"
-       id="radialGradient4394"
-       xlink:href="#linearGradient4348"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.66177697,-3.2424834e-7,5.5632116e-7,1.1354276,273.09596,-96.976308)" />
-  </defs>
-  <metadata
-     id="metadata3818">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-817.85712,-715.93359)"
-     id="layer1">
-    <g
-       transform="translate(14.984745,-0.12063576)"
-       id="g4389">
-      <rect
-         width="8.1443548"
-         height="6.0609155"
-         x="803.37238"
-         y="719.4939"
-         id="rect3832"
-         style="fill:url(#radialGradient4394);fill-opacity:1;stroke:#888a85;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:2;stroke-opacity:1;stroke-dasharray:none" />
-      <path
-         d="m 2.4622467,2.0134813 a 2.9673231,1.420527 0 0 1 5.9346461,10e-8 l -2.9673231,0 z"
-         transform="matrix(0.98668274,0,0,2.0515802,802.05109,715.32099)"
-         id="path4346"
-         style="fill:none;stroke:#888a85;stroke-width:0.68014622;stroke-linejoin:miter;stroke-miterlimit:2;stroke-opacity:1;stroke-dasharray:none" />
-      <path
-         d="m 807.32587,723.57494 0,-1.12645"
-         id="path4368"
-         style="fill:none;stroke:#ac5f08;stroke-width:1.04513526px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.69072164" />
-    </g>
-  </g>
-</svg>
diff --git a/skins/vector/images/mail-icon.png b/skins/vector/images/mail-icon.png
deleted file mode 100644 (file)
index 0d93a2f..0000000
Binary files a/skins/vector/images/mail-icon.png and /dev/null differ
diff --git a/skins/vector/images/mail-icon.svg b/skins/vector/images/mail-icon.svg
deleted file mode 100644 (file)
index cab6304..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="10"
-   height="10"
-   id="svg4396">
-  <defs
-     id="defs4398">
-    <linearGradient
-       id="linearGradient4947">
-      <stop
-         id="stop4949"
-         style="stop-color:#d2d2d2;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop4951"
-         style="stop-color:#f6f6f6;stop-opacity:0"
-         offset="1" />
-    </linearGradient>
-    <radialGradient
-       cx="861.14233"
-       cy="699.01233"
-       r="4.9871311"
-       fx="861.14233"
-       fy="699.01233"
-       id="radialGradient4962"
-       xlink:href="#linearGradient4947"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.1817158,0,0,1.1856764,-156.48316,-109.77743)" />
-  </defs>
-  <metadata
-     id="metadata4401">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-832.14288,-690.2193)"
-     id="layer1">
-    <g
-       transform="translate(-23.99948,-20.005085)"
-       id="g4957">
-      <path
-         d="m 856.64003,714.98211 4.51344,-4.27677 4.49122,4.2557 0,4.78239 -8.96019,0 z"
-         id="path4415"
-         style="fill:url(#radialGradient4962);fill-opacity:1;stroke:#888a85;stroke-width:0.96960205px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
-      <path
-         d="m 858.18557,715.14414 2.96409,-2.80866 2.94949,2.79482"
-         id="path4937"
-         style="fill:#a8a7a3;fill-opacity:1;stroke:none" />
-      <path
-         d="m 857.89337,719.26617 3.26025,-3.14859 3.23877,3.11734 -3.24112,-1.90625 z"
-         id="path4955"
-         style="fill:#888a85;fill-opacity:1;stroke:none" />
-    </g>
-  </g>
-</svg>
diff --git a/skins/vector/images/news-icon.png b/skins/vector/images/news-icon.png
deleted file mode 100644 (file)
index 6f27054..0000000
Binary files a/skins/vector/images/news-icon.png and /dev/null differ
diff --git a/skins/vector/images/news-icon.svg b/skins/vector/images/news-icon.svg
deleted file mode 100644 (file)
index e5514a7..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="10"
-   height="10"
-   id="svg4983">
-  <defs
-     id="defs4985">
-    <linearGradient
-       id="linearGradient5528">
-      <stop
-         id="stop5530"
-         style="stop-color:#cccccc;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop5532"
-         style="stop-color:#cccccc;stop-opacity:0"
-         offset="1" />
-    </linearGradient>
-    <linearGradient
-       x1="902.61218"
-       y1="696.32751"
-       x2="902.61218"
-       y2="694.04303"
-       id="linearGradient3824"
-       xlink:href="#linearGradient5528"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="translate(-19.98763,0.00341)" />
-  </defs>
-  <metadata
-     id="metadata4988">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-877.85712,-687.36218)"
-     id="layer1">
-    <path
-       d="m 885.19659,693.70929 c 0.18733,0.11152 0.2171,0.58028 0.28483,0.0765 0.21963,-0.21 0.25265,0.61085 0.31801,0.0641 0.27697,-0.42352 -0.0831,0.827 -0.17686,0.17405 -0.11702,-0.43251 -0.13186,0.58055 -0.33199,0.093 -0.0467,-0.13235 -0.0352,-0.27894 -0.0941,-0.40765 m -0.0951,0.25098 c -0.24545,-0.026 -0.58057,0.20963 -0.14983,0.20815 0.2341,0.24227 -0.5966,0.0435 -0.31586,-0.29597 0.073,-0.29368 0.48945,-0.19996 0.46582,0.0878 m -0.0898,-0.0264 c -0.008,-0.37273 -0.57907,0.10308 -3e-5,6e-5 m -1.12221,-0.4067 c 0.31303,-0.0182 0.47686,0.98363 0.45605,0.28209 0.0542,-0.83126 0.27546,1.00617 -0.15278,0.25362 -0.0894,-0.27779 -0.27195,-0.54907 -0.20757,-0.0888 -0.0326,0.82392 -0.13826,-0.33361 -0.0957,-0.44691 z m 1.30713,-1.84131 c 0.18733,0.11152 0.2171,0.58028 0.28483,0.0765 0.21963,-0.21 0.25265,0.61085 0.31801,0.0641 0.27697,-0.42352 -0.0831,0.827 -0.17686,0.17405 -0.11703,-0.43249 -0.13186,0.58055 -0.33199,0.093 -0.0467,-0.13235 -0.0352,-0.27894 -0.0941,-0.40765 m -0.0951,0.25098 c -0.24545,-0.026 -0.58058,0.20964 -0.14984,0.20816 0.23409,0.24222 -0.5966,0.0434 -0.31584,-0.29607 0.0729,-0.29368 0.48945,-0.19997 0.46581,0.0877 m -0.0898,-0.0264 c -0.008,-0.37272 -0.57905,0.1031 -3e-5,7e-5 m -1.12221,-0.40661 c 0.31303,-0.0182 0.47685,0.98364 0.45605,0.2821 0.0542,-0.83128 0.27546,1.00616 -0.15278,0.25361 -0.0894,-0.27779 -0.27195,-0.54907 -0.20757,-0.0888 -0.0326,0.82392 -0.13826,-0.33361 -0.0957,-0.44691 z m 1.40695,-2.02159 c -0.0925,0.22919 -0.31156,0.57023 0.14418,0.41318 -0.005,-0.13405 -0.10264,-0.27877 -0.14418,-0.41318 z m -0.0704,-0.11269 c 0.29905,0.0855 0.42028,0.62166 0.42088,0.84191 -0.13411,-0.4802 -0.68425,-0.0265 -0.73057,-0.076 0.0832,-0.2616 0.21061,-0.50913 0.3096,-0.76593 m -1.74281,0.31056 c 0.34612,-0.47913 0.56926,0.70098 0.21372,0.36363 0.0724,-0.32969 -0.28365,-0.36875 -0.1668,-0.0222 -0.26673,0.45246 -0.17742,-0.6565 -0.3994,-0.10395 -0.0864,0.678 -0.43164,-0.63601 0.14263,-0.31419 0.0903,0.008 0.17045,-0.0312 0.20982,0.0769 m -1.26048,0.25 c -0.10571,-0.34023 0.21201,-0.48784 0.17971,-0.0655 0.20532,0.47932 0.16846,-0.59018 0.40143,-0.15309 0.19369,0.48548 -0.51086,0.6449 -0.5806,0.21899 m -0.16777,-0.32628 c 0.003,0.21747 -0.51383,0.059 -0.0685,0.22157 0.38953,0.3392 -0.58676,0.41358 -0.309,0.22699 0.52432,-0.0372 -0.45958,-0.30319 0.0896,-0.4819 0.0946,-0.0287 0.2045,-0.0235 0.28796,0.0344 m -0.99688,0.46241 c 0.0892,0.4554 -0.3135,0.24019 -0.17953,-0.10036 -0.28045,-0.78623 1.07442,-0.23273 0.43248,0.1872 -0.0909,0.0271 -0.20018,-0.005 -0.25295,-0.0867 m 0.11952,-0.36409 c -0.39427,0.13009 0.34651,0.51437 0.0773,0.0311 l -0.034,-0.025 -0.0433,-0.006 z m -0.65285,-0.11717 c 0.42856,-0.041 0.0577,0.97963 -0.005,0.32973 0.003,-0.10996 0.007,-0.21971 0.005,-0.32973 z m 0,-0.21896 c 0.43196,-0.11169 -0.0481,0.43831 0,0 z m -0.64683,0.0316 c 0.44435,-0.0237 -0.0875,0.85036 0.53283,0.60364 -0.23411,0.42107 -0.67995,0.0409 -0.53283,-0.33773 0,-0.0886 0,-0.17727 0,-0.26591 z"
-       id="path3078"
-       style="fill:#000000;fill-opacity:1;stroke:none" />
-    <rect
-       width="2.8749001"
-       height="2.8749392"
-       x="879.96875"
-       y="691.46332"
-       id="rect5552"
-       style="fill:#c0c1be;fill-opacity:1;stroke:#000000;stroke-width:0.10008001;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:2;stroke-opacity:1;stroke-dasharray:none" />
-    <path
-       d="m 878.38837,687.89343 0,7.40625 c -2.1e-4,0.0102 0,0.021 0,0.0312 0,0.8311 0.6689,1.5 1.5,1.5 l 5.90625,0 c 0.0102,2.1e-4 0.021,0 0.0312,0 0.8311,0 1.5,-0.6689 1.5,-1.5 0,-0.0206 8.2e-4,-0.0421 0,-0.0625 l 0,-7.375 -8.9375,0 z"
-       id="path3797"
-       style="fill:url(#linearGradient3824);fill-opacity:1;stroke:#888a85;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-  </g>
-</svg>
index c001b47..0720f20 100644 (file)
@@ -1,7 +1 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="12" height="13">
-       <g stroke-width="2" stroke="#6c6c6c" fill="none">
-               <path d="m11.29 11.71-4-4"/>
-               <circle cx="5" cy="5" r="4"/>
-       </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#6c6c6c" fill="none"><path d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg>
\ No newline at end of file
index 20d945d..622d5f9 100644 (file)
@@ -1,7 +1 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="12" height="13">
-       <g stroke-width="2" stroke="#6c6c6c" fill="none">
-               <path d="m.71 11.71 4-4"/>
-               <circle cx="7" cy="5" r="4"/>
-       </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#6c6c6c" fill="none"><path d="M.71 11.71l4-4"/><circle cx="7" cy="5" r="4"/></g></svg>
\ No newline at end of file
diff --git a/skins/vector/images/talk-icon.png b/skins/vector/images/talk-icon.png
deleted file mode 100644 (file)
index 0332054..0000000
Binary files a/skins/vector/images/talk-icon.png and /dev/null differ
diff --git a/skins/vector/images/talk-icon.svg b/skins/vector/images/talk-icon.svg
deleted file mode 100644 (file)
index d65d57a..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="10"
-   height="10"
-   id="svg5587">
-  <defs
-     id="defs5589">
-    <linearGradient
-       id="linearGradient6134">
-      <stop
-         id="stop6136"
-         style="stop-color:#e9e9e9;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop6138"
-         style="stop-color:#e9e9e9;stop-opacity:0"
-         offset="1" />
-    </linearGradient>
-    <radialGradient
-       cx="755.80591"
-       cy="683.84875"
-       r="2.6564851"
-       fx="755.80591"
-       fy="683.84875"
-       id="radialGradient6146"
-       xlink:href="#linearGradient6134"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2.4898047,0,0,2.5230165,-1126.0032,-1041.5417)" />
-  </defs>
-  <metadata
-     id="metadata5592">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-763.57141,-681.64789)"
-     id="layer1">
-    <g
-       transform="matrix(1.0212411,0,0,0.97119998,-5.0201418,19.699049)"
-       id="g6142">
-      <path
-         d="m -8.625,0.4375 c -0.4851513,0 -0.875,0.38984873 -0.875,0.875 l 0,4.375 c 0,0.4851513 0.3898487,0.875 0.875,0.875 l 0.125,0 0,2.6739053 3.4513641,-2.6739053 2.5173859,0 c 0.4851513,0 0.875,-0.3898487 0.875,-0.875 l 0,-4.375 c 0,-0.48515127 -0.3898487,-0.875 -0.875,-0.875 z"
-         transform="translate(763.57141,681.64789)"
-         id="rect5606"
-         style="fill:#ffffff;fill-opacity:1;stroke:#888a85;stroke-width:0.98900002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:9.80000019;stroke-opacity:1;stroke-dasharray:none" />
-      <path
-         d="m 755.96029,683.3154 c -0.32861,0 -0.59267,0.23853 -0.59267,0.53539 l 0,2.67695 c 0,0.29685 0.26406,0.53539 0.59267,0.53539 l 0.0847,0 0,1.63611 2.33776,-1.63611 1.70516,0 c 0.32862,0 0.59268,-0.23854 0.59268,-0.53539 l 0,-2.67695 c 0,-0.29686 -0.26406,-0.53539 -0.59268,-0.53539 z"
-         id="path6124"
-         style="fill:url(#radialGradient6146);fill-opacity:1;stroke:none" />
-    </g>
-  </g>
-</svg>
index b41fd97..d52d547 100644 (file)
@@ -1,65 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="16"
-   height="16"
-   id="svg2">
-  <defs
-     id="defs4">
-    <linearGradient
-       id="linearGradient3788">
-      <stop
-         id="stop3790"
-         style="stop-color:#c2edff;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop3796"
-         style="stop-color:#68bdff;stop-opacity:1"
-         offset="0.5" />
-      <stop
-         id="stop3792"
-         style="stop-color:#ffffff;stop-opacity:1"
-         offset="1" />
-    </linearGradient>
-    <linearGradient
-       x1="13.470111"
-       y1="14.363379"
-       x2="4.596477"
-       y2="3.3969929"
-       id="linearGradient3804"
-       xlink:href="#linearGradient3788"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-        <dc:creator>
-          <cc:Agent>
-            <dc:title>Mateusz &quot;m4tx&quot; Maćkowski</dc:title>
-          </cc:Agent>
-        </dc:creator>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-693.14288,-698.64789)"
-     id="layer1">
-    <path
-       d="M 8.3337586,-0.92098331 10.85748,4.1926362 16.500695,5.0126434 12.417226,8.9930409 13.381202,14.613453 8.3337584,11.959854 3.286314,14.613452 4.2502902,8.9930409 0.16682217,5.012643 5.8100362,4.1926362 z"
-       transform="matrix(0.86225302,0,0,0.86225302,694.06156,700.58832)"
-       id="path3768"
-       style="fill:url(#linearGradient3804);fill-opacity:1;stroke:#c8b250;stroke-width:1.15975237;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><defs><linearGradient id="a"><stop offset="0" stop-color="#c2edff"/><stop offset=".5" stop-color="#68bdff"/><stop offset="1" stop-color="#fff"/></linearGradient><linearGradient x1="13.47" y1="14.363" x2="4.596" y2="3.397" id="b" xlink:href="#a" gradientUnits="userSpaceOnUse"/></defs><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" fill="url(#b)" stroke="#c8b250" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
index 80fb36e..cde7bc5 100644 (file)
@@ -1,65 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="16"
-   height="16"
-   id="svg2">
-  <defs
-     id="defs4">
-    <linearGradient
-       id="linearGradient3788">
-      <stop
-         id="stop3790"
-         style="stop-color:#c2edff;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop3796"
-         style="stop-color:#68bdff;stop-opacity:1"
-         offset="0.5" />
-      <stop
-         id="stop3792"
-         style="stop-color:#ffffff;stop-opacity:1"
-         offset="1" />
-    </linearGradient>
-    <linearGradient
-       x1="13.470111"
-       y1="14.363379"
-       x2="4.596477"
-       y2="3.3969929"
-       id="linearGradient3804"
-       xlink:href="#linearGradient3788"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-        <dc:creator>
-          <cc:Agent>
-            <dc:title>Mateusz &quot;m4tx&quot; Maćkowski</dc:title>
-          </cc:Agent>
-        </dc:creator>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-693.14288,-698.64789)"
-     id="layer1">
-    <path
-       d="M 8.3337586,-0.92098331 10.85748,4.1926362 16.500695,5.0126434 12.417226,8.9930409 13.381202,14.613453 8.3337584,11.959854 3.286314,14.613452 4.2502902,8.9930409 0.16682217,5.012643 5.8100362,4.1926362 z"
-       transform="matrix(0.86225302,0,0,0.86225302,694.06156,700.58832)"
-       id="path3768"
-       style="fill:url(#linearGradient3804);fill-opacity:1;stroke:#7cb5d1;stroke-width:1.15975237;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><defs><linearGradient id="a"><stop offset="0" stop-color="#c2edff"/><stop offset=".5" stop-color="#68bdff"/><stop offset="1" stop-color="#fff"/></linearGradient><linearGradient x1="13.47" y1="14.363" x2="4.596" y2="3.397" id="b" xlink:href="#a" gradientUnits="userSpaceOnUse"/></defs><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" fill="url(#b)" stroke="#7cb5d1" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
index 9b6f822..4335bcf 100644 (file)
@@ -1,207 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="12"
-   height="13.837458"
-   id="svg2108">
-  <metadata
-     id="metadata68">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs3">
-    <linearGradient
-       id="linearGradient4356">
-      <stop
-         id="stop4358"
-         style="stop-color:#000000;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop4360"
-         style="stop-color:#000000;stop-opacity:0"
-         offset="1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient4163">
-      <stop
-         id="stop4165"
-         style="stop-color:#3b74bc;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop4167"
-         style="stop-color:#2d5990;stop-opacity:1"
-         offset="1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3824">
-      <stop
-         id="stop3826"
-         style="stop-color:#ffffff;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop3828"
-         style="stop-color:#c9c9c9;stop-opacity:1"
-         offset="1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3816">
-      <stop
-         id="stop3818"
-         style="stop-color:#000000;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop3820"
-         style="stop-color:#000000;stop-opacity:0"
-         offset="1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3800">
-      <stop
-         id="stop3802"
-         style="stop-color:#f4d9b1;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop3804"
-         style="stop-color:#df9725;stop-opacity:1"
-         offset="1" />
-    </linearGradient>
-    <radialGradient
-       cx="31.112698"
-       cy="19.008621"
-       r="8.6620579"
-       fx="31.112698"
-       fy="19.008621"
-       id="radialGradient2243"
-       xlink:href="#linearGradient3816"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       cx="28.089741"
-       cy="27.203083"
-       r="13.56536"
-       fx="28.089741"
-       fy="27.203083"
-       id="radialGradient2245"
-       xlink:href="#linearGradient4163"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.297564,0,0,0.884831,-8.358505,4.940469)" />
-    <linearGradient
-       x1="30.935921"
-       y1="29.553486"
-       x2="30.935921"
-       y2="35.803486"
-       id="linearGradient2247"
-       xlink:href="#linearGradient3824"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       cx="31.112698"
-       cy="19.008621"
-       r="8.6620579"
-       fx="31.112698"
-       fy="19.008621"
-       id="radialGradient2249"
-       xlink:href="#linearGradient3816"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       cx="29.344931"
-       cy="17.064077"
-       r="9.1620579"
-       fx="29.344931"
-       fy="17.064077"
-       id="radialGradient2251"
-       xlink:href="#linearGradient3800"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.787998,0,0,0.787998,6.221198,3.617627)" />
-    <linearGradient
-       x1="20.661695"
-       y1="35.817974"
-       x2="22.626925"
-       y2="36.217758"
-       id="linearGradient2253"
-       xlink:href="#linearGradient4356"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.983375,0.181588,-0.181588,0.983375,6.231716,-2.651466)" />
-    <linearGradient
-       x1="22.686766"
-       y1="36.3904"
-       x2="21.408455"
-       y2="35.739632"
-       id="linearGradient2255"
-       xlink:href="#linearGradient4356"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(-0.977685,0.210075,0.210075,0.977685,55.1096,-3.945209)" />
-  </defs>
-  <g
-     transform="translate(-5.0000039,-32.070112)"
-     id="layer1"
-     style="display:inline" />
-  <g
-     transform="translate(-5.0000039,-32.070112)"
-     id="layer2"
-     style="display:inline">
-    <g
-       transform="matrix(0.39012793,0,0,0.39012793,-1.0891578,28.22979)"
-       id="g2230">
-      <path
-         d="m 39.774755,19.008621 a 8.6620579,8.6620579 0 1 1 -17.324115,0 8.6620579,8.6620579 0 1 1 17.324115,0 z"
-         transform="matrix(1.77551,0,0,0.959183,-24.25322,18.77153)"
-         id="path4306"
-         style="color:#000000;fill:url(#radialGradient2243);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible" />
-      <path
-         d="m 25.986174,41.636039 10.606602,0 c 3.005204,0 5.980484,-1.101932 7.071067,-4.242641 1.035639,-2.982476 0.176777,-8.662058 -6.540737,-13.258252 l -12.551146,0 c -6.717514,4.24264 -7.556991,10.044831 -6.010407,13.435028 1.575595,3.45379 4.24264,4.065865 7.424621,4.065865 z"
-         id="path4308"
-         style="color:#000000;fill:url(#radialGradient2245);fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
-      <path
-         d="m 26.693281,25.726136 c 3.18198,2.828427 4.596194,13.081476 4.596194,13.081476 0,0 1.414213,-10.253048 3.889087,-13.258252 l -8.485281,0.176776 z"
-         id="path4310"
-         style="color:#000000;fill:url(#linearGradient2247);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible" />
-      <path
-         d="m 28.972721,26.786797 c 0,0 -2.151323,1.660335 -1.965991,3.660533 -2.041226,-1.800794 -2.099873,-5.251524 -2.099873,-5.251524 l 4.065864,1.590991 z"
-         id="path4312"
-         style="color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible" />
-      <path
-         d="m 25.914862,40.593933 10.493447,-0.0221 c 2.639723,0 5.253161,-0.967919 6.211112,-3.726667 0.909689,-2.61976 -0.09472,-7.608614 -5.995279,-11.645837 L 25.099417,24.956264 c -5.900557,3.726667 -7.04262,8.823219 -5.662029,12.044182 1.380592,3.220963 3.395211,3.57139 6.477474,3.593487 z"
-         id="path4314"
-         style="opacity:0.21518986;color:#000000;fill:none;stroke:#ffffff;stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
-      <path
-         d="m 33.410795,26.786797 c 0,0 2.151323,1.660335 1.965991,3.660533 2.041226,-1.800794 2.099873,-5.251524 2.099873,-5.251524 l -4.065864,1.590991 z"
-         id="path4316"
-         style="color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible" />
-      <path
-         d="m 39.774755,19.008621 a 8.6620579,8.6620579 0 1 1 -17.324115,0 8.6620579,8.6620579 0 1 1 17.324115,0 z"
-         transform="translate(-0.125,3.5)"
-         id="path4318"
-         style="color:#000000;fill:url(#radialGradient2249);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible" />
-      <path
-         d="m 39.774755,19.008621 a 8.6620579,8.6620579 0 1 1 -17.324115,0 8.6620579,8.6620579 0 1 1 17.324115,0 z"
-         id="path4320"
-         style="color:#000000;fill:url(#radialGradient2251);fill-opacity:1;fill-rule:evenodd;stroke:#c17d11;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
-      <path
-         d="m 39.774755,19.008621 a 8.6620579,8.6620579 0 1 1 -17.324115,0 8.6620579,8.6620579 0 1 1 17.324115,0 z"
-         transform="matrix(0.877095,0,0,0.877095,3.823927,2.336267)"
-         id="path4322"
-         style="opacity:0.19620254;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.14012825px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
-      <path
-         d="m 21.85179,40.775197 c -1.247607,-0.544969 -1.805994,-1.858277 -1.805994,-1.858277 0.841281,-4.069136 3.719925,-7.046216 3.719925,-7.046216 0,0 -2.279321,6.411514 -1.913931,8.904493 z"
-         id="path4354"
-         style="opacity:0.22784807;color:#000000;fill:url(#linearGradient2253);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible" />
-      <path
-         d="m 40.757497,39.916846 c 1.231251,-0.580978 1.80438,-2.002321 1.80438,-2.002321 -0.95912,-4.042983 -3.976149,-6.842821 -3.976149,-6.842821 0,0 2.464593,6.342602 2.171769,8.845142 z"
-         id="path4364"
-         style="opacity:0.22784807;color:#000000;fill:url(#linearGradient2255);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible" />
-    </g>
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="13.837"><defs><linearGradient id="e"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#3b74bc"/><stop offset="1" stop-color="#2d5990"/></linearGradient><linearGradient id="c"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#c9c9c9"/></linearGradient><linearGradient id="a"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="d"><stop offset="0" stop-color="#f4d9b1"/><stop offset="1" stop-color="#df9725"/></linearGradient><radialGradient cx="31.113" cy="19.009" r="8.662" fx="31.113" fy="19.009" id="f" xlink:href="#a" gradientUnits="userSpaceOnUse"/><radialGradient cx="28.09" cy="27.203" r="13.565" fx="28.09" fy="27.203" id="g" xlink:href="#b" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.298 0 0 .885 -8.359 4.94)"/><linearGradient x1="30.936" y1="29.553" x2="30.936" y2="35.803" id="h" xlink:href="#c" gradientUnits="userSpaceOnUse"/><radialGradient cx="31.113" cy="19.009" r="8.662" fx="31.113" fy="19.009" id="i" xlink:href="#a" gradientUnits="userSpaceOnUse"/><radialGradient cx="29.345" cy="17.064" r="9.162" fx="29.345" fy="17.064" id="j" xlink:href="#d" gradientUnits="userSpaceOnUse" gradientTransform="matrix(.788 0 0 .788 6.221 3.618)"/><linearGradient x1="20.662" y1="35.818" x2="22.627" y2="36.218" id="k" xlink:href="#e" gradientUnits="userSpaceOnUse" gradientTransform="matrix(.983 .182 -.182 .983 6.232 -2.651)"/><linearGradient x1="22.687" y1="36.39" x2="21.408" y2="35.74" id="l" xlink:href="#e" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-.978 .21 .21 .978 55.11 -3.945)"/></defs><g color="#000"><path d="M39.775 19.009a8.662 8.662 0 1 1-17.324 0 8.662 8.662 0 1 1 17.324 0z" transform="matrix(.693 0 0 .374 -15.548 3.481)" fill="url(#f)" fill-rule="evenodd" overflow="visible"/><path d="M4.046 12.398h4.137c1.172 0 2.332-.43 2.758-1.655.404-1.163.069-3.378-2.551-5.171h-4.895c-2.62 1.655-2.947 3.917-2.344 5.24.614 1.347 1.655 1.586 2.896 1.586z" fill="url(#g)" fill-rule="evenodd" stroke="#204a87" stroke-linecap="round" stroke-linejoin="round" overflow="visible" stroke-width="0.39"/><path d="M4.321 6.193c1.241 1.103 1.793 5.102 1.793 5.102s.552-3.999 1.517-5.171l-3.309.069z" fill="url(#h)" fill-rule="evenodd" overflow="visible"/><path d="M5.21 6.607s-.839.648-.767 1.428c-.796-.702-.819-2.048-.819-2.048l1.586.62z" fill="#729fcf" fill-rule="evenodd" overflow="visible"/><path d="M4.018 11.992l4.092-.009c1.029 0 2.049-.377 2.422-1.453.355-1.022-.037-2.967-2.338-4.542l-4.495-.095c-2.301 1.453-2.747 3.441-2.208 4.697.538 1.256 1.324 1.393 2.526 1.401z" opacity=".215" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" overflow="visible" fill="none" stroke-width="0.39"/><path d="M6.941 6.607s.839.648.767 1.428c.796-.702.819-2.048.819-2.048l-1.586.62z" fill="#729fcf" fill-rule="evenodd" overflow="visible"/><path d="M39.775 19.009a8.662 8.662 0 1 1-17.324 0 8.662 8.662 0 1 1 17.324 0z" transform="matrix(.39 0 0 .39 -6.138 -2.475)" fill="url(#i)" fill-rule="evenodd" overflow="visible"/><path d="M39.775 19.009a8.662 8.662 0 1 1-17.324 0 8.662 8.662 0 1 1 17.324 0z" fill="url(#j)" fill-rule="evenodd" stroke="#c17d11" stroke-linecap="round" stroke-linejoin="round" overflow="visible" transform="matrix(.39 0 0 .39 -6.089 -3.84)"/><path d="M39.775 19.009a8.662 8.662 0 1 1-17.324 0 8.662 8.662 0 1 1 17.324 0z" transform="matrix(.342 0 0 .342 -4.598 -2.929)" opacity=".196" stroke="#fff" stroke-width="1.14" stroke-linecap="round" stroke-linejoin="round" overflow="visible" fill="none"/><path d="M2.433 12.062c-.487-.213-.704-.725-.704-.725.328-1.587 1.451-2.748 1.451-2.748s-.889 2.5-.746 3.473z" opacity=".228" fill="url(#k)" fill-rule="evenodd" overflow="visible"/><path d="M9.806 11.728c.48-.227.704-.781.704-.781-.374-1.577-1.551-2.669-1.551-2.669s.961 2.474.847 3.45z" opacity=".228" fill="url(#l)" fill-rule="evenodd" overflow="visible"/></g></svg>
\ No newline at end of file
diff --git a/skins/vector/images/video-icon.png b/skins/vector/images/video-icon.png
deleted file mode 100644 (file)
index ed85232..0000000
Binary files a/skins/vector/images/video-icon.png and /dev/null differ
diff --git a/skins/vector/images/video-icon.svg b/skins/vector/images/video-icon.svg
deleted file mode 100644 (file)
index 0b3d302..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="10"
-   height="10"
-   id="svg6734">
-  <defs
-     id="defs6736">
-    <linearGradient
-       id="linearGradient7265">
-      <stop
-         id="stop7267"
-         style="stop-color:#cccccc;stop-opacity:1"
-         offset="0" />
-      <stop
-         id="stop7269"
-         style="stop-color:#dfdfdf;stop-opacity:1"
-         offset="1" />
-    </linearGradient>
-    <radialGradient
-       cx="5.0034118"
-       cy="4.9650207"
-       r="4.999619"
-       fx="5.0034118"
-       fy="4.9650207"
-       id="radialGradient7327"
-       xlink:href="#linearGradient7265"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <metadata
-     id="metadata6739">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-903.57141,-715.93359)"
-     id="layer1">
-    <path
-       d="m 911.68723,725.33709 -0.61872,-0.92808 c 0,0 0.17677,0.92808 0.92808,1.01647 0.7513,0.0884 1.19324,0.0884 1.19324,0.0884"
-       id="path7292"
-       style="fill:none;stroke:#5f6060;stroke-width:0.89999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-    <path
-       d="m 9.5175309,4.9650207 a 4.5141191,4.5141191 0 1 1 -9.02823828,0 4.5141191,4.5141191 0 1 1 9.02823828,0 z"
-       transform="translate(903.4637,715.9024)"
-       id="path6755"
-       style="fill:url(#radialGradient7327);fill-opacity:1;stroke:#848484;stroke-width:0.89999998;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:9.80000019;stroke-opacity:1;stroke-dasharray:none" />
-    <g
-       transform="matrix(0.897287,0,0,0.897287,111.13225,74.055304)"
-       id="g7310">
-      <path
-         d="m 5.03125,2.59375 a 0.59375,0.59375 0 1 1 -1.1875,0 0.59375,0.59375 0 1 1 1.1875,0 z"
-         transform="matrix(1.4672484,-0.2948259,0.2948259,1.4672484,880.61345,716.13137)"
-         id="path7300"
-         style="fill:#818181;fill-opacity:1;stroke:none" />
-      <path
-         d="m 5.03125,2.59375 a 0.59375,0.59375 0 1 1 -1.1875,0 0.59375,0.59375 0 1 1 1.1875,0 z"
-         transform="matrix(1.4672484,-0.2948259,0.2948259,1.4672484,878.85062,718.47146)"
-         id="path7302"
-         style="fill:#818181;fill-opacity:1;stroke:none" />
-      <path
-         d="m 5.03125,2.59375 a 0.59375,0.59375 0 1 1 -1.1875,0 0.59375,0.59375 0 1 1 1.1875,0 z"
-         transform="matrix(1.4672484,-0.2948259,0.2948259,1.4672484,883.48161,716.7296)"
-         id="path7304"
-         style="fill:#818181;fill-opacity:1;stroke:none" />
-      <path
-         d="m 5.03125,2.59375 a 0.59375,0.59375 0 1 1 -1.1875,0 0.59375,0.59375 0 1 1 1.1875,0 z"
-         transform="matrix(1.4672484,-0.2948259,0.2948259,1.4672484,880.77974,720.67629)"
-         id="path7306"
-         style="fill:#818181;fill-opacity:1;stroke:none" />
-      <path
-         d="m 5.03125,2.59375 a 0.59375,0.59375 0 1 1 -1.1875,0 0.59375,0.59375 0 1 1 1.1875,0 z"
-         transform="matrix(1.4672484,-0.2948259,0.2948259,1.4672484,883.52712,719.65906)"
-         id="path7308"
-         style="fill:#818181;fill-opacity:1;stroke:none" />
-    </g>
-  </g>
-</svg>
index b78c978..664c671 100644 (file)
@@ -1,39 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="16"
-   height="16"
-   id="svg2">
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-        <dc:creator>
-          <cc:Agent>
-            <dc:title>Mateusz &quot;m4tx&quot; Maćkowski</dc:title>
-          </cc:Agent>
-        </dc:creator>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-693.14288,-698.64789)"
-     id="layer1">
-    <path
-       d="M 8.3337586,-0.92098331 10.85748,4.1926362 16.500695,5.0126434 12.417226,8.9930409 13.381202,14.613453 8.3337584,11.959854 3.286314,14.613452 4.2502902,8.9930409 0.16682217,5.012643 5.8100362,4.1926362 z"
-       transform="matrix(0.86225302,0,0,0.86225302,694.06156,700.58832)"
-       id="path3770"
-       style="fill:#ffffff;fill-opacity:1;stroke:#c8b250;stroke-width:1.15975237;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" fill="#fff" stroke="#c8b250" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
index 6b25f94..751eb14 100644 (file)
@@ -1,39 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="16"
-   height="16"
-   id="svg2">
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-        <dc:creator>
-          <cc:Agent>
-            <dc:title>Mateusz &quot;m4tx&quot; Maćkowski</dc:title>
-          </cc:Agent>
-        </dc:creator>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-693.14288,-698.64789)"
-     id="layer1">
-    <path
-       d="M 8.3337586,-0.92098331 10.85748,4.1926362 16.500695,5.0126434 12.417226,8.9930409 13.381202,14.613453 8.3337584,11.959854 3.286314,14.613452 4.2502902,8.9930409 0.16682217,5.012643 5.8100362,4.1926362 z"
-       transform="matrix(0.86225302,0,0,0.86225302,694.06156,700.58832)"
-       id="path2998"
-       style="fill:#ffffff;fill-opacity:1;stroke:#d1d1d1;stroke-width:1.15975237;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" fill="#fff" stroke="#d1d1d1" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
index 2654c8d..907b05b 100644 (file)
@@ -1,39 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   version="1.1"
-   width="16"
-   height="16"
-   id="svg2">
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-        <dc:creator>
-          <cc:Agent>
-            <dc:title>Mateusz &quot;m4tx&quot; Maćkowski</dc:title>
-          </cc:Agent>
-        </dc:creator>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     transform="translate(-693.14288,-698.64789)"
-     id="layer1">
-    <path
-       d="M 8.3337586,-0.92098331 10.85748,4.1926362 16.500695,5.0126434 12.417226,8.9930409 13.381202,14.613453 8.3337584,11.959854 3.286314,14.613452 4.2502902,8.9930409 0.16682217,5.012643 5.8100362,4.1926362 z"
-       transform="matrix(0.86225302,0,0,0.86225302,694.06156,700.58832)"
-       id="path2998"
-       style="fill:#ffffff;fill-opacity:1;stroke:#7cb5d1;stroke-width:1.15975237;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
-  </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" fill="#fff" stroke="#7cb5d1" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
index ebfab42..c4578aa 100644 (file)
@@ -3,7 +3,8 @@
 // Page content
 // FIXME: Use global variable since Echo and CentralNotice use this variable
 @content-border-color: #a7d7f9;
-@content-font-family: Arimo, "Liberation Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+// FIXME: Find an open font that works with this stack and is readable by Windows users
+@content-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
 @content-font-color: #252525;
 @content-font-size: 0.875em;
 @content-line-height: 1.6;
index 7237ef3..c8ec411 100644 (file)
@@ -30,9 +30,9 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
        /**
         * An error occurred.
         *
-        * @param  PHPUnit_Framework_Test $test
-        * @param  Exception              $e
-        * @param  float                  $time
+        * @param PHPUnit_Framework_Test $test
+        * @param Exception $e
+        * @param float $time
         */
        public function addError( PHPUnit_Framework_Test $test, Exception $e, $time ) {
                wfDebugLog( $this->logChannel, 'ERROR in ' . $this->getTestName( $test ) . ': ' . $this->getErrorName( $e ) );
@@ -41,9 +41,9 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
        /**
         * A failure occurred.
         *
-        * @param  PHPUnit_Framework_Test                 $test
-        * @param  PHPUnit_Framework_AssertionFailedError $e
-        * @param  float                                  $time
+        * @param PHPUnit_Framework_Test $test
+        * @param PHPUnit_Framework_AssertionFailedError $e
+        * @param float $time
         */
        public function addFailure( PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time ) {
                wfDebugLog( $this->logChannel, 'FAILURE in ' . $this->getTestName( $test ) . ': ' . $this->getErrorName( $e ) );
@@ -52,9 +52,9 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
        /**
         * Incomplete test.
         *
-        * @param  PHPUnit_Framework_Test $test
-        * @param  Exception              $e
-        * @param  float                  $time
+        * @param PHPUnit_Framework_Test $test
+        * @param Exception $e
+        * @param float $time
         */
        public function addIncompleteTest( PHPUnit_Framework_Test $test, Exception $e, $time ) {
                wfDebugLog( $this->logChannel, 'Incomplete test ' . $this->getTestName( $test ) . ': ' . $this->getErrorName( $e ) );
@@ -63,11 +63,11 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
        /**
         * Skipped test.
         *
-        * @param  PHPUnit_Framework_Test $test
-        * @param  Exception              $e
-        * @param  float                  $time
+        * @param PHPUnit_Framework_Test $test
+        * @param Exception $e
+        * @param float $time
         *
-        * @since  Method available since Release 3.0.0
+        * @since Method available since Release 3.0.0
         */
        public function addSkippedTest( PHPUnit_Framework_Test $test, Exception $e, $time ) {
                wfDebugLog( $this->logChannel, 'Skipped test ' . $this->getTestName( $test ) . ': ' . $this->getErrorName( $e ) );
@@ -76,8 +76,8 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
        /**
         * A test suite started.
         *
-        * @param  PHPUnit_Framework_TestSuite $suite
-        * @since  Method available since Release 2.2.0
+        * @param PHPUnit_Framework_TestSuite $suite
+        * @since Method available since Release 2.2.0
         */
        public function startTestSuite( PHPUnit_Framework_TestSuite $suite ) {
                wfDebugLog( $this->logChannel, 'START suite ' . $suite->getName() );
@@ -86,8 +86,8 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
        /**
         * A test suite ended.
         *
-        * @param  PHPUnit_Framework_TestSuite $suite
-        * @since  Method available since Release 2.2.0
+        * @param PHPUnit_Framework_TestSuite $suite
+        * @since Method available since Release 2.2.0
         */
        public function endTestSuite( PHPUnit_Framework_TestSuite $suite ) {
                wfDebugLog( $this->logChannel, 'END suite ' . $suite->getName() );
@@ -96,7 +96,7 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
        /**
         * A test started.
         *
-        * @param  PHPUnit_Framework_Test $test
+        * @param PHPUnit_Framework_Test $test
         */
        public function startTest( PHPUnit_Framework_Test $test ) {
                wfDebugLog( $this->logChannel, 'Start test ' . $this->getTestName( $test ) );
@@ -105,8 +105,8 @@ class MediaWikiPHPUnitTestListener implements PHPUnit_Framework_TestListener {
        /**
         * A test ended.
         *
-        * @param  PHPUnit_Framework_Test $test
-        * @param  float                  $time
+        * @param PHPUnit_Framework_Test $test
+        * @param float $time
         */
        public function endTest( PHPUnit_Framework_Test $test, $time ) {
                wfDebugLog( $this->logChannel, 'End test ' . $this->getTestName( $test ) );
index a332368..8093824 100644 (file)
@@ -517,4 +517,74 @@ class TitleTest extends MediaWikiTestCase {
                        array( 'User:John_Doe/subOne', 'subOne' ),
                );
        }
+
+       public function provideNewFromTitleValue() {
+               return array(
+                       array( new TitleValue( NS_MAIN, 'Foo' ) ),
+                       array( new TitleValue( NS_MAIN, 'Foo', 'bar' ) ),
+                       array( new TitleValue( NS_USER, 'Hansi_Maier' ) ),
+               );
+       }
+
+       /**
+        * @dataProvider provideNewFromTitleValue
+        */
+       public function testNewFromTitleValue( TitleValue $value ) {
+               $title = Title::newFromTitleValue( $value );
+
+               $dbkey = str_replace( ' ', '_', $value->getText() );
+               $this->assertEquals( $dbkey, $title->getDBkey() );
+               $this->assertEquals( $value->getNamespace(), $title->getNamespace() );
+               $this->assertEquals( $value->getFragment(), $title->getFragment() );
+       }
+
+       public function provideGetTitleValue() {
+               return array(
+                       array( 'Foo' ),
+                       array( 'Foo#bar' ),
+                       array( 'User:Hansi_Maier' ),
+               );
+       }
+
+       /**
+        * @dataProvider provideGetTitleValue
+        */
+       public function testGetTitleValue( $text ) {
+               $title = Title::newFromText( $text );
+               $value = $title->getTitleValue();
+
+               $dbkey = str_replace( ' ', '_', $value->getText() );
+               $this->assertEquals( $title->getDBkey(), $dbkey );
+               $this->assertEquals( $title->getNamespace(), $value->getNamespace() );
+               $this->assertEquals( $title->getFragment(), $value->getFragment() );
+       }
+
+       public function provideGetFragment() {
+               return array(
+                       array( 'Foo', '' ),
+                       array( 'Foo#bar', 'bar' ),
+                       array( 'Foo#bär', 'bär' ),
+
+                       // Inner whitespace is normalized
+                       array( 'Foo#bar_bar', 'bar bar' ),
+                       array( 'Foo#bar bar', 'bar bar' ),
+                       array( 'Foo#bar   bar', 'bar bar' ),
+
+                       // Leading whitespace is kept, trailing whitespace is trimmed.
+                       // XXX: Is this really want we want?
+                       array( 'Foo#_bar_bar_', ' bar bar' ),
+                       array( 'Foo# bar bar ', ' bar bar' ),
+               );
+       }
+
+       /**
+        * @dataProvider provideGetFragment
+        *
+        * @param $full
+        * @param $fragment
+        */
+       public function testGetFragment( $full, $fragment ) {
+               $title = Title::newFromText( $full );
+               $this->assertEquals( $fragment, $title->getFragment() );
+       }
 }
diff --git a/tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php b/tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php
new file mode 100644 (file)
index 0000000..73d7ff9
--- /dev/null
@@ -0,0 +1,160 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @license GPL 2+
+ * @author Daniel Kinzler
+ */
+
+/**
+ * @covers MediaWikiPageLinkRenderer
+ *
+ * @group Title
+ */
+class MediaWikiPageLinkRendererTest extends MediaWikiTestCase {
+
+       /**
+        * Returns a mock GenderCache that will return "female" always.
+        *
+        * @return GenderCache
+        */
+       private function getGenderCache() {
+               $genderCache = $this->getMockBuilder( 'GenderCache' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+
+               $genderCache->expects( $this->any() )
+                       ->method( 'getGenderOf' )
+                       ->will( $this->returnValue( 'female' ) );
+
+               return $genderCache;
+       }
+
+       public function provideGetPageUrl() {
+               return array(
+                       array(
+                               new TitleValue( NS_MAIN, 'Foo_Bar' ),
+                               array(),
+                               '/Foo_Bar'
+                       ),
+                       array(
+                               new TitleValue( NS_USER, 'Hansi_Maier', 'stuff' ),
+                               array( 'foo' => 'bar' ),
+                               '/User:Hansi_Maier?foo=bar#stuff'
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider provideGetPageUrl
+        */
+       public function testGetPageUrl( TitleValue $title, $params, $url ) {
+               // NOTE: was of Feb 2014, MediaWikiPageLinkRenderer *ignores* the
+               // WikitextTitleFormatter we pass here, and relies on the Linker
+               // class for generating the link! This may break the test e.g.
+               // of Linker uses a different language for the namespace names.
+
+               $lang = Language::factory( 'en' );
+
+               $formatter = new MediaWikiTitleCodec( $lang, $this->getGenderCache() );
+               $renderer = new MediaWikiPageLinkRenderer( $formatter, '/' );
+               $actual = $renderer->getPageUrl( $title, $params );
+
+               $this->assertEquals( $url, $actual );
+       }
+
+       public function provideRenderHtmlLink() {
+               return array(
+                       array(
+                               new TitleValue( NS_MAIN, 'Foo_Bar' ),
+                               'Foo Bar',
+                               '!<a .*href=".*?Foo_Bar.*?".*?>Foo Bar</a>!'
+                       ),
+                       array(
+                               //NOTE: Linker doesn't include fragments in "broken" links
+                               //NOTE: once this no longer uses Linker, we will get "2" instead of "User" for the namespace.
+                               new TitleValue( NS_USER, 'Hansi_Maier', 'stuff' ),
+                               'Hansi Maier\'s Stuff',
+                               '!<a .*href=".*?User:Hansi_Maier.*?>Hansi Maier\'s Stuff</a>!'
+                       ),
+                       array(
+                               //NOTE: Linker doesn't include fragments in "broken" links
+                               //NOTE: once this no longer uses Linker, we will get "2" instead of "User" for the namespace.
+                               new TitleValue( NS_USER, 'Hansi_Maier', 'stuff' ),
+                               null,
+                               '!<a .*href=".*?User:Hansi_Maier.*?>User:Hansi Maier#stuff</a>!'
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider provideRenderHtmlLink
+        */
+       public function testRenderHtmlLink( TitleValue $title, $text, $pattern ) {
+               // NOTE: was of Feb 2014, MediaWikiPageLinkRenderer *ignores* the
+               // WikitextTitleFormatter we pass here, and relies on the Linker
+               // class for generating the link! This may break the test e.g.
+               // of Linker uses a different language for the namespace names.
+
+               $lang = Language::factory( 'en' );
+
+               $formatter = new MediaWikiTitleCodec( $lang, $this->getGenderCache() );
+               $renderer = new MediaWikiPageLinkRenderer( $formatter );
+               $actual = $renderer->renderHtmlLink( $title, $text );
+
+               $this->assertRegExp( $pattern, $actual );
+       }
+
+       public function provideRenderWikitextLink() {
+               return array(
+                       array(
+                               new TitleValue( NS_MAIN, 'Foo_Bar' ),
+                               'Foo Bar',
+                               '[[:0:Foo Bar|Foo Bar]]'
+                       ),
+                       array(
+                               new TitleValue( NS_USER, 'Hansi_Maier', 'stuff' ),
+                               'Hansi Maier\'s Stuff',
+                               '[[:2:Hansi Maier#stuff|Hansi Maier&#39;s Stuff]]'
+                       ),
+                       array(
+                               new TitleValue( NS_USER, 'Hansi_Maier', 'stuff' ),
+                               null,
+                               '[[:2:Hansi Maier#stuff|2:Hansi Maier#stuff]]'
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider provideRenderWikitextLink
+        */
+       public function testRenderWikitextLink( TitleValue $title, $text, $expected ) {
+               $formatter = $this->getMock( 'TitleFormatter' );
+               $formatter->expects( $this->any() )
+                       ->method( 'getFullText' )
+                       ->will( $this->returnCallback(
+                               function( TitleValue $title ) {
+                                       return str_replace( '_', ' ', "$title" );
+                               }
+                       ));
+
+               $renderer = new MediaWikiPageLinkRenderer( $formatter, '/' );
+               $actual = $renderer->renderWikitextLink( $title, $text );
+
+               $this->assertEquals( $expected, $actual );
+       }
+}
diff --git a/tests/phpunit/includes/title/MediaWikiTitleCodecTest.php b/tests/phpunit/includes/title/MediaWikiTitleCodecTest.php
new file mode 100644 (file)
index 0000000..e4f9396
--- /dev/null
@@ -0,0 +1,372 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @license GPL 2+
+ * @author Daniel Kinzler
+ */
+
+/**
+ * @covers MediaWikiTitleCodec
+ *
+ * @group Title
+ * @group Database
+ *        ^--- needed because of global state in
+ */
+class MediaWikiTitleCodecTest extends MediaWikiTestCase {
+
+       public function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgLanguageCode' => 'en',
+                       'wgContLang' => Language::factory( 'en' ),
+                       // User language
+                       'wgLang' => Language::factory( 'en' ),
+                       'wgAllowUserJs' => false,
+                       'wgDefaultLanguageVariant' => false,
+                       'wgLocalInterwikis' => array( 'localtestiw' ),
+
+                       // NOTE: this is why global state is evil.
+                       // TODO: refactor access to the interwiki codes so it can be injected.
+                       'wgHooks' => array(
+                               'InterwikiLoadPrefix' => array(
+                                       function ( $prefix, &$data ) {
+                                               if ( $prefix === 'localtestiw' ) {
+                                                       $data = array( 'iw_url' => 'localtestiw' );
+                                               } elseif ( $prefix === 'remotetestiw' ) {
+                                                       $data = array( 'iw_url' => 'remotetestiw' );
+                                               }
+                                               return false;
+                                       }
+                               )
+                       )
+               ) );
+       }
+
+       /**
+        * Returns a mock GenderCache that will consider a user "female" if the
+        * first part of the user name ends with "a".
+        *
+        * @return GenderCache
+        */
+       private function getGenderCache() {
+               $genderCache = $this->getMockBuilder( 'GenderCache' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+
+               $genderCache->expects( $this->any() )
+                       ->method( 'getGenderOf' )
+                       ->will( $this->returnCallback( function( $userName ) {
+                               return preg_match( '/^[^- _]+a( |_|$)/u', $userName ) ? 'female' : 'male';
+                       } ) );
+
+               return $genderCache;
+       }
+
+       protected function makeCodec( $lang ) {
+               $gender = $this->getGenderCache();
+               $lang = Language::factory( $lang );
+               return new MediaWikiTitleCodec( $lang, $gender );
+       }
+
+       public function provideFormat() {
+               return array(
+                       array( NS_MAIN, 'Foo_Bar', '', 'en', 'Foo Bar' ),
+                       array( NS_USER, 'Hansi_Maier', 'stuff_and_so_on', 'en', 'User:Hansi Maier#stuff and so on' ),
+                       array( false, 'Hansi_Maier', '', 'en', 'Hansi Maier' ),
+                       array( NS_USER_TALK, 'hansi__maier', '', 'en', 'User talk:hansi  maier', 'User talk:Hansi maier' ),
+
+                       // getGenderCache() provides a mock that considers first
+                       // names ending in "a" to be female.
+                       array( NS_USER, 'Lisa_Müller', '', 'de', 'Benutzerin:Lisa Müller' ),
+               );
+       }
+
+       /**
+        * @dataProvider provideFormat
+        */
+       public function testFormat( $namespace, $text, $fragment, $lang, $expected, $normalized = null ) {
+               if ( $normalized === null ) {
+                       $normalized = $expected;
+               }
+
+               $codec = $this->makeCodec( $lang );
+               $actual = $codec->formatTitle( $namespace, $text, $fragment );
+
+               $this->assertEquals( $expected, $actual, 'formatted' );
+
+               // test round trip
+               $parsed = $codec->parseTitle( $actual, NS_MAIN );
+               $actual2 = $codec->formatTitle( $parsed->getNamespace(), $parsed->getText(), $parsed->getFragment() );
+
+               $this->assertEquals( $normalized, $actual2, 'normalized after round trip' );
+       }
+
+       public function provideGetText() {
+               return array(
+                       array( NS_MAIN, 'Foo_Bar', '', 'en', 'Foo Bar' ),
+                       array( NS_USER, 'Hansi_Maier', 'stuff_and_so_on', 'en', 'Hansi Maier' ),
+               );
+       }
+
+       /**
+        * @dataProvider provideGetText
+        */
+       public function testGetText( $namespace, $dbkey, $fragment, $lang, $expected ) {
+               $codec = $this->makeCodec( $lang );
+               $title = new TitleValue( $namespace, $dbkey, $fragment );
+
+               $actual = $codec->getText( $title );
+
+               $this->assertEquals( $expected, $actual );
+       }
+
+       public function provideGetPrefixedText() {
+               return array(
+                       array( NS_MAIN, 'Foo_Bar', '', 'en', 'Foo Bar' ),
+                       array( NS_USER, 'Hansi_Maier', 'stuff_and_so_on', 'en', 'User:Hansi Maier' ),
+
+                       // No capitalization or normalization is applied while formatting!
+                       array( NS_USER_TALK, 'hansi__maier', '', 'en', 'User talk:hansi  maier' ),
+
+                       // getGenderCache() provides a mock that considers first
+                       // names ending in "a" to be female.
+                       array( NS_USER, 'Lisa_Müller', '', 'de', 'Benutzerin:Lisa Müller' ),
+               );
+       }
+
+       /**
+        * @dataProvider provideGetPrefixedText
+        */
+       public function testGetPrefixedText( $namespace, $dbkey, $fragment, $lang, $expected ) {
+               $codec = $this->makeCodec( $lang );
+               $title = new TitleValue( $namespace, $dbkey, $fragment );
+
+               $actual = $codec->getPrefixedText( $title );
+
+               $this->assertEquals( $expected, $actual );
+       }
+
+       public function provideGetFullText() {
+               return array(
+                       array( NS_MAIN, 'Foo_Bar', '', 'en', 'Foo Bar' ),
+                       array( NS_USER, 'Hansi_Maier', 'stuff_and_so_on', 'en', 'User:Hansi Maier#stuff and so on' ),
+
+                       // No capitalization or normalization is applied while formatting!
+                       array( NS_USER_TALK, 'hansi__maier', '', 'en', 'User talk:hansi  maier' ),
+               );
+       }
+
+       /**
+        * @dataProvider provideGetFullText
+        */
+       public function testGetFullText( $namespace, $dbkey, $fragment, $lang, $expected ) {
+               $codec = $this->makeCodec( $lang );
+               $title = new TitleValue( $namespace, $dbkey, $fragment );
+
+               $actual = $codec->getFullText( $title );
+
+               $this->assertEquals( $expected, $actual );
+       }
+
+       public function provideParseTitle() {
+               //TODO: test capitalization and trimming
+               //TODO: test unicode normalization
+
+               return array(
+                       array( '  : Hansi_Maier _ ', NS_MAIN, 'en',
+                               new TitleValue( NS_MAIN, 'Hansi_Maier', '' ) ),
+                       array( 'User:::1', NS_MAIN, 'de',
+                               new TitleValue( NS_USER, '0:0:0:0:0:0:0:1', '' ) ),
+                       array( ' lisa Müller', NS_USER, 'de',
+                               new TitleValue( NS_USER, 'Lisa_Müller', '' ) ),
+                       array( 'benutzerin:lisa Müller#stuff', NS_MAIN, 'de',
+                               new TitleValue( NS_USER, 'Lisa_Müller', 'stuff' ) ),
+
+                       array( ':Category:Quux', NS_MAIN, 'en',
+                               new TitleValue( NS_CATEGORY, 'Quux', '' ) ),
+                       array( 'Category:Quux', NS_MAIN, 'en',
+                               new TitleValue( NS_CATEGORY, 'Quux', '' ) ),
+                       array( 'Category:Quux', NS_CATEGORY, 'en',
+                               new TitleValue( NS_CATEGORY, 'Quux', '' ) ),
+                       array( 'Quux', NS_CATEGORY, 'en',
+                               new TitleValue( NS_CATEGORY, 'Quux', '' ) ),
+                       array( ':Quux', NS_CATEGORY, 'en',
+                               new TitleValue( NS_MAIN, 'Quux', '' ) ),
+
+                       // getGenderCache() provides a mock that considers first
+                       // names ending in "a" to be female.
+
+                       array( 'a b c', NS_MAIN, 'en',
+                               new TitleValue( NS_MAIN, 'A_b_c' ) ),
+                       array( ' a  b  c ', NS_MAIN, 'en',
+                               new TitleValue( NS_MAIN, 'A_b_c' ) ),
+                       array( ' _ Foo __ Bar_ _', NS_MAIN, 'en',
+                               new TitleValue( NS_MAIN, 'Foo_Bar' ) ),
+
+                       //NOTE: cases copied from TitleTest::testSecureAndSplit. Keep in sync.
+                       array( 'Sandbox', NS_MAIN, 'en', ),
+                       array( 'A "B"', NS_MAIN, 'en', ),
+                       array( 'A \'B\'', NS_MAIN, 'en', ),
+                       array( '.com', NS_MAIN, 'en', ),
+                       array( '~', NS_MAIN, 'en', ),
+                       array( '"', NS_MAIN, 'en', ),
+                       array( '\'', NS_MAIN, 'en', ),
+
+                       array( 'Talk:Sandbox', NS_MAIN, 'en',
+                               new TitleValue( NS_TALK, 'Sandbox' ) ),
+                       array( 'Talk:Foo:Sandbox', NS_MAIN, 'en',
+                               new TitleValue( NS_TALK, 'Foo:Sandbox' ) ),
+                       array( 'File:Example.svg', NS_MAIN, 'en',
+                               new TitleValue( NS_FILE, 'Example.svg' ) ),
+                       array( 'File_talk:Example.svg', NS_MAIN, 'en',
+                               new TitleValue( NS_FILE_TALK, 'Example.svg' ) ),
+                       array( 'Foo/.../Sandbox', NS_MAIN, 'en',
+                               'Foo/.../Sandbox' ),
+                       array( 'Sandbox/...', NS_MAIN, 'en',
+                               'Sandbox/...' ),
+                       array( 'A~~', NS_MAIN, 'en',
+                               'A~~' ),
+                       // Length is 256 total, but only title part matters
+                       array( 'Category:' . str_repeat( 'x', 248 ), NS_MAIN, 'en',
+                               new TitleValue( NS_CATEGORY,
+                                       'X' . str_repeat( 'x', 247 ) ) ),
+                       array( str_repeat( 'x', 252 ), NS_MAIN, 'en',
+                               'X' . str_repeat( 'x', 251 ) )
+               );
+       }
+
+       /**
+        * @dataProvider provideParseTitle
+        */
+       public function testParseTitle( $text, $ns, $lang, $title = null ) {
+               if ( $title === null ) {
+                       $title = str_replace( ' ', '_', trim( $text ) );
+               }
+
+               if ( is_string( $title ) ) {
+                       $title = new TitleValue( NS_MAIN, $title, '' );
+               }
+
+               $codec = $this->makeCodec( $lang );
+               $actual = $codec->parseTitle( $text, $ns );
+
+               $this->assertEquals( $title, $actual );
+       }
+
+       public function provideParseTitle_invalid() {
+               //TODO: test unicode errors
+
+               return array(
+                       array( '#' ),
+                       array( '::' ),
+                       array( '::xx' ),
+                       array( '::##' ),
+                       array( ' :: x' ),
+
+                       array( 'Talk:File:Foo.jpg' ),
+                       array( 'Talk:localtestiw:Foo' ),
+                       array( 'remotetestiw:Foo' ),
+                       array( '::1' ), // only valid in user namespace
+                       array( 'User::x' ), // leading ":" in a user name is only valid of IPv6 addresses
+
+                       //NOTE: cases copied from TitleTest::testSecureAndSplit. Keep in sync.
+                       array( '' ),
+                       array( ':' ),
+                       array( '__  __' ),
+                       array( '  __  ' ),
+                       // Bad characters forbidden regardless of wgLegalTitleChars
+                       array( 'A [ B' ),
+                       array( 'A ] B' ),
+                       array( 'A { B' ),
+                       array( 'A } B' ),
+                       array( 'A < B' ),
+                       array( 'A > B' ),
+                       array( 'A | B' ),
+                       // URL encoding
+                       array( 'A%20B' ),
+                       array( 'A%23B' ),
+                       array( 'A%2523B' ),
+                       // XML/HTML character entity references
+                       // Note: Commented out because they are not marked invalid by the PHP test as
+                       // Title::newFromText runs Sanitizer::decodeCharReferencesAndNormalize first.
+                       //array( 'A &eacute; B' ),
+                       //array( 'A &#233; B' ),
+                       //array( 'A &#x00E9; B' ),
+                       // Subject of NS_TALK does not roundtrip to NS_MAIN
+                       array( 'Talk:File:Example.svg' ),
+                       // Directory navigation
+                       array( '.' ),
+                       array( '..' ),
+                       array( './Sandbox' ),
+                       array( '../Sandbox' ),
+                       array( 'Foo/./Sandbox' ),
+                       array( 'Foo/../Sandbox' ),
+                       array( 'Sandbox/.' ),
+                       array( 'Sandbox/..' ),
+                       // Tilde
+                       array( 'A ~~~ Name' ),
+                       array( 'A ~~~~ Signature' ),
+                       array( 'A ~~~~~ Timestamp' ),
+                       array( str_repeat( 'x', 256 ) ),
+                       // Namespace prefix without actual title
+                       array( 'Talk:' ),
+                       array( 'Category: ' ),
+                       array( 'Category: #bar' )
+               );
+       }
+
+       /**
+        * @dataProvider provideParseTitle_invalid
+        */
+       public function testParseTitle_invalid( $text ) {
+               $this->setExpectedException( 'MalformedTitleException' );
+
+               $codec = $this->makeCodec( 'en' );
+               $codec->parseTitle( $text, NS_MAIN );
+       }
+
+       public function provideGetNamespaceName() {
+               return array(
+                       array( NS_MAIN, 'Foo', 'en', '' ),
+                       array( NS_USER, 'Foo', 'en', 'User' ),
+                       array( NS_USER, 'Hansi Maier', 'de', 'Benutzer' ),
+
+                       // getGenderCache() provides a mock that considers first
+                       // names ending in "a" to be female.
+                       array( NS_USER, 'Lisa Müller', 'de', 'Benutzerin' ),
+               );
+       }
+
+       /**
+        * @dataProvider provideGetNamespaceName
+        *
+        * @param $namespace
+        * @param $text
+        * @param $lang
+        * @param $expected
+        *
+        * @internal param \TitleValue $title
+        */
+       public function testGetNamespaceName( $namespace, $text, $lang, $expected ) {
+               $codec = $this->makeCodec( $lang );
+               $name = $codec->getNamespaceName( $namespace, $text );
+
+               $this->assertEquals( $expected, $name );
+       }
+}
diff --git a/tests/phpunit/includes/title/TitleValueTest.php b/tests/phpunit/includes/title/TitleValueTest.php
new file mode 100644 (file)
index 0000000..3ba008d
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @license GPL 2+
+ * @author Daniel Kinzler
+ */
+
+/**
+ * @covers TitleValue
+ *
+ * @group Title
+ */
+class TitleValueTest extends MediaWikiTestCase {
+
+       public function testConstruction() {
+               $title = new TitleValue( NS_USER, 'TestThis', 'stuff' );
+
+               $this->assertEquals( NS_USER, $title->getNamespace() );
+               $this->assertEquals( 'TestThis', $title->getText() );
+               $this->assertEquals( 'stuff', $title->getFragment() );
+       }
+
+       public function badConstructorProvider() {
+               return array(
+                       array( 'foo', 'title', 'fragment' ),
+                       array( null, 'title', 'fragment' ),
+                       array( 2.3, 'title', 'fragment' ),
+
+                       array( NS_MAIN, 5, 'fragment' ),
+                       array( NS_MAIN, null, 'fragment' ),
+                       array( NS_MAIN, '', 'fragment' ),
+                       array( NS_MAIN, 'foo bar', '' ),
+                       array( NS_MAIN, 'bar_', '' ),
+                       array( NS_MAIN, '_foo', '' ),
+                       array( NS_MAIN, ' eek ', '' ),
+
+                       array( NS_MAIN, 'title', 5 ),
+                       array( NS_MAIN, 'title', null ),
+                       array( NS_MAIN, 'title', array() ),
+               );
+       }
+
+       /**
+        * @dataProvider badConstructorProvider
+        */
+       public function testConstructionErrors( $ns, $text, $fragment ) {
+               $this->setExpectedException( 'InvalidArgumentException' );
+               new TitleValue( $ns, $text, $fragment );
+       }
+
+       public function fragmentTitleProvider() {
+               return array(
+                       array( new TitleValue( NS_MAIN, 'Test' ), 'foo' ),
+                       array( new TitleValue( NS_TALK, 'Test', 'foo' ), '' ),
+                       array( new TitleValue( NS_CATEGORY, 'Test', 'foo' ), 'bar' ),
+               );
+       }
+
+       /**
+        * @dataProvider fragmentTitleProvider
+        */
+       public function testCreateFragmentTitle( TitleValue $title, $fragment ) {
+               $fragmentTitle = $title->createFragmentTitle( $fragment );
+
+               $this->assertEquals( $title->getNamespace(), $fragmentTitle->getNamespace() );
+               $this->assertEquals( $title->getText(), $fragmentTitle->getText() );
+               $this->assertEquals( $fragment, $fragmentTitle->getFragment() );
+       }
+
+       public function getTextProvider() {
+               return array(
+                       array( 'Foo', 'Foo' ),
+                       array( 'Foo_Bar', 'Foo Bar' ),
+               );
+       }
+
+       /**
+        * @dataProvider getTextProvider
+        */
+       public function testGetText( $dbkey, $text ) {
+               $title = new TitleValue( NS_MAIN, $dbkey );
+
+               $this->assertEquals( $text, $title->getText() );
+       }
+}
index 1eab5a3..50fa384 100644 (file)
@@ -2,6 +2,12 @@
 
 class UIDGeneratorTest extends MediaWikiTestCase {
 
+       protected function tearDown() {
+               // Bug: 44850
+               UIDGenerator::unitTestTearDown();
+               parent::tearDown();
+       }
+
        /**
         * @dataProvider provider_testTimestampedUID
         * @covers UIDGenerator::newTimestampedUID128
index 31470e8..607c435 100644 (file)
@@ -8,14 +8,14 @@ return array(
 
        'test.sinonjs' => array(
                'scripts' => array(
-                       'resources/sinonjs/sinon-1.9.0.js',
+                       'resources/lib/sinonjs/sinon-1.9.0.js',
                        // We want tests to work in IE, but can't include this as it
                        // will break the placeholders in Sinon because the hack it uses
                        // to hijack IE globals relies on running in the global scope
                        // and in ResourceLoader this won't be running in the global scope.
                        // Including it results (among other things) in sandboxed timers
                        // being broken due to Date inheritance being undefined.
-                       // 'resources/sinonjs/sinon-ie-1.9.0.js',
+                       // 'resources/lib/sinonjs/sinon-ie-1.9.0.js',
                ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
index 3be3642..e5066e0 100644 (file)
                this.server.respond();
        } );
 
+       QUnit.test( 'getToken( cached )', function ( assert ) {
+               QUnit.expect( 2 );
+
+               var api = new mw.Api();
+
+               // Get editToken for local wiki, this should not make
+               // a request as it should be retrieved from user.tokens.
+               api.getToken( 'edit' )
+                       .done( function ( token ) {
+                               assert.ok( token.length, 'Got a token' );
+                       } )
+                       .fail( function ( err ) {
+                               assert.equal( '', err, 'API error' );
+                       } );
+
+               assert.equal( this.server.requests.length, 0, 'Requests made' );
+       } );
+
+       QUnit.test( 'getToken( uncached )', function ( assert ) {
+               QUnit.expect( 2 );
+
+               var api = new mw.Api();
+
+               // Get a token of a type that isn't prepopulated by user.tokens.
+               // Could use "block" or "delete" here, but those could in theory
+               // be added to user.tokens, use a fake one instead.
+               api.getToken( 'testaction' )
+                       .done( function ( token ) {
+                               assert.ok( token.length, 'Got a token' );
+                       } )
+                       .fail( function ( err ) {
+                               assert.equal( '', err, 'API error' );
+                       } );
+
+               assert.equal( this.server.requests.length, 1, 'Requests made' );
+
+               this.server.respond( function ( request ) {
+                       request.respond( 200, { 'Content-Type': 'application/json' },
+                               '{ "tokens": { "testactiontoken": "0123abc" } }'
+                       );
+               } );
+       } );
+
 }( mediaWiki ) );
index f5091f9..41b0cb7 100644 (file)
 
        } );
 
-       QUnit.test( 'mw.hook', 10, function ( assert ) {
+       QUnit.test( 'mw.hook', 12, function ( assert ) {
                var hook, add, fire, chars, callback;
 
                mw.hook( 'test.hook.unfired' ).add( function () {
                } );
                mw.hook( 'test.hook.data' ).fire( 'example', ['two'] );
 
-               mw.hook( 'test.hook.chainable' ).add( function () {
-                       assert.ok( true, 'Chainable' );
-               } ).fire();
+               hook = mw.hook( 'test.hook.chainable' );
+               assert.strictEqual( hook.add(), hook, 'hook.add is chainable' );
+               assert.strictEqual( hook.remove(), hook, 'hook.remove is chainable' );
+               assert.strictEqual( hook.fire(), hook, 'hook.fire is chainable' );
 
                hook = mw.hook( 'test.hook.detach' );
                add = hook.add;